gdharness 1.2.30 → 1.2.32

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.
Files changed (37) hide show
  1. package/build/cli.js +7197 -6159
  2. package/build/godot/addons/gdharness_editor/bridge_client.gd +14 -0
  3. package/build/godot/addons/gdharness_editor/file_reads.gd +237 -0
  4. package/build/godot/addons/gdharness_editor/file_reads.gd.uid +1 -0
  5. package/build/godot/addons/gdharness_editor/plugin.gd +27 -0
  6. package/build/godot/addons/gdharness_editor/property_values.gd +80 -54
  7. package/build/godot/addons/gdharness_editor/scene_file.gd +38 -1
  8. package/build/godot/addons/gdharness_editor/serialisation.gd +46 -0
  9. package/build/godot/addons/gdharness_editor/tool_executor.gd +1 -0
  10. package/build/godot/addons/gdharness_editor/tools/class_tools.gd +22 -0
  11. package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd +64 -1
  12. package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +82 -44
  13. package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +178 -0
  14. package/build/godot/addons/gdharness_editor/tools/scene_placing.gd.uid +1 -0
  15. package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +73 -124
  16. package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +39 -0
  17. package/build/godot/addons/gdharness_runtime/runtime_hover.gd +285 -0
  18. package/build/godot/addons/gdharness_runtime/runtime_hover.gd.uid +1 -0
  19. package/build/godot/addons/gdharness_runtime/runtime_input.gd +151 -106
  20. package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +112 -0
  21. package/build/godot/addons/gdharness_runtime/runtime_mouse.gd.uid +1 -0
  22. package/build/godot/addons/gdharness_runtime/runtime_paths.gd +5 -4
  23. package/build/godot/addons/gdharness_runtime/runtime_values.gd +1 -47
  24. package/build/godot/addons/gdharness_runtime/serialisation.gd +46 -0
  25. package/build/godot/operations/audio_buses.gd +14 -1
  26. package/build/godot/operations/class_cache.gd +146 -35
  27. package/build/godot/operations/classdb_queries.gd +19 -12
  28. package/build/godot/operations/file_reads.gd +237 -0
  29. package/build/godot/operations/gdscript_authoring.gd +136 -19
  30. package/build/godot/operations/godot_operations.gd +24 -0
  31. package/build/godot/operations/project_config.gd +16 -6
  32. package/build/godot/operations/property_values.gd +767 -0
  33. package/build/godot/operations/rename_checks.gd +5 -2
  34. package/build/godot/operations/serialisation.gd +46 -0
  35. package/build/index.js +4896 -3872
  36. package/build/keeper.js +184 -71
  37. package/package.json +1 -1
