Skip to content

Commit f9995d0

Browse files
committed
Middle click and drag in stage should take precedence
1 parent ff6fae0 commit f9995d0

5 files changed

Lines changed: 63 additions & 1 deletion

File tree

‎src/editor/editor_stage_manager/editor_stage_view/editor_stage_view.go‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,17 @@ func (v *StageView) IsFlyCameraInputActive() bool {
7979
(m.Pressed(hid.MouseButtonRight) || m.Held(hid.MouseButtonRight))
8080
}
8181

82+
// IsCameraPanInputStarting reports the middle-button press that must reach the
83+
// camera on this frame so it can initialize its drag state.
84+
func (v *StageView) IsCameraPanInputStarting() bool {
85+
if !v.open || v.host == nil || v.host.Window == nil {
86+
return false
87+
}
88+
m := &v.host.Window.Mouse
89+
return m.Pressed(hid.MouseButtonMiddle) &&
90+
v.viewportContainsScreenPosition(m.ScreenPosition())
91+
}
92+
8293
func (v *StageView) SetViewportToolOwner(owner ViewportToolOwner) {
8394
v.toolOwner = owner
8495
}

‎src/editor/editor_stage_manager/editor_stage_view/stage_viewport_test.go‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313
"kaijuengine.com/engine"
1414
"kaijuengine.com/engine/ui"
1515
"kaijuengine.com/matrix"
16+
"kaijuengine.com/platform/hid"
17+
"kaijuengine.com/platform/windowing"
1618
"kaijuengine.com/rendering"
1719
)
1820

@@ -49,6 +51,27 @@ func TestStageViewportBoundsConvertsScreenBoxToLocalBottomArea(t *testing.T) {
4951
}
5052
}
5153

54+
func TestStageViewDetectsCameraPanStartInsideViewport(t *testing.T) {
55+
t.Parallel()
56+
57+
window := &windowing.Window{Mouse: hid.NewMouse()}
58+
window.Mouse.SetPosition(50, 50, 200, 100)
59+
window.Mouse.SetDown(hid.MouseButtonMiddle)
60+
view := StageView{
61+
host: &engine.Host{Window: window},
62+
open: true,
63+
viewport: stageViewportBounds{Left: 25, Top: 25, Width: 100, Height: 50},
64+
}
65+
66+
if !view.IsCameraPanInputStarting() {
67+
t.Fatal("middle press inside the stage viewport did not start camera pan input")
68+
}
69+
view.viewport = stageViewportBounds{Left: 125, Top: 25, Width: 50, Height: 50}
70+
if view.IsCameraPanInputStarting() {
71+
t.Fatal("middle press outside the stage viewport started camera pan input")
72+
}
73+
}
74+
5275
func TestStageTargetResizeFollowsViewportPanelSize(t *testing.T) {
5376
t.Parallel()
5477

‎src/editor/editor_workspace/stage_workspace/stage_workspace.go‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,11 @@ func (w *StageWorkspace) Update(deltaTime float64) {
255255
return
256256
}
257257
w.stageView.SyncStageViewport()
258-
if w.UiMan.Group.HasRequests() {
258+
resumeCameraPan := w.IsFocusedOnInput() && w.stageView.IsCameraPanInputStarting()
259+
if resumeCameraPan {
260+
w.UiMan.Group.ClearFocus()
261+
}
262+
if w.UiMan.Group.HasRequests() && !resumeCameraPan {
259263
return
260264
}
261265
if !w.IsFocusedOnInput() {

‎src/engine/ui/group.go‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ func (group *Group) IsFocusedOnInput() bool {
101101
return group.focus.IsType(ElementTypeInput) || group.focus.IsType(ElementTypeTextArea)
102102
}
103103

104+
// ClearFocus releases the currently focused element through its normal miss
105+
// handler so inputs can submit and blur just as they do when clicking elsewhere.
106+
func (group *Group) ClearFocus() {
107+
group.setFocus(nil)
108+
}
109+
104110
func (group *Group) Attach(host *engine.Host) {
105111
wGroup := weak.Make(group)
106112
group.updateId = host.UILateUpdater.AddUpdate(func(dt float64) {

‎src/engine/ui/group_test.go‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,21 @@ func TestGroupLateUpdateDispatchesFocusAndBlur(t *testing.T) {
7777
t.Fatalf("lateUpdate did not clear dispatched focus requests")
7878
}
7979
}
80+
81+
func TestGroupClearFocusDispatchesMiss(t *testing.T) {
82+
t.Parallel()
83+
84+
target := &UI{}
85+
missed := false
86+
target.events[EventTypeMiss].Add(func() { missed = true })
87+
group := Group{focus: target}
88+
89+
group.ClearFocus()
90+
91+
if !missed {
92+
t.Fatal("clearing focus did not dispatch a miss event")
93+
}
94+
if group.focus != nil {
95+
t.Fatal("clearing focus retained the focused element")
96+
}
97+
}

0 commit comments

Comments
 (0)