gdharness 1.3.41 → 1.3.42
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 +69 -38
- package/build/godot/addons/gdharness_editor/animation_reads.gd +31 -4
- package/build/godot/addons/gdharness_editor/file_reads.gd +34 -0
- package/build/godot/addons/gdharness_editor/headless_check.gd +29 -0
- package/build/godot/addons/gdharness_editor/scene_file.gd +27 -0
- package/build/godot/addons/gdharness_editor/tools/animation_states.gd +5 -2
- package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +6 -2
- package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +15 -0
- package/build/godot/addons/gdharness_editor/tools/scene_kin.gd +7 -2
- package/build/godot/addons/gdharness_editor/tools/scene_sharing.gd +59 -0
- package/build/godot/addons/gdharness_editor/tools/scene_sharing.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +64 -1
- package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +4 -1
- package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +4 -3
- package/build/godot/addons/gdharness_runtime/runtime_touch.gd +211 -0
- package/build/godot/addons/gdharness_runtime/runtime_touch.gd.uid +1 -0
- package/build/godot/operations/animation_reads.gd +31 -4
- package/build/godot/operations/file_reads.gd +34 -0
- package/build/godot/operations/gdscript_analysis.gd +19 -1
- package/build/godot/operations/gdscript_authoring.gd +55 -3
- package/build/godot/operations/input_actions.gd +1 -0
- package/build/godot/operations/project_config.gd +93 -0
- package/package.json +1 -1
package/build/cli.js
CHANGED
|
@@ -10478,7 +10478,12 @@ function ignoredLeftOut(report, ignored, declared, rowsIgnored = new Set) {
|
|
|
10478
10478
|
function caseOf(suite, element) {
|
|
10479
10479
|
const of = (kind) => element.children.filter((child) => child.name === kind).map((child) => {
|
|
10480
10480
|
const detail = child.text.trim();
|
|
10481
|
-
|
|
10481
|
+
const message = child.attributes["message"] ?? null;
|
|
10482
|
+
return {
|
|
10483
|
+
kind,
|
|
10484
|
+
message: kind === "error" ? raisedAt(message, detail) : message,
|
|
10485
|
+
detail: detail === "" ? null : detail
|
|
10486
|
+
};
|
|
10482
10487
|
});
|
|
10483
10488
|
const reports = [...of("failure"), ...of("error"), ...of("skipped")];
|
|
10484
10489
|
const status = reports.some((report) => report.kind === "error") ? "error" : reports.some((report) => report.kind === "failure") ? "failed" : reports.length > 0 ? "skipped" : "passed";
|
|
@@ -10492,6 +10497,17 @@ function caseOf(suite, element) {
|
|
|
10492
10497
|
reports
|
|
10493
10498
|
};
|
|
10494
10499
|
}
|
|
10500
|
+
function raisedAt(message, detail) {
|
|
10501
|
+
if (message === null) {
|
|
10502
|
+
return null;
|
|
10503
|
+
}
|
|
10504
|
+
const named = /^ERROR: \S+:\d+(?=\s|$)/.exec(message);
|
|
10505
|
+
const raised = /^\s*at '[^']*' in (\S+):(\d+)\s*$/m.exec(detail);
|
|
10506
|
+
if (named === null || raised === null) {
|
|
10507
|
+
return message;
|
|
10508
|
+
}
|
|
10509
|
+
return `ERROR: ${raised[1] ?? ""}:${raised[2] ?? ""}${message.slice(named[0].length)}`;
|
|
10510
|
+
}
|
|
10495
10511
|
function failedAnAssertion(entry) {
|
|
10496
10512
|
return entry.reports.some((report) => report.kind === "failure");
|
|
10497
10513
|
}
|
|
@@ -16434,7 +16450,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
16434
16450
|
returnType: { type: "string", description: "Functions: the return type." },
|
|
16435
16451
|
body: {
|
|
16436
16452
|
type: "string",
|
|
16437
|
-
description: "Functions: the body, its lines separated by \\n. Indent shared by every line is taken off
|
|
16453
|
+
description: "Functions: the body, its lines separated by \\n. Indent shared by every line is taken off, so it can be written indented or not, and each level is written in the script's own indentation, tabs or spaces."
|
|
16438
16454
|
},
|
|
16439
16455
|
varType: {
|
|
16440
16456
|
type: "string",
|
|
@@ -16554,7 +16570,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
16554
16570
|
{
|
|
16555
16571
|
name: "project_settings",
|
|
16556
16572
|
title: "Project settings",
|
|
16557
|
-
description: "Reads or writes project.godot (settings, autoloads, the main scene, input actions and plugins) and the audio bus layout, default_bus_layout.tres unless audio/buses/default_bus_layout names another. project_info include lists the autoloads, input actions and audio buses as the project holds them. A write with an editor open on the project is handed to the editor, which takes the settings the write changed or names from the file (named under editorAdopted), including a setting the file already held, since the editor can hold another value after the file was put back, or reloads the bus layout, so it answers the new values and does not save the old ones back over them. editorNote is an editor that could not take the write, or one on another release's addon that was not asked, which still holds the old values until editor_launch restart. An enabled plugin's code still loads on the editor's next start, and enable_plugin notes a script it would not load. set answers old_value and new_value, with was_new true when project.godot did not set the setting before, and was_default true when what it held was the engine's own default, which old_value then is.
|
|
16573
|
+
description: "Reads or writes project.godot (settings, autoloads, the main scene, input actions and plugins) and the audio bus layout, default_bus_layout.tres unless audio/buses/default_bus_layout names another. project_info include lists the autoloads, input actions and audio buses as the project holds them. A write with an editor open on the project is handed to the editor, which takes the settings the write changed or names from the file (named under editorAdopted), including a setting the file already held, since the editor can hold another value after the file was put back, or reloads the bus layout, so it answers the new values and does not save the old ones back over them. editorNote is an editor that could not take the write, or one on another release's addon that was not asked, which still holds the old values until editor_launch restart. An enabled plugin's code still loads on the editor's next start, and enable_plugin notes a script it would not load. set answers old_value and new_value, with was_new true when project.godot did not set the setting before, and was_default true when what it held was the engine's own default, which old_value then is, and overrides with overridesNote when a feature's override still replaces it. add_autoload refuses a name the editor's Autoload tab refuses: not an identifier, a keyword, a built-in type or an engine class. add_input_action on an existing action, a ui_ one included, replaces its events, and its deadzone when one is given, answering was_new false with old_events and old_deadzone. A set of the value the setting already holds, in the same type, writes nothing and answers unchanged true and saved false. unset takes a setting's line out of project.godot and answers removed, old_value and default_value, the value that holds now (null for a setting the engine does not declare; for an override, name.feature, holds is the base setting's value its builds read now); on one the file does not set it answers removed false and writes nothing, its note naming the nearest settings when the engine does not declare it either. Every write changes only the lines of the settings it names and keeps every other line as the file had it, in its place: the engine's own save would sort a dictionary's keys and write what a project_settings_override file laid over the project. get answers exists, true for any setting the engine knows, at_default, true when the value is the engine's own default and so has no line in project.godot, and overrides, the value each feature's override holds. An override answers override_of, its base setting, and one project.godot does not set answers exists false with holds, the base setting's value. Each setting under prefix carries at_default too, so a family read separates what the project sets from the engine's defaults; it is absent for a setting with no engine default, such as an input action the project added.",
|
|
16558
16574
|
parameters: {
|
|
16559
16575
|
projectPath: PROJECT_PATH,
|
|
16560
16576
|
setting: {
|
|
@@ -16924,7 +16940,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
16924
16940
|
name: "project_test",
|
|
16925
16941
|
title: "Run tests",
|
|
16926
16942
|
effect: "additive",
|
|
16927
|
-
description: "Runs the project's gdUnit4 tests and answers with every case that did not pass: where it is, and what the assertion said. Each entry under failed carries its first report as message and detail, and, when it has more than one, its reports under reports in the order the case met them: gdUnit4 goes on past a failed assertion, and a case can fail several and then stop on a runtime error, which makes its status error. Identical reports fold into one with times, at most twenty different ones are kept (reportsLeftOut counts the rest), and past about a megabyte the largest cases keep only their first message (failedWithoutDetail). failures counts the cases that failed an assertion and errors the cases that hit an error, so such a case counts in both. Suites where everything passed are counted, not listed, and an engine message keeps the frames above gdUnit4, not the twenty inside it; identical engine messages come back once under engineEntries, with times saying how often they were printed, and with script, line and function for the project script one points at, as editor_output's entries have. The class list is rebuilt first, so a suite written a moment ago is found, and the rebuild's answer is under classes. What changed on disk since it was imported is then imported before any suite runs, and named under importedFirst. On Windows and Linux the run gets a user:// of its own, away from a player's saves; on macOS the engine reads user:// off HOME, so it writes where the player keeps theirs, and savesNote says so. The run is headless unless a suite in it needs a window as gdharness test reads it, and then has one, on a desktop of its own on Windows. A run that found nothing to run is never called a pass, and names the path it looked in. A script that does not load stops gdUnit4 before any suite runs: its errors come back in full under scriptErrors, and the scripts that failed only because one they depend on did are listed by path under failedThroughDependency. When they failed on a class whose own script has a parser error, which gdUnit4 never names, that script is checked by the engine and its error comes first under scriptErrors, with the class it declares under declares, and the errors a script has only because that class did not resolve, which the engine reads as Variant, are kept apart under followFromUnresolved. An autoload that does not compile stops the run at once, its errors listed the same way. A client sending a progress token is told as each suite finishes, and at least every twenty seconds. A run that ends without a report, at its timeout or otherwise, names the suites it finished under suitesFinished, the failing ones with their failed cases under suitesFailing, and the one it was in under suiteRunning. When a client cuts a run off, that is kept in the project and the next project_test there carries it under previousRunCut. A run where nothing failed but orphan nodes were left comes back under warnings, with the count per suite: gdUnit4 decides its verdict on those and keeps them out of its report, so they are read off what it printed. A run whose every case passed is still not called passed when it printed a script error that no case failed on: gdUnit4 fails a case on the script errors its logger sees, and it cannot see a stack overflow, so the cases pass on whatever the faulted calls returned. Those errors come back under uncaughtScriptErrors, and under engineEntries by index with detailUnder rather than with their backtrace a second time; a backtrace that repeats, as a recursion's does, has each repeated frame or cycle of frames written once with the frames it covers and how many times. One raised inside assert_error(...).is_runtime_error is the test's own and is not listed there, and none are when the project turns off gdUnit4's report/godot/script_error setting; a suite declares them all the same. Needs gdUnit4 under addons/gdUnit4.",
|
|
16943
|
+
description: "Runs the project's gdUnit4 tests and answers with every case that did not pass: where it is, and what the assertion said. Each entry under failed carries its first report as message and detail, and, when it has more than one, its reports under reports in the order the case met them: gdUnit4 goes on past a failed assertion, and a case can fail several and then stop on a runtime error, which makes its status error. Identical reports fold into one with times, at most twenty different ones are kept (reportsLeftOut counts the rest), and past about a megabyte the largest cases keep only their first message (failedWithoutDetail). failures counts the cases that failed an assertion and errors the cases that hit an error, so such a case counts in both. Suites where everything passed are counted, not listed, and an engine message keeps the frames above gdUnit4, not the twenty inside it; identical engine messages come back once under engineEntries, with times saying how often they were printed, and with script, line and function for the project script one points at, as editor_output's entries have. The class list is rebuilt first, so a suite written a moment ago is found, and the rebuild's answer is under classes. What changed on disk since it was imported is then imported before any suite runs, and named under importedFirst. A suite it ran with no .uid beside it is named under uidsMissing, with uidsNote. On Windows and Linux the run gets a user:// of its own, away from a player's saves; on macOS the engine reads user:// off HOME, so it writes where the player keeps theirs, and savesNote says so. The run is headless unless a suite in it needs a window as gdharness test reads it, and then has one, on a desktop of its own on Windows. A run that found nothing to run is never called a pass, and names the path it looked in. A script that does not load stops gdUnit4 before any suite runs: its errors come back in full under scriptErrors, and the scripts that failed only because one they depend on did are listed by path under failedThroughDependency. When they failed on a class whose own script has a parser error, which gdUnit4 never names, that script is checked by the engine and its error comes first under scriptErrors, with the class it declares under declares, and the errors a script has only because that class did not resolve, which the engine reads as Variant, are kept apart under followFromUnresolved. An autoload that does not compile stops the run at once, its errors listed the same way. A client sending a progress token is told as each suite finishes, and at least every twenty seconds. A run that ends without a report, at its timeout or otherwise, names the suites it finished under suitesFinished, the failing ones with their failed cases under suitesFailing, and the one it was in under suiteRunning. When a client cuts a run off, that is kept in the project and the next project_test there carries it under previousRunCut. A run where nothing failed but orphan nodes were left comes back under warnings, with the count per suite: gdUnit4 decides its verdict on those and keeps them out of its report, so they are read off what it printed. A run whose every case passed is still not called passed when it printed a script error that no case failed on: gdUnit4 fails a case on the script errors its logger sees, and it cannot see a stack overflow, so the cases pass on whatever the faulted calls returned. Those errors come back under uncaughtScriptErrors, and under engineEntries by index with detailUnder rather than with their backtrace a second time; a backtrace that repeats, as a recursion's does, has each repeated frame or cycle of frames written once with the frames it covers and how many times. One raised inside assert_error(...).is_runtime_error is the test's own and is not listed there, and none are when the project turns off gdUnit4's report/godot/script_error setting; a suite declares them all the same. Needs gdUnit4 under addons/gdUnit4.",
|
|
16928
16944
|
answer: "passed is the verdict to read. exitCode is the engine's own exit, gdUnit4's code for what it saw (100 a case failed, 101 only warnings, 105 script errors it detected), and is 0 beside passed false when the run is failed for something gdUnit4 does not judge, such as an engine error no suite declared. time is gdUnit4's own sum of the seconds its cases took, from its report. tookMs is the whole call in milliseconds, from the class rebuild to the engine's exit, which is what a caller waits for, and tookMsBy splits it into the class rebuild (classes), the import after it (import) and the engine running the suites (engine), each with any wait for an engine slot or the editor's scan in it. The run is judged as gdharness test judges it: undeclaredErrors names each engine error that no suite declared in its GDHARNESS_EXPECTED_ERRORS constant, and each engine warning a suite printed and did not declare in its GDHARNESS_EXPECTED_WARNINGS, marked warning true, with the suite and the case that printed it, and declaredNotPrinted each declared error or warning its case did not print. gdUnit4 does not fail a case on push_error or push_warning, so a case that printed one undeclared is in neither failed nor errors: it is named here, and the run is failed for it. A declared text must be the whole line after ERROR: or WARNING: and its space, so a longer one its case printed holding the text is named under printedInstead. Either fails the run, and each suite holding one is listed with its count. leakedAtExit holds the engine's lines saying it exited still holding objects, resources, memory pages or a server's RIDs, which fail the run too, and the note names any script of the project Godot itself never frees and, on a run with engineArgs [\"--verbose\"], what the engine held. engineErrors counts every engine error the run printed but those a suite declared. orphans totals the orphan nodes gdUnit4 counted, and each suite that left some has its count, and a warning saying how to free them, under warnings, with left naming each case that left some (before or after for one of the suite's hooks, or the one value \"before or after\" where no case began and the two cannot be told apart) and the nodes, by class, name and script. suites lists only the suites with something to say (a case that failed, erred or was skipped, a hook that failed, orphans, or an error undeclared or declared and not printed), and suitesPassed counts the rest. A before() or after() that failed comes back under hookFailures with its suite, line and whole message; failures and errors count cases and leave it out, so the verdict names it as failed hooks, and the cases after a failed before() still run and are counted. Under classes, the classes each addon declares are counted under addedInAddons and changedInAddons rather than named, and a class the rebuild puts back that the cache had after the last rebuild is named under classes.lostSinceLastRebuild, which is the editor writing its shorter list over the file on every save until restarted. A suite needs a window when it declares const GDHARNESS_NEEDS_WINDOW: bool = true, or calls scene_runner and declares nothing; a run holding one has a window, at the size project.godot gives its viewport and with no sound, and windowed is true and windowNote names those suites and any saying it runs headless that shared the window. On a machine with no display such a run is headless, windowed is false, and windowNote says so. " + IMPORTED_FIRST,
|
|
16929
16945
|
parameters: {
|
|
16930
16946
|
projectPath: PROJECT_PATH,
|
|
@@ -17029,7 +17045,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
17029
17045
|
name: "scene_node",
|
|
17030
17046
|
title: "Scene nodes",
|
|
17031
17047
|
description: `One node in a scene file: add, read, set, duplicate, reparent or delete it, paint TileMap cells, or bake a navigation region. Any ClassDB node type or script class can be added, so a NavigationRegion2D, an AnimationTree or a Camera3D is an add with that nodeType and its properties, and another scene is instanced by an add with instancePath. A set with properties {"name": "Boss"} renames a node, and answers nodePath as its new path. A rename or a reparent carries the node paths naming the node, as the editor's rename does: NodePath values on nodes (in arrays, dictionaries, built-in resources, %unique paths) and the tracks its players' animations hold, saving a library kept in a .tres of its own, and answers each rewrite under retargeted and each path it left under notRetargeted. The move is followed into every other .tscn that instances or inherits this scene at any depth: the editable children, values, added nodes and connections named by the old path are rewritten, since Godot finds a moved node's values by unique_id but editable children only by path and drops the values kept below them on the next save, and that scene's node paths and tracks are carried as above. A delete rewrites no path, and answers under stillNaming what named the deleted node and now names nothing. A property holding a Resource takes the res:// path of one, so a texture, a material or a theme is a set like any other. A write is refused while the editor holds unsaved changes to the scene. A node this scene inherits takes values of this scene's own, and so does a node inside an instance of another scene once that instance's editableChildren is true; neither can be moved, renamed, copied or deleted, since the other scene makes it again on load. ${WITHOUT_AN_EDITOR}`,
|
|
17032
|
-
answer: "get answers nodeType, the node's engine class, with scriptClass when its script declares a class_name; nodePath, its path from the root however it was named; setHere, the properties this scene's own file sets on it; and valuesFrom, the scene every other value comes from, when another scene makes the node. A set that gives a property the value the node has without it (what the scene it comes from gives, or its default) leaves it out of the file, as the editor does, and answers it under notStored, with notStoredNote saying what it follows now. retargeted lists each path a rename or a reparent rewrote, as {scenePath, nodePath, property or animation and track, from, to}, and notRetargeted each it left, with a reason: a track kept in another scene or an imported file, or a value another scene gives that the move left naming nothing. followed names the other scenes a move rewrote, and notFollowed any left as they were, with why. scriptsNaming lists each line of a script that reads a node a rename, a reparent or a delete took by the path it had, as {scenePath, nodePath, script, line, from, to}: the script is on the node at nodePath, or is one that node's script extends, in this scene or one instancing or inheriting it, and to is the path that reaches the node from there now, absent after a delete. It reads $Path, %Unique, and a string handed to get_node, get_node_or_null or has_node on the node itself; a path built at run time is not seen. Scripts are left as they were, as the editor's own rename leaves them, so each line listed fails until it is changed. A 2D bake_navigation that read no obstacle says in its note that all its outlines enclose is walkable, and names the nodes giving obstacles that sit under no region. stillNaming lists each node path and track, here and in the scenes instancing or inheriting this one, that named a deleted node, and deletedWithIt each node of this scene's own that went with it, the nodes inside an instance going with the instance. groups lists, sorted, every group a node is in, on a get, an add that gave addGroups and every set that changes them; get adds groupsHere, the groups this file puts it in, when another scene puts it in others, and layers, each layer mask it answers (collision_layer, collision_mask, visibility_layer) as the layers it holds, {layer, name} with the name project.godot gives the layer. Each of these lists is answered only when it names anything. add and set answer each property given under properties as the node holds it once written; alsoChanged gives the other properties the engine changed in step with a set, as a Control's offsets with its size, and those a reparent changed to keep the node where it is drawn, as {was, now}; namesNoNode, each node path written naming no node. get adds placement, a Node3D's position, rotation_degrees and scale from its transform. " + ALSO_SAVED,
|
|
17048
|
+
answer: "get answers nodeType, the node's engine class, with scriptClass when its script declares a class_name; nodePath, its path from the root however it was named; setHere, the properties this scene's own file sets on it; and valuesFrom, the scene every other value comes from, when another scene makes the node. A set that gives a property the value the node has without it (what the scene it comes from gives, or its default) leaves it out of the file, as the editor does, and answers it under notStored, with notStoredNote saying what it follows now. retargeted lists each path a rename or a reparent rewrote, as {scenePath, nodePath, property or animation and track, from, to}, and notRetargeted each it left, with a reason: a track kept in another scene or an imported file, or a value another scene gives that the move left naming nothing. followed names the other scenes a move rewrote, and notFollowed any left as they were, with why. scriptsNaming lists each line of a script that reads a node a rename, a reparent or a delete took by the path it had, as {scenePath, nodePath, script, line, from, to}: the script is on the node at nodePath, or is one that node's script extends, in this scene or one instancing or inheriting it, and to is the path that reaches the node from there now, absent after a delete. It reads $Path, %Unique, and a string handed to get_node, get_node_or_null or has_node on the node itself; a path built at run time is not seen. Scripts are left as they were, as the editor's own rename leaves them, so each line listed fails until it is changed. A 2D bake_navigation that read no obstacle says in its note that all its outlines enclose is walkable, and names the nodes giving obstacles that sit under no region. stillNaming lists each node path and track, here and in the scenes instancing or inheriting this one, that named a deleted node, and deletedWithIt each node of this scene's own that went with it, the nodes inside an instance going with the instance. groups lists, sorted, every group a node is in, on a get, an add that gave addGroups and every set that changes them; get adds groupsHere, the groups this file puts it in, when another scene puts it in others, and layers, each layer mask it answers (collision_layer, collision_mask, visibility_layer) as the layers it holds, {layer, name} with the name project.godot gives the layer. Each of these lists is answered only when it names anything. add and set answer each property given under properties as the node holds it once written; alsoChanged gives the other properties the engine changed in step with a set, as a Control's offsets with its size, and those a reparent changed to keep the node where it is drawn, as {was, now}; namesNoNode, each node path written naming no node; sharedWith, for a property written through a resource built into the scene, each other {node, property} holding it, which changed too; setByScript, what a script that is not a tool set as a headless write ran, which the file does not hold; loadsAs, a value given that the file holds and the node's own script changes as the scene loads, as it loads. get adds placement, a Node3D's position, rotation_degrees and scale from its transform. " + ALSO_SAVED,
|
|
17033
17049
|
parameters: {
|
|
17034
17050
|
projectPath: PROJECT_PATH,
|
|
17035
17051
|
scenePath: SCENE_PATH,
|
|
@@ -17356,7 +17372,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
17356
17372
|
{
|
|
17357
17373
|
name: "script_edit",
|
|
17358
17374
|
title: "Edit scripts",
|
|
17359
|
-
description: "Creates a GDScript file, or adds functions, variables and signals to one. Every declaration written carries a type. Both load what they wrote under the project's own warning settings and answer with parses; the engine's reasons for a refusal come back under engine_messages. create answers with the extends and class_name the engine read (class_name null for a script declaring none), and a script declaring a class_name is put in the project's class list, with registered saying whether it is there, and an editor serving the project scans for it, so it resolves the class at once (editorRescanned); a class_name another script or an engine class holds, or an extends naming no class, is refused with nothing written. modify makes every addition or none, refuses with nothing changed additions that would stop a script that parses from parsing, giving the engine's reasons, and answers with the line each one is on in the file written; with an editor serving the project it reloads the script there too, so the editor's answers read what was written, and editorReloaded says so (editorNote when it could not, or when a script tab holds unsaved edits that saving would write over the file). rename renames a class or a member wherever the engine uses it and writes every file or none. A new name already taken is refused with nothing written, a member's included when a class inheriting it already uses the name in code, as a local or a parameter. changed lists each file with its changed lines as they now read, and leftAlone lists every other whole-word occurrence of the old name with what the tokenizer makes of it (code, string, comment, doc, nodePath, scene, text, or ignored for a file under a .gdignore directory, which is never changed) and, where it is not plain, why: a string that is the old name whole, such as find_children's type or a call's method name, which nothing renames or compiles and which is listed first; a node named like the class; a call on a value whose type the analyser could not tell. A member rename answers under languageServer how many requests it made and how long they took. A comment, documentation line, string or text file line with nothing more to say is given under leftAloneInProse by file, kind and line instead, and code that is certainly another symbol of the same name, a bare name in a file where nothing inherits the member or one the language server resolved to another declaration, under leftAloneOtherSymbols as each why with the files and lines it covers. summary.leftAlone counts each of the three lists beside the total. When those two grouped lists run past 300 lines, they are written with each line's text to a file under the project's .godot directory instead, of which the newest ten are kept, and leftAloneDetail names the file and counts what is in it. Read both before calling the rename done; nothing in them was changed. Afterwards an open editor scans the changed files and reloads every changed script, which is also the compile check, and its answer comes back under editor; with no editor the class cache is rebuilt and the changed scripts are compiled in a fresh engine, under classCache and compiled. written is true once the files are written, and ok is false when what came after the write failed: the files are left changed, and note says so.",
|
|
17375
|
+
description: "Creates a GDScript file, or adds functions, variables and signals to one. Every declaration written carries a type. Both load what they wrote under the project's own warning settings and answer with parses; the engine's reasons for a refusal come back under engine_messages. create answers with the extends and class_name the engine read (class_name null for a script declaring none), and writes the .uid beside the script as the editor does, answering it under uid; a script declaring a class_name is put in the project's class list, with registered saying whether it is there, and an editor serving the project scans for it, so it resolves the class at once (editorRescanned); a class_name another script or an engine class holds, or an extends naming no class, is refused with nothing written. modify makes every addition or none, refuses with nothing changed additions that would stop a script that parses from parsing, giving the engine's reasons, and answers with the line each one is on in the file written; with an editor serving the project it reloads the script there too, so the editor's answers read what was written, and editorReloaded says so (editorNote when it could not, or when a script tab holds unsaved edits that saving would write over the file). rename renames a class or a member wherever the engine uses it and writes every file or none. A new name already taken is refused with nothing written, a member's included when a class inheriting it already uses the name in code, as a local or a parameter. changed lists each file with its changed lines as they now read, and leftAlone lists every other whole-word occurrence of the old name with what the tokenizer makes of it (code, string, comment, doc, nodePath, scene, text, or ignored for a file under a .gdignore directory, which is never changed) and, where it is not plain, why: a string that is the old name whole, such as find_children's type or a call's method name, which nothing renames or compiles and which is listed first; a node named like the class; a call on a value whose type the analyser could not tell. A member rename answers under languageServer how many requests it made and how long they took. A comment, documentation line, string or text file line with nothing more to say is given under leftAloneInProse by file, kind and line instead, and code that is certainly another symbol of the same name, a bare name in a file where nothing inherits the member or one the language server resolved to another declaration, under leftAloneOtherSymbols as each why with the files and lines it covers. summary.leftAlone counts each of the three lists beside the total. When those two grouped lists run past 300 lines, they are written with each line's text to a file under the project's .godot directory instead, of which the newest ten are kept, and leftAloneDetail names the file and counts what is in it. Read both before calling the rename done; nothing in them was changed. Afterwards an open editor scans the changed files and reloads every changed script, which is also the compile check, and its answer comes back under editor; with no editor the class cache is rebuilt and the changed scripts are compiled in a fresh engine, under classCache and compiled. written is true once the files are written, and ok is false when what came after the write failed: the files are left changed, and note says so.",
|
|
17360
17376
|
parameters: {
|
|
17361
17377
|
projectPath: PROJECT_PATH,
|
|
17362
17378
|
scriptPath: SCRIPT_PATH,
|
|
@@ -17474,7 +17490,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
17474
17490
|
{
|
|
17475
17491
|
name: "resource_edit",
|
|
17476
17492
|
title: "Edit resources",
|
|
17477
|
-
description: 'Resource files: read one, create any ClassDB resource as .tres, change one, write a shader, build a TileSet, or set a Theme colour or font size. A material is a create with resourceType StandardMaterial3D, ShaderMaterial or CanvasItemMaterial. read answers with the properties the file sets, in the form modify takes, with resourceType the engine class and scriptClass the class_name of its script when it declares one, and a Theme lists its items there as "Button/colors/font_color", so a style box, a font or a constant is set through modify by that name, as "Button/styles/normal" given the res:// path of a StyleBox. A Curve, Curve2D or Curve3D reads as the inspector shows it, point_count and point_0/position and the rest, rather than the _data list the file stores, and so does one built into a resource or a scene. create and modify answer each property given under properties as the file holds it once saved, in the same form. A create or modify whose properties made the engine change others, as a Gradient given more colours than offsets gives each new point an offset of 0, names each of those under alsoChanged with what it held before and holds now. A property holding a resource takes its res:// path; a file never imported is refused with the reimport that imports it. move takes any file of the project, a script or an image as much as a resource, or a directory, and works from the files, so it needs no editor; one serving the project is brought up to it as after a move in its own FileSystem dock, its open scenes and cached resources named for the new paths and the project settings the move rewrote taken from the file. read needs no editor either: with none serving the project, a headless engine reads the file. The ops that write a resource go through the editor when one serves the project; with none, a headless engine runs the tool the editor would and the answer says so under writtenBy. That engine runs the script of the resource, where the editor runs only tool scripts, so what a script changes as the file loads or as a property is set is put back before the save, and a resource where that cannot be done is refused and the file left as it was.',
|
|
17493
|
+
description: 'Resource files: read one, create any ClassDB resource as .tres, change one, write a shader, build a TileSet, or set a Theme colour or font size. A material is a create with resourceType StandardMaterial3D, ShaderMaterial or CanvasItemMaterial. read answers with the properties the file sets, in the form modify takes, with resourceType the engine class and scriptClass the class_name of its script when it declares one, and a Theme lists its items there as "Button/colors/font_color", so a style box, a font or a constant is set through modify by that name, as "Button/styles/normal" given the res:// path of a StyleBox. A Curve, Curve2D or Curve3D reads as the inspector shows it, point_count and point_0/position and the rest, rather than the _data list the file stores, and so does one built into a resource or a scene. create and modify answer each property given under properties as the file holds it once saved, in the same form. A create or modify whose properties made the engine change others, as a Gradient given more colours than offsets gives each new point an offset of 0, names each of those under alsoChanged with what it held before and holds now. A property holding a resource takes its res:// path; a file never imported is refused with the reimport that imports it. move takes any file of the project, a script or an image as much as a resource, or a directory, and works from the files, so it needs no editor; one serving the project is brought up to it as after a move in its own FileSystem dock, its open scenes and cached resources named for the new paths and the project settings the move rewrote taken from the file. read needs no editor either: with none serving the project, a headless engine reads the file. The ops that write a resource go through the editor when one serves the project; with none, a headless engine runs the tool the editor would and the answer says so under writtenBy. That engine runs the script of the resource, where the editor runs only tool scripts, so what a script changes as the file loads or as a property is set is put back before the save, and answered under setByScript rather than alsoChanged, with setByScriptNote; a resource where that cannot be done is refused and the file left as it was. A read with none leaves out what such a script set as the file loaded.',
|
|
17478
17494
|
parameters: {
|
|
17479
17495
|
projectPath: PROJECT_PATH,
|
|
17480
17496
|
resourcePath: {
|
|
@@ -18172,15 +18188,15 @@ var init_tool_definitions = __esm(() => {
|
|
|
18172
18188
|
{
|
|
18173
18189
|
name: "runtime_input",
|
|
18174
18190
|
title: "Send input to the game",
|
|
18175
|
-
description: "Input to the running game: a whole click on a Control or a 3D node named by path or
|
|
18176
|
-
answer: `click: what was under the pointer, and what became of the control: in_tree, removed or freed. A button answers pressed_signal, whether its pressed signal fired during the click. Named by says, found says which match it was, its index being the index argument that presses the same match again, found.item names the tab, list entry, tree row or menu bar title pressed (kind; index, the item's own number in its control, which is not found.index; says; and for a row the column of the cell saying the words), and found.pressedOn says "the words" for words in a RichTextLabel pressed where they are drawn, or "the middle of the label" with a note saying why they could not be placed; on a rich label link_pressed says whether the press reached a link, with link_meta giving the meta the label reports clicked, an empty one included. A control scrolled into view first is scrolled each container out from it a frame after the one inside, and scrolled_into_view says whether a scroll value changed. A button in toggle mode, a CheckBox or CheckButton included, answers pressed with before and after, its button_pressed either side of the click: the same value twice is a click the game undid, and after is null when the click freed it. A refusal for a pointer turned off names where mouse_behavior_recursive was set. On a 3D node landed says the interface did not swallow the press: no control under the pointer stopped it, a control letting the pointer pass included, and every viewport on the way out from the room had the pointer over what shows the room. choose: what was chosen, read before the press, which is heard rather than assumed; what became of the control named (in_tree, removed or freed, since a game can rebuild its screen on the pick); and what the button in front of the menu shows now when it is still there. A menu is opened rather than clicked because its items are drawn rather than built, and the item is looked for as the menu stands once open, since a game can fill a menu as it opens. action, key, mouse_click and joypad_button: the event as it was sent, with whole saying whether the press was let go of again and pressed whether it is left held down (true only after pressed true), for a key the keycode, physical_keycode and unicode it carried, and for a controller button its number, its name and the device. mouse_motion: the position and the relative movement sent. mouse_drag: from, to, motions sent and relative_total. joypad_motion: the axis by number and name, the value and the device. key, mouse_click, click, joypad_button and joypad_motion answer actions, the InputMap actions the event also presses; for a motion, those its direction reaches past their deadzone, and none for one inside it. mouse_click, mouse_motion and mouse_drag answer hovered, the control under the pointer once the events are handled, or null over none; the other events are aimed at nothing. mouse_click with a press, and mouse_drag, answer press_went_to, the path of what the press went to (a control, or a window embedded over the point), read before it, or null when nothing there takes the pointer; given nodePath naming a Control, landed says whether that is the control or inside it. A click that did not land on a control whose mouse_filter is ignore, as a Label's is, says so under why_not_landed, and one on a control with something drawn over it names that, a window stacked above the one the control is in among them. An action, a key, a joypad_button or a joypad_motion answers focused with the path of the Control holding the keyboard focus when it went in, since that Control gets it before the game's _unhandled_input: Space or Enter on a focused button presses the button, and a stick or dpad pressing ui_down moves a focused list's selection, or the focus, and never reaches the game's handler. Where the press moved the focus, focused_after names the Control holding it once the event was handled, or null when nothing does. A key that a focused LineEdit or TextEdit took as typing names that field under typed_into, with what it holds under holds, since a field being edited keeps the key from the game's _unhandled_input. editing_ended true, on a key or on text, is a LineEdit that stopped being edited, as Enter does by submitting it: it keeps the focus, and nothing typed into it lands until it is clicked again. text with the focus on a control that is no LineEdit or TextEdit answers holds null and a note saying so, since a focused button takes a space or Enter as a press. A mouse_click, mouse_motion or mouse_drag given nodePath answers it under path, its points in the pixels of the window they went to, and that window under window when it is not the game's own. One with a point outside the viewport it went to says so under outside_viewport, with the viewport's rectangle, since no control there receives it.`,
|
|
18191
|
+
description: "Input to the running game: a whole click on a Control or a 3D node named by path or by the words on it, an item chosen out of a menu, typing into the focus, or a raw action, key, mouse button, mouse motion or drag, touch or finger drag. All of it works headless, where the viewport is the project's window size and the GUI only takes what is inside it. On gdharness's own desktop, where a windowed run goes, Windows refuses to say where the pointer is: every pointer answer there carries pointer_on_hidden_desktop, and the run's first pointer_note says why it matters: get_mouse_position() on the root window, and what derives from it, reads nonsense, while what reads the event itself (the control under it, hover, tooltips, input handlers) gets the injected position. A native window no real pointer has entered gets no hover from Godot, so the runtime supplies it there and the answers say hover_supplied.",
|
|
18192
|
+
answer: `click: what was under the pointer, and what became of the control: in_tree, removed or freed. A button answers pressed_signal, whether its pressed signal fired during the click. Named by says, found says which match it was, its index being the index argument that presses the same match again, found.item names the tab, list entry, tree row or menu bar title pressed (kind; index, the item's own number in its control, which is not found.index; says; and for a row the column of the cell saying the words), and found.pressedOn says "the words" for words in a RichTextLabel pressed where they are drawn, or "the middle of the label" with a note saying why they could not be placed; on a rich label link_pressed says whether the press reached a link, with link_meta giving the meta the label reports clicked, an empty one included. A control scrolled into view first is scrolled each container out from it a frame after the one inside, and scrolled_into_view says whether a scroll value changed. A button in toggle mode, a CheckBox or CheckButton included, answers pressed with before and after, its button_pressed either side of the click: the same value twice is a click the game undid, and after is null when the click freed it. A refusal for a pointer turned off names where mouse_behavior_recursive was set. On a 3D node landed says the interface did not swallow the press: no control under the pointer stopped it, a control letting the pointer pass included, and every viewport on the way out from the room had the pointer over what shows the room. choose: what was chosen, read before the press, which is heard rather than assumed; what became of the control named (in_tree, removed or freed, since a game can rebuild its screen on the pick); and what the button in front of the menu shows now when it is still there. A menu is opened rather than clicked because its items are drawn rather than built, and the item is looked for as the menu stands once open, since a game can fill a menu as it opens. action, key, mouse_click and joypad_button: the event as it was sent, with whole saying whether the press was let go of again and pressed whether it is left held down (true only after pressed true), for a key the keycode, physical_keycode and unicode it carried, and for a controller button its number, its name and the device. mouse_motion: the position and the relative movement sent. mouse_drag: from, to, motions sent and relative_total. touch: the finger's index, the position, whole and pressed as a mouse_click has them, and emulates_mouse; touch_drag: what mouse_drag answers, with index and emulates_mouse. joypad_motion: the axis by number and name, the value and the device. key, mouse_click, click, joypad_button and joypad_motion answer actions, the InputMap actions the event also presses; for a motion, those its direction reaches past their deadzone, and none for one inside it. mouse_click, mouse_motion and mouse_drag answer hovered, the control under the pointer once the events are handled, or null over none; the other events are aimed at nothing. mouse_click with a press, and mouse_drag, answer press_went_to, the path of what the press went to (a control, or a window embedded over the point), read before it, or null when nothing there takes the pointer; given nodePath naming a Control, landed says whether that is the control or inside it. A click that did not land on a control whose mouse_filter is ignore, as a Label's is, says so under why_not_landed, and one on a control with something drawn over it names that, a window stacked above the one the control is in among them. An action, a key, a joypad_button or a joypad_motion answers focused with the path of the Control holding the keyboard focus when it went in, since that Control gets it before the game's _unhandled_input: Space or Enter on a focused button presses the button, and a stick or dpad pressing ui_down moves a focused list's selection, or the focus, and never reaches the game's handler. Where the press moved the focus, focused_after names the Control holding it once the event was handled, or null when nothing does. A key that a focused LineEdit or TextEdit took as typing names that field under typed_into, with what it holds under holds, since a field being edited keeps the key from the game's _unhandled_input. editing_ended true, on a key or on text, is a LineEdit that stopped being edited, as Enter does by submitting it: it keeps the focus, and nothing typed into it lands until it is clicked again. text with the focus on a control that is no LineEdit or TextEdit answers holds null and a note saying so, since a focused button takes a space or Enter as a press. A mouse_click, mouse_motion or mouse_drag given nodePath answers it under path, its points in the pixels of the window they went to, and that window under window when it is not the game's own. One with a point outside the viewport it went to says so under outside_viewport, with the viewport's rectangle, since no control there receives it.`,
|
|
18177
18193
|
parameters: {
|
|
18178
18194
|
projectPath: RUNNING_PROJECT_PATH,
|
|
18179
18195
|
pid: RUNNING_PID,
|
|
18180
18196
|
nodePath: {
|
|
18181
18197
|
type: "string",
|
|
18182
|
-
ops: ["click", "choose", "mouse_click", "mouse_motion", "mouse_drag"],
|
|
18183
|
-
description: "click: the Control to click, at its centre, at x and y in its own space when those are given, or at the middle of the part on screen when no scroll brings its centre into view (said under pressed_on), or the 3D node to click, where it is drawn; with says, where to look for the control instead, default the whole tree. choose: the PopupMenu, or the OptionButton or MenuButton in front of one. mouse_click, mouse_motion, mouse_drag: the Control, Node2D or Window whose own space the points are in, a Window's being its own pixels; the events go to the window that shows it, a native one included, which the game's window pixels cannot reach, and the answer names it under window when it is not the game's own. Default the game's window."
|
|
18198
|
+
ops: ["click", "choose", "mouse_click", "mouse_motion", "mouse_drag", "touch", "touch_drag"],
|
|
18199
|
+
description: "click: the Control to click, at its centre, at x and y in its own space when those are given, or at the middle of the part on screen when no scroll brings its centre into view (said under pressed_on), or the 3D node to click, where it is drawn; with says, where to look for the control instead, default the whole tree. choose: the PopupMenu, or the OptionButton or MenuButton in front of one. mouse_click, mouse_motion, mouse_drag, touch, touch_drag: the Control, Node2D or Window whose own space the points are in, a Window's being its own pixels; the events go to the window that shows it, a native one included, which the game's window pixels cannot reach, and the answer names it under window when it is not the game's own. Default the game's window."
|
|
18184
18200
|
},
|
|
18185
18201
|
says: {
|
|
18186
18202
|
type: "string",
|
|
@@ -18194,15 +18210,15 @@ var init_tool_definitions = __esm(() => {
|
|
|
18194
18210
|
},
|
|
18195
18211
|
pressed: {
|
|
18196
18212
|
type: "boolean",
|
|
18197
|
-
ops: ["action", "key", "mouse_click", "joypad_button"],
|
|
18198
|
-
description: "action, key, mouse_click, joypad_button: leave it out and the press is a whole one, down and up a frame apart. true holds it down, false lets go of one being held. A wheel button held down is still a whole step, since a wheel is never held."
|
|
18213
|
+
ops: ["action", "key", "mouse_click", "joypad_button", "touch"],
|
|
18214
|
+
description: "action, key, mouse_click, joypad_button, touch: leave it out and the press is a whole one, down and up a frame apart. true holds it down, false lets go of one being held, a finger lifted at x and y. A wheel button held down is still a whole step, since a wheel is never held."
|
|
18199
18215
|
},
|
|
18200
18216
|
holdFrames: {
|
|
18201
18217
|
type: "integer",
|
|
18202
18218
|
minimum: 1,
|
|
18203
18219
|
maximum: 600,
|
|
18204
|
-
ops: ["action", "key", "mouse_click", "joypad_button"],
|
|
18205
|
-
description: "action, key, mouse_click, joypad_button: hold a whole press down for this many process frames and then let go, both inside the game, so a pour, a charge or a long press runs to a set length. A press, a frames wait and a release sent as three calls hold it for the time between the calls as well. The answer says held_frames, and under held_for the seconds the hold lasted and the physics_frames that ran in it: a process frame is no set time, and a headless game, drawing nothing, runs them far faster than the sixty physics ticks a second that _physics_process sees. Not with pressed, and not on a wheel step. Default 1."
|
|
18220
|
+
ops: ["action", "key", "mouse_click", "joypad_button", "touch"],
|
|
18221
|
+
description: "action, key, mouse_click, joypad_button, touch: hold a whole press down for this many process frames and then let go, both inside the game, so a pour, a charge or a long press runs to a set length. A press, a frames wait and a release sent as three calls hold it for the time between the calls as well. The answer says held_frames, and under held_for the seconds the hold lasted and the physics_frames that ran in it: a process frame is no set time, and a headless game, drawing nothing, runs them far faster than the sixty physics ticks a second that _physics_process sees. Not with pressed, and not on a wheel step. Default 1."
|
|
18206
18222
|
},
|
|
18207
18223
|
strength: {
|
|
18208
18224
|
type: "number",
|
|
@@ -18229,40 +18245,44 @@ var init_tool_definitions = __esm(() => {
|
|
|
18229
18245
|
},
|
|
18230
18246
|
index: {
|
|
18231
18247
|
type: "number",
|
|
18232
|
-
ops: ["click", "choose"],
|
|
18233
|
-
description: "click: which of several controls saying the words, counting from 0 in the order a refusal lists them, best matches first. choose: the item to take, by where it is in the list, when text will not do."
|
|
18248
|
+
ops: ["click", "choose", "touch", "touch_drag"],
|
|
18249
|
+
description: "click: which of several controls saying the words, counting from 0 in the order a refusal lists them, best matches first. choose: the item to take, by where it is in the list, when text will not do. touch, touch_drag: the finger, from 0, as InputEventScreenTouch.index; a second finger down at once is another index. Default 0."
|
|
18234
18250
|
},
|
|
18235
18251
|
shift: { type: "boolean", ops: ["key"], description: "key: hold Shift with it. Default false." },
|
|
18236
18252
|
ctrl: { type: "boolean", ops: ["key"], description: "key: hold Ctrl with it. Default false." },
|
|
18237
18253
|
alt: { type: "boolean", ops: ["key"], description: "key: hold Alt with it. Default false." },
|
|
18238
18254
|
x: {
|
|
18239
18255
|
type: "number",
|
|
18240
|
-
ops: ["click", "mouse_click", "mouse_motion", "mouse_drag"],
|
|
18241
|
-
description: "click: with y, the point to press in the control's own space instead of its centre, for a control that draws its parts itself; not with a 3D node, nor with says finding an item the control draws. mouse_click, mouse_motion: window pixels, or nodePath's own space when that is given. mouse_drag: where the press is, in the same space."
|
|
18256
|
+
ops: ["click", "mouse_click", "mouse_motion", "mouse_drag", "touch", "touch_drag"],
|
|
18257
|
+
description: "click: with y, the point to press in the control's own space instead of its centre, for a control that draws its parts itself; not with a 3D node, nor with says finding an item the control draws. mouse_click, mouse_motion, touch: window pixels, or nodePath's own space when that is given. mouse_drag, touch_drag: where the press is, in the same space."
|
|
18242
18258
|
},
|
|
18243
18259
|
y: {
|
|
18244
18260
|
type: "number",
|
|
18245
|
-
ops: ["click", "mouse_click", "mouse_motion", "mouse_drag"],
|
|
18246
|
-
description: "click, mouse_click, mouse_motion, mouse_drag: as x."
|
|
18261
|
+
ops: ["click", "mouse_click", "mouse_motion", "mouse_drag", "touch", "touch_drag"],
|
|
18262
|
+
description: "click, mouse_click, mouse_motion, mouse_drag, touch, touch_drag: as x."
|
|
18247
18263
|
},
|
|
18248
18264
|
toX: {
|
|
18249
18265
|
type: "number",
|
|
18250
|
-
ops: ["mouse_drag"],
|
|
18251
|
-
description: "mouse_drag: where the release is, in window pixels or nodePath's own space."
|
|
18266
|
+
ops: ["mouse_drag", "touch_drag"],
|
|
18267
|
+
description: "mouse_drag, touch_drag: where the release is, in window pixels or nodePath's own space."
|
|
18268
|
+
},
|
|
18269
|
+
toY: {
|
|
18270
|
+
type: "number",
|
|
18271
|
+
ops: ["mouse_drag", "touch_drag"],
|
|
18272
|
+
description: "mouse_drag, touch_drag: as toX."
|
|
18252
18273
|
},
|
|
18253
|
-
toY: { type: "number", ops: ["mouse_drag"], description: "mouse_drag: as toX." },
|
|
18254
18274
|
via: {
|
|
18255
18275
|
type: "array",
|
|
18256
18276
|
items: { type: "array", items: { type: "number" }, minItems: 2, maxItems: 2 },
|
|
18257
|
-
ops: ["mouse_drag"],
|
|
18258
|
-
description: "mouse_drag: points the stroke passes through on the way, in order, each [x, y] in the space x and y are in. The motions are spread along the whole stroke by distance. Default none: a straight line."
|
|
18277
|
+
ops: ["mouse_drag", "touch_drag"],
|
|
18278
|
+
description: "mouse_drag, touch_drag: points the stroke passes through on the way, in order, each [x, y] in the space x and y are in. The motions are spread along the whole stroke by distance. Default none: a straight line."
|
|
18259
18279
|
},
|
|
18260
18280
|
frames: {
|
|
18261
18281
|
type: "integer",
|
|
18262
18282
|
minimum: 1,
|
|
18263
18283
|
maximum: 600,
|
|
18264
|
-
ops: ["mouse_drag"],
|
|
18265
|
-
description: "mouse_drag: how many process frames the stroke takes, one motion each, as a real mouse sends one a frame; a hand takes about 20 to 60 for a stroke across a screen."
|
|
18284
|
+
ops: ["mouse_drag", "touch_drag"],
|
|
18285
|
+
description: "mouse_drag, touch_drag: how many process frames the stroke takes, one motion each, as a real mouse or finger sends one a frame; a hand takes about 20 to 60 for a stroke across a screen."
|
|
18266
18286
|
},
|
|
18267
18287
|
button: {
|
|
18268
18288
|
type: ["string", "number"],
|
|
@@ -18307,28 +18327,28 @@ var init_tool_definitions = __esm(() => {
|
|
|
18307
18327
|
operations: {
|
|
18308
18328
|
click: {
|
|
18309
18329
|
effect: "additive",
|
|
18310
|
-
summary: "press and release on a Control, a frame apart, named by nodePath or by says
|
|
18330
|
+
summary: "press and release on a Control, a frame apart, named by nodePath or by says (found under nodePath when both are given), or on a 3D node where it is drawn. A control hidden in a ScrollContainer is scrolled to first; a RichTextLabel link is pressed where its words are drawn. A disabled button, a control that does not process and one mouse_behavior_recursive turned off are refused, since the press would do nothing; by says, a reachable one is picked over it",
|
|
18311
18331
|
requires: []
|
|
18312
18332
|
},
|
|
18313
18333
|
choose: {
|
|
18314
18334
|
effect: "additive",
|
|
18315
|
-
summary: "take an item out of a menu, by
|
|
18335
|
+
summary: "take an item out of a menu, by its words or its place in the list: the menu is opened, the item found as it stands then and pressed through the engine's own path, which needs no window and not ui_accept's binding. A disabled or hidden button in front of the menu is refused, and so is a press the menu did not take",
|
|
18316
18336
|
requires: ["nodePath"]
|
|
18317
18337
|
},
|
|
18318
18338
|
action: { effect: "additive", summary: "press an action, or hold it", requires: ["action"] },
|
|
18319
18339
|
key: {
|
|
18320
18340
|
effect: "additive",
|
|
18321
|
-
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
|
|
18341
|
+
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 never reaches, so arrows move nothing and Enter closes it unchosen; choose selects there. Other windows are not like it: an embedded dialog whose owner reads keys in _input gets them",
|
|
18322
18342
|
requires: ["keycode"]
|
|
18323
18343
|
},
|
|
18324
18344
|
text: {
|
|
18325
18345
|
effect: "additive",
|
|
18326
|
-
summary: "type a string into the field being edited, a character at a time,
|
|
18346
|
+
summary: "type a string into the field being edited, a character at a time, saying what it landed in and what it then holds (a secret field as its mask). With a dialog focused, the field is that dialog's focus, where the keys go",
|
|
18327
18347
|
requires: ["text"]
|
|
18328
18348
|
},
|
|
18329
18349
|
mouse_click: {
|
|
18330
18350
|
effect: "additive",
|
|
18331
|
-
summary: "click a mouse button at a position, pressed and released a frame apart, each event carrying the buttons held
|
|
18351
|
+
summary: "click a mouse button at a position, pressed and released a frame apart, each event carrying the buttons held after it; the answer says whole. A drag is mouse_drag. A wheel button is always a whole step, as a mouse sends one: a lone wheel press holds the viewport on the control that took it, so every later click lands there",
|
|
18332
18352
|
requires: ["x", "y"]
|
|
18333
18353
|
},
|
|
18334
18354
|
mouse_motion: {
|
|
@@ -18338,17 +18358,27 @@ var init_tool_definitions = __esm(() => {
|
|
|
18338
18358
|
},
|
|
18339
18359
|
mouse_drag: {
|
|
18340
18360
|
effect: "additive",
|
|
18341
|
-
summary: "a whole drag in one call
|
|
18361
|
+
summary: "a whole drag in one call: press at x, y, a motion each frame, release at toX, toY; for a stir, a paint stroke or a slow slider",
|
|
18362
|
+
requires: ["x", "y", "toX", "toY", "frames"]
|
|
18363
|
+
},
|
|
18364
|
+
touch: {
|
|
18365
|
+
effect: "additive",
|
|
18366
|
+
summary: "press a finger at x, y and lift it a frame later, or hold it, as an InputEventScreenTouch; in the game's window the engine makes mouse events carrying DEVICE_ID_EMULATION from the first finger down, where emulate_mouse_from_touch is on (emulates_mouse)",
|
|
18367
|
+
requires: ["x", "y"]
|
|
18368
|
+
},
|
|
18369
|
+
touch_drag: {
|
|
18370
|
+
effect: "additive",
|
|
18371
|
+
summary: "mouse_drag for one finger: the touch, an InputEventScreenDrag each frame, and the lift",
|
|
18342
18372
|
requires: ["x", "y", "toX", "toY", "frames"]
|
|
18343
18373
|
},
|
|
18344
18374
|
joypad_button: {
|
|
18345
18375
|
effect: "additive",
|
|
18346
|
-
summary: "press a controller button, or hold it, as an InputEventJoypadButton,
|
|
18376
|
+
summary: "press a controller button, or hold it, as an InputEventJoypadButton, as a controller sends it to _input and _unhandled_input; an action bound to the button fires with it. Pressed and released a frame apart unless pressed says otherwise",
|
|
18347
18377
|
requires: ["button"]
|
|
18348
18378
|
},
|
|
18349
18379
|
joypad_motion: {
|
|
18350
18380
|
effect: "additive",
|
|
18351
|
-
summary: "move a stick or trigger axis to a value, as an InputEventJoypadMotion
|
|
18381
|
+
summary: "move a stick or trigger axis to a value, as an InputEventJoypadMotion; the axis stays there until another motion moves it",
|
|
18352
18382
|
requires: ["axis", "value"]
|
|
18353
18383
|
}
|
|
18354
18384
|
}
|
|
@@ -51632,7 +51662,7 @@ class GodotServer {
|
|
|
51632
51662
|
}, { tool: "runtime_input", op });
|
|
51633
51663
|
}
|
|
51634
51664
|
{
|
|
51635
|
-
const holding = op === "mouse_drag" ? (readPositiveNumber(args, "frames") ?? 1) + 2 : readPositiveNumber(args, "holdFrames");
|
|
51665
|
+
const holding = op === "mouse_drag" || op === "touch_drag" ? (readPositiveNumber(args, "frames") ?? 1) + 2 : readPositiveNumber(args, "holdFrames");
|
|
51636
51666
|
return await this.handleRuntimeCommand(`inject_${op}`, args, {
|
|
51637
51667
|
tool: "runtime_input",
|
|
51638
51668
|
op,
|
|
@@ -53165,7 +53195,8 @@ ${platform}`;
|
|
|
53165
53195
|
...printedLines,
|
|
53166
53196
|
savesNote,
|
|
53167
53197
|
...scanned,
|
|
53168
|
-
...windowSaid
|
|
53198
|
+
...windowSaid,
|
|
53199
|
+
classes: withAddonClassesCounted(classes.payload, cachedClasses(project.value.path) ?? new Map)
|
|
53169
53200
|
}, null, 2)
|
|
53170
53201
|
}
|
|
53171
53202
|
],
|
|
@@ -64,7 +64,13 @@ static func scene_states(scene_path: String, tree_path: String, state_machine_pa
|
|
|
64
64
|
player_path = "."
|
|
65
65
|
var found: Array = _bare(scene_path, player_path, "AnimationPlayer")
|
|
66
66
|
player = found[0]
|
|
67
|
-
var
|
|
67
|
+
var reached: Node = null
|
|
68
|
+
if player == null and not player_path.is_empty():
|
|
69
|
+
reached = _bare(scene_path, player_path, "Node")[0]
|
|
70
|
+
var unplayed: String = no_player(str(tree.anim_player), reached)
|
|
71
|
+
if reached != null:
|
|
72
|
+
reached.free()
|
|
73
|
+
var answer: Dictionary = states(tree, state_machine_path, player, player_path, unplayed)
|
|
68
74
|
tree.free()
|
|
69
75
|
if player != null:
|
|
70
76
|
player.free()
|
|
@@ -236,6 +242,20 @@ static func no_machine(tree: AnimationTree, state_machine_path: String) -> Strin
|
|
|
236
242
|
return "No state machine at " + state_machine_path
|
|
237
243
|
|
|
238
244
|
|
|
245
|
+
## Why no state finds its animation when [param anim_player], an AnimationTree's path to its
|
|
246
|
+
## player, reaches no AnimationPlayer: [param reached] is the node it reaches instead, null for none.
|
|
247
|
+
static func no_player(anim_player: String, reached: Node) -> String:
|
|
248
|
+
var until: String = "so no state plays anything until scene_node set points anim_player at one."
|
|
249
|
+
if anim_player.is_empty():
|
|
250
|
+
return "The AnimationTree has no anim_player, " + until
|
|
251
|
+
if reached == null:
|
|
252
|
+
return "The AnimationTree's anim_player %s reaches no node, %s" % [anim_player, until]
|
|
253
|
+
return (
|
|
254
|
+
"The AnimationTree's anim_player %s reaches %s, a %s rather than an AnimationPlayer, %s"
|
|
255
|
+
% [anim_player, reached.name, reached.get_class(), until]
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
|
|
239
259
|
## Why a state playing [param animation_name] from [param player], at [param player_path] from the
|
|
240
260
|
## scene root as playerNodePath takes it, plays nothing yet. anim_player is relative to the tree
|
|
241
261
|
## ("../Anim"), which no argument takes.
|
|
@@ -254,9 +274,14 @@ static func missing_animation(player: AnimationPlayer, player_path: String, anim
|
|
|
254
274
|
|
|
255
275
|
## The states and transitions of the state machine at [param state_machine_path] in [param tree].
|
|
256
276
|
## A state playing an animation says whether [param player], at [param player_path], has it, as
|
|
257
|
-
## add_state answers: a state naming one it lacks plays nothing, and says so only in a log.
|
|
277
|
+
## add_state answers: a state naming one it lacks plays nothing, and says so only in a log. With no
|
|
278
|
+
## player, each says [param unplayed], what [method no_player] made of the tree's path.
|
|
258
279
|
static func states(
|
|
259
|
-
tree: AnimationTree,
|
|
280
|
+
tree: AnimationTree,
|
|
281
|
+
state_machine_path: String,
|
|
282
|
+
player: AnimationPlayer,
|
|
283
|
+
player_path: String,
|
|
284
|
+
unplayed: String
|
|
260
285
|
) -> Dictionary:
|
|
261
286
|
var sm: AnimationNodeStateMachine = state_machine(tree, state_machine_path)
|
|
262
287
|
if sm == null:
|
|
@@ -270,7 +295,9 @@ static func states(
|
|
|
270
295
|
entry["animationName"] = str(plays.animation)
|
|
271
296
|
var found: bool = player != null and player.has_animation(plays.animation)
|
|
272
297
|
entry["animationFound"] = found
|
|
273
|
-
if player
|
|
298
|
+
if player == null:
|
|
299
|
+
entry["animationMissing"] = unplayed
|
|
300
|
+
elif not found:
|
|
274
301
|
entry["animationMissing"] = missing_animation(player, player_path, str(plays.animation))
|
|
275
302
|
listed.append(entry)
|
|
276
303
|
var transitions: Array[Dictionary] = []
|
|
@@ -517,6 +517,18 @@ static func resource(res_path: String, include_defaults: bool) -> Dictionary:
|
|
|
517
517
|
scripted[str(declared.get("name", ""))] = true
|
|
518
518
|
var serialiser: GdhSerialisation = GdhSerialisation.new()
|
|
519
519
|
var properties: Dictionary = {}
|
|
520
|
+
# A headless engine runs a script that is not a tool as the file loads, so what its _init and
|
|
521
|
+
# setters gave other properties read as values the file sets; the file's own lines say which it
|
|
522
|
+
# does. The editor runs no such script.
|
|
523
|
+
var untooled: bool = script != null and not script.is_tool() and not Engine.is_editor_hint()
|
|
524
|
+
var from_file: bool = (
|
|
525
|
+
untooled and file.ends_with(".tres") and not GdhShapes.STORED_APART.has(loaded.get_class())
|
|
526
|
+
)
|
|
527
|
+
var set_in_file: Dictionary = (
|
|
528
|
+
_names_set_in(FileAccess.get_file_as_string(file), res_path.trim_prefix(file).trim_prefix("::"))
|
|
529
|
+
if from_file
|
|
530
|
+
else {}
|
|
531
|
+
)
|
|
520
532
|
# A Curve's points are read off one with none, since the engine has no default for point_0.
|
|
521
533
|
var fresh: Object = (
|
|
522
534
|
ClassDB.instantiate(loaded.get_class()) if GdhShapes.STORED_APART.has(loaded.get_class()) else null
|
|
@@ -538,6 +550,8 @@ static func resource(res_path: String, include_defaults: bool) -> Dictionary:
|
|
|
538
550
|
)
|
|
539
551
|
if GdhSame.same(value, default):
|
|
540
552
|
continue
|
|
553
|
+
if from_file and not set_in_file.has(property):
|
|
554
|
+
continue
|
|
541
555
|
properties[property] = serialiser.serialize_value(value)
|
|
542
556
|
var answer: Dictionary = {
|
|
543
557
|
"ok": true, "resourcePath": res_path, "resourceType": loaded.get_class(), "properties": properties
|
|
@@ -552,6 +566,26 @@ static func resource(res_path: String, include_defaults: bool) -> Dictionary:
|
|
|
552
566
|
return answer
|
|
553
567
|
|
|
554
568
|
|
|
569
|
+
## The names the [code][resource][/code] section of [param text], a .tres file, sets, or those of the
|
|
570
|
+
## embedded resource with the id [param id] when one is given, as a set.
|
|
571
|
+
static func _names_set_in(text: String, id: String) -> Dictionary:
|
|
572
|
+
var names: Dictionary = {}
|
|
573
|
+
var inside: bool = false
|
|
574
|
+
var key: RegEx = RegEx.create_from_string("^([^\\s=\\[][^=]*?) = ")
|
|
575
|
+
for line: String in text.split("\n"):
|
|
576
|
+
if line.begins_with("["):
|
|
577
|
+
inside = (
|
|
578
|
+
line.begins_with("[resource]")
|
|
579
|
+
if id.is_empty()
|
|
580
|
+
else line.begins_with("[sub_resource") and line.contains('id="%s"' % id)
|
|
581
|
+
)
|
|
582
|
+
continue
|
|
583
|
+
var found: RegExMatch = key.search(line) if inside else null
|
|
584
|
+
if found != null:
|
|
585
|
+
names[found.get_string(1)] = true
|
|
586
|
+
return names
|
|
587
|
+
|
|
588
|
+
|
|
555
589
|
## The resource [param file] keeps under [param id], found in [param value] or anything it holds.
|
|
556
590
|
## The engine loads such a path only while the file is cached, and a read loads the file uncached,
|
|
557
591
|
## so it is looked for among what the file holds. A resource of another file is neither taken nor
|
|
@@ -505,6 +505,35 @@ static func setter_ran(object: Object, property: String, refused: String) -> Str
|
|
|
505
505
|
)
|
|
506
506
|
|
|
507
507
|
|
|
508
|
+
## Moves out of alsoChanged in [param answer] each of [param names], what a headless write put back
|
|
509
|
+
## as the doing of the script of [param owner], which is not a tool, to setByScript, with a note
|
|
510
|
+
## saying why the file does not hold it.
|
|
511
|
+
static func move_script_set(answer: Dictionary, names: Array, owner: String) -> void:
|
|
512
|
+
if not answer.has("alsoChanged"):
|
|
513
|
+
return
|
|
514
|
+
var changed: Dictionary = answer["alsoChanged"]
|
|
515
|
+
var by_script: Dictionary = {}
|
|
516
|
+
for key: Variant in names:
|
|
517
|
+
if changed.has(key):
|
|
518
|
+
by_script[key] = changed[key]
|
|
519
|
+
var _erased: bool = changed.erase(key)
|
|
520
|
+
if by_script.is_empty():
|
|
521
|
+
return
|
|
522
|
+
if changed.is_empty():
|
|
523
|
+
var _dropped: bool = answer.erase("alsoChanged")
|
|
524
|
+
answer["setByScript"] = by_script
|
|
525
|
+
var listed: Array = by_script.keys()
|
|
526
|
+
var pronoun: String = "it" if listed.size() == 1 else "them"
|
|
527
|
+
answer["setByScriptNote"] = (
|
|
528
|
+
(
|
|
529
|
+
"%s's script is not a tool, so it ran in the headless engine that wrote the file, and set %s "
|
|
530
|
+
+ "as it did. The file does not hold %s, as a save from the editor, where the script does not "
|
|
531
|
+
+ "run, would not; the script sets %s again when it runs in the game."
|
|
532
|
+
)
|
|
533
|
+
% [owner, ", ".join(listed), pronoun, pronoun]
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
|
|
508
537
|
## Why [param name] on [param what] cannot be saved as the file held it.
|
|
509
538
|
static func unasked(what: String, name: String, why: String = "") -> String:
|
|
510
539
|
return (
|
|
@@ -45,6 +45,17 @@ var root: Node = null
|
|
|
45
45
|
var path: String = ""
|
|
46
46
|
## What the last write saved, for its answer to read what the file now stores.
|
|
47
47
|
var written_pack: PackedScene = null
|
|
48
|
+
## The properties a headless write put back on each node the tool changed, by instance id, as a
|
|
49
|
+
## set: what the node's script, which is not a tool, changed as the tool wrote, and the file was
|
|
50
|
+
## not given.
|
|
51
|
+
var restored_by_write: Dictionary = {}
|
|
52
|
+
## What the scene loads with where it stores what the tool gave, by node path and then property:
|
|
53
|
+
## the node's script changed the value as the copy the write checks loaded.
|
|
54
|
+
var loads_as: Dictionary = {}
|
|
55
|
+
## The node paths in [member loads_as] whose script is not a tool, so an editor does not run it.
|
|
56
|
+
var loads_untooled: Dictionary = {}
|
|
57
|
+
## The pack a write's check reads, for [method stores] to answer from.
|
|
58
|
+
var _checked_pack: PackedScene = null
|
|
48
59
|
## The path of each node a scene this one inherits gives, with the file that makes it.
|
|
49
60
|
var _base_paths: Dictionary = {}
|
|
50
61
|
var _state: SceneState = null
|
|
@@ -564,6 +575,19 @@ func kept(saved: Node, loaded: Variant, given: Variant) -> bool:
|
|
|
564
575
|
return GdhSame.same(loaded, given)
|
|
565
576
|
|
|
566
577
|
|
|
578
|
+
## Whether the pack a write is checking stores [param given] for [param property] on the node at
|
|
579
|
+
## [param at], a path from the root.
|
|
580
|
+
func stores(at: String, property: String, given: Variant) -> bool:
|
|
581
|
+
if _checked_pack == null:
|
|
582
|
+
return false
|
|
583
|
+
var state: SceneState = _checked_pack.get_state()
|
|
584
|
+
for index: int in state.get_node_count():
|
|
585
|
+
if _relative(str(state.get_node_path(index))) == at:
|
|
586
|
+
var stored: Dictionary = _stored_at(state, index)
|
|
587
|
+
return stored.has(property) and GdhSame.same(stored[property], given)
|
|
588
|
+
return false
|
|
589
|
+
|
|
590
|
+
|
|
567
591
|
## Packs [member root], has [param check] read the result as the file will hold it, and writes the
|
|
568
592
|
## file only if the check answers "". Frees [member root] either way.
|
|
569
593
|
##
|
|
@@ -592,6 +616,7 @@ func write(check: Callable = Callable()) -> Dictionary:
|
|
|
592
616
|
var saved: Node = packed.instantiate(PackedScene.GEN_EDIT_STATE_MAIN)
|
|
593
617
|
if saved == null:
|
|
594
618
|
return refuse("The packed copy of %s did not instantiate, so nothing was written." % path)
|
|
619
|
+
_checked_pack = packed
|
|
595
620
|
var missing: String = str(check.call(saved))
|
|
596
621
|
saved.free()
|
|
597
622
|
if not missing.is_empty():
|
|
@@ -777,8 +802,10 @@ func _settled(packed: PackedScene) -> Array:
|
|
|
777
802
|
for found: Array in moved:
|
|
778
803
|
var node: Node = found[0]
|
|
779
804
|
var before: Dictionary = _before[node.get_instance_id()]
|
|
805
|
+
var restored: Dictionary = restored_by_write.get_or_add(node.get_instance_id(), {})
|
|
780
806
|
for name: String in found[1]:
|
|
781
807
|
node.set(name, before.get(name, GdhHeadlessCheck.default_of(node, name)))
|
|
808
|
+
restored[name] = true
|
|
782
809
|
current = PackedScene.new()
|
|
783
810
|
var packing: Error = current.pack(root)
|
|
784
811
|
if packing != OK:
|
|
@@ -29,7 +29,8 @@ func add_animation_state(args: Dictionary) -> Dictionary:
|
|
|
29
29
|
# are in use in every state machine.
|
|
30
30
|
if sm.has_node(StringName(state_name)):
|
|
31
31
|
return scene.refuse("The state machine already has a state named %s." % state_name)
|
|
32
|
-
var
|
|
32
|
+
var reached: Node = anim_tree.get_node_or_null(anim_tree.anim_player)
|
|
33
|
+
var player: AnimationPlayer = reached as AnimationPlayer
|
|
33
34
|
var found: bool = player != null and player.has_animation(StringName(animation_name))
|
|
34
35
|
|
|
35
36
|
var anim_node: AnimationNodeAnimation = AnimationNodeAnimation.new()
|
|
@@ -57,7 +58,9 @@ func add_animation_state(args: Dictionary) -> Dictionary:
|
|
|
57
58
|
}
|
|
58
59
|
# Written all the same, as the editor writes one: a state machine is often laid out before its
|
|
59
60
|
# animations are made, and refusing it stopped a tree being built in that order.
|
|
60
|
-
if player
|
|
61
|
+
if player == null:
|
|
62
|
+
answer["animationMissing"] = GdhAnimationReads.no_player(str(anim_tree.anim_player), reached)
|
|
63
|
+
elif not found:
|
|
61
64
|
answer["animationMissing"] = GdhAnimationReads.missing_animation(
|
|
62
65
|
player, scene.path_of(player), animation_name
|
|
63
66
|
)
|
|
@@ -259,9 +259,13 @@ func read_animation_states(args: Dictionary) -> Dictionary:
|
|
|
259
259
|
if opened[1] == null:
|
|
260
260
|
return opened[2]
|
|
261
261
|
var anim_tree: AnimationTree = opened[1]
|
|
262
|
-
var
|
|
262
|
+
var reached: Node = anim_tree.get_node_or_null(anim_tree.anim_player)
|
|
263
|
+
var player: AnimationPlayer = reached as AnimationPlayer
|
|
263
264
|
var player_path: String = "" if player == null else scene.path_of(player)
|
|
264
|
-
|
|
265
|
+
var unplayed: String = GdhAnimationReads.no_player(str(anim_tree.anim_player), reached)
|
|
266
|
+
return _read_in(
|
|
267
|
+
scene, GdhAnimationReads.states(anim_tree, state_machine_path, player, player_path, unplayed)
|
|
268
|
+
)
|
|
265
269
|
|
|
266
270
|
|
|
267
271
|
# =============================================================================
|