@@ -0,0 +1,285 @@
1
+ extends RefCounted
2
+
3
+ ## The hover Godot gives the controls under the pointer, supplied in a native window the operating
4
+ ## system has not said the pointer entered.
5
+ ##
6
+ ## With display/window/subwindows/embed_subwindows off, every window is a native one, and the engine
7
+ ## hovers a control in one only once the window has had its mouse-enter: Viewport::_update_mouse_over
8
+ ## asks the root which window the pointer is over, and only Window::_event_callback, called by the
9
+ ## platform when the pointer crosses into the window, sets it. An injected event never crosses
10
+ ## anything, and on gdharness's own desktop no pointer ever enters a window, so nothing was hovered.
11
+ ## A BaseButton takes a mouse press only while hovered, so every click on a button in such a window
12
+ ## was dropped while the press itself was routed to it. Reported from Tall Tales Inn, whose strip
13
+ ## window holds its first-run question, and traced through Godot 4.7.2's source.
14
+ ##
15
+ ## What is supplied is what the engine does once the window has been entered: the control its own
16
+ ## search finds under the point, MOUSE_ENTER and mouse_entered on it and on each holder the pointer
17
+ ## passes to, MOUSE_ENTER_SELF on it, and the exits in the engine's order when the pointer moves on.
18
+ ## The engine's own record of the hover is not reachable from a script, so
19
+ ## Viewport.gui_get_hovered_control() still answers null there; [method hovered_in] answers for both.
20
+
21
+ ## Per viewport, by instance id, the instance ids of the controls the supplied hover is on, outermost
22
+ ## first, ending with the one under the pointer, as the engine keeps its own.
23
+ var _supplied: Dictionary[int, Array] = {}
24
+
25
+ ## The windows whose mouse-enter and mouse-exit are listened for, and whether the platform has said
26
+ ## the pointer is inside each: once it has, the engine hovers there by itself.
27
+ var _listened: Dictionary[int, bool] = {}
28
+ var _inside: Dictionary[int, bool] = {}
29
+
30
+ ## Whether a script on a control declares `_has_point`, per script, since the search asks it of
31
+ ## every control it passes.
32
+ var _shapes: Dictionary[Script, bool] = {}
33
+
34
+
35
+ ## Whether the engine cannot hover anything in [param window]: a native window, with the root not
36
+ ## embedding windows, that the platform has not said the pointer is in.
37
+ func cannot_hover(window: Window) -> bool:
38
+ if window.is_embedded() or window.get_tree().root.gui_embed_subwindows:
39
+ return false
40
+ _listen(window)
41
+ return not _inside.get(window.get_instance_id(), false)
42
+
43
+
44
+ ## Hovers what is under [param point], in [param viewport]'s own coordinates, when the engine could
45
+ ## not; answers whether it did. Where the engine hovers by itself, any hover supplied before is
46
+ ## taken down first, so a control is never entered twice.
47
+ func follow(viewport: Viewport, point: Vector2) -> bool:
48
+ var window: Window = viewport as Window
49
+ if window == null:
50
+ return false
51
+ if not cannot_hover(window) or window.gui_get_hovered_control() != null:
52
+ _drop(window, 0)
53
+ return false
54
+ _hover(window, point)
55
+ return _supplied.has(window.get_instance_id())
56
+
57
+
58
+ ## The control hovered in [param viewport], by the engine or by this.
59
+ func hovered_in(viewport: Viewport) -> Control:
60
+ var own: Control = viewport.gui_get_hovered_control()
61
+ if own != null:
62
+ return own
63
+ var held: Array = _supplied.get(viewport.get_instance_id(), [])
64
+ if held.is_empty():
65
+ return null
66
+ var top: int = held.back()
67
+ return instance_from_id(top) as Control
68
+
69
+
70
+ ## Whether the hover in [param viewport] is one this supplied.
71
+ func supplied_in(viewport: Viewport) -> bool:
72
+ return viewport.gui_get_hovered_control() == null and _supplied.has(viewport.get_instance_id())
73
+
74
+
75
+ func _listen(window: Window) -> void:
76
+ var id: int = window.get_instance_id()
77
+ if _listened.has(id):
78
+ return
79
+ _listened[id] = true
80
+ var _entering: int = window.mouse_entered.connect(_entered.bind(window))
81
+ var _leaving: int = window.mouse_exited.connect(_left.bind(window))
82
+
83
+
84
+ func _entered(window: Window) -> void:
85
+ _inside[window.get_instance_id()] = true
86
+ _drop(window, 0)
87
+
88
+
89
+ func _left(window: Window) -> void:
90
+ _inside[window.get_instance_id()] = false
91
+
92
+
93
+ ## Viewport::_update_mouse_over for [param point]: the control under it entered, from the outermost
94
+ ## holder not already entered, and what is no longer under it left. Into what a SubViewportContainer
95
+ ## under it shows as well, as the engine carries the pointer there.
96
+ func _hover(viewport: Viewport, point: Vector2) -> void:
97
+ var over: Control = control_at(viewport, point)
98
+ var id: int = viewport.get_instance_id()
99
+ var held: Array = _supplied.get(id, [])
100
+ var was: int = 0
101
+ if not held.is_empty():
102
+ was = held.back()
103
+ var now: int = 0
104
+ if over != null:
105
+ now = over.get_instance_id()
106
+ if now != was:
107
+ var common: int = 0
108
+ var entering: Array[int] = []
109
+ var walk: CanvasItem = over
110
+ while walk != null:
111
+ var control: Control = walk as Control
112
+ if control != null:
113
+ var filter: Control.MouseFilter = control.get_mouse_filter_with_override()
114
+ if filter != Control.MOUSE_FILTER_IGNORE:
115
+ if held.has(control.get_instance_id()):
116
+ common = control.get_instance_id()
117
+ break
118
+ entering.append(control.get_instance_id())
119
+ if filter == Control.MOUSE_FILTER_STOP:
120
+ break
121
+ if walk.top_level:
122
+ break
123
+ walk = _parent_item(walk)
124
+ _drop(viewport, common)
125
+ if over != null:
126
+ var kept: Array = _supplied.get(id, [])
127
+ for index: int in range(entering.size() - 1, -1, -1):
128
+ var control: Control = instance_from_id(entering[index]) as Control
129
+ if control != null:
130
+ kept.append(entering[index])
131
+ control.notification(Control.NOTIFICATION_MOUSE_ENTER)
132
+ control.mouse_entered.emit()
133
+ _supplied[id] = kept
134
+ over.notification(Control.NOTIFICATION_MOUSE_ENTER_SELF)
135
+ var container: SubViewportContainer = over as SubViewportContainer
136
+ if container == null:
137
+ return
138
+ var inside: Vector2 = container.get_global_transform_with_canvas().affine_inverse() * point
139
+ if container.stretch:
140
+ inside /= container.stretch_shrink
141
+ for child: Node in container.get_children():
142
+ var shown: SubViewport = child as SubViewport
143
+ if shown != null and not shown.gui_disable_input:
144
+ _hover(shown, shown.get_final_transform().affine_inverse() * inside)
145
+
146
+
147
+ ## Viewport::_drop_mouse_over: the hovered control left, then each holder down to and not including
148
+ ## the one whose id is [param until], innermost first. What a SubViewportContainer left showed is
149
+ ## left too.
150
+ func _drop(viewport: Viewport, until: int) -> void:
151
+ var id: int = viewport.get_instance_id()
152
+ var held: Array = _supplied.get(id, [])
153
+ if held.is_empty():
154
+ var _had: bool = _supplied.erase(id)
155
+ return
156
+ var top: int = held.back()
157
+ var over: Control = instance_from_id(top) as Control
158
+ var container: SubViewportContainer = over as SubViewportContainer
159
+ if container != null:
160
+ for child: Node in container.get_children():
161
+ var shown: SubViewport = child as SubViewport
162
+ if shown != null:
163
+ _drop(shown, 0)
164
+ if over != null and over.is_inside_tree():
165
+ over.notification(Control.NOTIFICATION_MOUSE_EXIT_SELF)
166
+ var stop: int = held.find(until) + 1 if until != 0 else 0
167
+ for index: int in range(held.size() - 1, stop - 1, -1):
168
+ var leaving: int = held[index]
169
+ var control: Control = instance_from_id(leaving) as Control
170
+ if control != null and control.is_inside_tree():
171
+ control.notification(Control.NOTIFICATION_MOUSE_EXIT)
172
+ control.mouse_exited.emit()
173
+ var _sized: int = held.resize(stop)
174
+ if held.is_empty():
175
+ var _had: bool = _supplied.erase(id)
176
+ else:
177
+ _supplied[id] = held
178
+
179
+
180
+ ## Viewport::gui_find_control: the control a pointer at [param point] in [param viewport] is over,
181
+ ## searching the controls that hold no other control's place from the one drawn last.
182
+ ##
183
+ ## Where the engine asks a control's own has_point, a script's `_has_point` is asked and every other
184
+ ## control is its rect: TextureButton's click mask, GraphEdit, GraphFrame and FoldableContainer
185
+ ## answer it in C++ that a script cannot call, so for those this answers the rect they sit in.
186
+ func control_at(viewport: Viewport, point: Vector2) -> Control:
187
+ var roots: Array[Control] = []
188
+ _gather_roots(viewport, roots)
189
+ roots.sort_custom(_drawn_before)
190
+ for index: int in range(roots.size() - 1, -1, -1):
191
+ var root: Control = roots[index]
192
+ if not root.is_visible_in_tree():
193
+ continue
194
+ var holder: CanvasItem = _parent_item(root)
195
+ var transform: Transform2D = (
196
+ holder.get_global_transform_with_canvas() if holder != null else root.get_canvas_transform()
197
+ )
198
+ var found: Control = _at(root, point, transform)
199
+ if found != null:
200
+ return found
201
+ return null
202
+
203
+
204
+ ## The controls [param node] holds that the engine keeps as roots of [param node]'s viewport: drawn
205
+ ## on their own, or with no control above them. Not into another viewport, a window or a
206
+ ## SubViewport, whose controls are that one's.
207
+ static func _gather_roots(node: Node, roots: Array[Control]) -> void:
208
+ for child: Node in node.get_children():
209
+ if child is Viewport:
210
+ continue
211
+ var control: Control = child as Control
212
+ if control != null and _is_root(control):
213
+ roots.append(control)
214
+ _gather_roots(child, roots)
215
+
216
+
217
+ static func _is_root(control: Control) -> bool:
218
+ var walk: CanvasItem = control
219
+ while not walk.top_level:
220
+ var parent: CanvasItem = walk.get_parent() as CanvasItem
221
+ if parent == null:
222
+ return true
223
+ if parent is Control:
224
+ return false
225
+ walk = parent
226
+ return true
227
+
228
+
229
+ ## Control::CComparator: by canvas layer, then in tree order.
230
+ static func _drawn_before(first: Control, second: Control) -> bool:
231
+ var first_layer: int = _layer_of(first)
232
+ var second_layer: int = _layer_of(second)
233
+ if first_layer == second_layer:
234
+ return second.is_greater_than(first)
235
+ return first_layer < second_layer
236
+
237
+
238
+ static func _layer_of(item: CanvasItem) -> int:
239
+ var layer: CanvasLayer = item.get_canvas_layer_node()
240
+ return layer.layer if layer != null else 0
241
+
242
+
243
+ ## CanvasItem::get_parent_item, which a script cannot call.
244
+ static func _parent_item(item: CanvasItem) -> CanvasItem:
245
+ if item.top_level:
246
+ return null
247
+ return item.get_parent() as CanvasItem
248
+
249
+
250
+ ## Viewport::_gui_find_control_at_pos.
251
+ func _at(item: CanvasItem, point: Vector2, holder: Transform2D) -> Control:
252
+ if not item.visible:
253
+ return null
254
+ var matrix: Transform2D = holder * item.get_transform()
255
+ if matrix.determinant() == 0.0:
256
+ return null
257
+ var control: Control = item as Control
258
+ var local: Vector2 = matrix.affine_inverse() * point
259
+ if control == null or not control.is_clipping_contents() or _has_point(control, local):
260
+ for index: int in range(item.get_child_count() - 1, -1, -1):
261
+ var child: CanvasItem = item.get_child(index) as CanvasItem
262
+ if child == null or child.top_level:
263
+ continue
264
+ var found: Control = _at(child, point, matrix)
265
+ if found != null:
266
+ return found
267
+ if control == null or control.get_mouse_filter_with_override() == Control.MOUSE_FILTER_IGNORE:
268
+ return null
269
+ if not _has_point(control, local):
270
+ return null
271
+ return control
272
+
273
+
274
+ func _has_point(control: Control, local: Vector2) -> bool:
275
+ var attached: Variant = control.get_script()
276
+ if attached is Script:
277
+ var script: Script = attached
278
+ if not _shapes.has(script):
279
+ _shapes[script] = script.get_script_method_list().any(
280
+ func(method: Dictionary) -> bool: return method["name"] == "_has_point"
281
+ )
282
+ if _shapes[script]:
283
+ var inside: bool = control.call("_has_point", local)
284
+ return inside
285
+ return Rect2(Vector2.ZERO, control.size).has_point(local)
@@ -0,0 +1 @@
1
+ uid://b2e1nm8jwjkgw