gdharness 1.3.42 → 1.3.43
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 +62 -9
- package/build/godot/addons/auto_reload/auto_reload.gd +18 -19
- package/build/godot/addons/gdharness_editor/animation_reads.gd +55 -33
- package/build/godot/addons/gdharness_editor/bridge_client.gd +53 -58
- package/build/godot/addons/gdharness_editor/declared_values.gd +68 -32
- package/build/godot/addons/gdharness_editor/file_reads.gd +83 -42
- package/build/godot/addons/gdharness_editor/file_walk.gd +12 -5
- package/build/godot/addons/gdharness_editor/headless_check.gd +68 -44
- package/build/godot/addons/gdharness_editor/plugin.gd +2 -3
- package/build/godot/addons/gdharness_editor/property_paths.gd +22 -12
- package/build/godot/addons/gdharness_editor/property_values.gd +143 -78
- package/build/godot/addons/gdharness_editor/reading.gd +37 -12
- package/build/godot/addons/gdharness_editor/same_values.gd +4 -4
- package/build/godot/addons/gdharness_editor/scene_file.gd +109 -79
- package/build/godot/addons/gdharness_editor/scene_uids.gd +12 -6
- package/build/godot/addons/gdharness_editor/serialisation.gd +75 -51
- package/build/godot/addons/gdharness_editor/setting_reads.gd +7 -6
- package/build/godot/addons/gdharness_editor/tool_executor.gd +3 -6
- package/build/godot/addons/gdharness_editor/tools/animation_states.gd +37 -27
- package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +79 -49
- package/build/godot/addons/gdharness_editor/tools/animation_tracks.gd +70 -40
- package/build/godot/addons/gdharness_editor/tools/class_tools.gd +34 -30
- package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd +24 -22
- package/build/godot/addons/gdharness_editor/tools/navigation_bake.gd +49 -29
- package/build/godot/addons/gdharness_editor/tools/play_tools.gd +26 -21
- package/build/godot/addons/gdharness_editor/tools/profile_tools.gd +40 -40
- package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +166 -107
- package/build/godot/addons/gdharness_editor/tools/scene_groups.gd +16 -9
- package/build/godot/addons/gdharness_editor/tools/scene_kin.gd +68 -41
- package/build/godot/addons/gdharness_editor/tools/scene_paths.gd +35 -20
- package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +28 -13
- package/build/godot/addons/gdharness_editor/tools/scene_sharing.gd +12 -5
- package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +113 -67
- package/build/godot/addons/gdharness_editor/tools/script_paths.gd +20 -8
- package/build/godot/addons/gdharness_editor/tools/settings_tools.gd +11 -8
- package/build/godot/addons/gdharness_editor/tools/signal_tools.gd +47 -34
- package/build/godot/addons/gdharness_editor/tools/tileset_tools.gd +77 -50
- package/build/godot/addons/gdharness_editor/value_shapes.gd +5 -6
- package/build/godot/addons/gdharness_runtime/call_errors.gd +1 -2
- package/build/godot/addons/gdharness_runtime/declared_values.gd +68 -32
- package/build/godot/addons/gdharness_runtime/error_report.gd +1 -2
- package/build/godot/addons/gdharness_runtime/reading.gd +37 -12
- package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd +84 -63
- package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +149 -147
- package/build/godot/addons/gdharness_runtime/runtime_capture.gd +64 -42
- package/build/godot/addons/gdharness_runtime/runtime_changes.gd +184 -122
- package/build/godot/addons/gdharness_runtime/runtime_frames.gd +2 -2
- package/build/godot/addons/gdharness_runtime/runtime_hover.gd +24 -20
- package/build/godot/addons/gdharness_runtime/runtime_input.gd +134 -92
- package/build/godot/addons/gdharness_runtime/runtime_items.gd +29 -13
- package/build/godot/addons/gdharness_runtime/runtime_menus.gd +0 -1
- package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +34 -17
- package/build/godot/addons/gdharness_runtime/runtime_pad.gd +17 -13
- package/build/godot/addons/gdharness_runtime/runtime_paths.gd +84 -46
- package/build/godot/addons/gdharness_runtime/runtime_queries.gd +117 -79
- package/build/godot/addons/gdharness_runtime/runtime_says.gd +14 -17
- package/build/godot/addons/gdharness_runtime/runtime_screen.gd +23 -16
- package/build/godot/addons/gdharness_runtime/runtime_targets.gd +117 -66
- package/build/godot/addons/gdharness_runtime/runtime_touch.gd +15 -15
- package/build/godot/addons/gdharness_runtime/runtime_typing.gd +44 -27
- package/build/godot/addons/gdharness_runtime/runtime_values.gd +108 -73
- package/build/godot/addons/gdharness_runtime/runtime_waits.gd +111 -84
- package/build/godot/addons/gdharness_runtime/runtime_words.gd +10 -7
- package/build/godot/addons/gdharness_runtime/serialisation.gd +75 -51
- package/build/godot/addons/gdharness_runtime/value_shapes.gd +5 -6
- package/build/godot/addons/gdharness_tests/bench.gd +4 -5
- package/build/godot/addons/gdharness_tests/event.gd +10 -5
- package/build/godot/addons/gdharness_tests/share.gd +38 -18
- package/build/godot/addons/gdharness_tests/suites.gd +3 -3
- package/build/godot/addons/gdharness_tests/wait.gd +3 -2
- package/build/godot/loader/loader.gd +9 -9
- package/build/godot/operations/animation_reads.gd +55 -33
- package/build/godot/operations/audio_buses.gd +48 -19
- package/build/godot/operations/class_cache.gd +16 -11
- package/build/godot/operations/classdb_queries.gd +89 -44
- package/build/godot/operations/declared_values.gd +68 -32
- package/build/godot/operations/dependencies.gd +139 -93
- package/build/godot/operations/editor_tools.gd +9 -10
- package/build/godot/operations/export_presets.gd +100 -54
- package/build/godot/operations/file_reads.gd +83 -42
- package/build/godot/operations/file_walk.gd +12 -5
- package/build/godot/operations/gdscript_analysis.gd +86 -65
- package/build/godot/operations/gdscript_authoring.gd +83 -36
- package/build/godot/operations/godot_operations.gd +17 -11
- package/build/godot/operations/import_pipeline.gd +110 -59
- package/build/godot/operations/input_actions.gd +62 -39
- package/build/godot/operations/patterns.gd +3 -1
- package/build/godot/operations/plugins.gd +36 -16
- package/build/godot/operations/project_config.gd +53 -29
- package/build/godot/operations/project_diagnostics.gd +24 -11
- package/build/godot/operations/project_file.gd +16 -16
- package/build/godot/operations/project_validation.gd +71 -44
- package/build/godot/operations/property_paths.gd +22 -12
- package/build/godot/operations/property_values.gd +143 -78
- package/build/godot/operations/reading.gd +37 -12
- package/build/godot/operations/rename_checks.gd +2 -2
- package/build/godot/operations/resource_files.gd +11 -9
- package/build/godot/operations/same_values.gd +4 -4
- package/build/godot/operations/scene_connections.gd +27 -13
- package/build/godot/operations/script_check.gd +52 -49
- package/build/godot/operations/serialisation.gd +75 -51
- package/build/godot/operations/setting_reads.gd +7 -6
- package/build/godot/operations/value_shapes.gd +5 -6
- package/build/godot/tests/listed.gd +321 -268
- package/package.json +1 -1
|
@@ -22,7 +22,7 @@ func list_plugins(_params: Dictionary) -> Dictionary:
|
|
|
22
22
|
"addons_directory_exists": false,
|
|
23
23
|
"enabled_count": 0,
|
|
24
24
|
"disabled_count": 0,
|
|
25
|
-
"message": "No addons directory found in the project"
|
|
25
|
+
"message": "No addons directory found in the project",
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
var enabled_paths: Array[String] = _enabled_paths()
|
|
@@ -34,7 +34,7 @@ func list_plugins(_params: Dictionary) -> Dictionary:
|
|
|
34
34
|
var plugin_cfg_path: String = folder.path_join("plugin.cfg")
|
|
35
35
|
var name: String = folder.trim_prefix(addons_path)
|
|
36
36
|
var enabled: bool = plugin_cfg_path in enabled_paths
|
|
37
|
-
var plugin_info: Dictionary = {"name": name, "path": folder, "enabled": enabled}
|
|
37
|
+
var plugin_info: Dictionary = { "name": name, "path": folder, "enabled": enabled }
|
|
38
38
|
|
|
39
39
|
var plugin_config: ConfigFile = ConfigFile.new()
|
|
40
40
|
if plugin_config.load(plugin_cfg_path) == OK:
|
|
@@ -52,7 +52,7 @@ func list_plugins(_params: Dictionary) -> Dictionary:
|
|
|
52
52
|
"plugins": plugins,
|
|
53
53
|
"addons_directory_exists": true,
|
|
54
54
|
"enabled_count": enabled_count,
|
|
55
|
-
"disabled_count": plugins.size() - enabled_count
|
|
55
|
+
"disabled_count": plugins.size() - enabled_count,
|
|
56
56
|
}
|
|
57
57
|
# Enabled in the project with no plugin.cfg where the entry points: the editor reports each one
|
|
58
58
|
# as an error at every start and loads nothing for it.
|
|
@@ -99,7 +99,9 @@ func enable_plugin(params: Dictionary) -> Dictionary:
|
|
|
99
99
|
|
|
100
100
|
if plugin_cfg_path in enabled_paths:
|
|
101
101
|
return {
|
|
102
|
-
"plugin_name": plugin_name,
|
|
102
|
+
"plugin_name": plugin_name,
|
|
103
|
+
"action": "already_enabled",
|
|
104
|
+
"message": "Plugin is already enabled",
|
|
103
105
|
}
|
|
104
106
|
|
|
105
107
|
enabled_paths.append(plugin_cfg_path)
|
|
@@ -108,7 +110,9 @@ func enable_plugin(params: Dictionary) -> Dictionary:
|
|
|
108
110
|
return _log.failure("Failed to save project.godot: " + error_string(err))
|
|
109
111
|
|
|
110
112
|
var answer: Dictionary = {
|
|
111
|
-
"plugin_name": plugin_name,
|
|
113
|
+
"plugin_name": plugin_name,
|
|
114
|
+
"action": "enabled",
|
|
115
|
+
"enabled_plugins": _names_of(enabled_paths),
|
|
112
116
|
}
|
|
113
117
|
var unloadable: String = _why_not_loaded(plugin_cfg_path)
|
|
114
118
|
if not unloadable.is_empty():
|
|
@@ -116,9 +120,9 @@ func enable_plugin(params: Dictionary) -> Dictionary:
|
|
|
116
120
|
return answer
|
|
117
121
|
|
|
118
122
|
|
|
119
|
-
# What the editor finds wrong with the plugin at [param plugin_cfg_path] when it loads it, the
|
|
120
|
-
# EditorNode::set_addon_plugin_enabled makes, or "" when it would load. Written all the same,
|
|
121
|
-
# the script can be put right before the editor next starts.
|
|
123
|
+
# What the editor finds wrong with the plugin at [param plugin_cfg_path] when it loads it, the
|
|
124
|
+
# checks EditorNode::set_addon_plugin_enabled makes, or "" when it would load. Written all the same,
|
|
125
|
+
# since the script can be put right before the editor next starts.
|
|
122
126
|
static func _why_not_loaded(plugin_cfg_path: String) -> String:
|
|
123
127
|
var config: ConfigFile = ConfigFile.new()
|
|
124
128
|
if config.load(plugin_cfg_path) != OK:
|
|
@@ -134,11 +138,16 @@ static func _why_not_loaded(plugin_cfg_path: String) -> String:
|
|
|
134
138
|
# Loaded only to learn whether the editor could; what the engine says of a script that does not
|
|
135
139
|
# parse is about a file the answer does not describe.
|
|
136
140
|
printerr(GdhLog.ASIDE)
|
|
137
|
-
var script: Script = ResourceLoader.load(
|
|
141
|
+
var script: Script = ResourceLoader.load(
|
|
142
|
+
script_path, "Script", ResourceLoader.CACHE_MODE_IGNORE
|
|
143
|
+
)
|
|
138
144
|
printerr(GdhLog.RESUMED)
|
|
139
145
|
if script == null or script.get_instance_base_type() == &"":
|
|
140
146
|
return (
|
|
141
|
-
|
|
147
|
+
(
|
|
148
|
+
"%s does not compile, so the editor disables the plugin again at its next start."
|
|
149
|
+
% script_path
|
|
150
|
+
)
|
|
142
151
|
+ " script_diagnostics names the error."
|
|
143
152
|
)
|
|
144
153
|
if not ClassDB.is_parent_class(script.get_instance_base_type(), "EditorPlugin"):
|
|
@@ -161,7 +170,7 @@ func disable_plugin(params: Dictionary) -> Dictionary:
|
|
|
161
170
|
return {
|
|
162
171
|
"plugin_name": plugin_name,
|
|
163
172
|
"action": "already_disabled",
|
|
164
|
-
"message": "Plugin is not currently enabled"
|
|
173
|
+
"message": "Plugin is not currently enabled",
|
|
165
174
|
}
|
|
166
175
|
|
|
167
176
|
enabled_paths.erase(plugin_cfg_path)
|
|
@@ -169,7 +178,11 @@ func disable_plugin(params: Dictionary) -> Dictionary:
|
|
|
169
178
|
if err != OK:
|
|
170
179
|
return _log.failure("Failed to save project.godot: " + error_string(err))
|
|
171
180
|
|
|
172
|
-
return {
|
|
181
|
+
return {
|
|
182
|
+
"plugin_name": plugin_name,
|
|
183
|
+
"action": "disabled",
|
|
184
|
+
"enabled_plugins": _names_of(enabled_paths),
|
|
185
|
+
}
|
|
173
186
|
|
|
174
187
|
|
|
175
188
|
# Every entry in [editor_plugins], as the plugin.cfg path the editor stores. Paths rather than
|
|
@@ -180,13 +193,17 @@ func disable_plugin(params: Dictionary) -> Dictionary:
|
|
|
180
193
|
# hand-edited file can carry.
|
|
181
194
|
func _enabled_paths() -> Array[String]:
|
|
182
195
|
var paths: Array[String] = []
|
|
183
|
-
var enabled_value: Variant = ProjectSettings.get_setting(
|
|
196
|
+
var enabled_value: Variant = ProjectSettings.get_setting(
|
|
197
|
+
"editor_plugins/enabled", PackedStringArray()
|
|
198
|
+
)
|
|
184
199
|
if enabled_value is PackedStringArray:
|
|
185
200
|
var packed: PackedStringArray = enabled_value
|
|
186
201
|
paths.assign(packed)
|
|
187
202
|
elif enabled_value is String:
|
|
188
203
|
var listed: String = enabled_value
|
|
189
|
-
for m: RegExMatch in GdhPatterns.compiled("res://[^\"',)]+?plugin\\.cfg").search_all(
|
|
204
|
+
for m: RegExMatch in GdhPatterns.compiled("res://[^\"',)]+?plugin\\.cfg").search_all(
|
|
205
|
+
listed
|
|
206
|
+
):
|
|
190
207
|
paths.append(m.get_string())
|
|
191
208
|
return paths
|
|
192
209
|
|
|
@@ -197,7 +214,9 @@ static func _names_of(paths: Array[String]) -> Array[String]:
|
|
|
197
214
|
var names: Array[String] = []
|
|
198
215
|
for path: String in paths:
|
|
199
216
|
var inside: bool = path.begins_with("res://addons/") and path.ends_with("/plugin.cfg")
|
|
200
|
-
names.append(
|
|
217
|
+
names.append(
|
|
218
|
+
path.trim_prefix("res://addons/").trim_suffix("/plugin.cfg") if inside else path
|
|
219
|
+
)
|
|
201
220
|
return names
|
|
202
221
|
|
|
203
222
|
|
|
@@ -215,6 +234,7 @@ func _save_enabled_paths(paths: Array[String]) -> Error:
|
|
|
215
234
|
# Kept in an Array[String] and converted here, because appending to a packed array answers with
|
|
216
235
|
# whether it worked and a project holding return_value_discarded at error level will not compile
|
|
217
236
|
# a script that drops that answer. The conversion is what matters: an Array[String] handed to
|
|
218
|
-
# set_setting is written as Array[String]([...]), which the editor does not read as a plugin
|
|
237
|
+
# set_setting is written as Array[String]([...]), which the editor does not read as a plugin
|
|
238
|
+
# list.
|
|
219
239
|
ProjectSettings.set_setting("editor_plugins/enabled", PackedStringArray(paths))
|
|
220
240
|
return GdhProjectFile.save(["editor_plugins/enabled"])
|
|
@@ -100,9 +100,9 @@ func set_project_setting(params: Dictionary) -> Dictionary:
|
|
|
100
100
|
var in_file: bool = GdhProjectFile.sets(setting_path)
|
|
101
101
|
|
|
102
102
|
var wanted: int = _wanted_type(setting_path, old_value if had_value else null)
|
|
103
|
-
# A value of fields or a colour's html code is fitted as a property write fits it, so a value
|
|
104
|
-
# of them takes the other takes too. A number is left to the check below, which refuses one
|
|
105
|
-
# setting would cut where fitting it would cut it.
|
|
103
|
+
# A value of fields or a colour's html code is fitted as a property write fits it, so a value
|
|
104
|
+
# one of them takes the other takes too. A number is left to the check below, which refuses one
|
|
105
|
+
# the setting would cut where fitting it would cut it.
|
|
106
106
|
var final_value: Variant = _values.deserialize_value(value)
|
|
107
107
|
if final_value is Dictionary or (wanted == TYPE_COLOR and final_value is String):
|
|
108
108
|
final_value = _values.fitted(value, wanted)
|
|
@@ -110,8 +110,8 @@ func set_project_setting(params: Dictionary) -> Dictionary:
|
|
|
110
110
|
if not _converts_faithfully(final_value, wanted):
|
|
111
111
|
return _log.failure(_cannot_hold(setting_path, wanted, final_value))
|
|
112
112
|
final_value = type_convert(final_value, wanted)
|
|
113
|
-
# JSON carries every number as a float and a new setting has no declared type to fit one to, so
|
|
114
|
-
# whole number was saved as 800.0 beside an answer saying 800.
|
|
113
|
+
# JSON carries every number as a float and a new setting has no declared type to fit one to, so
|
|
114
|
+
# a whole number was saved as 800.0 beside an answer saying 800.
|
|
115
115
|
if not had_value and wanted == TYPE_NIL and final_value is float:
|
|
116
116
|
var number: float = final_value
|
|
117
117
|
if number == floorf(number) and absf(number) < 9.0e15:
|
|
@@ -132,7 +132,8 @@ func set_project_setting(params: Dictionary) -> Dictionary:
|
|
|
132
132
|
"saved": true,
|
|
133
133
|
}
|
|
134
134
|
# The same value in the same type is no change, and the file is left alone: a save rewrites it
|
|
135
|
-
# whole. The type is compared as well, so an int setting the file holds as 50.0 is still put
|
|
135
|
+
# whole. The type is compared as well, so an int setting the file holds as 50.0 is still put
|
|
136
|
+
# right.
|
|
136
137
|
if had_value and typeof(old_value) == typeof(final_value) and old_value == final_value:
|
|
137
138
|
answer["saved"] = false
|
|
138
139
|
answer["unchanged"] = true
|
|
@@ -173,7 +174,9 @@ func set_project_setting(params: Dictionary) -> Dictionary:
|
|
|
173
174
|
)
|
|
174
175
|
var made: Array[String] = _translations_made_by(missing)
|
|
175
176
|
if not made.is_empty():
|
|
176
|
-
said += (
|
|
177
|
+
said += (
|
|
178
|
+
"; project_import reimport makes the translation files from " + ", ".join(made)
|
|
179
|
+
)
|
|
177
180
|
answer["note"] = (str(answer["note"]) + " " if answer.has("note") else "") + said + "."
|
|
178
181
|
ProjectSettings.set_setting(setting_path, final_value)
|
|
179
182
|
var err: Error = GdhProjectFile.save([setting_path])
|
|
@@ -193,7 +196,10 @@ func set_project_setting(params: Dictionary) -> Dictionary:
|
|
|
193
196
|
)
|
|
194
197
|
)
|
|
195
198
|
answer["overridesNote"] = (
|
|
196
|
-
|
|
199
|
+
(
|
|
200
|
+
"Not every build reads what was written: %s. Set or unset an override to change "
|
|
201
|
+
+ "what its builds read."
|
|
202
|
+
)
|
|
197
203
|
% "; ".join(parts)
|
|
198
204
|
)
|
|
199
205
|
return answer
|
|
@@ -238,8 +244,9 @@ static func _translations_made_by(missing: Array[String]) -> Array[String]:
|
|
|
238
244
|
return sources
|
|
239
245
|
|
|
240
246
|
|
|
241
|
-
# Takes a setting's line out of project.godot, so the engine's default holds again, or nothing at
|
|
242
|
-
# for one the engine does not declare: the way back from a set, which writes a misspelt name as
|
|
247
|
+
# Takes a setting's line out of project.godot, so the engine's default holds again, or nothing at
|
|
248
|
+
# all for one the engine does not declare: the way back from a set, which writes a misspelt name as
|
|
249
|
+
# given.
|
|
243
250
|
func unset_project_setting(params: Dictionary) -> Dictionary:
|
|
244
251
|
var setting_path: String = str(params.get("setting", ""))
|
|
245
252
|
if setting_path.is_empty():
|
|
@@ -256,7 +263,9 @@ func unset_project_setting(params: Dictionary) -> Dictionary:
|
|
|
256
263
|
if not held or not GdhProjectFile.sets(setting_path):
|
|
257
264
|
answer["removed"] = false
|
|
258
265
|
answer["saved"] = false
|
|
259
|
-
answer["note"] =
|
|
266
|
+
answer["note"] = (
|
|
267
|
+
"project.godot does not set %s, so there was nothing to take out." % setting_path
|
|
268
|
+
)
|
|
260
269
|
var near: PackedStringArray = PackedStringArray() if held else _settings_near(setting_path)
|
|
261
270
|
if not near.is_empty():
|
|
262
271
|
answer["note"] += (
|
|
@@ -265,8 +274,8 @@ func unset_project_setting(params: Dictionary) -> Dictionary:
|
|
|
265
274
|
)
|
|
266
275
|
return _with_what_holds(answer, setting_path)
|
|
267
276
|
answer["old_value"] = _values.serialize_value(value)
|
|
268
|
-
# The default rather than null for a setting the engine declares: null takes the declaration
|
|
269
|
-
# as well, and a value at its default is left out of the file all the same.
|
|
277
|
+
# The default rather than null for a setting the engine declares: null takes the declaration
|
|
278
|
+
# away as well, and a value at its default is left out of the file all the same.
|
|
270
279
|
ProjectSettings.set_setting(setting_path, default_value)
|
|
271
280
|
var err: Error = GdhProjectFile.save([setting_path])
|
|
272
281
|
if err != OK:
|
|
@@ -340,7 +349,10 @@ static func _cannot_hold(setting_path: String, wanted: int, value: Variant) -> S
|
|
|
340
349
|
var declared: String = "%s is declared as %s" % [setting_path, type_string(wanted)]
|
|
341
350
|
var cost: String = " Setting it would save a different value than the one asked for."
|
|
342
351
|
if wanted == TYPE_INT and typeof(value) == TYPE_FLOAT:
|
|
343
|
-
return
|
|
352
|
+
return (
|
|
353
|
+
"%s, which holds whole numbers, and %s would be cut to fit.%s"
|
|
354
|
+
% [declared, str(value), cost]
|
|
355
|
+
)
|
|
344
356
|
if wanted in numbers and typeof(value) in numbers:
|
|
345
357
|
return "%s, and %s is not the same number as one.%s" % [declared, str(value), cost]
|
|
346
358
|
var given: String = type_string(typeof(value))
|
|
@@ -348,8 +360,8 @@ static func _cannot_hold(setting_path: String, wanted: int, value: Variant) -> S
|
|
|
348
360
|
return "%s, and %s (%s) cannot become one.%s" % [declared, JSON.stringify(value), given, remedy]
|
|
349
361
|
|
|
350
362
|
|
|
351
|
-
## Why [param tagged], a value whose tag could not be built, was not written to
|
|
352
|
-
## and how a value of that tag is written.
|
|
363
|
+
## Why [param tagged], a value whose tag could not be built, was not written to
|
|
364
|
+
## [param setting_path], and how a value of that tag is written.
|
|
353
365
|
static func _unbuilt(setting_path: String, tagged: Dictionary) -> String:
|
|
354
366
|
var tag: String = str(tagged["_type"])
|
|
355
367
|
var refused: String = (
|
|
@@ -362,7 +374,9 @@ static func _unbuilt(setting_path: String, tagged: Dictionary) -> String:
|
|
|
362
374
|
var keys: Array = shapes[0]
|
|
363
375
|
var parts: Array[String] = ['"_type": "%s"' % tag]
|
|
364
376
|
for key: Variant in keys:
|
|
365
|
-
parts.append(
|
|
377
|
+
parts.append(
|
|
378
|
+
'"%s": %s' % [key, "[...]" if tag.begins_with("Packed") and key == "value" else "..."]
|
|
379
|
+
)
|
|
366
380
|
return refused + " One is written as {%s}." % ", ".join(parts)
|
|
367
381
|
|
|
368
382
|
|
|
@@ -376,11 +390,14 @@ func add_autoload(params: Dictionary) -> Dictionary:
|
|
|
376
390
|
# every start. `enabled: false` used to write the entry without its asterisk and answer that it
|
|
377
391
|
# was disabled, and the autoload ran all the same.
|
|
378
392
|
if not GdhRead.as_bool(params.get("enabled", true), true):
|
|
379
|
-
return
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
393
|
+
return (
|
|
394
|
+
_log
|
|
395
|
+
. failure(
|
|
396
|
+
(
|
|
397
|
+
"An autoload cannot be added disabled: Godot loads every autoload in the list "
|
|
398
|
+
+ "at every start. global: false keeps its name out of the global scope and "
|
|
399
|
+
+ "still loads it; remove_autoload is what stops it loading"
|
|
400
|
+
)
|
|
384
401
|
)
|
|
385
402
|
)
|
|
386
403
|
|
|
@@ -414,7 +431,7 @@ func add_autoload(params: Dictionary) -> Dictionary:
|
|
|
414
431
|
"enabled": true,
|
|
415
432
|
"global": global,
|
|
416
433
|
"action": "unchanged",
|
|
417
|
-
"saved": false
|
|
434
|
+
"saved": false,
|
|
418
435
|
}
|
|
419
436
|
ProjectSettings.set_setting(setting, entry)
|
|
420
437
|
var err: Error = GdhProjectFile.save([setting])
|
|
@@ -452,7 +469,10 @@ static func _autoload_name_refusal(name: String) -> String:
|
|
|
452
469
|
if reason.is_empty():
|
|
453
470
|
return ""
|
|
454
471
|
return (
|
|
455
|
-
|
|
472
|
+
(
|
|
473
|
+
"%s cannot name an autoload: %s. Nothing was written; the editor's Autoload tab "
|
|
474
|
+
+ "refuses it too."
|
|
475
|
+
)
|
|
456
476
|
% [JSON.stringify(name), reason]
|
|
457
477
|
)
|
|
458
478
|
|
|
@@ -473,7 +493,7 @@ func remove_autoload(params: Dictionary) -> Dictionary:
|
|
|
473
493
|
if err != OK:
|
|
474
494
|
return _log.failure("Failed to save project.godot: " + error_string(err))
|
|
475
495
|
|
|
476
|
-
return {"name": name, "removed": true, "old_path": old_value.trim_prefix("*")}
|
|
496
|
+
return { "name": name, "removed": true, "old_path": old_value.trim_prefix("*") }
|
|
477
497
|
|
|
478
498
|
|
|
479
499
|
# List all autoload singletons
|
|
@@ -500,7 +520,7 @@ func list_autoloads(_params: Dictionary) -> Dictionary:
|
|
|
500
520
|
}
|
|
501
521
|
autoloads.append(autoload_info)
|
|
502
522
|
|
|
503
|
-
return {"autoloads": autoloads, "count": autoloads.size()}
|
|
523
|
+
return { "autoloads": autoloads, "count": autoloads.size() }
|
|
504
524
|
|
|
505
525
|
|
|
506
526
|
# Set the main scene
|
|
@@ -514,7 +534,9 @@ func set_main_scene(params: Dictionary) -> Dictionary:
|
|
|
514
534
|
|
|
515
535
|
if not FileAccess.file_exists(scene_path):
|
|
516
536
|
return _log.failure(
|
|
517
|
-
GdhFileWalk.new().with_nearest_files(
|
|
537
|
+
GdhFileWalk.new().with_nearest_files(
|
|
538
|
+
"Scene file does not exist: " + scene_path, scene_path
|
|
539
|
+
)
|
|
518
540
|
)
|
|
519
541
|
|
|
520
542
|
# The engine starts the game by instancing the main scene, so a script or any other resource set
|
|
@@ -526,7 +548,9 @@ func set_main_scene(params: Dictionary) -> Dictionary:
|
|
|
526
548
|
"%s is %s, not a scene, and the main scene has to be one"
|
|
527
549
|
% [scene_path, "a " + kind if not kind.is_empty() else "no resource the engine loads"]
|
|
528
550
|
)
|
|
529
|
-
return _log.failure(
|
|
551
|
+
return _log.failure(
|
|
552
|
+
GdhFileWalk.new().with_nearest_files(said, scene_path.get_basename() + ".tscn")
|
|
553
|
+
)
|
|
530
554
|
|
|
531
555
|
var old_main_scene: String = str(ProjectSettings.get_setting("application/run/main_scene", ""))
|
|
532
556
|
|
|
@@ -536,4 +560,4 @@ func set_main_scene(params: Dictionary) -> Dictionary:
|
|
|
536
560
|
if err != OK:
|
|
537
561
|
return _log.failure("Failed to save project settings: " + str(err))
|
|
538
562
|
|
|
539
|
-
return {"old_main_scene": old_main_scene, "new_main_scene": scene_path, "saved": true}
|
|
563
|
+
return { "old_main_scene": old_main_scene, "new_main_scene": scene_path, "saved": true }
|
|
@@ -40,14 +40,17 @@ func get_project_health(params: Dictionary) -> Dictionary:
|
|
|
40
40
|
# failed this check and lost points, while Godot's own guidance is to keep a scene's files
|
|
41
41
|
# together by feature, so the check failed projects for following the engine's advice.
|
|
42
42
|
|
|
43
|
-
checks["structure"] = {
|
|
43
|
+
checks["structure"] = {
|
|
44
|
+
"name": "Project Structure", "passed": details.is_empty(), "details": details,
|
|
45
|
+
}
|
|
44
46
|
|
|
45
47
|
# 2. Resource Check
|
|
46
48
|
if "resources" in check_categories:
|
|
47
49
|
var details: Array[String] = []
|
|
48
50
|
|
|
49
|
-
# Every format the engine imports, the list the import status reads: five of them were
|
|
50
|
-
# here, so a project of glTF models, fonts and WebP textures had nothing to
|
|
51
|
+
# Every format the engine imports, the list the import status reads: five of them were
|
|
52
|
+
# checked here, so a project of glTF models, fonts and WebP textures had nothing to
|
|
53
|
+
# reimport.
|
|
51
54
|
var resources: Array[String] = _files.find_files_with_extensions(
|
|
52
55
|
"res://", GdhImportPipeline.IMPORTABLE_EXTENSIONS
|
|
53
56
|
)
|
|
@@ -68,7 +71,7 @@ func get_project_health(params: Dictionary) -> Dictionary:
|
|
|
68
71
|
"details": details,
|
|
69
72
|
# What the check read: files the engine imports. A .tres is a resource and was counted
|
|
70
73
|
# under this name as none, beside a project holding one.
|
|
71
|
-
"importable_files": resources.size()
|
|
74
|
+
"importable_files": resources.size(),
|
|
72
75
|
}
|
|
73
76
|
|
|
74
77
|
# 3. Scripts Check
|
|
@@ -106,7 +109,7 @@ func get_project_health(params: Dictionary) -> Dictionary:
|
|
|
106
109
|
"name": "Scripts",
|
|
107
110
|
"passed": details.is_empty(),
|
|
108
111
|
"details": details,
|
|
109
|
-
"total_scripts": script_files.size()
|
|
112
|
+
"total_scripts": script_files.size(),
|
|
110
113
|
}
|
|
111
114
|
if compiled.has("checked"):
|
|
112
115
|
scripts["compiled"] = GdhRead.as_int(compiled["checked"])
|
|
@@ -123,14 +126,18 @@ func get_project_health(params: Dictionary) -> Dictionary:
|
|
|
123
126
|
for entry: Dictionary in GdhInputActions.new(_log).undefined_in_scripts():
|
|
124
127
|
details.append(GdhInputActions.undefined_line(entry))
|
|
125
128
|
deductions += 5
|
|
126
|
-
checks["references"] = {
|
|
129
|
+
checks["references"] = {
|
|
130
|
+
"name": "References", "passed": details.is_empty(), "details": details,
|
|
131
|
+
}
|
|
127
132
|
|
|
128
133
|
# 4. Scenes Check
|
|
129
134
|
if "scenes" in check_categories:
|
|
130
135
|
var details: Array[String] = []
|
|
131
136
|
|
|
132
137
|
# Binary scenes too, which a project may save instead and which counted as none.
|
|
133
|
-
var scene_files: Array[String] = _files.find_files_with_extensions(
|
|
138
|
+
var scene_files: Array[String] = _files.find_files_with_extensions(
|
|
139
|
+
"res://", ["tscn", "scn"]
|
|
140
|
+
)
|
|
134
141
|
if scene_files.size() == 0:
|
|
135
142
|
details.append("No scene files found in project")
|
|
136
143
|
deductions += 5
|
|
@@ -142,7 +149,7 @@ func get_project_health(params: Dictionary) -> Dictionary:
|
|
|
142
149
|
"name": "Scenes",
|
|
143
150
|
"passed": details.is_empty(),
|
|
144
151
|
"details": details,
|
|
145
|
-
"total_scenes": scene_files.size()
|
|
152
|
+
"total_scenes": scene_files.size(),
|
|
146
153
|
}
|
|
147
154
|
|
|
148
155
|
# 5. Configuration Check
|
|
@@ -162,7 +169,9 @@ func get_project_health(params: Dictionary) -> Dictionary:
|
|
|
162
169
|
details.append("No project name set")
|
|
163
170
|
deductions += 2
|
|
164
171
|
|
|
165
|
-
checks["config"] = {
|
|
172
|
+
checks["config"] = {
|
|
173
|
+
"name": "Configuration", "passed": details.is_empty(), "details": details,
|
|
174
|
+
}
|
|
166
175
|
|
|
167
176
|
var score: int = maxi(0, 100 - deductions)
|
|
168
177
|
|
|
@@ -193,7 +202,11 @@ func get_project_health(params: Dictionary) -> Dictionary:
|
|
|
193
202
|
var check: Dictionary = checks[category]
|
|
194
203
|
var found: Array[String] = check["details"]
|
|
195
204
|
for detail: String in found:
|
|
196
|
-
issues.append({"check": category, "detail": detail})
|
|
205
|
+
issues.append({ "check": category, "detail": detail })
|
|
197
206
|
return {
|
|
198
|
-
"score": score,
|
|
207
|
+
"score": score,
|
|
208
|
+
"grade": grade,
|
|
209
|
+
"checks": checks,
|
|
210
|
+
"issues": issues,
|
|
211
|
+
"recommendations": recommendations,
|
|
199
212
|
}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
extends RefCounted
|
|
2
|
-
|
|
3
2
|
## project.godot written through the engine's own save, in the order the file already held.
|
|
4
3
|
##
|
|
5
4
|
## The engine writes each section's keys in the order it registered them, and an engine running a
|
|
6
5
|
## script registers them in another order than the editor does, so a one-setting change moved lines
|
|
7
|
-
## nobody touched across several sections and a commit of it read as a rewrite. The save is still
|
|
8
|
-
## engine's, for what only it gets right: the header and the text of each value the call
|
|
9
|
-
## The order is taken from the file as it was, and so is every line of a key the call did
|
|
10
|
-
## because the engine writes its settings as it holds them rather than as the file had
|
|
11
|
-
## leaves out each key at its default, so a project holding `unsafe_call_argument=0` on
|
|
12
|
-
## the line to a change of another key. It writes a dictionary with its keys sorted, so
|
|
13
|
-
## session hooks, which run in the order listed, changed order. And it writes what a
|
|
6
|
+
## nobody touched across several sections and a commit of it read as a rewrite. The save is still
|
|
7
|
+
## the engine's, for what only it gets right: the header and the text of each value the call
|
|
8
|
+
## changed. The order is taken from the file as it was, and so is every line of a key the call did
|
|
9
|
+
## not change, because the engine writes its settings as it holds them rather than as the file had
|
|
10
|
+
## them. It leaves out each key at its default, so a project holding `unsafe_call_argument=0` on
|
|
11
|
+
## purpose lost the line to a change of another key. It writes a dictionary with its keys sorted, so
|
|
12
|
+
## gdUnit4's session hooks, which run in the order listed, changed order. And it writes what a
|
|
14
13
|
## `project_settings_override` file laid over the project, so a player's window mode in the user
|
|
15
14
|
## directory became the game's default.
|
|
16
15
|
|
|
@@ -42,8 +41,8 @@ static func save(changed: PackedStringArray) -> Error:
|
|
|
42
41
|
## [param before] with the lines of the settings in [param changed] as [param written] has them: one
|
|
43
42
|
## the engine wrote goes in its place, or where the engine put it relative to its neighbours when it
|
|
44
43
|
## is new, and one the engine left out leaves the file. Every other line is [param before]'s, in its
|
|
45
|
-
## place, and a key the engine wrote that the file did not hold and the call did not change stays
|
|
46
|
-
## The header is [param written]'s.
|
|
44
|
+
## place, and a key the engine wrote that the file did not hold and the call did not change stays
|
|
45
|
+
## out. The header is [param written]'s.
|
|
47
46
|
static func in_order_of(before: String, written: String, changed: PackedStringArray) -> String:
|
|
48
47
|
var old: Dictionary = _parsed(before)
|
|
49
48
|
var fresh: Dictionary = _parsed(written)
|
|
@@ -113,8 +112,8 @@ static func in_order_of(before: String, written: String, changed: PackedStringAr
|
|
|
113
112
|
fresh_keys[name].append(str(entry["key"]))
|
|
114
113
|
|
|
115
114
|
# The blank lines closing a section belong to its place in the file rather than to the section,
|
|
116
|
-
# so the last one keeps the ending the engine gave the file wherever it moved from. A section
|
|
117
|
-
# back sits between two others, which the engine parts with a blank line.
|
|
115
|
+
# so the last one keeps the ending the engine gave the file wherever it moved from. A section
|
|
116
|
+
# put back sits between two others, which the engine parts with a blank line.
|
|
118
117
|
var names: Array[String] = _merged(old_names, fresh_names)
|
|
119
118
|
var tails: Array[String] = []
|
|
120
119
|
for section: Dictionary in fresh_sections:
|
|
@@ -181,7 +180,8 @@ static func _merged(held: Array[String], wanted: Array[String]) -> Array[String]
|
|
|
181
180
|
|
|
182
181
|
|
|
183
182
|
## [param text] as a preamble (the header and anything before the first section) and its sections,
|
|
184
|
-
## each with its header line and the blank lines after it, its entries, and the blank lines closing
|
|
183
|
+
## each with its header line and the blank lines after it, its entries, and the blank lines closing
|
|
184
|
+
## it.
|
|
185
185
|
static func _parsed(text: String) -> Dictionary:
|
|
186
186
|
var preamble: String = ""
|
|
187
187
|
var sections: Array[Dictionary] = []
|
|
@@ -193,7 +193,7 @@ static func _parsed(text: String) -> Dictionary:
|
|
|
193
193
|
if not current.is_empty():
|
|
194
194
|
_close(current, body)
|
|
195
195
|
sections.append(current)
|
|
196
|
-
current = {"name": stripped.substr(1, stripped.length() - 2), "head": line}
|
|
196
|
+
current = { "name": stripped.substr(1, stripped.length() - 2), "head": line }
|
|
197
197
|
body = []
|
|
198
198
|
elif current.is_empty():
|
|
199
199
|
preamble += line
|
|
@@ -204,7 +204,7 @@ static func _parsed(text: String) -> Dictionary:
|
|
|
204
204
|
if not current.is_empty():
|
|
205
205
|
_close(current, body)
|
|
206
206
|
sections.append(current)
|
|
207
|
-
return {"preamble": preamble, "sections": sections}
|
|
207
|
+
return { "preamble": preamble, "sections": sections }
|
|
208
208
|
|
|
209
209
|
|
|
210
210
|
## Fills in [param section]'s entries and closing blank lines from the lines after its head. A blank
|
|
@@ -218,7 +218,7 @@ static func _close(section: Dictionary, body: Array[String]) -> void:
|
|
|
218
218
|
for line: String in body:
|
|
219
219
|
var stripped: String = line.strip_edges()
|
|
220
220
|
if entries.is_empty() or not (stripped.is_empty() or stripped.begins_with(";")):
|
|
221
|
-
entries.append({"key": _key_of(line), "text": line})
|
|
221
|
+
entries.append({ "key": _key_of(line), "text": line })
|
|
222
222
|
else:
|
|
223
223
|
var last: Dictionary = entries[entries.size() - 1]
|
|
224
224
|
last["text"] = str(last["text"]) + line
|