Created
December 13, 2023 21:27
-
-
Save Jayman2000/c153522e40fe9b50935c8ea68c14f334 to your computer and use it in GitHub Desktop.
Force a new version of Godot 3 to make any automatic changes that it’s going to make.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 🅭🄍1.0 This file is dedicated to the public domain using the CC0 1.0 Universal | |
# Public Domain Dedication <https://creativecommons.org/publicdomain/zero/1.0/>. | |
tool | |
extends EditorScript | |
signal finished_updating_scene_files | |
# If this was Godot 4, I would probably just use the built-in Callable type | |
# instead of creating my own. | |
class ActionToTakeOnPath extends Reference: | |
# Returns whether or not the action was successful. | |
func run( | |
_path: String, | |
_is_dir: bool, | |
_editor_interface: EditorInterface | |
): | |
push_error("ActionToTakeOnPath shouldn’t be used directly. Only subclasses of it should be used.") | |
return false | |
class DeletePath extends ActionToTakeOnPath: | |
func run( | |
path: String, | |
_is_dir: bool, | |
_editor_interface: EditorInterface | |
): | |
var successful := true | |
var error_code: int = Directory.new().remove(path) | |
if error_code != OK: | |
push_error("Failed to delete “%s”. Error code: %s" % [path, error_code]) | |
successful = false | |
return successful | |
class PotentiallyOpenPathAsScene extends ActionToTakeOnPath: | |
func run( | |
path: String, | |
is_dir: bool, | |
editor_interface: EditorInterface | |
): | |
var successful := true | |
if not is_dir: | |
var is_editable_resource = ResourceLoader.exists(path) | |
if is_editable_resource: | |
var resource : Resource = load(path) | |
if resource != null: | |
if resource is PackedScene: | |
editor_interface.open_scene_from_path(resource.resource_path) | |
# We need to wait a frame or else the | |
# EditorInterface will ignore all but one of our | |
# open_scene_from_path() calls. | |
var tree = editor_interface.get_base_control().get_tree() | |
yield(tree, "idle_frame") | |
else: | |
push_error("Failed to load “%s” as a resource." % [path]) | |
successful = false | |
return successful | |
func get_editors_tree() -> SceneTree: | |
return get_editor_interface().get_base_control().get_tree() | |
func fix_result(result) -> bool: | |
if result is bool: | |
return result | |
else: | |
push_error("result wasn’t a valid type. This should never happen.") | |
return false | |
func act_on_paths_in_dir_recursively( | |
dir_path: String, | |
action: ActionToTakeOnPath, | |
skip_hidden: bool | |
): | |
var successful := true | |
if not dir_path.ends_with("/"): | |
dir_path += "/" | |
var dir := Directory.new() | |
var error_code : int = dir.open(dir_path) | |
if error_code == OK: | |
error_code = dir.list_dir_begin(true, skip_hidden) | |
if error_code == OK: | |
var name : String = dir.get_next() | |
while name != "": | |
var path: String = dir_path + name | |
if dir.current_is_dir(): | |
if not act_on_paths_in_dir_recursively(path, action, skip_hidden): | |
successful = false | |
var result = action.run(path, dir.current_is_dir(), get_editor_interface()) | |
if result is GDScriptFunctionState: | |
result = yield(result, "completed") | |
if not fix_result(result): | |
successful = false | |
name = dir.get_next() | |
else: | |
push_error("Failed to list the contents of “%s”. Error code: %s" % [dir_path, error_code]) | |
successful = false | |
else: | |
push_error("Failed to open “%s” as a directory. Error code: %s" % [dir_path, error_code]) | |
successful = false | |
dir.list_dir_end() | |
return successful | |
func update_dot_import_files() -> void: | |
print("Updating .import files…") | |
print("Note: This will probably produce a bunch of errors about missing files. You can ignore those errors.") | |
var result = act_on_paths_in_dir_recursively("res://.import", DeletePath.new(), false) | |
if result: | |
# Thanks, Gnumaru for this workaround: | |
# <https://github.com/godotengine/godot-proposals/issues/1615> | |
# Reimport everything | |
OS.window_minimized = true | |
for i in 2: | |
yield(get_editors_tree(), "idle_frame") | |
OS.move_window_to_foreground() | |
print("Finished updating .import files.") | |
else: | |
push_error("Failed to update .import files.") | |
emit_signal("finished_updating_scene_files") | |
func update_scene_files(_resources = null) -> void: | |
print("Updating scene files…") | |
if act_on_paths_in_dir_recursively("res://", PotentiallyOpenPathAsScene.new(), true): | |
# If we were using Godot 4, then I would just do this: | |
#get_editor_interface().save_all_scenes() | |
# Since we’re in Godot 3, I have to tell the user to do that manually: | |
print("Please click Scene > Save All Scenes.") | |
else: | |
push_error("Failed to update .import files.") | |
emit_signal("finished_updating_scene_files") | |
func _run() -> void: | |
var error_code = get_editor_interface().get_resource_filesystem().connect( | |
"resources_reimported", | |
self, | |
"update_scene_files", | |
[], | |
CONNECT_ONESHOT | |
) | |
if error_code == OK: | |
var result = update_dot_import_files() | |
if result is GDScriptFunctionState: | |
yield(result, "completed") | |
else: | |
push_error("Failed to connect EditorFileSystem’s resources_reimported signal. This should never happen.") | |
# When Objects are freed, any signals that are connected to it are | |
# disconnected. It looks like this Script gets freed shortly after _run() | |
# finishes executing. Without this next line of code, this Script will get | |
# freed before the connection that I made earlier is triggered. | |
yield(self, "finished_updating_scene_files") | |
# This is a workaround for this issue: | |
# <https://github.com/godotengine/godot/issues/71998> | |
yield(get_editors_tree(), "idle_frame") | |
print("Done!") | |
func print_test(whatever): | |
print(whatever) | |
emit_signal("finished_updating_scene_files") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment