gdharness 1.0.0 → 1.0.1
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/README.md +2 -3
- package/build/cli.js +15 -6
- package/build/godot/addons/gdharness_runtime/runtime_input.gd +36 -4
- package/build/index.js +14 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,9 +26,8 @@ property reads right now, what the console printed, what broke and on which line
|
|
|
26
26
|
Hand this to your agent:
|
|
27
27
|
|
|
28
28
|
```text
|
|
29
|
-
Install gdharness
|
|
30
|
-
|
|
31
|
-
recommend back to me.
|
|
29
|
+
Install gdharness here by following https://aureliolo.github.io/gdharness/agent.md,
|
|
30
|
+
then tell me what it asked you to recommend back to me.
|
|
32
31
|
```
|
|
33
32
|
|
|
34
33
|
Or do it yourself, and pick your harness:
|
package/build/cli.js
CHANGED
|
@@ -16339,12 +16339,12 @@ var init_tool_definitions = __esm(() => {
|
|
|
16339
16339
|
relativeX: {
|
|
16340
16340
|
type: "number",
|
|
16341
16341
|
ops: ["mouse_motion"],
|
|
16342
|
-
description: "mouse_motion: movement
|
|
16342
|
+
description: "mouse_motion: the movement the event carries. Left out, it is the distance from where the pointer last was, which is what a control that drags reads; give it to send a motion the position does not show."
|
|
16343
16343
|
},
|
|
16344
16344
|
relativeY: {
|
|
16345
16345
|
type: "number",
|
|
16346
16346
|
ops: ["mouse_motion"],
|
|
16347
|
-
description: "mouse_motion:
|
|
16347
|
+
description: "mouse_motion: as relativeX."
|
|
16348
16348
|
}
|
|
16349
16349
|
},
|
|
16350
16350
|
requires: [],
|
|
@@ -16358,13 +16358,22 @@ var init_tool_definitions = __esm(() => {
|
|
|
16358
16358
|
requires: ["nodePath"]
|
|
16359
16359
|
},
|
|
16360
16360
|
action: { summary: "press an action, or hold it", requires: ["action"] },
|
|
16361
|
-
key: {
|
|
16361
|
+
key: {
|
|
16362
|
+
summary: "press a key, or hold it. Not for a menu a click has opened: an OptionButton or PopupMenu pops up as a window of its own that a key sent to the game never reaches, so an arrow moves nothing in it and Enter closes it with nothing chosen. choose is what selects there",
|
|
16363
|
+
requires: ["keycode"]
|
|
16364
|
+
},
|
|
16362
16365
|
text: {
|
|
16363
16366
|
summary: "type a string into the field being edited, a character at a time, and say what it landed in",
|
|
16364
16367
|
requires: ["text"]
|
|
16365
16368
|
},
|
|
16366
|
-
mouse_click: {
|
|
16367
|
-
|
|
16369
|
+
mouse_click: {
|
|
16370
|
+
summary: "one mouse button event at a position, carrying the buttons held once it has happened. A drag is a press held with pressed true, motions, and a release with pressed false",
|
|
16371
|
+
requires: ["x", "y"]
|
|
16372
|
+
},
|
|
16373
|
+
mouse_motion: {
|
|
16374
|
+
summary: "move the mouse to a position, carrying the distance from where it last was unless relativeX and relativeY say otherwise, and the buttons held, so a control that drags moves under a run of these between a held mouse_click and its release",
|
|
16375
|
+
requires: ["x", "y"]
|
|
16376
|
+
}
|
|
16368
16377
|
}
|
|
16369
16378
|
},
|
|
16370
16379
|
{
|
|
@@ -42080,7 +42089,7 @@ that is running, and the project on disk. ${TOOL_SPECS.length} tools, named \`do
|
|
|
42080
42089
|
| Press the next thing after a click that changed screen | \`runtime_wait until\` with \`says\` and a word the new screen shows, then the click. A click sent straight after a screen change lands on a control the new screen is about to free, answers \`landed: true\`, and does nothing; a frame count is a number nobody can pick correctly across a cold start and a warm one, and waiting for the words answered in about 130ms where twenty frames had not been enough |
|
|
42081
42090
|
| Fill in a field | \`runtime_input click\` on it, then \`runtime_input text\` with \`replace\`; a submitted field has to be clicked again |
|
|
42082
42091
|
| Click somebody standing in a 3D room | \`runtime_input click\` on the Node3D, which aims at what it draws |
|
|
42083
|
-
| Pick something out of a dropdown | \`runtime_input choose\` on it, by what the item says |
|
|
42092
|
+
| Pick something out of a dropdown | \`runtime_input choose\` on it, by what the item says, rather than a click and keys: the menu opens as a window of its own that an injected key never reaches, so Enter closes it with nothing chosen |
|
|
42084
42093
|
| Answer a dialog | \`runtime_input click\` on its button, or \`key\` Escape to dismiss it: an [AcceptDialog] reads that key itself and never asks the InputMap, so \`ui_cancel\` leaves it standing |
|
|
42085
42094
|
| Press a bound key | \`runtime_input action\` or \`key\`, a whole press unless you hold it |
|
|
42086
42095
|
| Where a 3D node is on screen | \`runtime_inspect\` \`rect\`, rather than unprojecting by hand |
|
|
@@ -341,15 +341,29 @@ func inject_mouse_click(params: Dictionary) -> Dictionary:
|
|
|
341
341
|
}
|
|
342
342
|
|
|
343
343
|
|
|
344
|
+
## Moves the pointer to a position, with the movement the event carries taken from where the
|
|
345
|
+
## pointer last was unless the caller says otherwise.
|
|
346
|
+
##
|
|
347
|
+
## A real pointer never arrives without a `relative`, and a control that drags reads that field
|
|
348
|
+
## rather than the position, so a motion carrying none leaves a grip where it was however far the
|
|
349
|
+
## position moved. The viewport remembers where the last motion put the pointer, injected or not,
|
|
350
|
+
## so the difference from there is what a real move would have carried. A relative the caller gives
|
|
351
|
+
## is kept, since a game may want to read a motion the position does not show.
|
|
344
352
|
func inject_mouse_motion(params: Dictionary) -> Dictionary:
|
|
345
353
|
var point: Variant = _read_point(params, "x", "y", "position")
|
|
346
354
|
if point is String:
|
|
347
355
|
return {"type": "error", "message": point}
|
|
348
356
|
var position: Vector2 = point
|
|
349
|
-
var
|
|
350
|
-
if
|
|
351
|
-
|
|
352
|
-
|
|
357
|
+
var relative: Vector2 = position - _host.get_viewport().get_mouse_position()
|
|
358
|
+
if params.has("relativeX") or params.has("relativeY"):
|
|
359
|
+
relative = Vector2(
|
|
360
|
+
Read.as_float(params.get("relativeX", 0.0)), Read.as_float(params.get("relativeY", 0.0))
|
|
361
|
+
)
|
|
362
|
+
elif params.has("relative"):
|
|
363
|
+
var movement: Variant = _read_point(params, "relativeX", "relativeY", "relative")
|
|
364
|
+
if movement is String:
|
|
365
|
+
return {"type": "error", "message": movement}
|
|
366
|
+
relative = movement
|
|
353
367
|
|
|
354
368
|
Input.parse_input_event(_motion(position, relative))
|
|
355
369
|
|
|
@@ -790,14 +804,21 @@ func _click_in_the_world(node_path: String, item: Node3D, params: Dictionary) ->
|
|
|
790
804
|
}
|
|
791
805
|
|
|
792
806
|
|
|
807
|
+
## The buttons a real pointer event carries are the ones held as it happens, and Input keeps that
|
|
808
|
+
## from every button event it is given, injected ones included, so a motion between a held click
|
|
809
|
+
## and its release is a drag to a control that reads the mask rather than remembering the click.
|
|
793
810
|
func _motion(position: Vector2, relative: Vector2) -> InputEventMouseMotion:
|
|
794
811
|
var event: InputEventMouseMotion = InputEventMouseMotion.new()
|
|
795
812
|
event.position = position
|
|
796
813
|
event.global_position = position
|
|
797
814
|
event.relative = relative
|
|
815
|
+
event.screen_relative = relative
|
|
816
|
+
event.button_mask = Input.get_mouse_button_mask()
|
|
798
817
|
return event
|
|
799
818
|
|
|
800
819
|
|
|
820
|
+
## A button event carries the buttons held once it has happened: the pressed one among them, the
|
|
821
|
+
## released one out. A wheel step is a button with no mask, as it is from a real mouse.
|
|
801
822
|
func _button(position: Vector2, button: int, pressed: bool, double: bool) -> InputEventMouseButton:
|
|
802
823
|
var event: InputEventMouseButton = InputEventMouseButton.new()
|
|
803
824
|
event.position = position
|
|
@@ -805,9 +826,20 @@ func _button(position: Vector2, button: int, pressed: bool, double: bool) -> Inp
|
|
|
805
826
|
event.button_index = button as MouseButton
|
|
806
827
|
event.pressed = pressed
|
|
807
828
|
event.double_click = double
|
|
829
|
+
var held: int = Input.get_mouse_button_mask()
|
|
830
|
+
var own: int = _mask_of(button)
|
|
831
|
+
event.button_mask = (held | own) if pressed else (held & ~own)
|
|
808
832
|
return event
|
|
809
833
|
|
|
810
834
|
|
|
835
|
+
## The mask bit for a button, which is the engine's own mapping: left 1, right 2, middle 4, the
|
|
836
|
+
## two extra buttons 128 and 256. The wheel steps between have none.
|
|
837
|
+
func _mask_of(button: int) -> int:
|
|
838
|
+
if button >= MOUSE_BUTTON_WHEEL_UP and button <= MOUSE_BUTTON_WHEEL_RIGHT:
|
|
839
|
+
return 0
|
|
840
|
+
return 1 << (button - 1)
|
|
841
|
+
|
|
842
|
+
|
|
811
843
|
## What to say about a name that is not a mouse button, with the ones that are.
|
|
812
844
|
func _no_such_button(named: Variant) -> Dictionary:
|
|
813
845
|
return {
|
package/build/index.js
CHANGED
|
@@ -29942,12 +29942,12 @@ var TOOL_SPECS = [
|
|
|
29942
29942
|
relativeX: {
|
|
29943
29943
|
type: "number",
|
|
29944
29944
|
ops: ["mouse_motion"],
|
|
29945
|
-
description: "mouse_motion: movement
|
|
29945
|
+
description: "mouse_motion: the movement the event carries. Left out, it is the distance from where the pointer last was, which is what a control that drags reads; give it to send a motion the position does not show."
|
|
29946
29946
|
},
|
|
29947
29947
|
relativeY: {
|
|
29948
29948
|
type: "number",
|
|
29949
29949
|
ops: ["mouse_motion"],
|
|
29950
|
-
description: "mouse_motion:
|
|
29950
|
+
description: "mouse_motion: as relativeX."
|
|
29951
29951
|
}
|
|
29952
29952
|
},
|
|
29953
29953
|
requires: [],
|
|
@@ -29961,13 +29961,22 @@ var TOOL_SPECS = [
|
|
|
29961
29961
|
requires: ["nodePath"]
|
|
29962
29962
|
},
|
|
29963
29963
|
action: { summary: "press an action, or hold it", requires: ["action"] },
|
|
29964
|
-
key: {
|
|
29964
|
+
key: {
|
|
29965
|
+
summary: "press a key, or hold it. Not for a menu a click has opened: an OptionButton or PopupMenu pops up as a window of its own that a key sent to the game never reaches, so an arrow moves nothing in it and Enter closes it with nothing chosen. choose is what selects there",
|
|
29966
|
+
requires: ["keycode"]
|
|
29967
|
+
},
|
|
29965
29968
|
text: {
|
|
29966
29969
|
summary: "type a string into the field being edited, a character at a time, and say what it landed in",
|
|
29967
29970
|
requires: ["text"]
|
|
29968
29971
|
},
|
|
29969
|
-
mouse_click: {
|
|
29970
|
-
|
|
29972
|
+
mouse_click: {
|
|
29973
|
+
summary: "one mouse button event at a position, carrying the buttons held once it has happened. A drag is a press held with pressed true, motions, and a release with pressed false",
|
|
29974
|
+
requires: ["x", "y"]
|
|
29975
|
+
},
|
|
29976
|
+
mouse_motion: {
|
|
29977
|
+
summary: "move the mouse to a position, carrying the distance from where it last was unless relativeX and relativeY say otherwise, and the buttons held, so a control that drags moves under a run of these between a held mouse_click and its release",
|
|
29978
|
+
requires: ["x", "y"]
|
|
29979
|
+
}
|
|
29971
29980
|
}
|
|
29972
29981
|
},
|
|
29973
29982
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"mcpName": "io.github.Aureliolo/gdharness",
|
|
5
5
|
"description": "A harness for driving a Godot 4 project from an agent: editor addons, a runtime bridge into the running game, an MCP server in front of them, and a CLI that installs and diagnoses the Godot side.",
|
|
6
6
|
"type": "module",
|