gdharness 1.3.8 → 1.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cli.js +4668 -3229
- package/build/godot/addons/gdharness_editor/animation_reads.gd +115 -4
- package/build/godot/addons/gdharness_editor/declared_values.gd +272 -0
- package/build/godot/addons/gdharness_editor/file_reads.gd +115 -18
- package/build/godot/addons/gdharness_editor/headless_check.gd +49 -2
- package/build/godot/addons/gdharness_editor/property_paths.gd +89 -16
- package/build/godot/addons/gdharness_editor/property_values.gd +180 -121
- package/build/godot/addons/gdharness_editor/reading.gd +112 -6
- package/build/godot/addons/gdharness_editor/scene_file.gd +117 -174
- package/build/godot/addons/gdharness_editor/scene_uids.gd +107 -0
- package/build/godot/addons/gdharness_editor/scene_uids.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/serialisation.gd +19 -29
- package/build/godot/addons/gdharness_editor/setting_reads.gd +121 -0
- package/build/godot/addons/gdharness_editor/setting_reads.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/tool_executor.gd +39 -6
- package/build/godot/addons/gdharness_editor/tools/animation_states.gd +263 -0
- package/build/godot/addons/gdharness_editor/tools/animation_states.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +49 -414
- package/build/godot/addons/gdharness_editor/tools/animation_tracks.gd +464 -0
- package/build/godot/addons/gdharness_editor/tools/animation_tracks.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/tools/class_tools.gd +37 -0
- package/build/godot/addons/gdharness_editor/tools/navigation_bake.gd +221 -0
- package/build/godot/addons/gdharness_editor/tools/navigation_bake.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +162 -483
- package/build/godot/addons/gdharness_editor/tools/scene_groups.gd +16 -0
- package/build/godot/addons/gdharness_editor/tools/scene_kin.gd +8 -4
- package/build/godot/addons/gdharness_editor/tools/scene_paths.gd +2 -1
- package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +10 -0
- package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +151 -8
- package/build/godot/addons/gdharness_editor/tools/settings_tools.gd +7 -30
- package/build/godot/addons/gdharness_editor/tools/signal_tools.gd +190 -38
- package/build/godot/addons/gdharness_editor/tools/tileset_tools.gd +485 -0
- package/build/godot/addons/gdharness_editor/tools/tileset_tools.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/value_shapes.gd +128 -1
- package/build/godot/addons/gdharness_runtime/call_errors.gd +8 -2
- package/build/godot/addons/gdharness_runtime/declared_values.gd +272 -0
- package/build/godot/addons/gdharness_runtime/reading.gd +112 -6
- package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +35 -3
- package/build/godot/addons/gdharness_runtime/runtime_capture.gd +5 -0
- package/build/godot/addons/gdharness_runtime/runtime_changes.gd +188 -30
- package/build/godot/addons/gdharness_runtime/runtime_input.gd +107 -104
- package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +17 -0
- package/build/godot/addons/gdharness_runtime/runtime_pad.gd +13 -4
- package/build/godot/addons/gdharness_runtime/runtime_paths.gd +320 -27
- package/build/godot/addons/gdharness_runtime/runtime_queries.gd +165 -20
- package/build/godot/addons/gdharness_runtime/runtime_screen.gd +49 -3
- package/build/godot/addons/gdharness_runtime/runtime_targets.gd +31 -2
- package/build/godot/addons/gdharness_runtime/runtime_values.gd +250 -10
- package/build/godot/addons/gdharness_runtime/runtime_waits.gd +279 -11
- package/build/godot/addons/gdharness_runtime/runtime_words.gd +27 -0
- package/build/godot/addons/gdharness_runtime/serialisation.gd +19 -29
- package/build/godot/addons/gdharness_runtime/value_shapes.gd +128 -1
- package/build/godot/operations/animation_reads.gd +115 -4
- package/build/godot/operations/audio_buses.gd +93 -7
- package/build/godot/operations/classdb_queries.gd +119 -7
- package/build/godot/operations/declared_values.gd +272 -0
- package/build/godot/operations/dependencies.gd +154 -41
- package/build/godot/operations/editor_tools.gd +29 -13
- package/build/godot/operations/export_presets.gd +602 -4
- package/build/godot/operations/file_reads.gd +115 -18
- package/build/godot/operations/gdscript_analysis.gd +14 -0
- package/build/godot/operations/gdscript_authoring.gd +12 -2
- package/build/godot/operations/godot_operations.gd +18 -2
- package/build/godot/operations/import_pipeline.gd +20 -221
- package/build/godot/operations/input_actions.gd +127 -51
- package/build/godot/operations/project_config.gd +113 -68
- package/build/godot/operations/project_diagnostics.gd +4 -0
- package/build/godot/operations/project_validation.gd +266 -0
- package/build/godot/operations/property_paths.gd +89 -16
- package/build/godot/operations/property_values.gd +180 -121
- package/build/godot/operations/reading.gd +112 -6
- package/build/godot/operations/scene_connections.gd +222 -0
- package/build/godot/operations/serialisation.gd +19 -29
- package/build/godot/operations/setting_reads.gd +121 -0
- package/build/godot/operations/value_shapes.gd +128 -1
- package/build/godot/tests/listed.gd +20 -13
- package/build/keeper.js +1402 -707
- package/package.json +1 -1
|
@@ -21,15 +21,6 @@ const GdhMouse = preload("runtime_mouse.gd")
|
|
|
21
21
|
## everything that process starts. Kept in step with `DESKTOP_VARIABLE` in src/desktop.ts.
|
|
22
22
|
const DESKTOP_VARIABLE: String = "GDHARNESS_DESKTOP"
|
|
23
23
|
|
|
24
|
-
## Node.ProcessMode as its names, for a refusal to say which one is in force.
|
|
25
|
-
const PROCESS_MODES: Dictionary[int, String] = {
|
|
26
|
-
Node.PROCESS_MODE_INHERIT: "INHERIT",
|
|
27
|
-
Node.PROCESS_MODE_PAUSABLE: "PAUSABLE",
|
|
28
|
-
Node.PROCESS_MODE_WHEN_PAUSED: "WHEN_PAUSED",
|
|
29
|
-
Node.PROCESS_MODE_ALWAYS: "ALWAYS",
|
|
30
|
-
Node.PROCESS_MODE_DISABLED: "DISABLED",
|
|
31
|
-
}
|
|
32
|
-
|
|
33
24
|
## Whether this run has had the pointer note in full; the game process is the run.
|
|
34
25
|
static var _pointer_explained: bool = false
|
|
35
26
|
|
|
@@ -151,50 +142,38 @@ func inject_action(params: Dictionary) -> Dictionary:
|
|
|
151
142
|
return {"type": "error", "message": "Action name required"}
|
|
152
143
|
|
|
153
144
|
if not InputMap.has_action(action):
|
|
154
|
-
return {"type": "error", "message":
|
|
145
|
+
return {"type": "error", "message": GdhValues.no_action(action)}
|
|
155
146
|
var holding: Variant = GdhValues.held_for(params)
|
|
156
147
|
if holding is String:
|
|
157
148
|
return {"type": "error", "message": holding}
|
|
158
149
|
var frames: int = holding
|
|
159
150
|
|
|
160
|
-
var focused: String =
|
|
151
|
+
var focused: String = GdhValues.focus_path(_host)
|
|
161
152
|
_say_action(action, whole or held, strength)
|
|
153
|
+
var shortcuts: Dictionary = {"shortcuts": [], "shortcut_pressed": null}
|
|
154
|
+
if whole or held:
|
|
155
|
+
shortcuts = await GdhValues.press_shortcuts(_host.get_tree().root, action)
|
|
162
156
|
var lasted: Variant = null
|
|
163
157
|
if whole:
|
|
164
158
|
# A frame between the halves at least, as a click has: a listener that acts on the press and
|
|
165
159
|
# a listener that acts on the release both get their own frame to do it in.
|
|
166
160
|
lasted = await GdhValues.hold(_host.get_tree(), frames)
|
|
167
161
|
_say_action(action, false, strength)
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
return _focus_noted(
|
|
171
|
-
{
|
|
172
|
-
"type": "input_injected",
|
|
173
|
-
"input_type": "action",
|
|
174
|
-
"action": action,
|
|
175
|
-
"pressed": held and not whole,
|
|
176
|
-
"whole": whole,
|
|
177
|
-
"held_frames": GdhValues.held_answer(whole, frames),
|
|
178
|
-
"held_for": lasted,
|
|
179
|
-
},
|
|
180
|
-
focused
|
|
181
|
-
)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
## The path of the Control holding the keyboard focus, or "" when none does. Read before a key or an
|
|
185
|
-
## action goes in, since pressing a focused button can move the focus.
|
|
186
|
-
func _focus_owner() -> String:
|
|
187
|
-
var holding: Control = _host.get_viewport().gui_get_focus_owner()
|
|
188
|
-
return "" if holding == null else str(holding.get_path())
|
|
189
|
-
|
|
162
|
+
# The engine hands a parsed event on at the next frame, so the focus is read after one.
|
|
163
|
+
await _host.get_tree().process_frame
|
|
190
164
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
165
|
+
var answer: Dictionary = {
|
|
166
|
+
"type": "input_injected",
|
|
167
|
+
"input_type": "action",
|
|
168
|
+
"action": action,
|
|
169
|
+
"shortcuts": shortcuts["shortcuts"],
|
|
170
|
+
"shortcut_pressed": shortcuts["shortcut_pressed"],
|
|
171
|
+
"pressed": held and not whole,
|
|
172
|
+
"whole": whole,
|
|
173
|
+
"held_frames": GdhValues.held_answer(whole, frames),
|
|
174
|
+
"held_for": lasted,
|
|
175
|
+
}
|
|
176
|
+
return GdhValues.focus_noted(answer, focused, _host)
|
|
198
177
|
|
|
199
178
|
|
|
200
179
|
func _say_action(action: String, down: bool, strength: float) -> void:
|
|
@@ -250,7 +229,7 @@ func inject_key(params: Dictionary) -> Dictionary:
|
|
|
250
229
|
# keys are the code points themselves, which is what makes this a mapping and not a table.
|
|
251
230
|
event.unicode = GdhValues.glyph_of(event.keycode, event.shift_pressed)
|
|
252
231
|
|
|
253
|
-
var focused: String =
|
|
232
|
+
var focused: String = GdhValues.focus_path(_host)
|
|
254
233
|
Input.parse_input_event(event)
|
|
255
234
|
var lasted: Variant = null
|
|
256
235
|
if whole:
|
|
@@ -258,25 +237,24 @@ func inject_key(params: Dictionary) -> Dictionary:
|
|
|
258
237
|
var up: InputEventKey = event.duplicate()
|
|
259
238
|
up.pressed = false
|
|
260
239
|
Input.parse_input_event(up)
|
|
261
|
-
|
|
240
|
+
await _host.get_tree().process_frame
|
|
262
241
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
)
|
|
242
|
+
var answer: Dictionary = {
|
|
243
|
+
"type": "input_injected",
|
|
244
|
+
"input_type": "key",
|
|
245
|
+
"held_frames": GdhValues.held_answer(whole, frames),
|
|
246
|
+
"held_for": lasted,
|
|
247
|
+
"keycode": event.keycode,
|
|
248
|
+
"physical_keycode": event.physical_keycode,
|
|
249
|
+
"shift": event.shift_pressed,
|
|
250
|
+
"ctrl": event.ctrl_pressed,
|
|
251
|
+
"alt": event.alt_pressed,
|
|
252
|
+
"unicode": event.unicode,
|
|
253
|
+
"actions": GdhValues.actions_of(event),
|
|
254
|
+
"pressed": held and not whole,
|
|
255
|
+
"whole": whole,
|
|
256
|
+
}
|
|
257
|
+
return GdhValues.focus_noted(answer, focused, _host)
|
|
280
258
|
|
|
281
259
|
|
|
282
260
|
## Clicks a mouse button at a position, and lets go of it again unless asked to hold it.
|
|
@@ -317,16 +295,28 @@ func inject_mouse_click(params: Dictionary) -> Dictionary:
|
|
|
317
295
|
# its drag from the press, which is where a real pointer would be.
|
|
318
296
|
var _moved: Vector2 = _arrive(position)
|
|
319
297
|
var supplied: bool = _follow_in_the_window(position)
|
|
320
|
-
|
|
298
|
+
# A double click's first click goes whole before it, as [method _click_button] sends one.
|
|
299
|
+
if double and held and not notch:
|
|
300
|
+
Input.parse_input_event(GdhMouse.button_event(position, button, true, false))
|
|
301
|
+
await _host.get_tree().process_frame
|
|
302
|
+
Input.parse_input_event(GdhMouse.button_event(position, button, false, false))
|
|
303
|
+
await _host.get_tree().process_frame
|
|
304
|
+
var press: InputEventMouseButton = GdhMouse.button_event(position, button, whole or held, double)
|
|
305
|
+
Input.parse_input_event(press)
|
|
321
306
|
var lasted: Variant = null
|
|
322
307
|
if notch:
|
|
323
|
-
Input.parse_input_event(
|
|
308
|
+
Input.parse_input_event(GdhMouse.button_event(position, button, false, false))
|
|
324
309
|
elif whole:
|
|
325
310
|
# A frame between the halves at least, as inject_action has, so a control that acts on the
|
|
326
311
|
# press and one that acts on the release each get a frame to do it in.
|
|
327
312
|
lasted = await GdhValues.hold(_host.get_tree(), frames)
|
|
328
|
-
Input.parse_input_event(
|
|
329
|
-
|
|
313
|
+
Input.parse_input_event(GdhMouse.button_event(position, button, false, false))
|
|
314
|
+
# Input hands the events on at the next frame, so the control under the pointer is read after it.
|
|
315
|
+
await _host.get_tree().process_frame
|
|
316
|
+
var hovered: Control = _hover.hovered_in(_host.get_viewport())
|
|
317
|
+
var hovered_path: Variant = null
|
|
318
|
+
if hovered != null:
|
|
319
|
+
hovered_path = str(hovered.get_path())
|
|
330
320
|
|
|
331
321
|
var at: Array[Vector2] = [position]
|
|
332
322
|
var said: Dictionary = _pointer_noted(
|
|
@@ -338,6 +328,8 @@ func inject_mouse_click(params: Dictionary) -> Dictionary:
|
|
|
338
328
|
"held_for": lasted,
|
|
339
329
|
"position": [position.x, position.y],
|
|
340
330
|
"button": button,
|
|
331
|
+
"hovered": hovered_path,
|
|
332
|
+
"actions": GdhValues.actions_of(press),
|
|
341
333
|
"pressed": held and not whole,
|
|
342
334
|
"whole": whole,
|
|
343
335
|
"double": double
|
|
@@ -419,7 +411,7 @@ func inject_mouse_drag(params: Dictionary) -> Dictionary:
|
|
|
419
411
|
var end: Vector2 = points[points.size() - 1]
|
|
420
412
|
var _moved: Vector2 = _arrive(start)
|
|
421
413
|
var supplied: bool = _follow_in_the_window(start)
|
|
422
|
-
Input.parse_input_event(
|
|
414
|
+
Input.parse_input_event(GdhMouse.button_event(start, button, true, false))
|
|
423
415
|
var travelled: Vector2 = Vector2.ZERO
|
|
424
416
|
for step: int in range(1, frames + 1):
|
|
425
417
|
await _host.get_tree().process_frame
|
|
@@ -429,7 +421,7 @@ func inject_mouse_drag(params: Dictionary) -> Dictionary:
|
|
|
429
421
|
supplied = _follow_in_the_window(at) or supplied
|
|
430
422
|
Input.parse_input_event(_motion(at, relative))
|
|
431
423
|
await _host.get_tree().process_frame
|
|
432
|
-
Input.parse_input_event(
|
|
424
|
+
Input.parse_input_event(GdhMouse.button_event(end, button, false, false))
|
|
433
425
|
await _host.get_tree().process_frame
|
|
434
426
|
|
|
435
427
|
var said: Dictionary = _pointer_noted(
|
|
@@ -550,6 +542,7 @@ func click(params: Dictionary) -> Dictionary:
|
|
|
550
542
|
# other words, a link among them. Said either way, so a press on the middle is never read as one
|
|
551
543
|
# on the words.
|
|
552
544
|
var aim: Vector2 = control.size * 0.5
|
|
545
|
+
var at_centre: bool = true
|
|
553
546
|
var item_scrolled: bool = false
|
|
554
547
|
if item != null:
|
|
555
548
|
var found_by_words: Dictionary = found
|
|
@@ -559,6 +552,7 @@ func click(params: Dictionary) -> Dictionary:
|
|
|
559
552
|
if placed_item.has("message"):
|
|
560
553
|
return placed_item
|
|
561
554
|
aim = placed_item["point"]
|
|
555
|
+
at_centre = false
|
|
562
556
|
item_scrolled = placed_item["scrolled"]
|
|
563
557
|
var rich: RichTextLabel = control as RichTextLabel
|
|
564
558
|
if found != null and rich != null:
|
|
@@ -566,6 +560,7 @@ func click(params: Dictionary) -> Dictionary:
|
|
|
566
560
|
var found_here: Dictionary = found
|
|
567
561
|
if placed.has("point"):
|
|
568
562
|
aim = placed["point"]
|
|
563
|
+
at_centre = false
|
|
569
564
|
found_here["pressedOn"] = "the words"
|
|
570
565
|
elif placed.has("unplaced"):
|
|
571
566
|
found_here["pressedOn"] = "the middle of the label"
|
|
@@ -602,6 +597,20 @@ func click(params: Dictionary) -> Dictionary:
|
|
|
602
597
|
}
|
|
603
598
|
local = control.get_global_transform_with_canvas() * aim
|
|
604
599
|
|
|
600
|
+
# A control taller or wider than what shows it has its centre out of sight at every scroll, and
|
|
601
|
+
# a player clicks the part they can see. Refused, it was called a control nothing could click.
|
|
602
|
+
var on_part: bool = false
|
|
603
|
+
if at_centre and not _in_sight(control, own, local):
|
|
604
|
+
var part: Variant = GdhScreen.shown_part(control)
|
|
605
|
+
if part is Rect2:
|
|
606
|
+
var seen: Rect2 = part
|
|
607
|
+
var middle: Vector2 = seen.get_center()
|
|
608
|
+
# The box of a turned control is wider than the control, so its middle may be off it.
|
|
609
|
+
var back: Vector2 = control.get_global_transform_with_canvas().affine_inverse() * middle
|
|
610
|
+
if seen.has_area() and Rect2(Vector2.ZERO, control.size).has_point(back):
|
|
611
|
+
local = middle
|
|
612
|
+
on_part = true
|
|
613
|
+
|
|
605
614
|
var reached: Dictionary = GdhScreen.reach(own, local)
|
|
606
615
|
var viewport: Viewport = reached["viewport"]
|
|
607
616
|
var centre: Vector2 = reached["point"]
|
|
@@ -638,6 +647,8 @@ func click(params: Dictionary) -> Dictionary:
|
|
|
638
647
|
if hovered != null:
|
|
639
648
|
hovered_path = str(hovered.get_path())
|
|
640
649
|
var landed: bool = hovered == control or (hovered != null and control.is_ancestor_of(hovered))
|
|
650
|
+
# Asked only of a miss, before the press restacks windows: hovered missed a window over it.
|
|
651
|
+
var cover: Node = null if landed else GdhTargets.drawn_over(control)
|
|
641
652
|
|
|
642
653
|
# The link a rich label says was pressed, which is its own word for what the press reached.
|
|
643
654
|
var links: Array = []
|
|
@@ -653,9 +664,7 @@ func click(params: Dictionary) -> Dictionary:
|
|
|
653
664
|
var was_pressed: Variant = null
|
|
654
665
|
if toggle != null and toggle.toggle_mode:
|
|
655
666
|
was_pressed = toggle.button_pressed
|
|
656
|
-
|
|
657
|
-
await _host.get_tree().process_frame
|
|
658
|
-
_press_button(viewport, _button(position, button, false, false))
|
|
667
|
+
var press: InputEventMouseButton = await _click_button(viewport, position, button, double)
|
|
659
668
|
# The release is what a button acts on, and a queue_free it causes lands at the end of
|
|
660
669
|
# this frame; the frame passes so the answer describes the control as the click left it.
|
|
661
670
|
await _host.get_tree().process_frame
|
|
@@ -675,9 +684,20 @@ func click(params: Dictionary) -> Dictionary:
|
|
|
675
684
|
"double": double,
|
|
676
685
|
"hovered": hovered_path,
|
|
677
686
|
"landed": landed,
|
|
687
|
+
"actions": GdhValues.actions_of(press),
|
|
678
688
|
"control_afterwards": afterwards,
|
|
679
689
|
"scrolled_into_view": scrolled,
|
|
680
690
|
}
|
|
691
|
+
if on_part:
|
|
692
|
+
answer["pressed_on"] = "the middle of the part on screen, since no scroll brings its centre into view"
|
|
693
|
+
# A Label and a TextureRect ignore the pointer unless told otherwise, so the click goes to what is
|
|
694
|
+
# under them, and landed false with that control as hovered said nothing of why.
|
|
695
|
+
if not landed and control.mouse_filter == Control.MOUSE_FILTER_IGNORE:
|
|
696
|
+
answer["why_not_landed"] = (
|
|
697
|
+
"%s's mouse_filter is ignore, so the pointer passes through it to what is under it" % node_path
|
|
698
|
+
)
|
|
699
|
+
elif cover != null:
|
|
700
|
+
answer["why_not_landed"] = "%s is drawn over it at the point clicked" % cover.get_path()
|
|
681
701
|
if found != null:
|
|
682
702
|
answer["found"] = found
|
|
683
703
|
if was_pressed != null:
|
|
@@ -718,7 +738,7 @@ func _takes_no_click(control: Control, node_path: String) -> String:
|
|
|
718
738
|
% [node_path, on]
|
|
719
739
|
)
|
|
720
740
|
if not control.can_process():
|
|
721
|
-
var why: String =
|
|
741
|
+
var why: String = GdhTargets.why_it_does_not_process(control, node_path)
|
|
722
742
|
var over: Node = GdhTargets.drawn_over(control)
|
|
723
743
|
var cover: String = "" if over == null else "; %s is drawn over it" % over.get_path()
|
|
724
744
|
if _host.get_tree().paused:
|
|
@@ -730,23 +750,6 @@ func _takes_no_click(control: Control, node_path: String) -> String:
|
|
|
730
750
|
return ""
|
|
731
751
|
|
|
732
752
|
|
|
733
|
-
## Which node's process_mode keeps [param control] from processing, and what it is. A node set to
|
|
734
|
-
## inherit takes its parent's, so the one deciding can be any node above it: the game turning a
|
|
735
|
-
## whole screen off while a menu shows over it reads, on the button, as a button turned off.
|
|
736
|
-
static func _why_it_does_not_process(control: Control, node_path: String) -> String:
|
|
737
|
-
var deciding: Node = control
|
|
738
|
-
while deciding.process_mode == Node.PROCESS_MODE_INHERIT and deciding.get_parent() != null:
|
|
739
|
-
deciding = deciding.get_parent()
|
|
740
|
-
# The root inherits from nothing, which processes as pausable.
|
|
741
|
-
var value: int = deciding.process_mode
|
|
742
|
-
if value == Node.PROCESS_MODE_INHERIT:
|
|
743
|
-
value = Node.PROCESS_MODE_PAUSABLE
|
|
744
|
-
var mode: String = PROCESS_MODES.get(value, str(value))
|
|
745
|
-
if deciding == control:
|
|
746
|
-
return "its process_mode is %s" % mode
|
|
747
|
-
return "%s inherits process_mode %s from %s" % [node_path, mode, deciding.get_path()]
|
|
748
|
-
|
|
749
|
-
|
|
750
753
|
## Why a click at [param control]'s centre would reach nothing, or "" when it would reach it: the
|
|
751
754
|
## centre outside the viewport it is drawn in, at [param local]; outside the viewport showing that
|
|
752
755
|
## one on the screen, which [param reached] holds with the centre there; or clipped away by a
|
|
@@ -799,6 +802,23 @@ func _no_window_note(viewport: Viewport) -> String:
|
|
|
799
802
|
##
|
|
800
803
|
## Any other viewport is pushed into directly: Input reaches only the game's window. That is a
|
|
801
804
|
## viewport with no place on the screen, since `GdhScreen.reach` carries every other one there.
|
|
805
|
+
## A press and its release a frame apart, answering with the press. A double click arrives as the
|
|
806
|
+
## engine gets one from the system: a whole click, then a second press marked as a double click and
|
|
807
|
+
## its release. Sent as the marked press alone, it pressed a button once where a player's presses it
|
|
808
|
+
## twice.
|
|
809
|
+
func _click_button(viewport: Viewport, position: Vector2, button: int, double: bool) -> InputEventMouseButton:
|
|
810
|
+
if double:
|
|
811
|
+
_press_button(viewport, GdhMouse.button_event(position, button, true, false))
|
|
812
|
+
await _host.get_tree().process_frame
|
|
813
|
+
_press_button(viewport, GdhMouse.button_event(position, button, false, false))
|
|
814
|
+
await _host.get_tree().process_frame
|
|
815
|
+
var press: InputEventMouseButton = GdhMouse.button_event(position, button, true, double)
|
|
816
|
+
_press_button(viewport, press)
|
|
817
|
+
await _host.get_tree().process_frame
|
|
818
|
+
_press_button(viewport, GdhMouse.button_event(position, button, false, false))
|
|
819
|
+
return press
|
|
820
|
+
|
|
821
|
+
|
|
802
822
|
func _press_button(viewport: Viewport, event: InputEventMouseButton) -> void:
|
|
803
823
|
if viewport == _host.get_tree().root:
|
|
804
824
|
Input.parse_input_event(event)
|
|
@@ -881,9 +901,7 @@ func _click_in_the_world(node_path: String, item: Node3D, params: Dictionary) ->
|
|
|
881
901
|
var through: Dictionary = _through_the_interface(out)
|
|
882
902
|
var hovered_path: Variant = through["hovered"]
|
|
883
903
|
|
|
884
|
-
|
|
885
|
-
await _host.get_tree().process_frame
|
|
886
|
-
_press_button(arriving, _button(position, button, false, false))
|
|
904
|
+
var _press: InputEventMouseButton = await _click_button(arriving, position, button, double)
|
|
887
905
|
await _host.get_tree().process_frame
|
|
888
906
|
|
|
889
907
|
return _pointer_noted(
|
|
@@ -979,18 +997,3 @@ func _motion(position: Vector2, relative: Vector2) -> InputEventMouseMotion:
|
|
|
979
997
|
event.screen_velocity = event.velocity
|
|
980
998
|
event.button_mask = Input.get_mouse_button_mask()
|
|
981
999
|
return event
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
## A button event carries the buttons held once it has happened: the pressed one among them, the
|
|
985
|
-
## released one out. A wheel step is a button with no mask, as it is from a real mouse.
|
|
986
|
-
func _button(position: Vector2, button: int, pressed: bool, double: bool) -> InputEventMouseButton:
|
|
987
|
-
var event: InputEventMouseButton = InputEventMouseButton.new()
|
|
988
|
-
event.position = position
|
|
989
|
-
event.global_position = position
|
|
990
|
-
event.button_index = button as MouseButton
|
|
991
|
-
event.pressed = pressed
|
|
992
|
-
event.double_click = double
|
|
993
|
-
var held: int = Input.get_mouse_button_mask()
|
|
994
|
-
var own: int = GdhMouse.mask_of(button)
|
|
995
|
-
event.button_mask = (held | own) if pressed else (held & ~own)
|
|
996
|
-
return event
|
|
@@ -65,6 +65,23 @@ static func mask_of(button: int) -> int:
|
|
|
65
65
|
return 1 << (button - 1)
|
|
66
66
|
|
|
67
67
|
|
|
68
|
+
## A button event carries the buttons held once it has happened: the pressed one among them, the
|
|
69
|
+
## released one out. A wheel step is a button with no mask, as it is from a real mouse.
|
|
70
|
+
static func button_event(
|
|
71
|
+
position: Vector2, button: int, pressed: bool, double: bool
|
|
72
|
+
) -> InputEventMouseButton:
|
|
73
|
+
var event: InputEventMouseButton = InputEventMouseButton.new()
|
|
74
|
+
event.position = position
|
|
75
|
+
event.global_position = position
|
|
76
|
+
event.button_index = button as MouseButton
|
|
77
|
+
event.pressed = pressed
|
|
78
|
+
event.double_click = double
|
|
79
|
+
var held: int = Input.get_mouse_button_mask()
|
|
80
|
+
var own: int = mask_of(button)
|
|
81
|
+
event.button_mask = (held | own) if pressed else (held & ~own)
|
|
82
|
+
return event
|
|
83
|
+
|
|
84
|
+
|
|
68
85
|
## [param answer], saying so when one of [param points] lies outside [param viewport]: the GUI picks
|
|
69
86
|
## what is under the pointer only inside it, so such a press or motion reaches no control, and its
|
|
70
87
|
## answer read the same as one that landed.
|
|
@@ -68,16 +68,19 @@ func inject_joypad_button(params: Dictionary) -> Dictionary:
|
|
|
68
68
|
return {"type": "error", "message": holding}
|
|
69
69
|
var frames: int = holding
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
var focused: String = GdhValues.focus_path(_host)
|
|
72
|
+
var event: InputEventJoypadButton = _button(button, device, whole or held)
|
|
73
|
+
Input.parse_input_event(event)
|
|
72
74
|
var lasted: Variant = null
|
|
73
75
|
if whole:
|
|
74
76
|
# A frame between the halves at least, as a key has, so a game that acts on the press and one
|
|
75
77
|
# that acts on the release each get a frame to do it in.
|
|
76
78
|
lasted = await GdhValues.hold(_host.get_tree(), frames)
|
|
77
79
|
Input.parse_input_event(_button(button, device, false))
|
|
78
|
-
|
|
80
|
+
# The engine hands a parsed event on at the next frame, so the focus is read after one.
|
|
81
|
+
await _host.get_tree().process_frame
|
|
79
82
|
|
|
80
|
-
|
|
83
|
+
var answer: Dictionary = {
|
|
81
84
|
"type": "input_injected",
|
|
82
85
|
"input_type": "joypad_button",
|
|
83
86
|
"held_frames": GdhValues.held_answer(whole, frames),
|
|
@@ -85,9 +88,11 @@ func inject_joypad_button(params: Dictionary) -> Dictionary:
|
|
|
85
88
|
"button": button,
|
|
86
89
|
"button_name": _name_of(button, JOY_BUTTONS),
|
|
87
90
|
"device": device,
|
|
91
|
+
"actions": GdhValues.actions_of(event),
|
|
88
92
|
"pressed": held and not whole,
|
|
89
93
|
"whole": whole,
|
|
90
94
|
}
|
|
95
|
+
return GdhValues.focus_noted(answer, focused, _host)
|
|
91
96
|
|
|
92
97
|
|
|
93
98
|
## Moves a stick or trigger axis to a value, where it stays until another motion moves it, as a
|
|
@@ -110,16 +115,20 @@ func inject_joypad_motion(params: Dictionary) -> Dictionary:
|
|
|
110
115
|
event.axis = axis as JoyAxis
|
|
111
116
|
event.axis_value = value
|
|
112
117
|
event.device = device
|
|
118
|
+
var focused: String = GdhValues.focus_path(_host)
|
|
113
119
|
Input.parse_input_event(event)
|
|
120
|
+
await _host.get_tree().process_frame
|
|
114
121
|
|
|
115
|
-
|
|
122
|
+
var answer: Dictionary = {
|
|
116
123
|
"type": "input_injected",
|
|
117
124
|
"input_type": "joypad_motion",
|
|
118
125
|
"axis": axis,
|
|
119
126
|
"axis_name": _name_of(axis, JOY_AXES),
|
|
120
127
|
"value": value,
|
|
121
128
|
"device": device,
|
|
129
|
+
"actions": GdhValues.actions_of(event),
|
|
122
130
|
}
|
|
131
|
+
return GdhValues.focus_noted(answer, focused, _host)
|
|
123
132
|
|
|
124
133
|
|
|
125
134
|
static func _button(button: int, device: int, down: bool) -> InputEventJoypadButton:
|