diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..eb6a43b1 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,11 @@ +# This file contains a list of Git commit hashes that should be hidden from the +# regular Git history. Typically, this includes commits involving mass auto-formatting +# or other normalizations. Commit hashes *must* use the full 40-character notation. +# To apply the ignore list in your local Git client, you must run: +# +# git config blame.ignoreRevsFile .git-blame-ignore-revs +# +# This file is automatically used by GitHub.com's blame view. + +# Format GDScript files +fdc1edd4d231782b51c5ae2a1e4f4a027a370b9f diff --git a/game/addons/openvic-plugin/ReleaseExportEditorPlugin.gd b/game/addons/openvic-plugin/ReleaseExportEditorPlugin.gd index 0d7731b4..80022f45 100644 --- a/game/addons/openvic-plugin/ReleaseExportEditorPlugin.gd +++ b/game/addons/openvic-plugin/ReleaseExportEditorPlugin.gd @@ -1,35 +1,42 @@ extends EditorExportPlugin -var _repo_hash : StringName = "0000000000000000000000000000000000000000" -var _repo_short_hash : StringName = "0000000" -var _repo_tag : StringName = "" -var _repo_release_name : StringName = "" +var _repo_hash: StringName = "0000000000000000000000000000000000000000" +var _repo_short_hash: StringName = "0000000" +var _repo_tag: StringName = "" +var _repo_release_name: StringName = "" + func _get_name(): return "OpenVic-ReleaseExportEditorPlugin" + func _export_file(path: String, type: String, features: PackedStringArray) -> void: - if path != "res://src/GIT_INFO.gd": return - var GitInfoScript : String = "" + if path != "res://src/GIT_INFO.gd": + return + var GitInfoScript: String = "" _get_commit_long() _get_commit_short() _get_tag() _get_release_name() GitInfoScript = "class_name _GIT_INFO_\nextends RefCounted\n\n" - GitInfoScript += "const commit_hash : StringName = &\""+ _repo_hash +"\"\n" - GitInfoScript += "const short_hash : StringName = &\""+ _repo_short_hash +"\"\n" - GitInfoScript += "const tag : StringName = &\""+ _repo_tag +"\"\n" - GitInfoScript += "const release_name : StringName = &\""+ _repo_release_name +"\"\n" + GitInfoScript += 'const commit_hash : StringName = &"' + _repo_hash + '"\n' + GitInfoScript += 'const short_hash : StringName = &"' + _repo_short_hash + '"\n' + GitInfoScript += 'const tag : StringName = &"' + _repo_tag + '"\n' + GitInfoScript += 'const release_name : StringName = &"' + _repo_release_name + '"\n' add_file(path, GitInfoScript.to_ascii_buffer(), false) skip() + # Based on # https://github.com/godotengine/godot/blob/6ef2f358c741c993b5cdc9680489e2c4f5da25cc/methods.py#L102-L133 # REQUIREMENTS: # * UIFUN-298 -var _cached_hash : StringName = &"" +var _cached_hash: StringName = &"" + + func _get_commit_hash() -> StringName: - if not _cached_hash.is_empty(): return _cached_hash + if not _cached_hash.is_empty(): + return _cached_hash var git_hash := OS.get_environment("OPENVIC_COMMIT") if not git_hash.is_empty(): @@ -44,7 +51,9 @@ func _get_commit_hash() -> StringName: git_folder = module_folder.substr(8) if FileAccess.file_exists(git_folder.path_join("HEAD")): - var head := FileAccess.open(git_folder.path_join("HEAD"), FileAccess.READ).get_line().strip_edges() + var head := ( + FileAccess.open(git_folder.path_join("HEAD"), FileAccess.READ).get_line().strip_edges() + ) if head.begins_with("ref: "): var ref := head.substr(5) var parts := git_folder.split("/") @@ -55,8 +64,11 @@ func _get_commit_hash() -> StringName: if FileAccess.file_exists(head): git_hash = FileAccess.open(head, FileAccess.READ).get_line().strip_edges() elif FileAccess.file_exists(packedrefs): - for line in FileAccess.open(packedrefs, FileAccess.READ).get_as_text().split("\n", false): - if line.begins_with("#"): continue + for line in FileAccess.open(packedrefs, FileAccess.READ).get_as_text().split( + "\n", false + ): + if line.begins_with("#"): + continue var line_split := line.split(" ") var line_hash := line_split[0] var line_ref = line_split[1] @@ -70,10 +82,11 @@ func _get_commit_hash() -> StringName: return git_hash + # REQUIREMENTS: # * UIFUN-296 func _try_get_tag() -> StringName: - var result : StringName = OS.get_environment("OPENVIC_TAG") + var result: StringName = OS.get_environment("OPENVIC_TAG") if result.is_empty(): var git_output := [] if OS.execute("git", ["describe", "--tags", "--abbrev=0"], git_output) == -1: @@ -82,30 +95,34 @@ func _try_get_tag() -> StringName: result = git_output[0].trim_suffix("\n") return result + func _get_commit_long(): var result := _get_commit_hash() if not result.is_empty(): _repo_hash = result print("Hash: " + _repo_hash) + # REQUIREMENTS: # * UIFUN-300 func _get_commit_short(): - var result := _get_commit_hash().substr(0,7) + var result := _get_commit_hash().substr(0, 7) if not result.is_empty(): _repo_short_hash = result print("Short Hash: " + _repo_short_hash) + func _get_tag(): var result := _try_get_tag() if not result.is_empty(): _repo_tag = result print("Tag: " + _repo_tag) + # REQUIREMENTS: # * UIFUN-295 func _get_release_name(): - var result : StringName = OS.get_environment("OPENVIC_RELEASE") + var result: StringName = OS.get_environment("OPENVIC_RELEASE") if result.is_empty(): result = _try_get_tag() if not result.is_empty(): diff --git a/game/addons/openvic-plugin/openvic-plugin.gd b/game/addons/openvic-plugin/openvic-plugin.gd index dec03121..cd5e9028 100644 --- a/game/addons/openvic-plugin/openvic-plugin.gd +++ b/game/addons/openvic-plugin/openvic-plugin.gd @@ -1,9 +1,12 @@ @tool extends EditorPlugin -const ReleaseExportEditorPlugin := preload("res://addons/openvic-plugin/ReleaseExportEditorPlugin.gd") +const ReleaseExportEditorPlugin := preload( + "res://addons/openvic-plugin/ReleaseExportEditorPlugin.gd" +) var release_export_editor_plugin := ReleaseExportEditorPlugin.new() + func _enter_tree() -> void: add_export_plugin(release_export_editor_plugin) diff --git a/game/src/GIT_INFO.gd b/game/src/GIT_INFO.gd index 23f2e4fb..b907047e 100644 --- a/game/src/GIT_INFO.gd +++ b/game/src/GIT_INFO.gd @@ -2,8 +2,7 @@ class_name _GIT_INFO_ extends RefCounted - -const commit_hash : StringName = &"0000000000000000000000000000000000000000" -const short_hash : StringName = &"0000000" -const tag : StringName = &"" -const release_name : StringName = &"" +const commit_hash: StringName = &"0000000000000000000000000000000000000000" +const short_hash: StringName = &"0000000" +const tag: StringName = &"" +const release_name: StringName = &"" diff --git a/game/src/Game/Autoload/Argument/ArgumentOption.gd b/game/src/Game/Autoload/Argument/ArgumentOption.gd index 9c0e731e..f2e13599 100644 --- a/game/src/Game/Autoload/Argument/ArgumentOption.gd +++ b/game/src/Game/Autoload/Argument/ArgumentOption.gd @@ -2,63 +2,83 @@ class_name ArgumentOption extends Resource -@export var name : StringName -@export var aliases : Array[StringName] = [] -@export var type : Variant.Type : - get: return type +@export var name: StringName +@export var aliases: Array[StringName] = [] +@export var type: Variant.Type: + get: + return type set(v): type = v match v: - TYPE_BOOL: default_value = false - TYPE_INT: default_value = 0 - TYPE_FLOAT: default_value = 0.0 - TYPE_STRING: default_value = "" - TYPE_STRING_NAME: default_value = &"" - TYPE_PACKED_STRING_ARRAY: default_value = PackedStringArray() - TYPE_COLOR: default_value = Color() - _: default_value = null + TYPE_BOOL: + default_value = false + TYPE_INT: + default_value = 0 + TYPE_FLOAT: + default_value = 0.0 + TYPE_STRING: + default_value = "" + TYPE_STRING_NAME: + default_value = &"" + TYPE_PACKED_STRING_ARRAY: + default_value = PackedStringArray() + TYPE_COLOR: + default_value = Color() + _: + default_value = null notify_property_list_changed() -var default_value : Variant -@export var description : String +var default_value: Variant +@export var description: String -func _init(_name := "", _type := TYPE_NIL, _description := "", default : Variant = null) -> void: + +func _init(_name := "", _type := TYPE_NIL, _description := "", default: Variant = null) -> void: name = _name type = _type if default != null and typeof(default) == type: default_value = default description = _description -func add_alias(alias : StringName) -> ArgumentOption: + +func add_alias(alias: StringName) -> ArgumentOption: aliases.append(alias) return self + func get_type_string() -> StringName: match type: - TYPE_NIL: return "null" - TYPE_BOOL: return "boolean" - TYPE_INT: return "integer" - TYPE_FLOAT: return "float" - TYPE_STRING, TYPE_STRING_NAME: return "string" - TYPE_PACKED_STRING_ARRAY: return "string array" - TYPE_COLOR: return "color" + TYPE_NIL: + return "null" + TYPE_BOOL: + return "boolean" + TYPE_INT: + return "integer" + TYPE_FLOAT: + return "float" + TYPE_STRING, TYPE_STRING_NAME: + return "string" + TYPE_PACKED_STRING_ARRAY: + return "string array" + TYPE_COLOR: + return "color" return "" -func _get(property : StringName) -> Variant: - if property == "default_value": return default_value + +func _get(property: StringName) -> Variant: + if property == "default_value": + return default_value return null -func _set(property : StringName, value : Variant) -> bool: + +func _set(property: StringName, value: Variant) -> bool: if property == "default_value": default_value = value return true return false + func _get_property_list() -> Array[Dictionary]: var properties := [] as Array[Dictionary] - properties.append({ - "name": "default_value", - "type": type - }) + properties.append({"name": "default_value", "type": type}) return properties diff --git a/game/src/Game/Autoload/Argument/ArgumentParser.gd b/game/src/Game/Autoload/Argument/ArgumentParser.gd index 4ce8b64c..52d3edef 100644 --- a/game/src/Game/Autoload/Argument/ArgumentParser.gd +++ b/game/src/Game/Autoload/Argument/ArgumentParser.gd @@ -3,58 +3,172 @@ extends Node const argument_setting_path := &"openvic/data/arguments" -@export var option_array : Array[ArgumentOption] = [ - ArgumentOption.new( - "help", - TYPE_BOOL, - "Displays help and quits.", - false - ).add_alias(&"h") +@export var option_array: Array[ArgumentOption] = [ + ArgumentOption.new("help", TYPE_BOOL, "Displays help and quits.", false).add_alias(&"h") ] -const color_name_array : PackedStringArray =[ - "aliceblue", "antiquewhite", "aqua", "aquamarine", - "azure", "beige", "bisque", "black", "blanchedalmond", - "blue", "blueviolet", "brown", "burlywood", "cadetblue", - "chartreuse", "chocolate", "coral", "cornflower", "cornsilk", - "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", - "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", - "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", - "darkslateblue", "darkslategray", "darkturquoise", "darkviolet", - "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick", - "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite", - "gold", "goldenrod", "gray", "green", "greenyellow", "honeydew", - "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender", - "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral", - "lightcyan", "lightgoldenrod", "lightgray", "lightgreen", "lightpink", - "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", - "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta", - "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", - "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen", - "mediumturquoise", "mediumvioletred", "midnightblue", "mintcream", - "mistyrose", "moccasin", "navajowhite", "navyblue", "oldlace", "olive", - "olivedrab", "orange", "orangered", "orchid", "palegoldenrod", - "palegreen", "paleturquoise", "palevioletred", "papayawhip", - "peachpuff", "peru", "pink", "plum", "powderblue", "purple", - "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown", - "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", - "skyblue", "slateblue", "slategray", "snow", "springgreen", "steelblue", - "tan", "teal", "thistle", "tomato", "transparent", "turquoise", "violet", - "webgray", "webgreen", "webmaroon", "webpurple", "wheat", "white", - "whitesmoke", "yellow", "yellowgreen" +const color_name_array: PackedStringArray = [ + "aliceblue", + "antiquewhite", + "aqua", + "aquamarine", + "azure", + "beige", + "bisque", + "black", + "blanchedalmond", + "blue", + "blueviolet", + "brown", + "burlywood", + "cadetblue", + "chartreuse", + "chocolate", + "coral", + "cornflower", + "cornsilk", + "crimson", + "cyan", + "darkblue", + "darkcyan", + "darkgoldenrod", + "darkgray", + "darkgreen", + "darkkhaki", + "darkmagenta", + "darkolivegreen", + "darkorange", + "darkorchid", + "darkred", + "darksalmon", + "darkseagreen", + "darkslateblue", + "darkslategray", + "darkturquoise", + "darkviolet", + "deeppink", + "deepskyblue", + "dimgray", + "dodgerblue", + "firebrick", + "floralwhite", + "forestgreen", + "fuchsia", + "gainsboro", + "ghostwhite", + "gold", + "goldenrod", + "gray", + "green", + "greenyellow", + "honeydew", + "hotpink", + "indianred", + "indigo", + "ivory", + "khaki", + "lavender", + "lavenderblush", + "lawngreen", + "lemonchiffon", + "lightblue", + "lightcoral", + "lightcyan", + "lightgoldenrod", + "lightgray", + "lightgreen", + "lightpink", + "lightsalmon", + "lightseagreen", + "lightskyblue", + "lightslategray", + "lightsteelblue", + "lightyellow", + "lime", + "limegreen", + "linen", + "magenta", + "maroon", + "mediumaquamarine", + "mediumblue", + "mediumorchid", + "mediumpurple", + "mediumseagreen", + "mediumslateblue", + "mediumspringgreen", + "mediumturquoise", + "mediumvioletred", + "midnightblue", + "mintcream", + "mistyrose", + "moccasin", + "navajowhite", + "navyblue", + "oldlace", + "olive", + "olivedrab", + "orange", + "orangered", + "orchid", + "palegoldenrod", + "palegreen", + "paleturquoise", + "palevioletred", + "papayawhip", + "peachpuff", + "peru", + "pink", + "plum", + "powderblue", + "purple", + "rebeccapurple", + "red", + "rosybrown", + "royalblue", + "saddlebrown", + "salmon", + "sandybrown", + "seagreen", + "seashell", + "sienna", + "silver", + "skyblue", + "slateblue", + "slategray", + "snow", + "springgreen", + "steelblue", + "tan", + "teal", + "thistle", + "tomato", + "transparent", + "turquoise", + "violet", + "webgray", + "webgreen", + "webmaroon", + "webpurple", + "wheat", + "white", + "whitesmoke", + "yellow", + "yellowgreen" ] -func has_argument_support(arg_name : StringName, include_aliases : bool = false) -> bool: + +func has_argument_support(arg_name: StringName, include_aliases: bool = false) -> bool: return option_array.any( - func(opt : ArgumentOption) -> bool: + func(opt: ArgumentOption) -> bool: if include_aliases and arg_name in opt.aliases: return true return opt.name == arg_name ) -func get_argument(arg_name : StringName, default_val : Variant = null) -> Variant: + +func get_argument(arg_name: StringName, default_val: Variant = null) -> Variant: if ProjectSettings.has_setting(argument_setting_path): - var arg_setting : Variant = ProjectSettings.get_setting_with_override(argument_setting_path) + var arg_setting: Variant = ProjectSettings.get_setting_with_override(argument_setting_path) if not arg_setting is Dictionary: push_error("Argument setting is not a dictionary.") return default_val @@ -62,9 +176,10 @@ func get_argument(arg_name : StringName, default_val : Variant = null) -> Varian else: return default_val -func set_argument(arg_name : StringName, value : Variant) -> void: + +func set_argument(arg_name: StringName, value: Variant) -> void: if ProjectSettings.has_setting(argument_setting_path): - var arg_setting : Variant = null + var arg_setting: Variant = null arg_setting = ProjectSettings.get_setting_with_override(argument_setting_path) if not arg_setting is Dictionary: push_error("Argument setting is not a dictionary.") @@ -74,11 +189,12 @@ func set_argument(arg_name : StringName, value : Variant) -> void: return push_error("Argument setting has not been set yet.") + func _set_argument_setting() -> void: - var argument_dictionary : Dictionary = {} + var argument_dictionary: Dictionary = {} if ProjectSettings.has_setting(argument_setting_path): argument_dictionary = ProjectSettings.get_setting_with_override(argument_setting_path) - for option : ArgumentOption in option_array: + for option: ArgumentOption in option_array: argument_dictionary[option.name] = option.default_value _parse_argument_list(argument_dictionary, OS.get_cmdline_args()) @@ -86,94 +202,153 @@ func _set_argument_setting() -> void: ProjectSettings.set_setting(argument_setting_path, argument_dictionary) -func _parse_value(arg_name : StringName, value_string : String, type : Variant.Type) -> Variant: + +func _parse_value(arg_name: StringName, value_string: String, type: Variant.Type) -> Variant: match type: - TYPE_NIL: return null + TYPE_NIL: + return null TYPE_BOOL: value_string = value_string.to_lower() - if value_string == "true" or value_string == "t" or value_string == "yes" or value_string == "y": + if ( + value_string == "true" + or value_string == "t" + or value_string == "yes" + or value_string == "y" + ): return true - if value_string == "false" or value_string == "f" or value_string == "no" or value_string == "n": + if ( + value_string == "false" + or value_string == "f" + or value_string == "no" + or value_string == "n" + ): return false - push_error("'%s' must be a valid boolean, '%s' is an invalid value." % [arg_name, value_string]) + push_error( + "'%s' must be a valid boolean, '%s' is an invalid value." % [arg_name, value_string] + ) return null TYPE_INT: if value_string.is_valid_int(): return value_string.to_int() - push_error("'%s' must be a valid integer, '%s' is an invalid value." % [arg_name, value_string]) + push_error( + "'%s' must be a valid integer, '%s' is an invalid value." % [arg_name, value_string] + ) return null TYPE_FLOAT: if value_string.is_valid_float(): return value_string.to_float() - push_error("'%s' must be a valid float, '%s' is an invalid value." % [arg_name, value_string]) + push_error( + "'%s' must be a valid float, '%s' is an invalid value." % [arg_name, value_string] + ) return null TYPE_STRING, TYPE_STRING_NAME, TYPE_PACKED_STRING_ARRAY: return value_string TYPE_COLOR: if Color.html_is_valid(value_string) or value_string.to_lower() in color_name_array: return Color.from_string(value_string, Color()) - push_error("'%s' must be an html Color or Color name, '%s' is an invalid value." % [arg_name, value_string]) + push_error( + ( + "'%s' must be an html Color or Color name, '%s' is an invalid value." + % [arg_name, value_string] + ) + ) return null # Unsupported types - TYPE_VECTOR2, \ - TYPE_VECTOR2I, \ - TYPE_VECTOR3, \ - TYPE_VECTOR3I, \ - TYPE_VECTOR4, \ - TYPE_VECTOR4I, \ - TYPE_RECT2, \ - TYPE_RECT2I: + TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_VECTOR3, TYPE_VECTOR3I, TYPE_VECTOR4, TYPE_VECTOR4I, TYPE_RECT2, TYPE_RECT2I: push_warning("Value type '%s' may not be supported." % type) var data_array := value_string.lstrip("(").rstrip(")").split(",", false) - for index : int in data_array.size(): + for index: int in data_array.size(): data_array[index] = " " + data_array[index].strip_edges() match type: TYPE_VECTOR2: if data_array.size() != 2: - push_error("'%s' value must be a Vector2, '%s' is an invalid value." % [arg_name, value_string]) + push_error( + ( + "'%s' value must be a Vector2, '%s' is an invalid value." + % [arg_name, value_string] + ) + ) return null return str_to_var("Vector2(%s )" % ",".join(data_array)) TYPE_VECTOR2I: if data_array.size() != 2: - push_error("'%s' value must be a Vector2i, '%s' is an invalid value." % [arg_name, value_string]) + push_error( + ( + "'%s' value must be a Vector2i, '%s' is an invalid value." + % [arg_name, value_string] + ) + ) return null return str_to_var("Vector2i(%s )" % ",".join(data_array)) TYPE_VECTOR3: if data_array.size() != 2: - push_error("'%s' value must be a Vector3, '%s' is an invalid value." % [arg_name, value_string]) + push_error( + ( + "'%s' value must be a Vector3, '%s' is an invalid value." + % [arg_name, value_string] + ) + ) return null return str_to_var("Vector3(%s )" % ",".join(data_array)) TYPE_VECTOR3I: if data_array.size() != 2: - push_error("'%s' value must be a Vector3i, '%s' is an invalid value." % [arg_name, value_string]) + push_error( + ( + "'%s' value must be a Vector3i, '%s' is an invalid value." + % [arg_name, value_string] + ) + ) return null return str_to_var("Vector3i(%s )" % ",".join(data_array)) TYPE_VECTOR4: if data_array.size() != 2: - push_error("'%s' value must be a Vector4, '%s' is an invalid value." % [arg_name, value_string]) + push_error( + ( + "'%s' value must be a Vector4, '%s' is an invalid value." + % [arg_name, value_string] + ) + ) return null return str_to_var("Vector4(%s )" % ",".join(data_array)) TYPE_VECTOR4I: if data_array.size() != 2: - push_error("'%s' value must be a Vector4i, '%s' is an invalid value." % [arg_name, value_string]) + push_error( + ( + "'%s' value must be a Vector4i, '%s' is an invalid value." + % [arg_name, value_string] + ) + ) return null return str_to_var("Vector4i(%s )" % ",".join(data_array)) TYPE_RECT2: if data_array.size() != 2: - push_error("'%s' value must be a Rect2, '%s' is an invalid value." % [arg_name, value_string]) + push_error( + ( + "'%s' value must be a Rect2, '%s' is an invalid value." + % [arg_name, value_string] + ) + ) return null return str_to_var("Rect2(%s )" % ",".join(data_array)) TYPE_RECT2I: if data_array.size() != 2: - push_error("'%s' value must be a Rect2i, '%s' is an invalid value." % [arg_name, value_string]) + push_error( + ( + "'%s' value must be a Rect2i, '%s' is an invalid value." + % [arg_name, value_string] + ) + ) return null return str_to_var("Rect2i(%s )" % ",".join(data_array)) _: - push_error("'%s' value of type '%s' requested but could not be parsed." % [arg_name, type]) + push_error( + "'%s' value of type '%s' requested but could not be parsed." % [arg_name, type] + ) return null return null + # Missing types # TYPE_TRANSFORM2D = 11 # TYPE_VECTOR4 = 12 @@ -200,20 +375,23 @@ func _parse_value(arg_name : StringName, value_string : String, type : Variant.T # TYPE_PACKED_VECTOR3_ARRAY = 36 # TYPE_PACKED_COLOR_ARRAY = 37 -func _add_argument(dictionary : Dictionary, option : ArgumentOption, argument : Variant) -> void: + +func _add_argument(dictionary: Dictionary, option: ArgumentOption, argument: Variant) -> void: if option.type == TYPE_PACKED_STRING_ARRAY: dictionary[option.name] += PackedStringArray([argument]) else: dictionary[option.name] = argument -func _parse_argument_list(dictionary : Dictionary, arg_list : PackedStringArray, is_game_args : bool = false) -> Dictionary: - var current_key : String = "" - var current_option : ArgumentOption = null - for arg : String in arg_list: +func _parse_argument_list( + dictionary: Dictionary, arg_list: PackedStringArray, is_game_args: bool = false +) -> Dictionary: + var current_key: String = "" + var current_option: ArgumentOption = null + for arg: String in arg_list: if current_option != null: if not arg.begins_with("-"): - var result : Variant = _parse_value(current_key, arg, current_option.type) + var result: Variant = _parse_value(current_key, arg, current_option.type) if result != null: _add_argument(dictionary, current_option, result) current_option = null @@ -230,13 +408,18 @@ func _parse_argument_list(dictionary : Dictionary, arg_list : PackedStringArray, # Support for Unix shorthand of multiple boolean arguments # eg: "-abc" means a == true, b == true, c == true if arg.length() > 1 and arg[0] != "-" and arg[1] != "=": - for c : String in arg: + for c: String in arg: if not ((c >= "a" and c <= "z") or (c >= "A" and c <= "Z")): - push_warning("Parsing shorthand alias containing '%s', perhaps you meant '--%s'? Skipping argument." % [c, arg]) + push_warning( + ( + "Parsing shorthand alias containing '%s', perhaps you meant '--%s'? Skipping argument." + % [c, arg] + ) + ) break var alias_found := false - for o : ArgumentOption in option_array: - if o.aliases.any(func(v : StringName) -> bool: return c == v): + for o: ArgumentOption in option_array: + if o.aliases.any(func(v: StringName) -> bool: return c == v): if o.type == TYPE_BOOL: dictionary[o.name] = true else: @@ -263,8 +446,8 @@ func _parse_argument_list(dictionary : Dictionary, arg_list : PackedStringArray, if key.length() > 2 and key.begins_with("-"): key = key.substr(1) - for o : ArgumentOption in option_array: - if key == o.name or o.aliases.any(func(v : StringName) -> bool: return key == v): + for o: ArgumentOption in option_array: + if key == o.name or o.aliases.any(func(v: StringName) -> bool: return key == v): current_option = o break @@ -274,27 +457,38 @@ func _parse_argument_list(dictionary : Dictionary, arg_list : PackedStringArray, current_key = key if first_equal > -1: - var arg_result : Variant = _parse_value(key, value, current_option.type) + var arg_result: Variant = _parse_value(key, value, current_option.type) if arg_result != null: _add_argument(dictionary, current_option, arg_result) current_option = null elif current_option.type == TYPE_BOOL: dictionary[current_option.name] = true else: - push_warning("Argument '%s' treated like a boolean but does not support a boolean value, skipping." % key) + push_warning( + ( + "Argument '%s' treated like a boolean but does not support a boolean value, skipping." + % key + ) + ) elif is_game_args: push_warning("Non-argument '%s' found, skipping." % arg) return dictionary + func _print_help() -> void: - var project_name : StringName = ProjectSettings.get_setting_with_override(&"application/config/name") - var project_version : String = _GIT_INFO_.tag - var project_hash : String = _GIT_INFO_.short_hash - var project_website : String = "https://openvic.com" - var project_description : String = ProjectSettings.get_setting_with_override(&"application/config/description") + var project_name: StringName = ProjectSettings.get_setting_with_override( + &"application/config/name" + ) + var project_version: String = _GIT_INFO_.tag + var project_hash: String = _GIT_INFO_.short_hash + var project_website: String = "https://openvic.com" + var project_description: String = ProjectSettings.get_setting_with_override( + &"application/config/description" + ) print_rich( -""" + ( + """ %s - %s - %s - %s %s @@ -302,23 +496,47 @@ func _print_help() -> void: Options: """ - % [ - project_name, - project_version, - project_hash, - project_website, - project_description, - "usage: %s [options]" % OS.get_executable_path().get_file() - ] + % [ + project_name, + project_version, + project_hash, + project_website, + project_description, + "usage: %s [options]" % OS.get_executable_path().get_file() + ] + ) ) - for option : ArgumentOption in option_array: - print_rich(" --%s%s%s" % [ - (option.name + (",-%s" % (",-".join(option.aliases)) if option.aliases.size() > 0 else "")).rpad(45), - ("Type: %s - Default Value: %s" % [option.get_type_string(), option.default_value]).rpad(45), - option.description - ]) + for option: ArgumentOption in option_array: + print_rich( + ( + " --%s%s%s" + % [ + ( + ( + option.name + + ( + ",-%s" % (",-".join(option.aliases)) + if option.aliases.size() > 0 + else "" + ) + ) + . rpad(45) + ), + ( + ( + "Type: %s - Default Value: %s" + % [option.get_type_string(), option.default_value] + ) + . rpad(45) + ), + option.description + ] + ) + ) + func _ready() -> void: - if Engine.is_editor_hint(): return + if Engine.is_editor_hint(): + return _set_argument_setting() GameDebug._singleton = GameDebug.new() diff --git a/game/src/Game/Autoload/Events.gd b/game/src/Game/Autoload/Events.gd index 091a1226..5f6cb5d4 100644 --- a/game/src/Game/Autoload/Events.gd +++ b/game/src/Game/Autoload/Events.gd @@ -3,8 +3,9 @@ ## It does such by providing a global interface of signals that are connected to and emitted by that are guaranteed to exist. extends Node -var Options : OptionsEventsObject -var NationManagementScreens : NationManagementScreensEventsObject +var Options: OptionsEventsObject +var NationManagementScreens: NationManagementScreensEventsObject + func _init() -> void: Options = OptionsEventsObject.new() diff --git a/game/src/Game/Autoload/Events/NationManagementScreens.gd b/game/src/Game/Autoload/Events/NationManagementScreens.gd index 4bdca6de..ef139248 100644 --- a/game/src/Game/Autoload/Events/NationManagementScreens.gd +++ b/game/src/Game/Autoload/Events/NationManagementScreens.gd @@ -1,25 +1,28 @@ class_name NationManagementScreensEventsObject extends RefCounted -signal update_active_nation_management_screen(screen : NationManagement.Screen) +signal update_active_nation_management_screen(screen: NationManagement.Screen) + +var _current_screen: NationManagement.Screen = NationManagement.Screen.NONE -var _current_screen : NationManagement.Screen = NationManagement.Screen.NONE # Set the current nation management screen. This emits an update signal to force # the argument screen to update, even if it was already the current screen. # Used by miscellaneous screen opening buttons (e.g. in province overview panel) # and by the close and toggle functions below. -func open_nation_management_screen(screen : NationManagement.Screen) -> void: +func open_nation_management_screen(screen: NationManagement.Screen) -> void: _current_screen = screen update_active_nation_management_screen.emit(_current_screen) + # Close the screen if it is already open. Used for screens' close buttons. -func close_nation_management_screen(screen : NationManagement.Screen) -> void: +func close_nation_management_screen(screen: NationManagement.Screen) -> void: if screen == _current_screen: open_nation_management_screen(NationManagement.Screen.NONE) + # Either switch to the screen or close it if it is already open. Used for topbar's buttons. -func toggle_nation_management_screen(screen : NationManagement.Screen) -> void: +func toggle_nation_management_screen(screen: NationManagement.Screen) -> void: if screen == _current_screen: screen = NationManagement.Screen.NONE open_nation_management_screen(screen) diff --git a/game/src/Game/Autoload/Events/Options.gd b/game/src/Game/Autoload/Events/Options.gd index f3fd706b..7dd2ae36 100644 --- a/game/src/Game/Autoload/Events/Options.gd +++ b/game/src/Game/Autoload/Events/Options.gd @@ -3,11 +3,13 @@ extends RefCounted signal save_settings(save_file: ConfigFile) signal load_settings(load_file: ConfigFile) -signal reset_settings() +signal reset_settings + func load_settings_from_file() -> void: load_settings.emit(_settings_file) + # REQUIREMENTS # * SS-11 # * UIFUN-13 @@ -16,17 +18,22 @@ func save_settings_to_file() -> void: save_settings.emit(_settings_file) _settings_file.save(_settings_file_path) + func try_reset_settings() -> void: reset_settings.emit() -const settings_file_path_setting : String = "openvic/settings/settings_file_path" + +const settings_file_path_setting: String = "openvic/settings/settings_file_path" # REQUIREMENTS # * FS-561 -const settings_file_path_default : String = "user://settings.cfg" +const settings_file_path_default: String = "user://settings.cfg" -var _settings_file_path : String = ProjectSettings.get_setting(settings_file_path_setting, settings_file_path_default) +var _settings_file_path: String = ProjectSettings.get_setting( + settings_file_path_setting, settings_file_path_default +) var _settings_file := ConfigFile.new() + # REQUIREMENTS # * SS-9 # * UIFUN-7, UIFUN-12 diff --git a/game/src/Game/Autoload/GameLoader.gd b/game/src/Game/Autoload/GameLoader.gd index 000ee208..6670df12 100644 --- a/game/src/Game/Autoload/GameLoader.gd +++ b/game/src/Game/Autoload/GameLoader.gd @@ -1,6 +1,7 @@ extends Node -var ShaderManager : ShaderManagerClass +var ShaderManager: ShaderManagerClass + func _init() -> void: ShaderManager = ShaderManagerClass.new() diff --git a/game/src/Game/Autoload/GuiScale.gd b/game/src/Game/Autoload/GuiScale.gd index b8af59c8..210a6632 100644 --- a/game/src/Game/Autoload/GuiScale.gd +++ b/game/src/Game/Autoload/GuiScale.gd @@ -1,16 +1,15 @@ extends Node -const error_guiscale : float = -1.0 +const error_guiscale: float = -1.0 -@export -var minimum_guiscale : float = 0.1 +@export var minimum_guiscale: float = 0.1 -const _starting_guiscales : Dictionary = { - float(0.5) : &"0.5x", +const _starting_guiscales: Dictionary = { + float(0.5): &"0.5x", float(0.75): &"0.75x", - float(1) : &"1x", - float(1.5) : &"1.5x", - float(2) : &"2x", + float(1): &"1x", + float(1.5): &"1.5x", + float(2): &"2x", } var _guiscales: Dictionary @@ -18,45 +17,59 @@ var _guiscales: Dictionary #Similar to Resolution.gd, but we don't bother checking for strings from files #and we have floats instead of vector2 integers + func _ready() -> void: assert(minimum_guiscale > 0, "Minimum gui scale must be positive") - for guiscale_value : float in _starting_guiscales: + for guiscale_value: float in _starting_guiscales: add_guiscale(guiscale_value, _starting_guiscales[guiscale_value]) assert(not _guiscales.is_empty(), "No valid starting gui scales!") -func has_guiscale(guiscale_value : float) -> bool: + +func has_guiscale(guiscale_value: float) -> bool: return guiscale_value in _guiscales -func add_guiscale(guiscale_value: float, guiscale_name: StringName=&"") -> bool: - if has_guiscale(guiscale_value): return true - var scale_dict := { value = guiscale_value } + +func add_guiscale(guiscale_value: float, guiscale_name: StringName = &"") -> bool: + if has_guiscale(guiscale_value): + return true + var scale_dict := {value = guiscale_value} if not guiscale_name.is_empty(): scale_dict.display_name = guiscale_name else: scale_dict.display_name = StringName("%sx" % guiscale_value) if guiscale_value < minimum_guiscale: - push_error("GUI scale %s is smaller than the minimum %s" % [scale_dict.display_name, minimum_guiscale]) + push_error( + ( + "GUI scale %s is smaller than the minimum %s" + % [scale_dict.display_name, minimum_guiscale] + ) + ) return false _guiscales[guiscale_value] = scale_dict return true + #returns floats func get_guiscale_value_list() -> Array: var list := _guiscales.keys() - list.sort_custom(func(a : float, b : float) -> bool: return a > b) + list.sort_custom(func(a: float, b: float) -> bool: return a > b) return list -func get_guiscale_display_name(guiscale_value : float) -> StringName: + +func get_guiscale_display_name(guiscale_value: float) -> StringName: return _guiscales.get(guiscale_value, {display_name = &"unknown gui scale"}).display_name + func get_current_guiscale() -> float: return get_tree().root.content_scale_factor -func set_guiscale(guiscale:float) -> void: + +func set_guiscale(guiscale: float) -> void: print("New GUI scale: %f" % guiscale) if not has_guiscale(guiscale): push_warning("Setting GUI Scale to non-standard value %sx" % [guiscale]) get_tree().root.content_scale_factor = guiscale + func reset_guiscale() -> void: set_guiscale(get_current_guiscale()) diff --git a/game/src/Game/Autoload/Resolution.gd b/game/src/Game/Autoload/Resolution.gd index c25c9fde..8b38a86f 100644 --- a/game/src/Game/Autoload/Resolution.gd +++ b/game/src/Game/Autoload/Resolution.gd @@ -1,35 +1,38 @@ extends Node -signal resolution_added(value : Vector2i) +signal resolution_added(value: Vector2i) -const error_resolution : Vector2i = Vector2i(-1,-1) +const error_resolution: Vector2i = Vector2i(-1, -1) -@export -var minimum_resolution : Vector2i = Vector2i(1,1) +@export var minimum_resolution: Vector2i = Vector2i(1, 1) # REQUIREMENTS: # * SS-130, SS-131, SS-132, SS-133 -const _starting_resolutions : Array[Vector2i] = [ - Vector2i(3840,2160), - Vector2i(2560,1080), - Vector2i(1920,1080), - Vector2i(1366,768), - Vector2i(1536,864), - Vector2i(1280,720), - Vector2i(1440,900), - Vector2i(1600,900), - Vector2i(1024,600), - Vector2i(800,600) +const _starting_resolutions: Array[Vector2i] = [ + Vector2i(3840, 2160), + Vector2i(2560, 1080), + Vector2i(1920, 1080), + Vector2i(1366, 768), + Vector2i(1536, 864), + Vector2i(1280, 720), + Vector2i(1440, 900), + Vector2i(1600, 900), + Vector2i(1024, 600), + Vector2i(800, 600) ] -var _resolutions : Array[Vector2i] +var _resolutions: Array[Vector2i] + +const _regex_pattern: String = "(\\d+)\\s*[xX,]\\s*(\\d+)" +var _regex: RegEx -const _regex_pattern : String = "(\\d+)\\s*[xX,]\\s*(\\d+)" -var _regex : RegEx func _ready() -> void: - assert(minimum_resolution.x > 0 and minimum_resolution.y > 0, "Minimum resolution must be positive!") - for resolution_value : Vector2i in _starting_resolutions: + assert( + minimum_resolution.x > 0 and minimum_resolution.y > 0, + "Minimum resolution must be positive!" + ) + for resolution_value: Vector2i in _starting_resolutions: add_resolution(resolution_value) assert(not _resolutions.is_empty(), "No valid starting resolutions!") @@ -37,31 +40,48 @@ func _ready() -> void: var err := _regex.compile(_regex_pattern) assert(err == OK, "Resolution RegEx failed to compile!") -func has_resolution(resolution_value : Vector2i) -> bool: + +func has_resolution(resolution_value: Vector2i) -> bool: return resolution_value in _resolutions -func add_resolution(resolution_value : Vector2i) -> bool: - if has_resolution(resolution_value): return true + +func add_resolution(resolution_value: Vector2i) -> bool: + if has_resolution(resolution_value): + return true if resolution_value.x < minimum_resolution.x or resolution_value.y < minimum_resolution.y: - push_error("Resolution %dx%d is smaller than minimum (%dx%d)" % [resolution_value.x, resolution_value.y, minimum_resolution.x, minimum_resolution.y]) + push_error( + ( + "Resolution %dx%d is smaller than minimum (%dx%d)" + % [ + resolution_value.x, + resolution_value.y, + minimum_resolution.x, + minimum_resolution.y + ] + ) + ) return false _resolutions.append(resolution_value) resolution_added.emit(resolution_value) return true + func get_resolution_value_list() -> Array[Vector2i]: - var list : Array[Vector2i] = [] + var list: Array[Vector2i] = [] # Return a sorted copy instead of a reference to the private array list.append_array(_resolutions) - list.sort_custom(func(a : Vector2i, b : Vector2i) -> bool: return a > b) + list.sort_custom(func(a: Vector2i, b: Vector2i) -> bool: return a > b) return list -func get_resolution_value_from_string(resolution_string : String) -> Vector2i: + +func get_resolution_value_from_string(resolution_string: String) -> Vector2i: if not resolution_string.is_empty(): var result := _regex.search(resolution_string) - if result: return Vector2i(result.get_string(1).to_int(), result.get_string(2).to_int()) + if result: + return Vector2i(result.get_string(1).to_int(), result.get_string(2).to_int()) return error_resolution + func get_current_resolution() -> Vector2i: var viewport := get_viewport() if viewport != null: @@ -75,9 +95,12 @@ func get_current_resolution() -> Vector2i: push_error("Trying to get resolution before window exists!") return error_resolution -func set_resolution(resolution : Vector2i) -> void: + +func set_resolution(resolution: Vector2i) -> void: if not has_resolution(resolution): - push_warning("Setting resolution to non-standard value %sx%s" % [resolution.x, resolution.y]) + push_warning( + "Setting resolution to non-standard value %sx%s" % [resolution.x, resolution.y] + ) var viewport := get_viewport() if viewport != null: var window := viewport.get_window() @@ -87,10 +110,11 @@ func set_resolution(resolution : Vector2i) -> void: window.content_scale_size = resolution _: window.size = resolution - window.content_scale_size = Vector2i(0,0) + window.content_scale_size = Vector2i(0, 0) return push_error("Trying to set resolution before window exists!") + func get_current_window_mode() -> Window.Mode: var viewport := get_viewport() if viewport != null: @@ -100,7 +124,8 @@ func get_current_window_mode() -> Window.Mode: push_error("Trying to get window mode before it exists!") return Window.MODE_WINDOWED -func set_window_mode(mode : Window.Mode) -> void: + +func set_window_mode(mode: Window.Mode) -> void: var viewport := get_viewport() if viewport != null: var window := viewport.get_window() @@ -113,6 +138,7 @@ func set_window_mode(mode : Window.Mode) -> void: return push_error("Trying to set window mode before it exists!") + func get_current_monitor() -> int: var viewport := get_viewport() if viewport != null: @@ -122,7 +148,8 @@ func get_current_monitor() -> int: push_error("Trying to get monitor index before window exists!") return 0 -func set_monitor(index : int) -> void: + +func set_monitor(index: int) -> void: var viewport := get_viewport() if viewport != null: var window := viewport.get_window() diff --git a/game/src/Game/Autoload/SaveManager.gd b/game/src/Game/Autoload/SaveManager.gd index 688e1638..fa7982e1 100644 --- a/game/src/Game/Autoload/SaveManager.gd +++ b/game/src/Game/Autoload/SaveManager.gd @@ -4,38 +4,50 @@ extends Node # * FS-28 const save_directory_setting := &"openvic/data/saves_directory" -var current_save : SaveResource -var current_session_tag : StringName +var current_save: SaveResource +var current_session_tag: StringName + +var _save_dictionary: Dictionary = {} +var _dirty_save: SaveResource -var _save_dictionary : Dictionary = {} -var _dirty_save : SaveResource func _ready() -> void: - var saves_dir_path : String = ProjectSettings.get_setting_with_override(save_directory_setting) + var saves_dir_path: String = ProjectSettings.get_setting_with_override(save_directory_setting) assert(saves_dir_path != null, "'%s' setting could not be found." % save_directory_setting) DirAccess.make_dir_recursive_absolute(saves_dir_path) var saves_dir := DirAccess.open(saves_dir_path) - for file : String in saves_dir.get_files(): + for file: String in saves_dir.get_files(): var save := SaveResource.new() save.load_save(saves_dir_path.path_join(file)) add_or_replace_save(save, true) -func get_save_file_name(save_name : StringName, session_tag : StringName = current_session_tag) -> StringName: + +func get_save_file_name( + save_name: StringName, session_tag: StringName = current_session_tag +) -> StringName: return ("%s - %s" % [save_name, session_tag]).validate_filename() -func make_new_save(save_name : String, session_tag : StringName = current_session_tag) -> SaveResource: + +func make_new_save( + save_name: String, session_tag: StringName = current_session_tag +) -> SaveResource: var file_name := get_save_file_name(save_name, session_tag) + ".tres" var new_save := SaveResource.new() - new_save.set_file_path(save_name, ProjectSettings.get_setting_with_override(save_directory_setting).path_join(file_name)) + new_save.set_file_path( + save_name, + ProjectSettings.get_setting_with_override(save_directory_setting).path_join(file_name) + ) print(new_save.file_path) new_save.session_tag = session_tag return new_save -func has_save(save_name : StringName, session_tag : StringName = current_session_tag) -> bool: + +func has_save(save_name: StringName, session_tag: StringName = current_session_tag) -> bool: return _save_dictionary.has(get_save_file_name(save_name, session_tag)) -func add_or_replace_save(save : SaveResource, ignore_dirty : bool = false) -> void: + +func add_or_replace_save(save: SaveResource, ignore_dirty: bool = false) -> void: var binded_func := _on_save_deleted_or_moved.bind(save) save.deleted.connect(binded_func) save.trash_moved.connect(binded_func) @@ -43,13 +55,17 @@ func add_or_replace_save(save : SaveResource, ignore_dirty : bool = false) -> vo if not ignore_dirty: _dirty_save = save -func delete_save(save : SaveResource) -> void: + +func delete_save(save: SaveResource) -> void: save.delete() + func flush_save() -> void: - if _dirty_save == null: return + if _dirty_save == null: + return _dirty_save.flush_save() _dirty_save = null -func _on_save_deleted_or_moved(save : SaveResource) -> void: + +func _on_save_deleted_or_moved(save: SaveResource) -> void: _save_dictionary.erase(get_save_file_name(save.save_name, save.session_tag)) diff --git a/game/src/Game/Autoload/SoundManager.gd b/game/src/Game/Autoload/SoundManager.gd index 520afb12..30fabc43 100644 --- a/game/src/Game/Autoload/SoundManager.gd +++ b/game/src/Game/Autoload/SoundManager.gd @@ -3,23 +3,25 @@ extends Node # REQUIREMENTS: # * SS-68 -const _audio_directory_path : StringName = &"res://assets/audio/sfx/" +const _audio_directory_path: StringName = &"res://assets/audio/sfx/" -var _loaded_sound : Dictionary = {} +var _loaded_sound: Dictionary = {} + +var _bus_to_stream_player: Dictionary = {} -var _bus_to_stream_player : Dictionary = {} # REQUIREMENTS: # * SND-10 func _ready() -> void: var dir := DirAccess.open(_audio_directory_path) - for fname : String in dir.get_files(): + for fname: String in dir.get_files(): match fname.get_extension(): "ogg", "wav", "mp3": - _loaded_sound[fname.get_basename()] = load(_audio_directory_path.path_join(fname)) # SND-10 + _loaded_sound[fname.get_basename()] = load(_audio_directory_path.path_join(fname)) # SND-10 + -func play_stream(sound : AudioStream, bus_type : String, volume : float = 1.0) -> void: - var player : AudioStreamPlayer = _bus_to_stream_player.get(bus_type) +func play_stream(sound: AudioStream, bus_type: String, volume: float = 1.0) -> void: + var player: AudioStreamPlayer = _bus_to_stream_player.get(bus_type) if player == null: player = AudioStreamPlayer.new() player.bus = bus_type @@ -27,27 +29,31 @@ func play_stream(sound : AudioStream, bus_type : String, volume : float = 1.0) - _bus_to_stream_player[bus_type] = player add_child(player) player.play() - var poly_playback : AudioStreamPlaybackPolyphonic = player.get_stream_playback() + var poly_playback: AudioStreamPlaybackPolyphonic = player.get_stream_playback() player.volume_db = linear_to_db(volume) poly_playback.play_stream(sound) -func play(sound : String, bus_type : String) -> void: + +func play(sound: String, bus_type: String) -> void: play_stream(_loaded_sound[sound], bus_type) + # REQUIREMENTS: # * SND-7 -func play_effect_stream(sound : AudioStream, volume : float = 1.0) -> void: +func play_effect_stream(sound: AudioStream, volume: float = 1.0) -> void: play_stream(sound, "SFX", volume) -func play_effect(sound : String) -> void: + +func play_effect(sound: String) -> void: play(sound, "SFX") -func play_effect_compat(sfx : String, fallback : AudioStream=null) -> void: - var sound:AudioStreamWAV = SoundSingleton.get_sound_stream(sfx) - var volume:float = SoundSingleton.get_sound_base_volume(sfx) + +func play_effect_compat(sfx: String, fallback: AudioStream = null) -> void: + var sound: AudioStreamWAV = SoundSingleton.get_sound_stream(sfx) + var volume: float = SoundSingleton.get_sound_base_volume(sfx) if sound != null: - play_effect_stream(sound,volume) + play_effect_stream(sound, volume) elif fallback != null: push_warning("Failed to find sound %s, playing fallback instead" % sfx) play_effect_stream(fallback) diff --git a/game/src/Game/Autoload/WindowOverride.gd b/game/src/Game/Autoload/WindowOverride.gd index 578aee02..185a431d 100644 --- a/game/src/Game/Autoload/WindowOverride.gd +++ b/game/src/Game/Autoload/WindowOverride.gd @@ -2,12 +2,15 @@ extends Node const VideoOptions = preload("res://src/Game/Menu/OptionMenu/VideoTab.tscn") + func _init() -> void: var window_id := DisplayServer.get_window_list()[0] DisplayServer.window_set_size(Vector2(1280.0, 720.0), window_id) + func _ready() -> void: - if ArgumentParser.get_argument(&"help"): return + if ArgumentParser.get_argument(&"help"): + return _on_SceneTree_idle() # Hack to ensure Video Options load var video := VideoOptions.instantiate() @@ -15,6 +18,7 @@ func _ready() -> void: add_child(video) video.queue_free() + func _on_SceneTree_idle() -> void: var window := get_window() window.set_mode(Window.MODE_FULLSCREEN) @@ -24,4 +28,6 @@ func _on_SceneTree_idle() -> void: var screen_pos := DisplayServer.screen_get_position(window.current_screen) var screen_size := DisplayServer.screen_get_size(window.current_screen) window.position = screen_pos + (screen_size - window.size) / 2 - ProjectSettings.set_setting.call_deferred("display/window/per_pixel_transparency/allowed", false) + ProjectSettings.set_setting.call_deferred( + "display/window/per_pixel_transparency/allowed", false + ) diff --git a/game/src/Game/GameMenu.gd b/game/src/Game/GameMenu.gd index 974c1d94..dd5ebbdd 100644 --- a/game/src/Game/GameMenu.gd +++ b/game/src/Game/GameMenu.gd @@ -1,19 +1,22 @@ extends Control -@export var _main_menu : Control -@export var _options_menu : Control -@export var _lobby_menu : Control -@export var _credits_menu : Control +@export var _main_menu: Control +@export var _options_menu: Control +@export var _lobby_menu: Control +@export var _credits_menu: Control + # REQUIREMENTS # * SS-10 func _ready() -> void: Events.Options.load_settings_from_file() + func _on_main_menu_new_game_button_pressed() -> void: _lobby_menu.show() _main_menu.hide() + # REQUIREMENTS # * SS-6 # * UIFUN-5 diff --git a/game/src/Game/GameSession/BillboardManager.gd b/game/src/Game/GameSession/BillboardManager.gd index f14986b8..4728e7ad 100644 --- a/game/src/Game/GameSession/BillboardManager.gd +++ b/game/src/Game/GameSession/BillboardManager.gd @@ -1,41 +1,42 @@ extends MultiMeshInstance3D -@export var _map_view : MapView +@export var _map_view: MapView -const SCALE_FACTOR : float = 1.0 / 96.0 +const SCALE_FACTOR: float = 1.0 / 96.0 enum BillboardType { NONE, RGO, CRIME, NATIONAL_FOCUS, CAPITAL } -const BILLBOARD_NAMES : Dictionary = { +const BILLBOARD_NAMES: Dictionary = { BillboardType.RGO: &"tradegoods", BillboardType.CRIME: &"crimes", BillboardType.NATIONAL_FOCUS: &"national_focus", BillboardType.CAPITAL: &"capital" } -const BILLBOARD_DIMS : Dictionary = { +const BILLBOARD_DIMS: Dictionary = { # Should be 0.8, but something else seems to be contributing to vertical # stretching so we use 0.7 to account for that. BillboardType.RGO: Vector2(1.0, 0.7), - BillboardType.CRIME: Vector2(1.0, 1.0), BillboardType.NATIONAL_FOCUS: Vector2(1.0, 1.0), BillboardType.CAPITAL: Vector2(1.0, 1.0) } -enum MapModes { REVOLT_RISK = 2, INFRASTRUCTURE = 5, COLONIAL = 6, NATIONAL_FOCUS = 9, RGO_OUTPUT = 10 } +enum MapModes { + REVOLT_RISK = 2, INFRASTRUCTURE = 5, COLONIAL = 6, NATIONAL_FOCUS = 9, RGO_OUTPUT = 10 +} -var provinces_size : int = 0 -var total_capitals_size : int = 0 +var provinces_size: int = 0 +var total_capitals_size: int = 0 # Given a BillboardType, get the index for the texture in the shader. # This is to reduce the number of magic indeces in the code # to get the proper billboard image -var billboard_type_to_index : Dictionary +var billboard_type_to_index: Dictionary -var textures : Array[Texture2D] -var frames : PackedByteArray -var scales : PackedVector2Array +var textures: Array[Texture2D] +var frames: PackedByteArray +var scales: PackedVector2Array -var current_province_billboard : BillboardType = BillboardType.NONE -var province_billboards_visible : bool = true +var current_province_billboard: BillboardType = BillboardType.NONE +var province_billboards_visible: bool = true # ============== Billboards ============= # Billboards are displayed using a multimesh (batch drawn mesh) @@ -57,17 +58,18 @@ var province_billboards_visible : bool = true # for map modes such as RGO output, while "Capital billboards" refers to the # to country capitals. + func _ready() -> void: - const name_key : StringName = &"name" - const texture_key : StringName = &"texture" - const scale_key : StringName = &"scale" - const no_of_frames_key : StringName = &"noFrames" + const name_key: StringName = &"name" + const texture_key: StringName = &"texture" + const scale_key: StringName = &"scale" + const no_of_frames_key: StringName = &"noFrames" - for billboard : Dictionary in MapItemSingleton.get_billboards(): - var billboard_name : StringName = billboard[name_key] + for billboard: Dictionary in MapItemSingleton.get_billboards(): + var billboard_name: StringName = billboard[name_key] - var billboard_type : BillboardType = BillboardType.NONE - for key : BillboardType in BILLBOARD_NAMES: + var billboard_type: BillboardType = BillboardType.NONE + for key: BillboardType in BILLBOARD_NAMES: if billboard_name == BILLBOARD_NAMES[key]: billboard_type = key break @@ -75,16 +77,16 @@ func _ready() -> void: if billboard_type == BillboardType.NONE: continue - var texture_name : StringName = billboard[texture_key] - var billboard_scale : float = billboard[scale_key] - var no_of_frames : int = billboard[no_of_frames_key] + var texture_name: StringName = billboard[texture_key] + var billboard_scale: float = billboard[scale_key] + var no_of_frames: int = billboard[no_of_frames_key] #fix the alpha edges of the billboard textures - var texture : ImageTexture = AssetManager.get_texture(texture_name) + var texture: ImageTexture = AssetManager.get_texture(texture_name) if texture == null: - push_error("Texture for billboard \"", billboard_name, "\" was null!") + push_error('Texture for billboard "', billboard_name, '" was null!') continue - var image : Image = texture.get_image() + var image: Image = texture.get_image() image.fix_alpha_edges() texture.set_image(image) @@ -97,7 +99,7 @@ func _ready() -> void: frames.push_back(no_of_frames) scales.push_back(BILLBOARD_DIMS[billboard_type] * billboard_scale * SCALE_FACTOR) - var material : ShaderMaterial = multimesh.mesh.surface_get_material(0) + var material: ShaderMaterial = multimesh.mesh.surface_get_material(0) if material == null: push_error("ShaderMaterial for billboards was null") return @@ -107,7 +109,7 @@ func _ready() -> void: material.set_shader_parameter(&"sizes", scales) multimesh.mesh.surface_set_material(0, material) - var positions : PackedVector2Array = MapItemSingleton.get_province_positions() + var positions: PackedVector2Array = MapItemSingleton.get_province_positions() provinces_size = positions.size() total_capitals_size = MapItemSingleton.get_max_capital_count() @@ -120,7 +122,7 @@ func _ready() -> void: push_error("MapView export varible for BillboardManager must be set!") return - for province_index : int in provinces_size: + for province_index: int in provinces_size: multimesh.set_instance_transform( province_index + total_capitals_size, Transform3D(Basis(), _map_view._map_to_world_coords(positions[province_index])) @@ -131,13 +133,14 @@ func _ready() -> void: GameSingleton.mapmode_changed.connect(_on_map_mode_changed) GameSingleton.gamestate_updated.connect(_on_game_state_changed) + # Fetch the nation capitals and setup billboards for them func set_capitals() -> void: - var capital_positions : PackedVector2Array = MapItemSingleton.get_capital_positions() - var capitals_size : int = capital_positions.size() - var image_index : int = billboard_type_to_index[BillboardType.CAPITAL] + var capital_positions: PackedVector2Array = MapItemSingleton.get_capital_positions() + var capitals_size: int = capital_positions.size() + var image_index: int = billboard_type_to_index[BillboardType.CAPITAL] - for capital_index : int in capitals_size: + for capital_index: int in capitals_size: multimesh.set_instance_transform( capital_index, Transform3D(Basis(), _map_view._map_to_world_coords(capital_positions[capital_index])) @@ -147,26 +150,21 @@ func set_capitals() -> void: # frame=1 because frame=0 would cause capitals not to show # and as an index its fine, since the shader UVs will wrap around # 1.0 to 2.0 --> 0.0 to 1.0 so the capital image is preserved - multimesh.set_instance_custom_data( - capital_index, - Color(image_index, 1.0, 0.0, 0.0) - ) + multimesh.set_instance_custom_data(capital_index, Color(image_index, 1.0, 0.0, 0.0)) # For every country that doesn't exist, make the capital invisible - for capital_index : int in range(capitals_size, total_capitals_size): - multimesh.set_instance_custom_data( - capital_index, - Color(image_index, 0.0, 0.0, 0.0) - ) + for capital_index: int in range(capitals_size, total_capitals_size): + multimesh.set_instance_custom_data(capital_index, Color(image_index, 0.0, 0.0, 0.0)) + # Should provinces display RGO, crime, ..., or no billboard func update_province_billboards() -> void: # If current_province_billboard is NONE then image_index will fall back to -1 - var image_index : int = billboard_type_to_index.get(current_province_billboard, -1) + var image_index: int = billboard_type_to_index.get(current_province_billboard, -1) if not province_billboards_visible or image_index < 0: multimesh.visible_instance_count = total_capitals_size else: - var icons : PackedByteArray + var icons: PackedByteArray match current_province_billboard: BillboardType.RGO: icons = MapItemSingleton.get_rgo_icons() @@ -179,7 +177,7 @@ func update_province_billboards() -> void: return # Capitals are first in the array, so start iterating after them - for province_index : int in provinces_size: + for province_index: int in provinces_size: multimesh.set_instance_custom_data( province_index + total_capitals_size, Color(image_index, icons[province_index], 0.0, 0.0) @@ -187,24 +185,29 @@ func update_province_billboards() -> void: multimesh.visible_instance_count = total_capitals_size + provinces_size + func _on_game_state_changed() -> void: update_province_billboards() set_capitals() + # There are essentially 3 visibility states we can be in # 1: parchment view -> no billboards visible # 2: not parchment nor detail -> only capitals visible # 3: detail map -> province and capital billboards visible # So set_visible here is essentially to toggle the visibility of capitals -func detailed_map(visible : bool) -> void: + +func detailed_map(visible: bool) -> void: province_billboards_visible = visible update_province_billboards() -func parchment_view(is_parchment : bool) -> void: + +func parchment_view(is_parchment: bool) -> void: set_visible(not is_parchment) -func _on_map_mode_changed(map_mode : int) -> void: + +func _on_map_mode_changed(map_mode: int) -> void: match map_mode: MapModes.INFRASTRUCTURE, MapModes.COLONIAL, MapModes.RGO_OUTPUT: current_province_billboard = BillboardType.RGO diff --git a/game/src/Game/GameSession/GameSession.gd b/game/src/Game/GameSession/GameSession.gd index 1fac9d5c..fbe3e1d1 100644 --- a/game/src/Game/GameSession/GameSession.gd +++ b/game/src/Game/GameSession/GameSession.gd @@ -1,7 +1,8 @@ extends Control -@export var _model_manager : ModelManager -@export var _game_session_menu : Control +@export var _model_manager: ModelManager +@export var _game_session_menu: Control + func _ready() -> void: Events.Options.load_settings_from_file() @@ -15,9 +16,11 @@ func _ready() -> void: Keychain.initialize_profiles() -func _process(_delta : float) -> void: + +func _process(_delta: float) -> void: GameSingleton.update_clock() + # REQUIREMENTS: # * SS-42 func _on_game_session_menu_button_pressed() -> void: diff --git a/game/src/Game/GameSession/GameSessionMenu.gd b/game/src/Game/GameSession/GameSessionMenu.gd index 7db05720..766c925e 100644 --- a/game/src/Game/GameSession/GameSessionMenu.gd +++ b/game/src/Game/GameSession/GameSessionMenu.gd @@ -1,27 +1,32 @@ extends PanelContainer -@export var _main_menu_scene : PackedScene +@export var _main_menu_scene: PackedScene -@export var _main_menu_dialog : AcceptDialog -@export var _quit_dialog : AcceptDialog +@export var _main_menu_dialog: AcceptDialog +@export var _quit_dialog: AcceptDialog -var _main_menu_save_button : Button -var _main_menu_save_separator : Control -var _quit_save_button : Button -var _quit_save_separator : Control +var _main_menu_save_button: Button +var _main_menu_save_separator: Control +var _quit_save_button: Button +var _quit_save_separator: Control signal save_button_pressed signal load_button_pressed signal options_button_pressed + func _ready() -> void: - _main_menu_save_button = _main_menu_dialog.add_button("DIALOG_SAVE_AND_RESIGN", true, &"save_and_main_menu") + _main_menu_save_button = _main_menu_dialog.add_button( + "DIALOG_SAVE_AND_RESIGN", true, &"save_and_main_menu" + ) _quit_save_button = _quit_dialog.add_button("DIALOG_SAVE_AND_QUIT", true, &"save_and_quit") - # Neccessary to center the save buttons and preserve the reference to the separator elements - var dialog_hbox : HBoxContainer = _main_menu_dialog.get_child(2, true) + # Necessary to center the save buttons and preserve the reference to the separator elements + var dialog_hbox: HBoxContainer = _main_menu_dialog.get_child(2, true) var index := _main_menu_save_button.get_index(true) - dialog_hbox.move_child(_main_menu_save_button, _main_menu_dialog.get_ok_button().get_index(true)) + dialog_hbox.move_child( + _main_menu_save_button, _main_menu_dialog.get_ok_button().get_index(true) + ) dialog_hbox.move_child(_main_menu_dialog.get_ok_button(), index) _main_menu_save_separator = dialog_hbox.get_child(_main_menu_save_button.get_index(true) - 1) @@ -31,18 +36,21 @@ func _ready() -> void: dialog_hbox.move_child(_quit_dialog.get_ok_button(), index) _quit_save_separator = dialog_hbox.get_child(_quit_save_button.get_index(true) - 1) + func hide_save_dialog_button() -> void: _main_menu_save_button.hide() _main_menu_save_separator.hide() _quit_save_button.hide() _quit_save_separator.hide() + func show_save_dialog_button() -> void: _main_menu_save_button.show() _main_menu_save_separator.show() _quit_save_button.show() _quit_save_separator.show() + # REQUIREMENTS: # * SS-47 # * UIFUN-69 @@ -51,30 +59,36 @@ func _on_main_menu_confirmed() -> void: SaveManager.current_save = null get_tree().change_scene_to_packed(_main_menu_scene) + # REQUIREMENTS: # * SS-48 # * UIFUN-70 func _on_quit_confirmed() -> void: get_tree().quit() + # REQUIREMENTS: # * SS-7, SS-46 # * UIFUN-11 func _on_options_button_pressed() -> void: options_button_pressed.emit() -func _on_main_menu_dialog_custom_action(action : StringName) -> void: + +func _on_main_menu_dialog_custom_action(action: StringName) -> void: match action: &"save_and_main_menu": _on_main_menu_confirmed() -func _on_quit_dialog_custom_action(action : StringName) -> void: + +func _on_quit_dialog_custom_action(action: StringName) -> void: match action: &"save_and_quit": _on_quit_confirmed() + func _on_save_button_pressed() -> void: save_button_pressed.emit() + func _on_load_button_pressed() -> void: load_button_pressed.emit() diff --git a/game/src/Game/GameSession/Ledger.gd b/game/src/Game/GameSession/Ledger.gd index 00769e90..c3d76cdf 100644 --- a/game/src/Game/GameSession/Ledger.gd +++ b/game/src/Game/GameSession/Ledger.gd @@ -14,7 +14,7 @@ enum Page { PRICE_HISTORY, NUMBER_OF_PAGES } -const _page_titles : PackedStringArray = [ +const _page_titles: PackedStringArray = [ "LEDGER_HEADER_RANK", "LEDGER_HEADER_COUNTRYCOMPARE", "LEDGER_HEADER_COUNTRYPARTY", @@ -28,8 +28,9 @@ const _page_titles : PackedStringArray = [ "LEDGER_HEADER_GOODS_PRICEHISTORY" ] -var _current_page : Page = Page.NATION_RANKING: - get: return _current_page +var _current_page: Page = Page.NATION_RANKING: + get: + return _current_page set(new_page): _current_page = new_page while _current_page < 0: @@ -37,10 +38,11 @@ var _current_page : Page = Page.NATION_RANKING: _current_page %= Page.NUMBER_OF_PAGES _update_info() -var _page_title_label : GUILabel -var _page_number_label : GUILabel +var _page_title_label: GUILabel +var _page_number_label: GUILabel # TODO - add variables to store any nodes you'll need to refer in more than one function call + func _ready(): MenuSingleton.search_cache_changed.connect(_update_info) @@ -48,15 +50,15 @@ func _ready(): set_click_mask_from_nodepaths([^"./ledger/ledger_bg"]) - var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./ledger/close") + var close_button: GUIIconButton = get_gui_icon_button_from_nodepath(^"./ledger/close") if close_button: close_button.pressed.connect(hide) - var previous_page_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./ledger/prev") + var previous_page_button: GUIIconButton = get_gui_icon_button_from_nodepath(^"./ledger/prev") if previous_page_button: previous_page_button.pressed.connect(func() -> void: _current_page -= 1) - var next_page_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./ledger/next") + var next_page_button: GUIIconButton = get_gui_icon_button_from_nodepath(^"./ledger/next") if next_page_button: next_page_button.pressed.connect(func() -> void: _current_page += 1) @@ -67,6 +69,7 @@ func _ready(): hide() + func toggle_visibility() -> void: if is_visible(): hide() @@ -74,6 +77,7 @@ func toggle_visibility() -> void: show() _update_info() + func _update_info() -> void: if is_visible(): if _page_title_label: diff --git a/game/src/Game/GameSession/MapText.gd b/game/src/Game/GameSession/MapText.gd index 619c72ff..15de4652 100644 --- a/game/src/Game/GameSession/MapText.gd +++ b/game/src/Game/GameSession/MapText.gd @@ -1,36 +1,40 @@ class_name MapText extends Node3D -@export var _map_view : MapView +@export var _map_view: MapView -var _province_name_font : Font +var _province_name_font: Font + +const _province_name_scale: float = 1.0 / 48.0 -const _province_name_scale : float = 1.0 / 48.0 func _ready() -> void: _province_name_font = AssetManager.get_font(&"mapfont_56") + func _clear_children() -> void: - var child_count : int = get_child_count() + var child_count: int = get_child_count() while child_count > 0: child_count -= 1 - var child : Node = get_child(child_count) + var child: Node = get_child(child_count) remove_child(child) child.queue_free() + func generate_map_names() -> void: _clear_children() - for dict : Dictionary in GameSingleton.get_province_names(): + for dict: Dictionary in GameSingleton.get_province_names(): _add_province_name(dict) -func _add_province_name(dict : Dictionary) -> void: - const identifier_key : StringName = &"identifier" - const position_key : StringName = &"position" - const rotation_key : StringName = &"rotation" - const scale_key : StringName = &"scale" - var label : Label3D = Label3D.new() +func _add_province_name(dict: Dictionary) -> void: + const identifier_key: StringName = &"identifier" + const position_key: StringName = &"position" + const rotation_key: StringName = &"rotation" + const scale_key: StringName = &"scale" + + var label: Label3D = Label3D.new() label.set_draw_flag(Label3D.FLAG_DOUBLE_SIDED, false) label.set_modulate(Color.BLACK) @@ -38,7 +42,7 @@ func _add_province_name(dict : Dictionary) -> void: label.set_font(_province_name_font) label.set_vertical_alignment(VERTICAL_ALIGNMENT_BOTTOM) - var identifier : String = dict[identifier_key] + var identifier: String = dict[identifier_key] label.set_name(identifier) label.set_text(GUINode.format_province_name(identifier)) diff --git a/game/src/Game/GameSession/MapView.gd b/game/src/Game/GameSession/MapView.gd index 6bf84f30..8e12ac4d 100644 --- a/game/src/Game/GameSession/MapView.gd +++ b/game/src/Game/GameSession/MapView.gd @@ -1,64 +1,70 @@ class_name MapView extends Node3D -signal map_view_camera_changed(near_left : Vector2, far_left : Vector2, far_right : Vector2, near_right : Vector2) -signal parchment_view_changed(is_parchment_view : bool) -signal detailed_view_changed(is_detailed_view : bool) - -const _action_north : StringName = &"map_north" -const _action_east : StringName = &"map_east" -const _action_south : StringName = &"map_south" -const _action_west : StringName = &"map_west" -const _action_zoom_in : StringName = &"map_zoom_in" -const _action_zoom_out : StringName = &"map_zoom_out" -const _action_drag : StringName = &"map_drag" -const _action_click : StringName = &"map_click" -const _action_right_click : StringName = &"map_right_click" - -@export var _camera : Camera3D - -@export var _cardinal_move_speed : float = 2.5 +signal map_view_camera_changed( + near_left: Vector2, far_left: Vector2, far_right: Vector2, near_right: Vector2 +) +signal parchment_view_changed(is_parchment_view: bool) +signal detailed_view_changed(is_detailed_view: bool) + +const _action_north: StringName = &"map_north" +const _action_east: StringName = &"map_east" +const _action_south: StringName = &"map_south" +const _action_west: StringName = &"map_west" +const _action_zoom_in: StringName = &"map_zoom_in" +const _action_zoom_out: StringName = &"map_zoom_out" +const _action_drag: StringName = &"map_drag" +const _action_click: StringName = &"map_click" +const _action_right_click: StringName = &"map_right_click" + +@export var _camera: Camera3D + +@export var _cardinal_move_speed: float = 2.5 @export var _edge_move_threshold: float = 0.025 @export var _edge_move_speed: float = 2.5 -var _drag_anchor : Vector2 -var _drag_active : bool = false +var _drag_anchor: Vector2 +var _drag_active: bool = false -var _mouse_over_viewport : bool = true +var _mouse_over_viewport: bool = true -@export var _zoom_target_min : float = 0.075 -@export var _zoom_target_max : float = 5.0 -@export var _zoom_target_step : float = (_zoom_target_max - _zoom_target_min) / 64.0 -@export var _zoom_epsilon : float = _zoom_target_step * 0.005 -@export var _zoom_speed : float = 5.0 +@export var _zoom_target_min: float = 0.075 +@export var _zoom_target_max: float = 5.0 +@export var _zoom_target_step: float = (_zoom_target_max - _zoom_target_min) / 64.0 +@export var _zoom_epsilon: float = _zoom_target_step * 0.005 +@export var _zoom_speed: float = 5.0 # _zoom_target's starting value is ignored as it is updated to the camera's height by _ready, # hence why it is not exported and just has _zoom_target_max as a placeholder. -var _zoom_target : float = _zoom_target_max: - get: return _zoom_target - set(v): _zoom_target = clamp(v, _zoom_target_min, _zoom_target_max) -const _zoom_position_multiplier = 3.14159 # Horizontal movement coefficient during zoom -var _zoom_position : Vector2 +var _zoom_target: float = _zoom_target_max: + get: + return _zoom_target + set(v): + _zoom_target = clamp(v, _zoom_target_min, _zoom_target_max) +const _zoom_position_multiplier = 3.14159 # Horizontal movement coefficient during zoom +var _zoom_position: Vector2 # Display the parchment map above this height -@export var _zoom_parchment_threshold : float = _zoom_target_min + (_zoom_target_max - _zoom_target_min) / 4 +@export +var _zoom_parchment_threshold: float = _zoom_target_min + (_zoom_target_max - _zoom_target_min) / 4 # Display details like models and province names below this height -@export var _zoom_detailed_threshold : float = _zoom_parchment_threshold / 2 +@export var _zoom_detailed_threshold: float = _zoom_parchment_threshold / 2 -var _is_parchment_view : bool = false -var _is_detailed_view : bool = false +var _is_parchment_view: bool = false +var _is_detailed_view: bool = false -@export var _map_mesh_instance : MeshInstance3D -var _map_mesh : MapMesh -var _map_shader_material : ShaderMaterial -var _map_mesh_corner : Vector2 -var _map_mesh_dims : Vector2 +@export var _map_mesh_instance: MeshInstance3D +var _map_mesh: MapMesh +var _map_shader_material: ShaderMaterial +var _map_mesh_corner: Vector2 +var _map_mesh_dims: Vector2 -@export var _map_background_instance : MeshInstance3D +@export var _map_background_instance: MeshInstance3D -var _mouse_pos_viewport : Vector2 = Vector2(0.5, 0.5) -var _mouse_pos_map : Vector2 = Vector2(0.5, 0.5) -var _viewport_dims : Vector2 = Vector2(1, 1) +var _mouse_pos_viewport: Vector2 = Vector2(0.5, 0.5) +var _mouse_pos_map: Vector2 = Vector2(0.5, 0.5) +var _viewport_dims: Vector2 = Vector2(1, 1) + +@export var _map_text: MapText -@export var _map_text : MapText # ??? Strange Godot/GDExtension Bug ??? # Upon first opening a clone of this repo with the Godot Editor, @@ -89,22 +95,26 @@ func _ready() -> void: _map_shader_material = map_material if not _map_mesh_instance.mesh is MapMesh: - push_error("Invalid map mesh class: ", _map_mesh_instance.mesh.get_class(), "(expected MapMesh)") + push_error( + "Invalid map mesh class: ", _map_mesh_instance.mesh.get_class(), "(expected MapMesh)" + ) return _map_mesh = _map_mesh_instance.mesh _map_mesh.set_aspect_ratio(GameSingleton.get_map_aspect_ratio()) # Get map mesh bounds - var map_mesh_aabb : AABB = _map_mesh.get_core_aabb() * _map_mesh_instance.transform + var map_mesh_aabb: AABB = _map_mesh.get_core_aabb() * _map_mesh_instance.transform _map_mesh_corner = Vector2( min(map_mesh_aabb.position.x, map_mesh_aabb.end.x), min(map_mesh_aabb.position.z, map_mesh_aabb.end.z) ) - _map_mesh_dims = abs(Vector2( - map_mesh_aabb.position.x - map_mesh_aabb.end.x, - map_mesh_aabb.position.z - map_mesh_aabb.end.z - )) + _map_mesh_dims = abs( + Vector2( + map_mesh_aabb.position.x - map_mesh_aabb.end.x, + map_mesh_aabb.position.z - map_mesh_aabb.end.z + ) + ) GameSingleton.province_selected.connect(_on_province_selected) @@ -113,32 +123,43 @@ func _ready() -> void: return if not _map_background_instance.mesh is PlaneMesh: - push_error("Invalid map background mesh class: ", _map_background_instance.mesh.get_class(), "(expected PlaneMesh)") + push_error( + "Invalid map background mesh class: ", + _map_background_instance.mesh.get_class(), + "(expected PlaneMesh)" + ) return - var scaled_dims : Vector3 = _map_background_instance.transform.affine_inverse() * Vector3(_map_mesh_dims.x, 0.0, _map_mesh_dims.y) + var scaled_dims: Vector3 = ( + _map_background_instance.transform.affine_inverse() + * Vector3(_map_mesh_dims.x, 0.0, _map_mesh_dims.y) + ) scaled_dims.x *= 1.0 + 2.0 * _map_mesh.get_repeat_proportion() scaled_dims.z *= 2.0 (_map_background_instance.mesh as PlaneMesh).set_size(Vector2(scaled_dims.x, scaled_dims.z)) _map_text.generate_map_names() + func _notification(what: int) -> void: if what == NOTIFICATION_WM_MOUSE_EXIT: _mouse_over_viewport = false unset_hovered_province() -func _world_to_map_coords(pos : Vector3) -> Vector2: + +func _world_to_map_coords(pos: Vector3) -> Vector2: return (Vector2(pos.x, pos.z) - _map_mesh_corner) / _map_mesh_dims -func _map_to_world_coords(pos : Vector2) -> Vector3: + +func _map_to_world_coords(pos: Vector2) -> Vector3: pos = pos * _map_mesh_dims + _map_mesh_corner return Vector3(pos.x, 0, pos.y) -func _viewport_to_world_coords(pos_viewport : Vector2) -> Vector3: + +func _viewport_to_world_coords(pos_viewport: Vector2) -> Vector3: var ray_origin := _camera.project_ray_origin(pos_viewport) var ray_normal := _camera.project_ray_normal(pos_viewport) # Plane with normal (0,1,0) facing upwards, at a distance 0 from the origin - var intersection : Variant = Plane(0, 1, 0, 0).intersects_ray(ray_origin, ray_normal) + var intersection: Variant = Plane(0, 1, 0, 0).intersects_ray(ray_origin, ray_normal) if typeof(intersection) == TYPE_VECTOR3: return intersection else: @@ -147,18 +168,27 @@ func _viewport_to_world_coords(pos_viewport : Vector2) -> Vector3: push_error("Invalid intersection: ", intersection) return _map_to_world_coords(Vector2(0.5, 0.5)) -func _viewport_to_map_coords(pos_viewport : Vector2) -> Vector2: + +func _viewport_to_map_coords(pos_viewport: Vector2) -> Vector2: return _world_to_map_coords(_viewport_to_world_coords(pos_viewport)) -func look_at_map_position(pos : Vector2) -> void: - var viewport_centre : Vector2 = Vector2(0.5, 0.5) * _viewport_dims / GuiScale.get_current_guiscale() - var pos_delta : Vector3 = _map_to_world_coords(pos) - _viewport_to_world_coords(viewport_centre) + +func look_at_map_position(pos: Vector2) -> void: + var viewport_centre: Vector2 = ( + Vector2(0.5, 0.5) * _viewport_dims / GuiScale.get_current_guiscale() + ) + var pos_delta: Vector3 = _map_to_world_coords(pos) - _viewport_to_world_coords(viewport_centre) _camera.position.x += pos_delta.x _camera.position.z += pos_delta.z + func zoom_in() -> void: _zoom_target -= _zoom_target_step - _zoom_position = (Vector2(0.5, 0.5) - _mouse_pos_viewport * GuiScale.get_current_guiscale() / _viewport_dims) * _zoom_position_multiplier + _zoom_position = ( + (Vector2(0.5, 0.5) - _mouse_pos_viewport * GuiScale.get_current_guiscale() / _viewport_dims) + * _zoom_position_multiplier + ) + func zoom_out() -> void: _zoom_target += _zoom_target_step @@ -166,60 +196,80 @@ func zoom_out() -> void: # cursor location. I'm not sure if we want to preserve this behavior. _zoom_position = Vector2() -func set_hovered_province_index(hover_index : int) -> void: - _map_shader_material.set_shader_parameter(GameLoader.ShaderManager.param_hover_index, hover_index) -func set_hovered_province_at(pos : Vector2) -> void: +func set_hovered_province_index(hover_index: int) -> void: + _map_shader_material.set_shader_parameter( + GameLoader.ShaderManager.param_hover_index, hover_index + ) + + +func set_hovered_province_at(pos: Vector2) -> void: var hover_index := GameSingleton.get_province_index_from_uv_coords(pos) set_hovered_province_index(hover_index) + func unset_hovered_province() -> void: set_hovered_province_index(0) + var _province_hover_dirty := false + + func queue_province_hover_update() -> void: - if not _mouse_over_viewport: return + if not _mouse_over_viewport: + return _province_hover_dirty = true + func _update_province_hover() -> void: - if not _province_hover_dirty: return + if not _province_hover_dirty: + return _province_hover_dirty = false if _mouse_over_viewport: set_hovered_province_at(_viewport_to_map_coords(_mouse_pos_viewport)) -func _on_province_selected(index : int) -> void: + +func _on_province_selected(index: int) -> void: _map_shader_material.set_shader_parameter(GameLoader.ShaderManager.param_selected_index, index) print("Province selected with index: ", index) -func _input(event : InputEvent) -> void: + +func _input(event: InputEvent) -> void: if event is InputEventMouseMotion: _mouse_pos_viewport = get_window().get_mouse_position() elif _drag_active and event.is_action_released(_action_drag): _drag_active = false + # REQUIREMENTS # * SS-31 # * SS-75 var _cardinal_movement_vector := Vector2.ZERO -func _unhandled_input(event : InputEvent) -> void: + + +func _unhandled_input(event: InputEvent) -> void: if event is InputEventMouseMotion: _mouse_over_viewport = true queue_province_hover_update() - elif event.is_action(_action_north) or event.is_action(_action_south)\ - or event.is_action(_action_east) or event.is_action(_action_west): - _cardinal_movement_vector = Input.get_vector( - _action_west, - _action_east, - _action_north, - _action_south - ) * _cardinal_move_speed + elif ( + event.is_action(_action_north) + or event.is_action(_action_south) + or event.is_action(_action_east) + or event.is_action(_action_west) + ): + _cardinal_movement_vector = ( + Input.get_vector(_action_west, _action_east, _action_north, _action_south) + * _cardinal_move_speed + ) elif event.is_action_pressed(_action_click): if _mouse_over_viewport: # Check if the mouse is outside of bounds if _map_mesh.is_valid_uv_coord(_mouse_pos_map): - GameSingleton.set_selected_province(GameSingleton.get_province_index_from_uv_coords(_mouse_pos_map)) + GameSingleton.set_selected_province( + GameSingleton.get_province_index_from_uv_coords(_mouse_pos_map) + ) else: print("Clicked outside the map!") elif event.is_action_pressed(_action_right_click): @@ -227,7 +277,9 @@ func _unhandled_input(event : InputEvent) -> void: if _map_mesh.is_valid_uv_coord(_mouse_pos_map): # TODO - open diplomacy screen on province owner or viewed country if province has no owner #Events.NationManagementScreens.open_nation_management_screen(NationManagement.Screen.DIPLOMACY) - GameSingleton.set_viewed_country_by_province_index(GameSingleton.get_province_index_from_uv_coords(_mouse_pos_map)) + GameSingleton.set_viewed_country_by_province_index( + GameSingleton.get_province_index_from_uv_coords(_mouse_pos_map) + ) else: print("Right-clicked outside the map!") elif event.is_action_pressed(_action_drag): @@ -240,7 +292,8 @@ func _unhandled_input(event : InputEvent) -> void: elif event.is_action_pressed(_action_zoom_out, true): zoom_out() -func _process(delta : float) -> void: + +func _process(delta: float) -> void: if _cardinal_movement_vector != Vector2.ZERO and get_window().gui_get_focus_owner() != null: _cardinal_movement_vector = Vector2.ZERO @@ -264,10 +317,11 @@ func _process(delta : float) -> void: # Update province hover if dirty _update_province_hover() + # REQUIREMENTS # * UIFUN-124 -func _movement_process(delta : float) -> void: - var direction : Vector2 +func _movement_process(delta: float) -> void: + var direction: Vector2 if _drag_active: direction = (_drag_anchor - _mouse_pos_map) * _map_mesh_dims else: @@ -278,36 +332,51 @@ func _movement_process(delta : float) -> void: direction *= _camera.position.y * delta _camera.position += Vector3(direction.x, 0, direction.y) + # REQUIREMENTS # * UIFUN-125 func _edge_scrolling_vector() -> Vector2: if not _mouse_over_viewport: return Vector2() - var mouse_vector := _mouse_pos_viewport * GuiScale.get_current_guiscale() / _viewport_dims - Vector2(0.5, 0.5) + var mouse_vector := ( + _mouse_pos_viewport * GuiScale.get_current_guiscale() / _viewport_dims - Vector2(0.5, 0.5) + ) # Only scroll if outside the move threshold. - if abs(mouse_vector.x) < 0.5 - _edge_move_threshold and abs(mouse_vector.y) < 0.5 - _edge_move_threshold: + if ( + abs(mouse_vector.x) < 0.5 - _edge_move_threshold + and abs(mouse_vector.y) < 0.5 - _edge_move_threshold + ): return Vector2() return mouse_vector * _edge_move_speed + func _clamp_over_map() -> void: - _camera.position.x = _map_mesh_corner.x + fposmod(_camera.position.x - _map_mesh_corner.x, _map_mesh_dims.x) - _camera.position.z = clamp(_camera.position.z, _map_mesh_corner.y, _map_mesh_corner.y + _map_mesh_dims.y) + _camera.position.x = ( + _map_mesh_corner.x + fposmod(_camera.position.x - _map_mesh_corner.x, _map_mesh_dims.x) + ) + _camera.position.z = clamp( + _camera.position.z, _map_mesh_corner.y, _map_mesh_corner.y + _map_mesh_dims.y + ) -func _update_view_states(force_signal : bool) -> void: - var new_is_parchment_view : bool = _camera.position.y >= _zoom_parchment_threshold - _zoom_epsilon + +func _update_view_states(force_signal: bool) -> void: + var new_is_parchment_view: bool = ( + _camera.position.y >= _zoom_parchment_threshold - _zoom_epsilon + ) if force_signal or new_is_parchment_view != _is_parchment_view: _is_parchment_view = new_is_parchment_view parchment_view_changed.emit(_is_parchment_view) - var new_is_detailed_view : bool = _camera.position.y <= _zoom_detailed_threshold + _zoom_epsilon + var new_is_detailed_view: bool = _camera.position.y <= _zoom_detailed_threshold + _zoom_epsilon if force_signal or new_is_detailed_view != _is_detailed_view: _is_detailed_view = new_is_detailed_view detailed_view_changed.emit(_is_detailed_view) + # REQUIREMENTS # * SS-74 # * UIFUN-123 -func _zoom_process(delta : float) -> void: +func _zoom_process(delta: float) -> void: var height := _camera.position.y var zoom := _zoom_target - height var zoom_delta := zoom * _zoom_speed * delta @@ -323,18 +392,26 @@ func _zoom_process(delta : float) -> void: ) # TODO - smooth transition similar to smooth zoom _update_view_states(false) - var parchment_mapmode : bool = GameSingleton.is_parchment_mapmode_allowed() and _is_parchment_view - _map_shader_material.set_shader_parameter(GameLoader.ShaderManager.param_parchment_mix, float(parchment_mapmode)) + var parchment_mapmode: bool = ( + GameSingleton.is_parchment_mapmode_allowed() and _is_parchment_view + ) + _map_shader_material.set_shader_parameter( + GameLoader.ShaderManager.param_parchment_mix, float(parchment_mapmode) + ) + func _update_orientation() -> void: const up := Vector3(0, 0, -1) var dir := Vector3(0, -1, 0) if _is_detailed_view: # Zero at the transition point, increases as you zoom further in - var delta : float = (_zoom_detailed_threshold - _camera.position.y) / _zoom_detailed_threshold + var delta: float = ( + (_zoom_detailed_threshold - _camera.position.y) / _zoom_detailed_threshold + ) dir.z = -(delta ** 2) _camera.look_at(_camera.position + dir, up) + func _update_minimap_viewport() -> void: var near_left := _viewport_to_map_coords(Vector2(0, _viewport_dims.y)) var far_left := _viewport_to_map_coords(Vector2(0, 0)) @@ -342,23 +419,28 @@ func _update_minimap_viewport() -> void: var near_right := _viewport_to_map_coords(_viewport_dims) map_view_camera_changed.emit(near_left, far_left, far_right, near_right) + func _update_mouse_map_position() -> void: _mouse_pos_map = _viewport_to_map_coords(_mouse_pos_viewport) -func _on_minimap_clicked(pos_clicked : Vector2) -> void: + +func _on_minimap_clicked(pos_clicked: Vector2) -> void: pos_clicked *= _map_mesh_dims _camera.position.x = pos_clicked.x _camera.position.z = pos_clicked.y _clamp_over_map() queue_province_hover_update() + func _is_viewport_inactive() -> bool: return not get_window().has_focus() or get_window().is_input_handled() + func enable_processing() -> void: set_process_unhandled_input(true) set_process(true) + func disable_processing() -> void: set_process_unhandled_input(false) set_process(false) diff --git a/game/src/Game/GameSession/Menubar.gd b/game/src/Game/GameSession/Menubar.gd index 7f606ad0..1afa00ea 100644 --- a/game/src/Game/GameSession/Menubar.gd +++ b/game/src/Game/GameSession/Menubar.gd @@ -5,22 +5,25 @@ signal ledger_button_pressed signal search_button_pressed signal zoom_in_button_pressed signal zoom_out_button_pressed -signal minimap_clicked(pos_clicked : Vector2) +signal minimap_clicked(pos_clicked: Vector2) -var _menu_button : GUIIconButton +var _menu_button: GUIIconButton -var _mapmode_button_group : ButtonGroup +var _mapmode_button_group: ButtonGroup # We use this instead of the ButtonGroup's get_buttons() as we can add null # entries for any missing buttons, ensuring each button is at the right index. -var _mapmode_buttons : Array[GUIIconButton] -var _minimap_icon : GUIIcon -var _viewport_points : PackedVector2Array +var _mapmode_buttons: Array[GUIIconButton] +var _minimap_icon: GUIIcon +var _viewport_points: PackedVector2Array + # REQUIREMENTS: # * UI-550, UI-552, UI-554, UI-561, UI-562, UI-563 func _add_mapmode_button() -> void: - var index : int = _mapmode_buttons.size() - var button : GUIIconButton = get_gui_icon_button_from_nodepath("./menubar/mapmode_%d" % (index + 1)) + var index: int = _mapmode_buttons.size() + var button: GUIIconButton = get_gui_icon_button_from_nodepath( + "./menubar/mapmode_%d" % (index + 1) + ) if button: button.tooltip_string = GameSingleton.get_mapmode_localisation_key(index) button.toggle_mode = true @@ -28,30 +31,30 @@ func _add_mapmode_button() -> void: button.pressed.connect(_mapmode_pressed.bind(index)) _mapmode_buttons.push_back(button) + func _ready() -> void: add_gui_element("menubar", "menubar") - hide_nodes([ - ^"./menubar/messagelog_window", # TODO: implement - ^"./menubar/OPENbutton", # not quite sure what this is - ^"./menubar/menubar_plans_toggle", # TODO: implement, v low priority - ^"./menubar/menubar_plans_open", # TODO: implement, v low priority - ^"./menubar/menubar_mail_bg", # TODO: implement - ^"./menubar/menubar_msg_diplo", # TODO: implement - ^"./menubar/menubar_msg_settings", # TODO: implement - ^"./menubar/menubar_msg_combat", # TODO: implement - ^"./menubar/menubar_msg_diplo", # TODO: implement - ^"./menubar/menubar_msg_unit", # TODO: implement - ^"./menubar/menubar_msg_province", # TODO: implement - ^"./menubar/menubar_msg_event", # TODO: implement - ^"./menubar/menubar_msg_other", # TODO: implement - ^"./menubar/chat_window", # TODO: Multiplayer - ]) - - set_click_mask_from_nodepaths([ - ^"./menubar/minimap_bg", - ^"./menubar/menubar_bg" - ]) + hide_nodes( + [ + ^"./menubar/messagelog_window", # TODO: implement + ^"./menubar/OPENbutton", # not quite sure what this is + ^"./menubar/menubar_plans_toggle", # TODO: implement, v low priority + ^"./menubar/menubar_plans_open", # TODO: implement, v low priority + ^"./menubar/menubar_mail_bg", # TODO: implement + ^"./menubar/menubar_msg_diplo", # TODO: implement + ^"./menubar/menubar_msg_settings", # TODO: implement + ^"./menubar/menubar_msg_combat", # TODO: implement + ^"./menubar/menubar_msg_diplo", # TODO: implement + ^"./menubar/menubar_msg_unit", # TODO: implement + ^"./menubar/menubar_msg_province", # TODO: implement + ^"./menubar/menubar_msg_event", # TODO: implement + ^"./menubar/menubar_msg_other", # TODO: implement + ^"./menubar/chat_window", # TODO: Multiplayer + ] + ) + + set_click_mask_from_nodepaths([^"./menubar/minimap_bg", ^"./menubar/menubar_bg"]) # TODO: add keyboard shortcuts (and shortcut tooltips) where vanilla does by default + use key bindings in settings @@ -61,21 +64,23 @@ func _ready() -> void: _menu_button.pressed.connect(_on_game_session_menu_button_pressed) # TODO: implement ledger - var ledger_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./menubar/ledger_button") + var ledger_button: GUIIconButton = get_gui_icon_button_from_nodepath(^"./menubar/ledger_button") if ledger_button: ledger_button.tooltip_string = "M_LEDGER_BUTTON" ledger_button.pressed.connect(_on_ledger_button_pressed) - var search_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./menubar/button_goto") + var search_button: GUIIconButton = get_gui_icon_button_from_nodepath(^"./menubar/button_goto") if search_button: search_button.tooltip_string = "M_GOTO_BUTTON" search_button.pressed.connect(_on_search_button_pressed) - var zoom_in_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./menubar/map_zoom_in") + var zoom_in_button: GUIIconButton = get_gui_icon_button_from_nodepath(^"./menubar/map_zoom_in") if zoom_in_button: zoom_in_button.pressed.connect(_on_zoom_in_button_pressed) - var zoom_out_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./menubar/map_zoom_out") + var zoom_out_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./menubar/map_zoom_out" + ) if zoom_out_button: zoom_out_button.pressed.connect(_on_zoom_out_button_pressed) @@ -87,7 +92,7 @@ func _ready() -> void: add_child(_minimap_icon) _mapmode_button_group = ButtonGroup.new() - for index : int in GameSingleton.get_mapmode_count(): + for index: int in GameSingleton.get_mapmode_count(): _add_mapmode_button() GameSingleton.mapmode_changed.connect(_on_mapmode_changed) @@ -95,33 +100,48 @@ func _ready() -> void: # This will set the mapmode in GameSingleton which in turn updates the buttons so that the right one is pressed _mapmode_pressed(0) + func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("menu_pause"): _menu_button.pressed.emit() + # REQUIREMENTS: # * UIFUN-10 func _on_game_session_menu_button_pressed() -> void: game_session_menu_button_pressed.emit() + func _on_ledger_button_pressed() -> void: ledger_button_pressed.emit() + func _on_search_button_pressed() -> void: search_button_pressed.emit() + # REQUIREMENTS: # * SS-76 # * UIFUN-129, UIFUN-131, UIFUN-133, UIFUN-140, UIFUN-141, UIFUN-142 -func _mapmode_pressed(index : int) -> void: +func _mapmode_pressed(index: int) -> void: GameSingleton.set_mapmode(index) - print("Mapmode set to \"%s\" (index: %d, identifier: %s)" % [ - tr(GameSingleton.get_mapmode_localisation_key(index)), index, GameSingleton.get_mapmode_identifier(index) - ]) - -func _on_mapmode_changed(index : int) -> void: - var current_mapmode_button : GUIIconButton = _mapmode_button_group.get_pressed_button() - var new_mapmode_button : GUIIconButton = _mapmode_buttons[index] if 0 <= index and index < _mapmode_buttons.size() else null + print( + ( + 'Mapmode set to "%s" (index: %d, identifier: %s)' + % [ + tr(GameSingleton.get_mapmode_localisation_key(index)), + index, + GameSingleton.get_mapmode_identifier(index) + ] + ) + ) + + +func _on_mapmode_changed(index: int) -> void: + var current_mapmode_button: GUIIconButton = _mapmode_button_group.get_pressed_button() + var new_mapmode_button: GUIIconButton = ( + _mapmode_buttons[index] if 0 <= index and index < _mapmode_buttons.size() else null + ) if current_mapmode_button != new_mapmode_button: if new_mapmode_button: @@ -131,16 +151,19 @@ func _on_mapmode_changed(index : int) -> void: # current_mapmode_button can't be null as it isn't equal to new_mapmode_button which is null current_mapmode_button.button_pressed = false + # REQUIREMENTS: # * UIFUN-269 func _on_zoom_in_button_pressed() -> void: zoom_in_button_pressed.emit() + # REQUIREMENTS: # * UIFUN-270 func _on_zoom_out_button_pressed() -> void: zoom_out_button_pressed.emit() + # REQUIREMENTS # * SS-80 # * UI-752 @@ -148,32 +171,38 @@ func _minimap_draw() -> void: if _viewport_points.size() > 1: _minimap_icon.draw_multiline(_viewport_points, Color.WHITE, -1) + # REQUIREMENTS # * SS-81 # * UIFUN-127 -func _minimap_gui_input(_event : InputEvent) -> void: - const _action_click : StringName = &"map_click" +func _minimap_gui_input(_event: InputEvent) -> void: + const _action_click: StringName = &"map_click" if Input.is_action_pressed(_action_click): - var pos_clicked : Vector2 = _minimap_icon.get_local_mouse_position() / _minimap_icon.size - Vector2(0.5, 0.5) + var pos_clicked: Vector2 = ( + _minimap_icon.get_local_mouse_position() / _minimap_icon.size - Vector2(0.5, 0.5) + ) if abs(pos_clicked.x) < 0.5 and abs(pos_clicked.y) < 0.5: minimap_clicked.emit(pos_clicked) + # Returns the point on the line going through p and q with the specific x coord -func _intersect_x(p : Vector2, q : Vector2, x : float) -> Vector2: +func _intersect_x(p: Vector2, q: Vector2, x: float) -> Vector2: if p.x == q.x: return Vector2(x, 0.5 * (p.y + q.y)) - var t : float = (x - q.x) / (p.x - q.x) + var t: float = (x - q.x) / (p.x - q.x) return q + t * (p - q) + # Returns the point on the line going through p and q with the specific y coord -func _intersect_y(p : Vector2, q : Vector2, y : float) -> Vector2: +func _intersect_y(p: Vector2, q: Vector2, y: float) -> Vector2: if p.y == q.y: return Vector2(0.5 * (p.x + q.x), y) - var t : float = (y - q.y) / (p.y - q.y) + var t: float = (y - q.y) / (p.y - q.y) return q + t * (p - q) -func _add_line_looped_over_x(left : Vector2, right : Vector2) -> void: - const _one_x : Vector2 = Vector2(1, 0) + +func _add_line_looped_over_x(left: Vector2, right: Vector2) -> void: + const _one_x: Vector2 = Vector2(1, 0) if left.x < 0: if right.x < 0: _viewport_points.push_back(left + _one_x) @@ -200,8 +229,11 @@ func _add_line_looped_over_x(left : Vector2, right : Vector2) -> void: _viewport_points.push_back(left) _viewport_points.push_back(right) + # This can break if the viewport is rotated too far! -func _on_map_view_camera_changed(near_left : Vector2, far_left : Vector2, far_right : Vector2, near_right : Vector2) -> void: +func _on_map_view_camera_changed( + near_left: Vector2, far_left: Vector2, far_right: Vector2, near_right: Vector2 +) -> void: # Bound far y coords if far_left.y < 0: far_left = _intersect_y(near_left, far_left, 0) @@ -220,6 +252,6 @@ func _on_map_view_camera_changed(near_left : Vector2, far_left : Vector2, far_ri _add_line_looped_over_x(near_right, far_right) if _minimap_icon: - for i : int in _viewport_points.size(): + for i: int in _viewport_points.size(): _viewport_points[i] *= _minimap_icon.size _minimap_icon.queue_redraw() diff --git a/game/src/Game/GameSession/ModelManager.gd b/game/src/Game/GameSession/ModelManager.gd index 8cec49dc..fd79ba4f 100644 --- a/game/src/Game/GameSession/ModelManager.gd +++ b/game/src/Game/GameSession/ModelManager.gd @@ -1,45 +1,51 @@ class_name ModelManager extends Node3D -@export var _map_view : MapView +@export var _map_view: MapView + +const MODEL_SCALE: float = 1.0 / 256.0 -const MODEL_SCALE : float = 1.0 / 256.0 func generate_units() -> void: XACLoader.setup_flag_shader() - for unit : Dictionary in ModelSingleton.get_units(): + for unit: Dictionary in ModelSingleton.get_units(): _generate_unit(unit) -func _generate_unit(unit_dict : Dictionary) -> void: - const culture_key : StringName = &"culture" - const model_key : StringName = &"model" - const mount_model_key : StringName = &"mount_model" - const mount_attach_node_key : StringName = &"mount_attach_node" - const flag_index_key : StringName = &"flag_index" - const flag_floating_key : StringName = &"flag_floating" - const position_key : StringName = &"position" - const rotation_key : StringName = &"rotation" - const primary_colour_key : StringName = &"primary_colour" - const secondary_colour_key : StringName = &"secondary_colour" - const tertiary_colour_key : StringName = &"tertiary_colour" - - var model : Node3D = _generate_model(unit_dict[model_key], unit_dict[culture_key]) + +func _generate_unit(unit_dict: Dictionary) -> void: + const culture_key: StringName = &"culture" + const model_key: StringName = &"model" + const mount_model_key: StringName = &"mount_model" + const mount_attach_node_key: StringName = &"mount_attach_node" + const flag_index_key: StringName = &"flag_index" + const flag_floating_key: StringName = &"flag_floating" + const position_key: StringName = &"position" + const rotation_key: StringName = &"rotation" + const primary_colour_key: StringName = &"primary_colour" + const secondary_colour_key: StringName = &"secondary_colour" + const tertiary_colour_key: StringName = &"tertiary_colour" + + var model: Node3D = _generate_model(unit_dict[model_key], unit_dict[culture_key]) if not model: return if mount_model_key in unit_dict and mount_attach_node_key in unit_dict: # This must be a UnitModel so we can attach the rider to it - var mount_model : Node3D = _generate_model(unit_dict[mount_model_key], unit_dict[culture_key], true) + var mount_model: Node3D = _generate_model( + unit_dict[mount_model_key], unit_dict[culture_key], true + ) if mount_model: mount_model.attach_model(unit_dict[mount_attach_node_key], model) model = mount_model - var rotation : float = unit_dict.get(rotation_key, 0.0) + var rotation: float = unit_dict.get(rotation_key, 0.0) - var flag_dict : Dictionary = ModelSingleton.get_flag_model(unit_dict.get(flag_floating_key, false)) + var flag_dict: Dictionary = ModelSingleton.get_flag_model( + unit_dict.get(flag_floating_key, false) + ) if flag_dict: - var flag_model : UnitModel = _generate_model(flag_dict, "", true) + var flag_model: UnitModel = _generate_model(flag_dict, "", true) if flag_model: flag_model.set_flag_index(unit_dict[flag_index_key]) flag_model.current_anim = UnitModel.Anim.IDLE @@ -50,7 +56,9 @@ func _generate_unit(unit_dict : Dictionary) -> void: model.scale *= MODEL_SCALE model.rotate_y(PI + rotation) - model.set_position(_map_view._map_to_world_coords(unit_dict[position_key]) + Vector3(0, 0.1 * MODEL_SCALE, 0)) + model.set_position( + _map_view._map_to_world_coords(unit_dict[position_key]) + Vector3(0, 0.1 * MODEL_SCALE, 0) + ) if model is UnitModel: model.current_anim = UnitModel.Anim.IDLE @@ -61,89 +69,104 @@ func _generate_unit(unit_dict : Dictionary) -> void: add_child(model) + func generate_buildings() -> void: - for building : Dictionary in ModelSingleton.get_buildings(): + for building: Dictionary in ModelSingleton.get_buildings(): _generate_building(building) -func _generate_building(building_dict : Dictionary) -> void: - const model_key : StringName = &"model" - const position_key : StringName = &"position" - const rotation_key : StringName = &"rotation" - var model : Node3D = _generate_model(building_dict[model_key]) +func _generate_building(building_dict: Dictionary) -> void: + const model_key: StringName = &"model" + const position_key: StringName = &"position" + const rotation_key: StringName = &"rotation" + + var model: Node3D = _generate_model(building_dict[model_key]) if not model: return model.scale *= MODEL_SCALE model.rotate_y(PI + building_dict.get(rotation_key, 0.0)) - model.set_position(_map_view._map_to_world_coords(building_dict[position_key]) + Vector3(0, 0.1 * MODEL_SCALE, 0)) + model.set_position( + ( + _map_view._map_to_world_coords(building_dict[position_key]) + + Vector3(0, 0.1 * MODEL_SCALE, 0) + ) + ) add_child(model) -func _generate_model(model_dict : Dictionary, culture : String = "", is_unit : bool = false) -> Node3D: - const file_key : StringName = &"file" - const scale_key : StringName = &"scale" - const idle_key : StringName = &"idle" - const move_key : StringName = &"move" - const attack_key : StringName = &"attack" - const attachments_key : StringName = &"attachments" - const animation_file_key : StringName = &"file" - const animation_time_key : StringName = &"time" +func _generate_model(model_dict: Dictionary, culture: String = "", is_unit: bool = false) -> Node3D: + const file_key: StringName = &"file" + const scale_key: StringName = &"scale" + const idle_key: StringName = &"idle" + const move_key: StringName = &"move" + const attack_key: StringName = &"attack" + const attachments_key: StringName = &"attachments" + + const animation_file_key: StringName = &"file" + const animation_time_key: StringName = &"time" - const attachment_node_key : StringName = &"node" - const attachment_model_key : StringName = &"model" + const attachment_node_key: StringName = &"node" + const attachment_model_key: StringName = &"model" # Model - is_unit = is_unit or ( - # Needed for animations - idle_key in model_dict or move_key in model_dict or attack_key in model_dict - # Currently needs UnitModel's attach_model helper function - or attachments_key in model_dict + is_unit = ( + is_unit + or ( + # Needed for animations + idle_key in model_dict + or move_key in model_dict + or attack_key in model_dict + # Currently needs UnitModel's attach_model helper function + or attachments_key in model_dict + ) ) - var model : Node3D = XACLoader.get_xac_model(model_dict[file_key], is_unit) + var model: Node3D = XACLoader.get_xac_model(model_dict[file_key], is_unit) if not model: return null model.scale *= model_dict[scale_key] if model is UnitModel: # Animations - var idle_dict : Dictionary = model_dict.get(idle_key, {}) + var idle_dict: Dictionary = model_dict.get(idle_key, {}) if idle_dict: model.idle_anim = XSMLoader.get_xsm_animation(idle_dict[animation_file_key]) model.scroll_speed_idle = idle_dict[animation_time_key] - var move_dict : Dictionary = model_dict.get(move_key, {}) + var move_dict: Dictionary = model_dict.get(move_key, {}) if move_dict: model.move_anim = XSMLoader.get_xsm_animation(move_dict[animation_file_key]) model.scroll_speed_move = move_dict[animation_time_key] - var attack_dict : Dictionary = model_dict.get(attack_key, {}) + var attack_dict: Dictionary = model_dict.get(attack_key, {}) if attack_dict: model.attack_anim = XSMLoader.get_xsm_animation(attack_dict[animation_file_key]) model.scroll_speed_attack = attack_dict[animation_time_key] # Attachments - for attachment_dict : Dictionary in model_dict.get(attachments_key, []): - var attachment_model : Node3D = _generate_model(attachment_dict[attachment_model_key], culture) + for attachment_dict: Dictionary in model_dict.get(attachments_key, []): + var attachment_model: Node3D = _generate_model( + attachment_dict[attachment_model_key], culture + ) if attachment_model: model.attach_model(attachment_dict[attachment_node_key], attachment_model) if culture: - const gun_bone_name : String = "GunNode" + const gun_bone_name: String = "GunNode" if model.has_bone(gun_bone_name): - var gun_dict : Dictionary = ModelSingleton.get_cultural_gun_model(culture) + var gun_dict: Dictionary = ModelSingleton.get_cultural_gun_model(culture) if gun_dict: - var gun_model : Node3D = _generate_model(gun_dict, culture) + var gun_model: Node3D = _generate_model(gun_dict, culture) if gun_model: model.attach_model(gun_bone_name, gun_model) - const helmet_bone_name : String = "HelmetNode" + const helmet_bone_name: String = "HelmetNode" if model.has_bone(helmet_bone_name): - var helmet_dict : Dictionary = ModelSingleton.get_cultural_helmet_model(culture) + var helmet_dict: Dictionary = ModelSingleton.get_cultural_helmet_model(culture) if helmet_dict: - var helmet_model : Node3D = _generate_model(helmet_dict, culture) + var helmet_model: Node3D = _generate_model(helmet_dict, culture) if helmet_model: model.attach_model(helmet_bone_name, helmet_model) diff --git a/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd b/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd index 10446e3c..0275eac1 100644 --- a/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd +++ b/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd @@ -1,49 +1,52 @@ extends GUINode -var _active : bool = false -var _incVal : int = 0 # incremental value to see the UI update, replace later by real values +var _active: bool = false +var _incVal: int = 0 # incremental value to see the UI update, replace later by real values # income -var _lower_class_label : GUILabel -var _middle_class_label : GUILabel -var _upper_class_label : GUILabel -var _gold_label : GUILabel -var _total_inc_label : GUILabel +var _lower_class_label: GUILabel +var _middle_class_label: GUILabel +var _upper_class_label: GUILabel +var _gold_label: GUILabel +var _total_inc_label: GUILabel # debt -var _national_bank_label : GUILabel -var _total_funds_label : GUILabel -var _debt_val_label : GUILabel -var _interest_val_label : GUILabel +var _national_bank_label: GUILabel +var _total_funds_label: GUILabel +var _debt_val_label: GUILabel +var _interest_val_label: GUILabel # costs -var _nat_stock_val_label : GUILabel -var _nat_stock_exp_label : GUILabel -var _mil_cost_val_label : GUILabel -var _overseas_cost_val_label : GUILabel -var _ind_sub_val_label : GUILabel -var _admin_efficiency_label : GUILabel -var _education_exp_label : GUILabel -var _administration_exp_label : GUILabel -var _social_exp_label : GUILabel -var _military_exp_label : GUILabel -var _total_exp_label : GUILabel +var _nat_stock_val_label: GUILabel +var _nat_stock_exp_label: GUILabel +var _mil_cost_val_label: GUILabel +var _overseas_cost_val_label: GUILabel +var _ind_sub_val_label: GUILabel +var _admin_efficiency_label: GUILabel +var _education_exp_label: GUILabel +var _administration_exp_label: GUILabel +var _social_exp_label: GUILabel +var _military_exp_label: GUILabel +var _total_exp_label: GUILabel # others -var _tariffs_percent_label : GUILabel -var _tariff_val_label : GUILabel -var _diplomatic_balance_label : GUILabel -var _balance_label : GUILabel +var _tariffs_percent_label: GUILabel +var _tariff_val_label: GUILabel +var _diplomatic_balance_label: GUILabel +var _balance_label: GUILabel -var _lower_class_chart : GUIPieChart -var _middle_class_chart : GUIPieChart -var _upper_class_chart : GUIPieChart -var _debt_chart : GUIPieChart +var _lower_class_chart: GUIPieChart +var _middle_class_chart: GUIPieChart +var _upper_class_chart: GUIPieChart +var _debt_chart: GUIPieChart + +const _screen: NationManagement.Screen = NationManagement.Screen.BUDGET -const _screen : NationManagement.Screen = NationManagement.Screen.BUDGET # TODO - testing function, should be replaced with calls to SIM which trigger UI updates through gamestate_updated -func _on_tax_slider_changed(slider : GUIScrollbar, label : GUILabel, tooltip : String, value : int) -> void: +func _on_tax_slider_changed( + slider: GUIScrollbar, label: GUILabel, tooltip: String, value: int +) -> void: label.text = "%s¤" % GUINode.float_to_string_dp(value, 3 if abs(value) < 1000 else 1) slider.set_tooltip_string("%s: §Y%s%%" % [tr(tooltip), GUINode.float_to_string_dp(value, 1)]) @@ -51,15 +54,21 @@ func _on_tax_slider_changed(slider : GUIScrollbar, label : GUILabel, tooltip : S func _ready() -> void: GameSingleton.gamestate_updated.connect(_update_info) - Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + Events.NationManagementScreens.update_active_nation_management_screen.connect( + _on_update_active_nation_management_screen + ) add_gui_element("country_budget", "country_budget") set_click_mask_from_nodepaths([^"./country_budget/main_bg"]) - var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/close_button") + var close_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./country_budget/close_button" + ) if close_button: - close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + close_button.pressed.connect( + Events.NationManagementScreens.close_nation_management_screen.bind(_screen) + ) # labels # income @@ -93,90 +102,165 @@ func _ready() -> void: # sliders # income - var _lower_class_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/tax_0_slider") + var _lower_class_slider: GUIScrollbar = get_gui_scrollbar_from_nodepath( + ^"./country_budget/tax_0_slider" + ) if _lower_class_slider and _lower_class_label: _lower_class_slider.value_changed.connect( - func (value : int) -> void: - _on_tax_slider_changed(_lower_class_slider, _lower_class_label, "BUDGET_TAX_POOR", value) + func(value: int) -> void: + _on_tax_slider_changed( + _lower_class_slider, _lower_class_label, "BUDGET_TAX_POOR", value + ) ) _lower_class_slider.emit_value_changed() - var _middle_class_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/tax_1_slider") + var _middle_class_slider: GUIScrollbar = get_gui_scrollbar_from_nodepath( + ^"./country_budget/tax_1_slider" + ) if _middle_class_slider and _middle_class_label: _middle_class_slider.value_changed.connect( - func (value : int) -> void: - _on_tax_slider_changed(_middle_class_slider, _middle_class_label, "BUDGET_TAX_MIDDLE", value) + func(value: int) -> void: + _on_tax_slider_changed( + _middle_class_slider, _middle_class_label, "BUDGET_TAX_MIDDLE", value + ) ) _middle_class_slider.emit_value_changed() - var _upper_class_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/tax_2_slider") + var _upper_class_slider: GUIScrollbar = get_gui_scrollbar_from_nodepath( + ^"./country_budget/tax_2_slider" + ) if _upper_class_slider and _upper_class_label: _upper_class_slider.value_changed.connect( - func (value : int) -> void: - _on_tax_slider_changed(_upper_class_slider, _upper_class_label, "BUDGET_TAX_RICH", value) + func(value: int) -> void: + _on_tax_slider_changed( + _upper_class_slider, _upper_class_label, "BUDGET_TAX_RICH", value + ) ) _upper_class_slider.emit_value_changed() # costs - var _land_stockpile_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/land_stockpile_slider") + var _land_stockpile_slider: GUIScrollbar = get_gui_scrollbar_from_nodepath( + ^"./country_budget/land_stockpile_slider" + ) if _land_stockpile_slider and _mil_cost_val_label: - _land_stockpile_slider.value_changed.connect(func(value : int) -> void: _mil_cost_val_label.text = "%s¤" % GUINode.float_to_string_dp(value, 2)) + _land_stockpile_slider.value_changed.connect( + func(value: int) -> void: + _mil_cost_val_label.text = "%s¤" % GUINode.float_to_string_dp(value, 2) + ) _land_stockpile_slider.emit_value_changed() - var _naval_stockpile_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/naval_stockpile_slider") + var _naval_stockpile_slider: GUIScrollbar = get_gui_scrollbar_from_nodepath( + ^"./country_budget/naval_stockpile_slider" + ) if _naval_stockpile_slider and _overseas_cost_val_label: - _naval_stockpile_slider.value_changed.connect(func(value : int) -> void: _overseas_cost_val_label.text = "%s¤" % GUINode.float_to_string_dp(value, 1)) + _naval_stockpile_slider.value_changed.connect( + func(value: int) -> void: + _overseas_cost_val_label.text = "%s¤" % GUINode.float_to_string_dp(value, 1) + ) _naval_stockpile_slider.emit_value_changed() - var _projects_stockpile_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/projects_stockpile_slider") + var _projects_stockpile_slider: GUIScrollbar = get_gui_scrollbar_from_nodepath( + ^"./country_budget/projects_stockpile_slider" + ) if _projects_stockpile_slider: if _nat_stock_val_label: - _projects_stockpile_slider.value_changed.connect(func(value : int) -> void: _nat_stock_val_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value)) + _projects_stockpile_slider.value_changed.connect( + func(value: int) -> void: + _nat_stock_val_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value) + ) if _nat_stock_exp_label: - _projects_stockpile_slider.value_changed.connect(func(value : int) -> void: _nat_stock_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value)) + _projects_stockpile_slider.value_changed.connect( + func(value: int) -> void: + _nat_stock_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value) + ) _projects_stockpile_slider.emit_value_changed() - var _exp_0_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/exp_0_slider") + var _exp_0_slider: GUIScrollbar = get_gui_scrollbar_from_nodepath( + ^"./country_budget/exp_0_slider" + ) if _exp_0_slider and _education_exp_label: - _exp_0_slider.value_changed.connect(func(value : int) -> void: _education_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value)) + _exp_0_slider.value_changed.connect( + func(value: int) -> void: + _education_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value) + ) _exp_0_slider.emit_value_changed() - var _exp_1_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/exp_1_slider") + var _exp_1_slider: GUIScrollbar = get_gui_scrollbar_from_nodepath( + ^"./country_budget/exp_1_slider" + ) if _exp_1_slider: if _administration_exp_label: - _exp_1_slider.value_changed.connect(func(value : int) -> void: _administration_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value)) + _exp_1_slider.value_changed.connect( + func(value: int) -> void: + _administration_exp_label.text = ( + "%s¤" % GUINode.float_to_string_dp_dynamic(value) + ) + ) if _admin_efficiency_label: - _exp_1_slider.value_changed.connect(func(value : int) -> void: _admin_efficiency_label.text = "%s%%" % GUINode.float_to_string_dp(value, 1)) + _exp_1_slider.value_changed.connect( + func(value: int) -> void: + _admin_efficiency_label.text = "%s%%" % GUINode.float_to_string_dp(value, 1) + ) _exp_1_slider.emit_value_changed() - var _exp_2_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/exp_2_slider") + var _exp_2_slider: GUIScrollbar = get_gui_scrollbar_from_nodepath( + ^"./country_budget/exp_2_slider" + ) if _exp_2_slider and _social_exp_label: - _exp_2_slider.value_changed.connect(func(value : int) -> void: _social_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value)) + _exp_2_slider.value_changed.connect( + func(value: int) -> void: + _social_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value) + ) _exp_2_slider.emit_value_changed() - var _exp_3_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/exp_3_slider") + var _exp_3_slider: GUIScrollbar = get_gui_scrollbar_from_nodepath( + ^"./country_budget/exp_3_slider" + ) if _exp_3_slider and _military_exp_label: - _exp_3_slider.value_changed.connect(func(value : int) -> void: _military_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value)) + _exp_3_slider.value_changed.connect( + func(value: int) -> void: + _military_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value) + ) _exp_3_slider.emit_value_changed() # others - var _tariff_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/tariff_slider") + var _tariff_slider: GUIScrollbar = get_gui_scrollbar_from_nodepath( + ^"./country_budget/tariff_slider" + ) if _tariff_slider: if _tariff_val_label: - _tariff_slider.value_changed.connect(func(value : int) -> void: _tariff_val_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value)) + _tariff_slider.value_changed.connect( + func(value: int) -> void: + _tariff_val_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value) + ) if _tariffs_percent_label: - _tariff_slider.value_changed.connect(func(value : int) -> void: _tariffs_percent_label.text = "%s%%" % GUINode.float_to_string_dp(value, 1)) + _tariff_slider.value_changed.connect( + func(value: int) -> void: + _tariffs_percent_label.text = "%s%%" % GUINode.float_to_string_dp(value, 1) + ) _tariff_slider.emit_value_changed() # debt buttons - var _tab_takenloans_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/tab_takenloans") + var _tab_takenloans_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./country_budget/tab_takenloans" + ) if _tab_takenloans_button: _tab_takenloans_button.pressed.connect(_switch_loans_tab.bind(true)) - var _tab_givenloans_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/tab_givenloans") + var _tab_givenloans_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./country_budget/tab_givenloans" + ) if _tab_givenloans_button: _tab_givenloans_button.pressed.connect(_switch_loans_tab.bind(false)) - var _debt_sort_country_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/debt_sort_country") + var _debt_sort_country_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./country_budget/debt_sort_country" + ) if _debt_sort_country_button: _debt_sort_country_button.pressed.connect(_sort_loans.bind(true)) - var _debt_sort_amount_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/debt_sort_amount") + var _debt_sort_amount_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./country_budget/debt_sort_amount" + ) if _debt_sort_amount_button: _debt_sort_amount_button.pressed.connect(_sort_loans.bind(false)) - var _take_loan_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/take_loan") + var _take_loan_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./country_budget/take_loan" + ) if _take_loan_button: _take_loan_button.pressed.connect(_take_loan) - var _repay_loan_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/repay_loan") + var _repay_loan_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./country_budget/repay_loan" + ) if _repay_loan_button: _repay_loan_button.pressed.connect(_repay_loan) @@ -190,15 +274,18 @@ func _ready() -> void: _update_info() -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: _update_info() -func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + +func _on_update_active_nation_management_screen(active_screen: NationManagement.Screen) -> void: _active = active_screen == _screen _update_info() + func _update_info() -> void: # TODO - remove _incVal and link the true data with the UI _incVal += 1 @@ -233,8 +320,14 @@ func _update_info() -> void: _total_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(_incVal + 1) if _balance_label: - var balance : float = _incVal * 2.5 - _balance_label.text = "§%s%s¤" % ["G+" if balance > 0.0 else "R" if balance < 0.0 else "Y+", GUINode.float_to_string_dp_dynamic(balance)] + var balance: float = _incVal * 2.5 + _balance_label.text = ( + "§%s%s¤" + % [ + "G+" if balance > 0.0 else "R" if balance < 0.0 else "Y+", + GUINode.float_to_string_dp_dynamic(balance) + ] + ) # TODO - set strata tax and debt charts # TODO - update sliders to reflect changes in limits @@ -244,22 +337,26 @@ func _update_info() -> void: else: hide() -func _switch_loans_tab(taken_loans : bool) -> void: + +func _switch_loans_tab(taken_loans: bool) -> void: # TODO - code the necessary logic #if taken_loans: #else: # given loans pass -func _sort_loans(sort_by_country : bool) -> void: + +func _sort_loans(sort_by_country: bool) -> void: # TODO - code the necessary logic #if sort_by_country: #else: # sort by amount pass + func _take_loan() -> void: # TODO - code the necessary logic pass + func _repay_loan() -> void: # TODO - code the necessary logic pass diff --git a/game/src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd b/game/src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd index bf0d46ed..20c8e3c8 100644 --- a/game/src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd +++ b/game/src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd @@ -1,33 +1,43 @@ extends GUINode -var _active : bool = false +var _active: bool = false + +const _screen: NationManagement.Screen = NationManagement.Screen.DIPLOMACY -const _screen : NationManagement.Screen = NationManagement.Screen.DIPLOMACY func _ready() -> void: GameSingleton.gamestate_updated.connect(_update_info) - Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + Events.NationManagementScreens.update_active_nation_management_screen.connect( + _on_update_active_nation_management_screen + ) add_gui_element("country_diplomacy", "country_diplomacy") set_click_mask_from_nodepaths([^"./country_diplomacy/main_bg"]) - var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_diplomacy/close_button") + var close_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./country_diplomacy/close_button" + ) if close_button: - close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + close_button.pressed.connect( + Events.NationManagementScreens.close_nation_management_screen.bind(_screen) + ) _update_info() -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: _update_info() -func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + +func _on_update_active_nation_management_screen(active_screen: NationManagement.Screen) -> void: _active = active_screen == _screen _update_info() + func _update_info() -> void: if _active: # TODO - update UI state diff --git a/game/src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd b/game/src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd index 11d40d15..b7f1a993 100644 --- a/game/src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd +++ b/game/src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd @@ -1,33 +1,43 @@ extends GUINode -var _active : bool = false +var _active: bool = false + +const _screen: NationManagement.Screen = NationManagement.Screen.MILITARY -const _screen : NationManagement.Screen = NationManagement.Screen.MILITARY func _ready() -> void: GameSingleton.gamestate_updated.connect(_update_info) - Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + Events.NationManagementScreens.update_active_nation_management_screen.connect( + _on_update_active_nation_management_screen + ) add_gui_element("country_military", "country_military") set_click_mask_from_nodepaths([^"./country_military/main_bg"]) - var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_military/close_button") + var close_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./country_military/close_button" + ) if close_button: - close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + close_button.pressed.connect( + Events.NationManagementScreens.close_nation_management_screen.bind(_screen) + ) _update_info() -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: _update_info() -func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + +func _on_update_active_nation_management_screen(active_screen: NationManagement.Screen) -> void: _active = active_screen == _screen _update_info() + func _update_info() -> void: if _active: # TODO - update UI state diff --git a/game/src/Game/GameSession/NationManagementScreen/PoliticsMenu.gd b/game/src/Game/GameSession/NationManagementScreen/PoliticsMenu.gd index aa614215..28e0820e 100644 --- a/game/src/Game/GameSession/NationManagementScreen/PoliticsMenu.gd +++ b/game/src/Game/GameSession/NationManagementScreen/PoliticsMenu.gd @@ -1,33 +1,43 @@ extends GUINode -var _active : bool = false +var _active: bool = false + +const _screen: NationManagement.Screen = NationManagement.Screen.POLITICS -const _screen : NationManagement.Screen = NationManagement.Screen.POLITICS func _ready() -> void: GameSingleton.gamestate_updated.connect(_update_info) - Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + Events.NationManagementScreens.update_active_nation_management_screen.connect( + _on_update_active_nation_management_screen + ) add_gui_element("country_politics", "country_politics") set_click_mask_from_nodepaths([^"./country_politics/main_bg"]) - var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_politics/close_button") + var close_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./country_politics/close_button" + ) if close_button: - close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + close_button.pressed.connect( + Events.NationManagementScreens.close_nation_management_screen.bind(_screen) + ) _update_info() -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: _update_info() -func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + +func _on_update_active_nation_management_screen(active_screen: NationManagement.Screen) -> void: _active = active_screen == _screen _update_info() + func _update_info() -> void: if _active: # TODO - update UI state diff --git a/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd b/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd index 643d550c..0cf545d9 100644 --- a/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd +++ b/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd @@ -1,59 +1,59 @@ extends GUINode -var _active : bool = false - -const _screen : NationManagement.Screen = NationManagement.Screen.POPULATION - -const _scene_name : String = "country_pops" - -var _pop_screen_panel : Panel - -var _province_listbox : GUIListBox -var _province_list_scroll_index : int = 0 -var _province_list_types : Array[MenuSingleton.ProvinceListEntry] -var _province_list_indices : PackedInt32Array -var _province_list_panels : Array[Panel] -var _province_list_buttons : Array[GUIIconButton] -var _province_list_name_labels : Array[GUILabel] -var _province_list_size_labels : Array[GUILabel] -var _province_list_growth_icons : Array[GUIIcon] -var _province_list_colony_buttons : Array[GUIIconButton] -var _province_list_national_focus_buttons : Array[GUIIconButton] -var _province_list_expand_buttons : Array[GUIIconButton] - -var _pop_filter_buttons : Array[GUIIconButton] -var _pop_filter_icons : Array[GFXSpriteTexture] -var _pop_filter_selected_icons : Array[GFXButtonStateTexture] -var _pop_filter_hover_icons : Array[GFXButtonStateTexture] - -var _distribution_charts : Array[GUIPieChart] -var _distribution_lists : Array[GUIListBox] - -var _pop_list_scrollbar : GUIScrollbar -var _pop_list_scroll_index : int = 0 - -var _pop_list_rows : Array[Panel] -var _pop_list_size_labels : Array[GUILabel] -var _pop_list_type_buttons : Array[GUIIconButton] -var _pop_list_producing_icons : Array[GUIIcon] -var _pop_list_culture_labels : Array[GUILabel] -var _pop_list_religion_icons : Array[GUIIcon] -var _pop_list_location_labels : Array[GUILabel] -var _pop_list_militancy_labels : Array[GUILabel] -var _pop_list_consciousness_labels : Array[GUILabel] -var _pop_list_ideology_charts : Array[GUIPieChart] -var _pop_list_issues_charts : Array[GUIPieChart] -var _pop_list_unemployment_progressbars : Array[GUIProgressBar] -var _pop_list_cash_labels : Array[GUILabel] -var _pop_list_life_needs_progressbars : Array[GUIProgressBar] -var _pop_list_everyday_needs_progressbars : Array[GUIProgressBar] -var _pop_list_luxury_needs_progressbars : Array[GUIProgressBar] -var _pop_list_rebel_icons : Array[GUIIcon] -var _pop_list_social_movement_icons : Array[GUIIcon] -var _pop_list_political_movement_icons : Array[GUIIcon] -var _pop_list_national_movement_flags : Array[GUIMaskedFlag] -var _pop_list_size_change_icons : Array[GUIIcon] -var _pop_list_literacy_labels : Array[GUILabel] +var _active: bool = false + +const _screen: NationManagement.Screen = NationManagement.Screen.POPULATION + +const _scene_name: String = "country_pops" + +var _pop_screen_panel: Panel + +var _province_listbox: GUIListBox +var _province_list_scroll_index: int = 0 +var _province_list_types: Array[MenuSingleton.ProvinceListEntry] +var _province_list_indices: PackedInt32Array +var _province_list_panels: Array[Panel] +var _province_list_buttons: Array[GUIIconButton] +var _province_list_name_labels: Array[GUILabel] +var _province_list_size_labels: Array[GUILabel] +var _province_list_growth_icons: Array[GUIIcon] +var _province_list_colony_buttons: Array[GUIIconButton] +var _province_list_national_focus_buttons: Array[GUIIconButton] +var _province_list_expand_buttons: Array[GUIIconButton] + +var _pop_filter_buttons: Array[GUIIconButton] +var _pop_filter_icons: Array[GFXSpriteTexture] +var _pop_filter_selected_icons: Array[GFXButtonStateTexture] +var _pop_filter_hover_icons: Array[GFXButtonStateTexture] + +var _distribution_charts: Array[GUIPieChart] +var _distribution_lists: Array[GUIListBox] + +var _pop_list_scrollbar: GUIScrollbar +var _pop_list_scroll_index: int = 0 + +var _pop_list_rows: Array[Panel] +var _pop_list_size_labels: Array[GUILabel] +var _pop_list_type_buttons: Array[GUIIconButton] +var _pop_list_producing_icons: Array[GUIIcon] +var _pop_list_culture_labels: Array[GUILabel] +var _pop_list_religion_icons: Array[GUIIcon] +var _pop_list_location_labels: Array[GUILabel] +var _pop_list_militancy_labels: Array[GUILabel] +var _pop_list_consciousness_labels: Array[GUILabel] +var _pop_list_ideology_charts: Array[GUIPieChart] +var _pop_list_issues_charts: Array[GUIPieChart] +var _pop_list_unemployment_progressbars: Array[GUIProgressBar] +var _pop_list_cash_labels: Array[GUILabel] +var _pop_list_life_needs_progressbars: Array[GUIProgressBar] +var _pop_list_everyday_needs_progressbars: Array[GUIProgressBar] +var _pop_list_luxury_needs_progressbars: Array[GUIProgressBar] +var _pop_list_rebel_icons: Array[GUIIcon] +var _pop_list_social_movement_icons: Array[GUIIcon] +var _pop_list_political_movement_icons: Array[GUIIcon] +var _pop_list_national_movement_flags: Array[GUIMaskedFlag] +var _pop_list_size_change_icons: Array[GUIIcon] +var _pop_list_literacy_labels: Array[GUILabel] func _ready() -> void: GameSingleton.gamestate_updated.connect(_update_info) @@ -69,7 +69,7 @@ func _ready() -> void: set_click_mask_from_nodepaths([^"./country_pop/main_bg"]) - var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_pop/close_button") + var close_button: GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_pop/close_button") if close_button: close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) @@ -83,7 +83,7 @@ func _ready() -> void: _update_info() -func _generate_province_list_row(index : int, type : MenuSingleton.ProvinceListEntry) -> Error: +func _generate_province_list_row(index: int, type: MenuSingleton.ProvinceListEntry) -> Error: while _province_list_types.size() <= index: _province_list_types.push_back(MenuSingleton.LIST_ENTRY_NONE) _province_list_indices.push_back(-1) @@ -117,13 +117,13 @@ func _generate_province_list_row(index : int, type : MenuSingleton.ProvinceListE if type == MenuSingleton.LIST_ENTRY_NONE: return OK - const gui_element_names : Dictionary = { + const gui_element_names: Dictionary = { MenuSingleton.LIST_ENTRY_COUNTRY: "poplistitem_country", MenuSingleton.LIST_ENTRY_STATE: "poplistitem_state", MenuSingleton.LIST_ENTRY_PROVINCE: "poplistitem_province" } - var entry_panel : Panel = GUINode.generate_gui_element(_scene_name, gui_element_names[type]) + var entry_panel: Panel = GUINode.generate_gui_element(_scene_name, gui_element_names[type]) if not entry_panel: return FAILED @@ -178,28 +178,28 @@ func _setup_province_list() -> void: func _setup_sort_buttons() -> void: # button_path : NodePath, clear_text : bool, sort_key : GameSingleton.PopSortKey - const sort_button_info : Array[Array] = [ - [^"./country_pop/sortby_size_button", false, MenuSingleton.SORT_SIZE], - [^"./country_pop/sortby_type_button", false, MenuSingleton.SORT_TYPE], - [^"./country_pop/sortby_nationality_button", false, MenuSingleton.SORT_CULTURE], - [^"./country_pop/sortby_religion_button", false, MenuSingleton.SORT_RELIGION], - [^"./country_pop/sortby_location_button", false, MenuSingleton.SORT_LOCATION], - [^"./country_pop/sortby_mil_button", true, MenuSingleton.SORT_MILITANCY], - [^"./country_pop/sortby_con_button", true, MenuSingleton.SORT_CONSCIOUSNESS], - [^"./country_pop/sortby_ideology_button", true, MenuSingleton.SORT_IDEOLOGY], - [^"./country_pop/sortby_issues_button", true, MenuSingleton.SORT_ISSUES], - [^"./country_pop/sortby_unemployment_button", true, MenuSingleton.SORT_UNEMPLOYMENT], - [^"./country_pop/sortby_cash_button", true, MenuSingleton.SORT_CASH], - [^"./country_pop/sortby_subsistence_button", true, MenuSingleton.SORT_LIFE_NEEDS], - [^"./country_pop/sortby_eve_button", true, MenuSingleton.SORT_EVERYDAY_NEEDS], - [^"./country_pop/sortby_luxury_button", true, MenuSingleton.SORT_LUXURY_NEEDS], - [^"./country_pop/sortby_revoltrisk_button", true, MenuSingleton.SORT_REBEL_FACTION], - [^"./country_pop/sortby_change_button", true, MenuSingleton.SORT_SIZE_CHANGE], - [^"./country_pop/sortby_literacy_button", true, MenuSingleton.SORT_LITERACY] + const sort_button_info: Array[Array] = [ + [^"./country_pop/sortby_size_button", false, MenuSingleton.SORT_SIZE], + [^"./country_pop/sortby_type_button", false, MenuSingleton.SORT_TYPE], + [^"./country_pop/sortby_nationality_button", false, MenuSingleton.SORT_CULTURE], + [^"./country_pop/sortby_religion_button", false, MenuSingleton.SORT_RELIGION], + [^"./country_pop/sortby_location_button", false, MenuSingleton.SORT_LOCATION], + [^"./country_pop/sortby_mil_button", true, MenuSingleton.SORT_MILITANCY], + [^"./country_pop/sortby_con_button", true, MenuSingleton.SORT_CONSCIOUSNESS], + [^"./country_pop/sortby_ideology_button", true, MenuSingleton.SORT_IDEOLOGY], + [^"./country_pop/sortby_issues_button", true, MenuSingleton.SORT_ISSUES], + [^"./country_pop/sortby_unemployment_button", true, MenuSingleton.SORT_UNEMPLOYMENT], + [^"./country_pop/sortby_cash_button", true, MenuSingleton.SORT_CASH], + [^"./country_pop/sortby_subsistence_button", true, MenuSingleton.SORT_LIFE_NEEDS], + [^"./country_pop/sortby_eve_button", true, MenuSingleton.SORT_EVERYDAY_NEEDS], + [^"./country_pop/sortby_luxury_button", true, MenuSingleton.SORT_LUXURY_NEEDS], + [^"./country_pop/sortby_revoltrisk_button", true, MenuSingleton.SORT_REBEL_FACTION], + [^"./country_pop/sortby_change_button", true, MenuSingleton.SORT_SIZE_CHANGE], + [^"./country_pop/sortby_literacy_button", true, MenuSingleton.SORT_LITERACY] ] - for button_info : Array in sort_button_info: - var sort_button : GUIIconButton = get_gui_icon_button_from_nodepath(button_info[0]) + for button_info: Array in sort_button_info: + var sort_button: GUIIconButton = get_gui_icon_button_from_nodepath(button_info[0]) if sort_button: if button_info[1]: sort_button.set_text("") @@ -210,16 +210,16 @@ func _setup_pop_filter_buttons() -> void: push_error("Cannot set up pop filter buttons without pop screen to add them to") return - var pop_filter_sprite_indices : PackedInt32Array = MenuSingleton.get_population_menu_pop_filter_setup_info() + var pop_filter_sprite_indices: PackedInt32Array = MenuSingleton.get_population_menu_pop_filter_setup_info() - var pop_filter_start : Vector2 = GUINode.get_gui_position(_scene_name, "popfilter_start") - var pop_filter_step : Vector2 = GUINode.get_gui_position(_scene_name, "popfilter_offset") + var pop_filter_start: Vector2 = GUINode.get_gui_position(_scene_name, "popfilter_start") + var pop_filter_step: Vector2 = GUINode.get_gui_position(_scene_name, "popfilter_offset") - for index : int in pop_filter_sprite_indices.size(): - var pop_filter_button : GUIIconButton = GUINode.get_gui_icon_button_from_node(GUINode.generate_gui_element(_scene_name, "pop_filter_button")) - var pop_filter_icon : GFXSpriteTexture = null - var pop_filter_selected_icon : GFXButtonStateTexture = null - var pop_filter_hover_icon : GFXButtonStateTexture = null + for index: int in pop_filter_sprite_indices.size(): + var pop_filter_button: GUIIconButton = GUINode.get_gui_icon_button_from_node(GUINode.generate_gui_element(_scene_name, "pop_filter_button")) + var pop_filter_icon: GFXSpriteTexture = null + var pop_filter_selected_icon: GFXButtonStateTexture = null + var pop_filter_hover_icon: GFXButtonStateTexture = null if pop_filter_button: _pop_screen_panel.add_child(pop_filter_button) @@ -237,11 +237,11 @@ func _setup_pop_filter_buttons() -> void: _pop_filter_selected_icons.push_back(pop_filter_selected_icon) _pop_filter_hover_icons.push_back(pop_filter_hover_icon) - var select_all_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_pop/popfilter_ALL") + var select_all_button: GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_pop/popfilter_ALL") if select_all_button: select_all_button.pressed.connect(MenuSingleton.population_menu_select_all_pop_filters) - var deselect_all_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_pop/popfilter_DESELECT_ALL") + var deselect_all_button: GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_pop/popfilter_DESELECT_ALL") if deselect_all_button: deselect_all_button.pressed.connect(MenuSingleton.population_menu_deselect_all_pop_filters) @@ -250,23 +250,23 @@ func _setup_distribution_windows() -> void: push_error("Cannot set up distribution windows without pop screen to add them to") return - const columns : int = 3 + const columns: int = 3 - var distribution_names : PackedStringArray = MenuSingleton.get_population_menu_distribution_setup_info() + var distribution_names: PackedStringArray = MenuSingleton.get_population_menu_distribution_setup_info() - var distribution_start : Vector2 = GUINode.get_gui_position(_scene_name, "popdistribution_start") - var distribution_step : Vector2 = GUINode.get_gui_position(_scene_name, "popdistribution_offset") + var distribution_start: Vector2 = GUINode.get_gui_position(_scene_name, "popdistribution_start") + var distribution_step: Vector2 = GUINode.get_gui_position(_scene_name, "popdistribution_offset") - for index : int in distribution_names.size(): - var distribution_panel : Panel = GUINode.generate_gui_element(_scene_name, "distribution_window") - var distribution_chart : GUIPieChart = null - var distribution_list : GUIListBox = null + for index: int in distribution_names.size(): + var distribution_panel: Panel = GUINode.generate_gui_element(_scene_name, "distribution_window") + var distribution_chart: GUIPieChart = null + var distribution_list: GUIListBox = null if distribution_panel: _pop_screen_panel.add_child(distribution_panel) distribution_panel.set_position(distribution_start + distribution_step * Vector2(index % columns, index / columns)) - var name_label : GUILabel = GUINode.get_gui_label_from_node(distribution_panel.get_node(^"./item_name")) + var name_label: GUILabel = GUINode.get_gui_label_from_node(distribution_panel.get_node(^"./item_name")) if name_label: name_label.set_text(distribution_names[index]) @@ -279,19 +279,19 @@ func _setup_distribution_windows() -> void: func _setup_pop_list() -> void: _pop_list_scrollbar = get_gui_scrollbar_from_nodepath(^"./country_pop/external_scroll_slider") - var pop_list_panel : Panel = get_panel_from_nodepath(^"./country_pop/pop_list") + var pop_list_panel: Panel = get_panel_from_nodepath(^"./country_pop/pop_list") if not pop_list_panel: return if _pop_list_scrollbar: _pop_list_scrollbar.value_changed.connect( - func (value : int) -> void: + func(value: int) -> void: _pop_list_scroll_index = value _update_pop_list() ) pop_list_panel.gui_input.connect( - func (event : InputEvent) -> void: + func(event: InputEvent) -> void: if event is InputEventMouseButton: if event.is_pressed(): if event.get_button_index() == MOUSE_BUTTON_WHEEL_UP: @@ -300,9 +300,9 @@ func _setup_pop_list() -> void: _pop_list_scrollbar.increment_value() ) - var height : float = 0.0 + var height: float = 0.0 while height < pop_list_panel.size.y: - var pop_row_panel : Panel = GUINode.generate_gui_element(_scene_name, "popinfomember_popview") + var pop_row_panel: Panel = GUINode.generate_gui_element(_scene_name, "popinfomember_popview") if not pop_row_panel: break @@ -313,7 +313,7 @@ func _setup_pop_list() -> void: _pop_list_size_labels.push_back(GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_size"))) - var pop_type_button : GUIIconButton = GUINode.get_gui_icon_button_from_node(pop_row_panel.get_node(^"./pop_type")) + var pop_type_button: GUIIconButton = GUINode.get_gui_icon_button_from_node(pop_row_panel.get_node(^"./pop_type")) # TODO - open pop details menu on pop type button press _pop_list_type_buttons.push_back(pop_type_button) @@ -337,12 +337,12 @@ func _setup_pop_list() -> void: _pop_list_cash_labels.push_back(GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_cash"))) - var pop_list_life_needs_progressbar : GUIProgressBar = GUINode.get_gui_progress_bar_from_node(pop_row_panel.get_node(^"./lifeneed_progress")) + var pop_list_life_needs_progressbar: GUIProgressBar = GUINode.get_gui_progress_bar_from_node(pop_row_panel.get_node(^"./lifeneed_progress")) _pop_list_life_needs_progressbars.push_back(pop_list_life_needs_progressbar) if pop_list_life_needs_progressbar: pop_list_life_needs_progressbar.position += Vector2(1, 0) - var pop_list_everyday_needs_progressbar : GUIProgressBar = GUINode.get_gui_progress_bar_from_node(pop_row_panel.get_node(^"./eveneed_progress")) + var pop_list_everyday_needs_progressbar: GUIProgressBar = GUINode.get_gui_progress_bar_from_node(pop_row_panel.get_node(^"./eveneed_progress")) _pop_list_everyday_needs_progressbars.push_back(pop_list_everyday_needs_progressbar) if pop_list_everyday_needs_progressbar: pop_list_everyday_needs_progressbar.position += Vector2(1, 0) @@ -361,13 +361,13 @@ func _setup_pop_list() -> void: _pop_list_literacy_labels.push_back(GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_literacy"))) -func _notification(what : int) -> void: +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: MenuSingleton.population_menu_update_locale_sort_cache() _update_info() -func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: +func _on_update_active_nation_management_screen(active_screen: NationManagement.Screen) -> void: _active = active_screen == _screen _update_info() @@ -383,10 +383,10 @@ func _update_info() -> void: else: hide() -func get_growth_icon_index(size_change : int) -> int: +func get_growth_icon_index(size_change: int) -> int: return 1 + int(size_change <= 0) + int(size_change < 0) -func _update_province_list(scroll_index : int = -1) -> void: +func _update_province_list(scroll_index: int = -1) -> void: if not _province_listbox: return @@ -395,21 +395,21 @@ func _update_province_list(scroll_index : int = -1) -> void: _province_list_scroll_index = _province_listbox.get_scroll_index() - var province_list_info_list : Array[Dictionary] = MenuSingleton.get_population_menu_province_list_rows(_province_list_scroll_index, _province_listbox.get_fixed_visible_items()) + var province_list_info_list: Array[Dictionary] = MenuSingleton.get_population_menu_province_list_rows(_province_list_scroll_index, _province_listbox.get_fixed_visible_items()) - for index : int in province_list_info_list.size(): - const type_key : StringName = &"type" - const index_key : StringName = &"index" - const name_key : StringName = &"name" - const size_key : StringName = &"size" - const change_key : StringName = &"change" - const selected_key : StringName = &"selected" - const expanded_key : StringName = &"expanded" - const colony_key : StringName = &"colony" + for index: int in province_list_info_list.size(): + const type_key: StringName = &"type" + const index_key: StringName = &"index" + const name_key: StringName = &"name" + const size_key: StringName = &"size" + const change_key: StringName = &"change" + const selected_key: StringName = &"selected" + const expanded_key: StringName = &"expanded" + const colony_key: StringName = &"colony" - var province_list_info : Dictionary = province_list_info_list[index] + var province_list_info: Dictionary = province_list_info_list[index] - var type : MenuSingleton.ProvinceListEntry = province_list_info[type_key] + var type: MenuSingleton.ProvinceListEntry = province_list_info[type_key] if _generate_province_list_row(index, type) != OK: continue @@ -444,7 +444,7 @@ func _update_province_list(scroll_index : int = -1) -> void: # TODO - set _province_list_national_focus_buttons[index] # Clear any excess rows - for index : int in range(province_list_info_list.size(), _province_list_types.size()): + for index: int in range(province_list_info_list.size(), _province_list_types.size()): _generate_province_list_row(index, MenuSingleton.LIST_ENTRY_NONE) func _update_pops() -> void: @@ -453,22 +453,22 @@ func _update_pops() -> void: _update_pop_list() func _update_pop_filters() -> void: - var pop_filter_info_list : Array[Dictionary] = MenuSingleton.get_population_menu_pop_filter_info() + var pop_filter_info_list: Array[Dictionary] = MenuSingleton.get_population_menu_pop_filter_info() - for index : int in pop_filter_info_list.size(): - const pop_filter_count_key : StringName = &"count" - const pop_filter_change_key : StringName = &"change" - const pop_filter_selected_key : StringName = &"selected" + for index: int in pop_filter_info_list.size(): + const pop_filter_count_key: StringName = &"count" + const pop_filter_change_key: StringName = &"change" + const pop_filter_selected_key: StringName = &"selected" - var pop_filter_info : Dictionary = pop_filter_info_list[index] + var pop_filter_info: Dictionary = pop_filter_info_list[index] - var pop_filter_button : GUIIconButton = _pop_filter_buttons[index] + var pop_filter_button: GUIIconButton = _pop_filter_buttons[index] if not pop_filter_button: continue pop_filter_button.disabled = pop_filter_info[pop_filter_count_key] <= 0 - const normal_theme : StringName = &"normal" - const hover_theme : StringName = &"hover" + const normal_theme: StringName = &"normal" + const hover_theme: StringName = &"hover" if pop_filter_info[pop_filter_selected_key] or pop_filter_button.disabled: pop_filter_button.get_theme_stylebox(normal_theme).set_texture(_pop_filter_icons[index]) @@ -479,39 +479,39 @@ func _update_pop_filters() -> void: # TODO - size and promotion/demotion change tooltip func _update_distributions(): - const slice_identifier_key : StringName = &"identifier" - const slice_colour_key : StringName = &"colour" - const slice_weight_key : StringName = &"weight" + const slice_identifier_key: StringName = &"identifier" + const slice_colour_key: StringName = &"colour" + const slice_weight_key: StringName = &"weight" - var distribution_info_list : Array[Array] = MenuSingleton.get_population_menu_distribution_info() + var distribution_info_list: Array[Array] = MenuSingleton.get_population_menu_distribution_info() - for distribution_index : int in distribution_info_list.size(): - var distribution_info : Array[Dictionary] = distribution_info_list[distribution_index] + for distribution_index: int in distribution_info_list.size(): + var distribution_info: Array[Dictionary] = distribution_info_list[distribution_index] if _distribution_charts[distribution_index]: _distribution_charts[distribution_index].set_slices_array(distribution_info) if _distribution_lists[distribution_index]: - distribution_info.sort_custom(func(a : Dictionary, b : Dictionary) -> bool: return a[slice_weight_key] > b[slice_weight_key]) + distribution_info.sort_custom(func(a: Dictionary, b: Dictionary) -> bool: return a[slice_weight_key] > b[slice_weight_key]) - var list : GUIListBox = _distribution_lists[distribution_index] + var list: GUIListBox = _distribution_lists[distribution_index] list.clear_children(distribution_info.size()) while list.get_child_count() < distribution_info.size(): - var child : Panel = GUINode.generate_gui_element(_scene_name, "pop_legend_item") + var child: Panel = GUINode.generate_gui_element(_scene_name, "pop_legend_item") if not child: break child.set_mouse_filter(Control.MOUSE_FILTER_IGNORE) list.add_child(child) - for list_index : int in min(list.get_child_count(), distribution_info.size()): + for list_index: int in min(list.get_child_count(), distribution_info.size()): - var child : Panel = list.get_child(list_index) + var child: Panel = list.get_child(list_index) - var distribution_row : Dictionary = distribution_info[list_index] + var distribution_row: Dictionary = distribution_info[list_index] - var colour_icon : GUIIcon = GUINode.get_gui_icon_from_node(child.get_node(^"./legend_color")) + var colour_icon: GUIIcon = GUINode.get_gui_icon_from_node(child.get_node(^"./legend_color")) if colour_icon: colour_icon.set_modulate(distribution_row[slice_colour_key]) colour_icon.set_tooltip_string_and_substitution_dict( @@ -522,17 +522,17 @@ func _update_distributions(): } ) - var identifier_label : GUILabel = GUINode.get_gui_label_from_node(child.get_node(^"./legend_title")) + var identifier_label: GUILabel = GUINode.get_gui_label_from_node(child.get_node(^"./legend_title")) if identifier_label: identifier_label.set_text(distribution_row[slice_identifier_key]) - var weight_label : GUILabel = GUINode.get_gui_label_from_node(child.get_node(^"./legend_value")) + var weight_label: GUILabel = GUINode.get_gui_label_from_node(child.get_node(^"./legend_value")) if weight_label: weight_label.set_text("%s%%" % GUINode.float_to_string_dp(distribution_row[slice_weight_key] * 100.0, 1)) func _update_pop_list() -> void: if _pop_list_scrollbar: - var max_scroll_index : int = MenuSingleton.get_population_menu_pop_row_count() - _pop_list_rows.size() + var max_scroll_index: int = MenuSingleton.get_population_menu_pop_row_count() - _pop_list_rows.size() if max_scroll_index > 0: _pop_list_scrollbar.set_limits(0, max_scroll_index) _pop_list_scrollbar.show() @@ -542,29 +542,29 @@ func _update_pop_list() -> void: var pop_rows = MenuSingleton.get_population_menu_pop_rows(_pop_list_scroll_index, _pop_list_rows.size()) - for index : int in _pop_list_rows.size(): + for index: int in _pop_list_rows.size(): if not _pop_list_rows[index]: continue if index < pop_rows.size(): - const pop_size_key : StringName = &"size" - const pop_type_icon_key : StringName = &"pop_type_icon" - const pop_culture_key : StringName = &"culture" - const pop_religion_icon_key : StringName = &"religion_icon" - const pop_location_key : StringName = &"location" - const pop_militancy_key : StringName = &"militancy" - const pop_consciousness_key : StringName = &"consciousness" - const pop_ideology_key : StringName = &"ideology" - const pop_issues_key : StringName = &"issues" - const pop_unemployment_key : StringName = &"unemployment" - const pop_cash_key : StringName = &"cash" - const pop_life_needs_key : StringName = &"life_needs" - const pop_everyday_needs_key : StringName = &"everyday_needs" - const pop_luxury_needs_key : StringName = &"luxury_needs" - const pop_rebel_icon_key : StringName = &"rebel_icon" - const pop_size_change_key : StringName = &"size_change" - const pop_literacy_key : StringName = &"literacy" - - var pop_row : Dictionary = pop_rows[index] + const pop_size_key: StringName = &"size" + const pop_type_icon_key: StringName = &"pop_type_icon" + const pop_culture_key: StringName = &"culture" + const pop_religion_icon_key: StringName = &"religion_icon" + const pop_location_key: StringName = &"location" + const pop_militancy_key: StringName = &"militancy" + const pop_consciousness_key: StringName = &"consciousness" + const pop_ideology_key: StringName = &"ideology" + const pop_issues_key: StringName = &"issues" + const pop_unemployment_key: StringName = &"unemployment" + const pop_cash_key: StringName = &"cash" + const pop_life_needs_key: StringName = &"life_needs" + const pop_everyday_needs_key: StringName = &"everyday_needs" + const pop_luxury_needs_key: StringName = &"luxury_needs" + const pop_rebel_icon_key: StringName = &"rebel_icon" + const pop_size_change_key: StringName = &"size_change" + const pop_literacy_key: StringName = &"literacy" + + var pop_row: Dictionary = pop_rows[index] if _pop_list_size_labels[index]: _pop_list_size_labels[index].set_text(GUINode.int_to_string_suffixed(pop_row[pop_size_key])) @@ -580,7 +580,7 @@ func _update_pop_list() -> void: # TODO - replace with actual religion _pop_list_religion_icons[index].set_tooltip_string("Religion #%d" % pop_row[pop_religion_icon_key]) if _pop_list_location_labels[index]: - var province_name : String = GUINode.format_province_name(pop_row.get(pop_location_key, "")) + var province_name: String = GUINode.format_province_name(pop_row.get(pop_location_key, "")) _pop_list_location_labels[index].set_text(province_name) _pop_list_location_labels[index].set_tooltip_string(province_name) if _pop_list_militancy_labels[index]: @@ -596,7 +596,7 @@ func _update_pop_list() -> void: if _pop_list_issues_charts[index]: _pop_list_issues_charts[index].set_slices_array(pop_row[pop_issues_key]) if _pop_list_unemployment_progressbars[index]: - var unemployment : float = pop_row[pop_unemployment_key] + var unemployment: float = pop_row[pop_unemployment_key] _pop_list_unemployment_progressbars[index].set_value_no_signal(unemployment) _pop_list_unemployment_progressbars[index].set_tooltip_string("%s: §Y%s%%" % [ tr("UNEMPLOYMENT"), GUINode.float_to_string_dp(unemployment * 100.0, 3) @@ -607,25 +607,25 @@ func _update_pop_list() -> void: "VAL": GUINode.float_to_string_dp(1.23, 2) }) if _pop_list_life_needs_progressbars[index]: - var life_needs : float = pop_row[pop_life_needs_key] + var life_needs: float = pop_row[pop_life_needs_key] _pop_list_life_needs_progressbars[index].set_value_no_signal(life_needs) _pop_list_life_needs_progressbars[index].set_tooltip_string_and_substitution_dict("GETTING_NEEDS", { "NEED": "LIFE_NEEDS", "VAL": GUINode.float_to_string_dp(life_needs * 100.0, 1) }) if _pop_list_everyday_needs_progressbars[index]: - var everyday_needs : float = pop_row[pop_everyday_needs_key] + var everyday_needs: float = pop_row[pop_everyday_needs_key] _pop_list_everyday_needs_progressbars[index].set_value_no_signal(everyday_needs) _pop_list_everyday_needs_progressbars[index].set_tooltip_string_and_substitution_dict("GETTING_NEEDS", { "NEED": "EVERYDAY_NEEDS", "VAL": GUINode.float_to_string_dp(everyday_needs * 100.0, 1) }) if _pop_list_luxury_needs_progressbars[index]: - var luxury_needs : float = pop_row[pop_luxury_needs_key] + var luxury_needs: float = pop_row[pop_luxury_needs_key] _pop_list_luxury_needs_progressbars[index].set_value_no_signal(luxury_needs) _pop_list_luxury_needs_progressbars[index].set_tooltip_string_and_substitution_dict("GETTING_NEEDS", { "NEED": "LUXURY_NEEDS", "VAL": GUINode.float_to_string_dp(luxury_needs * 100.0, 1) }) if _pop_list_rebel_icons[index]: - var rebel_icon : int = pop_row.get(pop_rebel_icon_key, 0) + var rebel_icon: int = pop_row.get(pop_rebel_icon_key, 0) if rebel_icon > 0: _pop_list_rebel_icons[index].set_icon_index(rebel_icon) _pop_list_rebel_icons[index].show() @@ -641,7 +641,7 @@ func _update_pop_list() -> void: _pop_list_national_movement_flags[index].hide() if _pop_list_size_change_icons[index]: - var pop_change : int = pop_row[pop_size_change_key] + var pop_change: int = pop_row[pop_size_change_key] _pop_list_size_change_icons[index].set_icon_index(get_growth_icon_index(pop_change)) _pop_list_size_change_icons[index].set_tooltip_string("%s §%s%s" % [ tr("POPULATION_CHANGED_BY"), "G+" if pop_change > 0 else "Y+" if pop_change == 0 else "R", str(pop_change) diff --git a/game/src/Game/GameSession/NationManagementScreen/ProductionMenu.gd b/game/src/Game/GameSession/NationManagementScreen/ProductionMenu.gd index c83a3516..4b770087 100644 --- a/game/src/Game/GameSession/NationManagementScreen/ProductionMenu.gd +++ b/game/src/Game/GameSession/NationManagementScreen/ProductionMenu.gd @@ -1,36 +1,48 @@ extends GUINode -var _active : bool = false +var _active: bool = false + +const _screen: NationManagement.Screen = NationManagement.Screen.PRODUCTION -const _screen : NationManagement.Screen = NationManagement.Screen.PRODUCTION func _ready() -> void: GameSingleton.gamestate_updated.connect(_update_info) - Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + Events.NationManagementScreens.update_active_nation_management_screen.connect( + _on_update_active_nation_management_screen + ) add_gui_element("country_production", "country_production") - var project_listbox : GUIListBox = get_gui_listbox_from_nodepath(^"./country_production/good_production/project_listbox") + var project_listbox: GUIListBox = get_gui_listbox_from_nodepath( + ^"./country_production/good_production/project_listbox" + ) if project_listbox: project_listbox.mouse_filter = Control.MOUSE_FILTER_IGNORE set_click_mask_from_nodepaths([^"./country_production/main_bg"]) - var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_production/close_button") + var close_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./country_production/close_button" + ) if close_button: - close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + close_button.pressed.connect( + Events.NationManagementScreens.close_nation_management_screen.bind(_screen) + ) _update_info() -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: _update_info() -func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + +func _on_update_active_nation_management_screen(active_screen: NationManagement.Screen) -> void: _active = active_screen == _screen _update_info() + func _update_info() -> void: if _active: # TODO - update UI state diff --git a/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd b/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd index 8386fef3..a0b5c5d4 100644 --- a/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd +++ b/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd @@ -1,33 +1,43 @@ extends GUINode -var _active : bool = false +var _active: bool = false + +const _screen: NationManagement.Screen = NationManagement.Screen.TECHNOLOGY -const _screen : NationManagement.Screen = NationManagement.Screen.TECHNOLOGY func _ready() -> void: GameSingleton.gamestate_updated.connect(_update_info) - Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + Events.NationManagementScreens.update_active_nation_management_screen.connect( + _on_update_active_nation_management_screen + ) add_gui_element("country_technology", "country_technology") set_click_mask_from_nodepaths([^"./country_technology/main_bg"]) - var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_technology/close_button") + var close_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./country_technology/close_button" + ) if close_button: - close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + close_button.pressed.connect( + Events.NationManagementScreens.close_nation_management_screen.bind(_screen) + ) _update_info() -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: _update_info() -func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + +func _on_update_active_nation_management_screen(active_screen: NationManagement.Screen) -> void: _active = active_screen == _screen _update_info() + func _update_info() -> void: if _active: # TODO - update UI state diff --git a/game/src/Game/GameSession/NationManagementScreen/TradeMenu.gd b/game/src/Game/GameSession/NationManagementScreen/TradeMenu.gd index 4c9cd773..042bba39 100644 --- a/game/src/Game/GameSession/NationManagementScreen/TradeMenu.gd +++ b/game/src/Game/GameSession/NationManagementScreen/TradeMenu.gd @@ -1,33 +1,43 @@ extends GUINode -var _active : bool = false +var _active: bool = false + +const _screen: NationManagement.Screen = NationManagement.Screen.TRADE -const _screen : NationManagement.Screen = NationManagement.Screen.TRADE func _ready() -> void: GameSingleton.gamestate_updated.connect(_update_info) - Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + Events.NationManagementScreens.update_active_nation_management_screen.connect( + _on_update_active_nation_management_screen + ) add_gui_element("country_trade", "country_trade") set_click_mask_from_nodepaths([^"./country_trade/main_bg"]) - var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_trade/close_button") + var close_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./country_trade/close_button" + ) if close_button: - close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + close_button.pressed.connect( + Events.NationManagementScreens.close_nation_management_screen.bind(_screen) + ) _update_info() -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: _update_info() -func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + +func _on_update_active_nation_management_screen(active_screen: NationManagement.Screen) -> void: _active = active_screen == _screen _update_info() + func _update_info() -> void: if _active: # TODO - update UI state diff --git a/game/src/Game/GameSession/ProvinceOverviewPanel.gd b/game/src/Game/GameSession/ProvinceOverviewPanel.gd index 86d93329..2a19e7ea 100644 --- a/game/src/Game/GameSession/ProvinceOverviewPanel.gd +++ b/game/src/Game/GameSession/ProvinceOverviewPanel.gd @@ -1,55 +1,56 @@ extends GUINode # Header -var _province_name_label : GUILabel -var _state_name_label : GUILabel -var _slave_status_icon : GUIIcon -var _colony_status_button : GUIIconButton -var _administrative_percentage_label : GUILabel -var _owner_percentage_label : GUILabel -var _province_modifiers_overlapping_elements_box : GUIOverlappingElementsBox -var _terrain_type_icon : GUIIcon -var _life_rating_bar : GUIProgressBar -var _controller_flag : GUIMaskedFlag +var _province_name_label: GUILabel +var _state_name_label: GUILabel +var _slave_status_icon: GUIIcon +var _colony_status_button: GUIIconButton +var _administrative_percentage_label: GUILabel +var _owner_percentage_label: GUILabel +var _province_modifiers_overlapping_elements_box: GUIOverlappingElementsBox +var _terrain_type_icon: GUIIcon +var _life_rating_bar: GUIProgressBar +var _controller_flag: GUIMaskedFlag # Statistics -var _rgo_icon : GUIIcon -var _rgo_produced_label : GUILabel -var _rgo_income_label : GUILabel -var _rgo_employment_percentage_icon : GUIIcon -var _rgo_employment_population_label : GUILabel -var _rgo_employment_percentage_label : GUILabel -var _crime_name_label : GUILabel -var _crime_icon : GUIIcon -var _crime_fighting_label : GUILabel -var _total_population_label : GUILabel -var _migration_label : GUILabel -var _population_growth_label : GUILabel -var _pop_types_piechart : GUIPieChart -var _pop_ideologies_piechart : GUIPieChart -var _pop_cultures_piechart : GUIPieChart -var _supply_limit_label : GUILabel -var _cores_overlapping_elements_box : GUIOverlappingElementsBox +var _rgo_icon: GUIIcon +var _rgo_produced_label: GUILabel +var _rgo_income_label: GUILabel +var _rgo_employment_percentage_icon: GUIIcon +var _rgo_employment_population_label: GUILabel +var _rgo_employment_percentage_label: GUILabel +var _crime_name_label: GUILabel +var _crime_icon: GUIIcon +var _crime_fighting_label: GUILabel +var _total_population_label: GUILabel +var _migration_label: GUILabel +var _population_growth_label: GUILabel +var _pop_types_piechart: GUIPieChart +var _pop_ideologies_piechart: GUIPieChart +var _pop_cultures_piechart: GUIPieChart +var _supply_limit_label: GUILabel +var _cores_overlapping_elements_box: GUIOverlappingElementsBox # Buildings -var _buildings_panel : Panel -var _building_slots : Array[BuildingSlot] +var _buildings_panel: Panel +var _building_slots: Array[BuildingSlot] + # REQUIREMENTS: # * UI-183, UI-185, UI-186, UI-765, UI-187, UI-188, UI-189 # * UI-191, UI-193, UI-194, UI-766, UI-195, UI-196, UI-197 # * UI-199, UI-201, UI-202, UI-767, UI-203, UI-204, UI-205 class BuildingSlot: - var _slot_index : int - var _slot_node : Control + var _slot_index: int + var _slot_node: Control - var _building_icon : GUIIcon - var _expand_button : GUIIconButton - var _expanding_icon : GUIIcon - var _expanding_progress_bar : GUIProgressBar - var _expanding_label : GUILabel + var _building_icon: GUIIcon + var _expand_button: GUIIconButton + var _expanding_icon: GUIIcon + var _expanding_progress_bar: GUIProgressBar + var _expanding_label: GUILabel - func _init(new_slot_index : int, new_slot_node : Control) -> void: + func _init(new_slot_index: int, new_slot_node: Control) -> void: if new_slot_index < 0: push_error("Invalid building slot index: ", new_slot_index) return @@ -59,7 +60,7 @@ class BuildingSlot: return _slot_node = new_slot_node - for icon_index : int in MenuSingleton.get_province_building_count(): + for icon_index: int in MenuSingleton.get_province_building_count(): var icon := _slot_node.get_node("build_icon%d" % icon_index) if icon: if icon_index == _slot_index: @@ -72,9 +73,15 @@ class BuildingSlot: building_name.text = MenuSingleton.get_province_building_identifier(_slot_index) _expand_button = GUINode.get_gui_icon_button_from_node(_slot_node.get_node(^"./expand")) if _expand_button: - _expand_button.pressed.connect(func() -> void: MenuSingleton.expand_selected_province_building(_slot_index)) - _expanding_icon = GUINode.get_gui_icon_from_node(_slot_node.get_node(^"./underconstruction_icon")) - _expanding_progress_bar = GUINode.get_gui_progress_bar_from_node(_slot_node.get_node(^"./building_progress")) + _expand_button.pressed.connect( + func() -> void: MenuSingleton.expand_selected_province_building(_slot_index) + ) + _expanding_icon = GUINode.get_gui_icon_from_node( + _slot_node.get_node(^"./underconstruction_icon") + ) + _expanding_progress_bar = GUINode.get_gui_progress_bar_from_node( + _slot_node.get_node(^"./building_progress") + ) if _expanding_progress_bar: _expanding_progress_bar.max_value = 1.0 _expanding_progress_bar.step = _expanding_progress_bar.max_value / 100 @@ -82,18 +89,23 @@ class BuildingSlot: enum ExpansionState { CannotExpand, CanExpand, Preparing, Expanding } - func update_info(info : Dictionary) -> void: - const building_info_level_key : StringName = &"level" - const building_info_expansion_state_key : StringName = &"expansion_state" - const building_info_start_date_key : StringName = &"start_date" - const building_info_end_date_key : StringName = &"end_date" - const building_info_expansion_progress_key : StringName = &"expansion_progress" + func update_info(info: Dictionary) -> void: + const building_info_level_key: StringName = &"level" + const building_info_expansion_state_key: StringName = &"expansion_state" + const building_info_start_date_key: StringName = &"start_date" + const building_info_end_date_key: StringName = &"end_date" + const building_info_expansion_progress_key: StringName = &"expansion_progress" if _building_icon: _building_icon.set_icon_index(info.get(building_info_level_key, 0) + 1) - var expansion_state : int = info.get(building_info_expansion_state_key, ExpansionState.CannotExpand) - var expansion_in_progress : bool = expansion_state == ExpansionState.Preparing or expansion_state == ExpansionState.Expanding + var expansion_state: int = info.get( + building_info_expansion_state_key, ExpansionState.CannotExpand + ) + var expansion_in_progress: bool = ( + expansion_state == ExpansionState.Preparing + or expansion_state == ExpansionState.Expanding + ) if _expand_button: _expand_button.visible = not expansion_in_progress @@ -109,12 +121,15 @@ class BuildingSlot: if _expanding_label: _expanding_label.visible = expansion_in_progress -var _selected_index : int: - get: return _selected_index + +var _selected_index: int: + get: + return _selected_index set(v): _selected_index = v _update_info() -var _province_info : Dictionary +var _province_info: Dictionary + func _ready() -> void: GameSingleton.province_selected.connect(_on_province_selected) @@ -130,145 +145,232 @@ func _ready() -> void: prov_view.mouse_filter = Control.MOUSE_FILTER_IGNORE set_click_mask_from_nodepaths([^"./province_view/background"]) - var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./province_view/close_button") + var close_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./province_view/close_button" + ) if close_button: close_button.pressed.connect(_on_close_button_pressed) # Header - _province_name_label = get_gui_label_from_nodepath(^"./province_view/province_view_header/province_name") - _state_name_label = get_gui_label_from_nodepath(^"./province_view/province_view_header/state_name") + _province_name_label = get_gui_label_from_nodepath( + ^"./province_view/province_view_header/province_name" + ) + _state_name_label = get_gui_label_from_nodepath( + ^"./province_view/province_view_header/state_name" + ) if _state_name_label: # State names are already translated in the MenuSingleton _state_name_label.auto_translate = false - _slave_status_icon = get_gui_icon_from_nodepath(^"./province_view/province_view_header/slave_state_icon") + _slave_status_icon = get_gui_icon_from_nodepath( + ^"./province_view/province_view_header/slave_state_icon" + ) if _slave_status_icon: _slave_status_icon.set_icon_index(MenuSingleton.get_slave_pop_icon_index()) - _colony_status_button = get_gui_icon_button_from_nodepath(^"./province_view/province_view_header/colony_button") - var admin_icon : GUIIcon = get_gui_icon_from_nodepath(^"./province_view/province_view_header/admin_icon") + _colony_status_button = get_gui_icon_button_from_nodepath( + ^"./province_view/province_view_header/colony_button" + ) + var admin_icon: GUIIcon = get_gui_icon_from_nodepath( + ^"./province_view/province_view_header/admin_icon" + ) if admin_icon: admin_icon.set_icon_index(MenuSingleton.get_administrative_pop_icon_index()) - _administrative_percentage_label = get_gui_label_from_nodepath(^"./province_view/province_view_header/admin_efficiency") - _owner_percentage_label = get_gui_label_from_nodepath(^"./province_view/province_view_header/owner_presence") - _province_modifiers_overlapping_elements_box = get_gui_overlapping_elements_box_from_nodepath(^"./province_view/province_view_header/province_modifiers") - if _province_modifiers_overlapping_elements_box and _province_modifiers_overlapping_elements_box.set_gui_child_element_name("province_interface", "prov_state_modifier") != OK: - _province_modifiers_overlapping_elements_box = null # hide province modifiers box since we can't do anything with it - _terrain_type_icon = get_gui_icon_from_nodepath(^"./province_view/province_view_header/prov_terrain") - _life_rating_bar = get_gui_progress_bar_from_nodepath(^"./province_view/province_view_header/liferating") - _controller_flag = get_gui_masked_flag_from_nodepath(^"./province_view/province_view_header/controller_flag") + _administrative_percentage_label = get_gui_label_from_nodepath( + ^"./province_view/province_view_header/admin_efficiency" + ) + _owner_percentage_label = get_gui_label_from_nodepath( + ^"./province_view/province_view_header/owner_presence" + ) + _province_modifiers_overlapping_elements_box = get_gui_overlapping_elements_box_from_nodepath( + ^"./province_view/province_view_header/province_modifiers" + ) + if ( + _province_modifiers_overlapping_elements_box + and ( + _province_modifiers_overlapping_elements_box.set_gui_child_element_name( + "province_interface", "prov_state_modifier" + ) + != OK + ) + ): + _province_modifiers_overlapping_elements_box = null # hide province modifiers box since we can't do anything with it + _terrain_type_icon = get_gui_icon_from_nodepath( + ^"./province_view/province_view_header/prov_terrain" + ) + _life_rating_bar = get_gui_progress_bar_from_nodepath( + ^"./province_view/province_view_header/liferating" + ) + _controller_flag = get_gui_masked_flag_from_nodepath( + ^"./province_view/province_view_header/controller_flag" + ) # Statistics _rgo_icon = get_gui_icon_from_nodepath(^"./province_view/province_statistics/goods_type") - _rgo_produced_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/produced") + _rgo_produced_label = get_gui_label_from_nodepath( + ^"./province_view/province_statistics/produced" + ) _rgo_income_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/income") - _rgo_employment_percentage_icon = get_gui_icon_from_nodepath(^"./province_view/province_statistics/employment_ratio") - _rgo_employment_population_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/rgo_population") - _rgo_employment_percentage_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/rgo_percent") - _crime_name_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/crime_name") + _rgo_employment_percentage_icon = get_gui_icon_from_nodepath( + ^"./province_view/province_statistics/employment_ratio" + ) + _rgo_employment_population_label = get_gui_label_from_nodepath( + ^"./province_view/province_statistics/rgo_population" + ) + _rgo_employment_percentage_label = get_gui_label_from_nodepath( + ^"./province_view/province_statistics/rgo_percent" + ) + _crime_name_label = get_gui_label_from_nodepath( + ^"./province_view/province_statistics/crime_name" + ) _crime_icon = get_gui_icon_from_nodepath(^"./province_view/province_statistics/crime_icon") - _crime_fighting_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/crimefight_percent") - _total_population_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/total_population") + _crime_fighting_label = get_gui_label_from_nodepath( + ^"./province_view/province_statistics/crimefight_percent" + ) + _total_population_label = get_gui_label_from_nodepath( + ^"./province_view/province_statistics/total_population" + ) _migration_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/migration") - _population_growth_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/growth") - _pop_types_piechart = get_gui_pie_chart_from_nodepath(^"./province_view/province_statistics/workforce_chart") - _pop_ideologies_piechart = get_gui_pie_chart_from_nodepath(^"./province_view/province_statistics/ideology_chart") - _pop_cultures_piechart = get_gui_pie_chart_from_nodepath(^"./province_view/province_statistics/culture_chart") - var population_menu_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./province_view/province_statistics/open_popscreen") + _population_growth_label = get_gui_label_from_nodepath( + ^"./province_view/province_statistics/growth" + ) + _pop_types_piechart = get_gui_pie_chart_from_nodepath( + ^"./province_view/province_statistics/workforce_chart" + ) + _pop_ideologies_piechart = get_gui_pie_chart_from_nodepath( + ^"./province_view/province_statistics/ideology_chart" + ) + _pop_cultures_piechart = get_gui_pie_chart_from_nodepath( + ^"./province_view/province_statistics/culture_chart" + ) + var population_menu_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./province_view/province_statistics/open_popscreen" + ) if population_menu_button: population_menu_button.pressed.connect( func() -> void: MenuSingleton.population_menu_select_province(_selected_index) _on_close_button_pressed() - Events.NationManagementScreens.open_nation_management_screen(NationManagement.Screen.POPULATION) + Events.NationManagementScreens.open_nation_management_screen( + NationManagement.Screen.POPULATION + ) ) - _supply_limit_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/supply_limit_label") - _cores_overlapping_elements_box = get_gui_overlapping_elements_box_from_nodepath(^"./province_view/province_statistics/core_icons") - if _cores_overlapping_elements_box and _cores_overlapping_elements_box.set_gui_child_element_name("province_interface", "province_core") != OK: - _cores_overlapping_elements_box = null # hide cores box since we can't do anything with it + _supply_limit_label = get_gui_label_from_nodepath( + ^"./province_view/province_statistics/supply_limit_label" + ) + _cores_overlapping_elements_box = get_gui_overlapping_elements_box_from_nodepath( + ^"./province_view/province_statistics/core_icons" + ) + if ( + _cores_overlapping_elements_box + and ( + _cores_overlapping_elements_box.set_gui_child_element_name( + "province_interface", "province_core" + ) + != OK + ) + ): + _cores_overlapping_elements_box = null # hide cores box since we can't do anything with it _buildings_panel = get_panel_from_nodepath(^"./province_view/province_buildings") if _buildings_panel: - var target_slot_count : int = MenuSingleton.get_province_building_count() - var slot_y : float = 0.0 - for current_slot_count : int in target_slot_count: - var slot := GUINode.generate_gui_element("province_interface", "building", "building_slot_%d" % current_slot_count) + var target_slot_count: int = MenuSingleton.get_province_building_count() + var slot_y: float = 0.0 + for current_slot_count: int in target_slot_count: + var slot := GUINode.generate_gui_element( + "province_interface", "building", "building_slot_%d" % current_slot_count + ) if slot: _buildings_panel.add_child(slot) slot.set_position(Vector2(0.0, slot_y)) slot_y += slot.get_size().y _building_slots.push_back(BuildingSlot.new(current_slot_count, slot)) else: - push_error("Failed to generate building slot ", current_slot_count, " / ", target_slot_count) + push_error( + "Failed to generate building slot ", + current_slot_count, + " / ", + target_slot_count + ) break - hide_nodes([ - ^"./province_view/province_view_header/state_modifiers", - ^"./province_view/province_view_header/occupation_progress", - ^"./province_view/province_view_header/occupation_icon", - ^"./province_view/province_view_header/occupation_flag", - ^"./province_view/province_colony", - ^"./province_view/province_other", - ^"./province_view/province_buildings/army_size", - ^"./province_view/province_buildings/army_text", - ^"./province_view/province_buildings/navy_text", - ^"./province_view/national_focus_window", - ]) + hide_nodes( + [ + ^"./province_view/province_view_header/state_modifiers", + ^"./province_view/province_view_header/occupation_progress", + ^"./province_view/province_view_header/occupation_icon", + ^"./province_view/province_view_header/occupation_flag", + ^"./province_view/province_colony", + ^"./province_view/province_other", + ^"./province_view/province_buildings/army_size", + ^"./province_view/province_buildings/army_text", + ^"./province_view/province_buildings/navy_text", + ^"./province_view/national_focus_window", + ] + ) _update_info() -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: _update_info() + enum ColonyStatus { STATE, PROTECTORATE, COLONY } + # This assumes _cores_overlapping_elements_box is non-null -func _set_core_flag(core_index : int, country : String) -> void: - var core_flag_button : GUIMaskedFlagButton = GUINode.get_gui_masked_flag_button_from_node( +func _set_core_flag(core_index: int, country: String) -> void: + var core_flag_button: GUIMaskedFlagButton = GUINode.get_gui_masked_flag_button_from_node( _cores_overlapping_elements_box.get_child(core_index).get_node(^"./country_flag") ) if core_flag_button: core_flag_button.set_flag_country_name(country) + func _update_info() -> void: - const _province_info_province_key : StringName = &"province" - const _province_info_state_key : StringName = &"state" - const _province_info_slave_status_key : StringName = &"slave_status" - const _province_info_colony_status_key : StringName = &"colony_status" - const _province_info_terrain_type_key : StringName = &"terrain_type" - const _province_info_life_rating_key : StringName = &"life_rating" - const _province_info_controller_key : StringName = &"controller" - const _province_info_rgo_name_key : StringName = &"rgo_name" - const _province_info_rgo_icon_key : StringName = &"rgo_icon" - const _province_info_rgo_total_employees_key : StringName = &"rgo_total_employees" - const _province_info_rgo_employment_percentage_key : StringName = &"rgo_employment_percentage" - const _province_info_rgo_employment_tooltip_key : StringName = &"rgo_employment_tooltip" - const _province_info_rgo_output_quantity_yesterday_key : StringName = &"rgo_output_quantity_yesterday" - const _province_info_rgo_revenue_yesterday_key : StringName = &"rgo_revenue_yesterday" - const _province_info_crime_name_key : StringName = &"crime_name" - const _province_info_crime_icon_key : StringName = &"crime_icon" - const _province_info_total_population_key : StringName = &"total_population" - const _province_info_pop_types_key : StringName = &"pop_types" - const _province_info_pop_ideologies_key : StringName = &"pop_ideologies" - const _province_info_pop_cultures_key : StringName = &"pop_cultures" - const _province_info_cores_key : StringName = &"cores" - const _province_info_buildings_key : StringName = &"buildings" - - const _missing_suffix : String = "_MISSING" + const _province_info_province_key: StringName = &"province" + const _province_info_state_key: StringName = &"state" + const _province_info_slave_status_key: StringName = &"slave_status" + const _province_info_colony_status_key: StringName = &"colony_status" + const _province_info_terrain_type_key: StringName = &"terrain_type" + const _province_info_life_rating_key: StringName = &"life_rating" + const _province_info_controller_key: StringName = &"controller" + const _province_info_rgo_name_key: StringName = &"rgo_name" + const _province_info_rgo_icon_key: StringName = &"rgo_icon" + const _province_info_rgo_total_employees_key: StringName = &"rgo_total_employees" + const _province_info_rgo_employment_percentage_key: StringName = &"rgo_employment_percentage" + const _province_info_rgo_employment_tooltip_key: StringName = &"rgo_employment_tooltip" + const _province_info_rgo_output_quantity_yesterday_key: StringName = &"rgo_output_quantity_yesterday" + const _province_info_rgo_revenue_yesterday_key: StringName = &"rgo_revenue_yesterday" + const _province_info_crime_name_key: StringName = &"crime_name" + const _province_info_crime_icon_key: StringName = &"crime_icon" + const _province_info_total_population_key: StringName = &"total_population" + const _province_info_pop_types_key: StringName = &"pop_types" + const _province_info_pop_ideologies_key: StringName = &"pop_ideologies" + const _province_info_pop_cultures_key: StringName = &"pop_cultures" + const _province_info_cores_key: StringName = &"cores" + const _province_info_buildings_key: StringName = &"buildings" + + const _missing_suffix: String = "_MISSING" _province_info = MenuSingleton.get_province_info_from_index(_selected_index) if _province_info: # Header if _province_name_label: - _province_name_label.text = GUINode.format_province_name(_province_info.get(_province_info_province_key, _missing_suffix)) + _province_name_label.text = GUINode.format_province_name( + _province_info.get(_province_info_province_key, _missing_suffix) + ) if _state_name_label: - _state_name_label.text = _province_info.get(_province_info_state_key, tr(_province_info_state_key + _missing_suffix)) + _state_name_label.text = _province_info.get( + _province_info_state_key, tr(_province_info_state_key + _missing_suffix) + ) if _slave_status_icon: _slave_status_icon.visible = _province_info.get(_province_info_slave_status_key, false) - var colony_status : ColonyStatus = _province_info.get(_province_info_colony_status_key, 0) + var colony_status: ColonyStatus = _province_info.get(_province_info_colony_status_key, 0) if _colony_status_button: if colony_status == ColonyStatus.STATE: _colony_status_button.hide() @@ -285,48 +387,72 @@ func _update_info() -> void: if _province_modifiers_overlapping_elements_box: # TODO - replace example icons with those from the province's list of modifier instances _province_modifiers_overlapping_elements_box.set_child_count(8) - for i : int in _province_modifiers_overlapping_elements_box.get_child_count(): - var button : GUIIconButton = GUINode.get_gui_icon_button_from_node( - _province_modifiers_overlapping_elements_box.get_child(i).get_node(^"./modifier") + for i: int in _province_modifiers_overlapping_elements_box.get_child_count(): + var button: GUIIconButton = GUINode.get_gui_icon_button_from_node( + _province_modifiers_overlapping_elements_box.get_child(i).get_node( + ^"./modifier" + ) ) if button: button.set_icon_index(2 * i + (i & 1) + 1) if _terrain_type_icon: - var terrain_type : String = _province_info.get(_province_info_terrain_type_key, "") + var terrain_type: String = _province_info.get(_province_info_terrain_type_key, "") if terrain_type: - const _terrain_type_prefix : String = "GFX_terrainimg_" - if _terrain_type_icon.set_gfx_texture_sprite_name(_terrain_type_prefix + terrain_type) != OK: + const _terrain_type_prefix: String = "GFX_terrainimg_" + if ( + _terrain_type_icon.set_gfx_texture_sprite_name( + _terrain_type_prefix + terrain_type + ) + != OK + ): push_error("Failed to set terrain type texture: ", terrain_type) if _life_rating_bar: _life_rating_bar.value = _province_info.get(_province_info_life_rating_key, 0) / 100.0 if _controller_flag: - _controller_flag.set_flag_country_name(_province_info.get(_province_info_controller_key, "")) + _controller_flag.set_flag_country_name( + _province_info.get(_province_info_controller_key, "") + ) # Statistics if _rgo_icon: _rgo_icon.set_icon_index(_province_info.get(_province_info_rgo_icon_key, -1) + 2) if _rgo_produced_label: - _rgo_produced_label.text = GUINode.float_to_string_dp(_province_info.get(_province_info_rgo_output_quantity_yesterday_key, 0), 3) + _rgo_produced_label.text = GUINode.float_to_string_dp( + _province_info.get(_province_info_rgo_output_quantity_yesterday_key, 0), 3 + ) if _rgo_income_label: - _rgo_income_label.text = "%s¤" % GUINode.float_to_string_dp(_province_info.get(_province_info_rgo_revenue_yesterday_key, 0), 3) + _rgo_income_label.text = ( + "%s¤" + % GUINode.float_to_string_dp( + _province_info.get(_province_info_rgo_revenue_yesterday_key, 0), 3 + ) + ) - var rgo_employment_tooltip : String = _province_info.get(_province_info_rgo_employment_tooltip_key, "") + var rgo_employment_tooltip: String = _province_info.get( + _province_info_rgo_employment_tooltip_key, "" + ) if _rgo_employment_percentage_icon: - _rgo_employment_percentage_icon.set_icon_index(int(_province_info.get(_province_info_rgo_employment_percentage_key, 0) / 10) + 1) + _rgo_employment_percentage_icon.set_icon_index( + int(_province_info.get(_province_info_rgo_employment_percentage_key, 0) / 10) + 1 + ) _rgo_employment_percentage_icon.set_tooltip_string(rgo_employment_tooltip) if _rgo_employment_population_label: - _rgo_employment_population_label.text = GUINode.int_to_string_suffixed(_province_info.get(_province_info_rgo_total_employees_key, 0)) + _rgo_employment_population_label.text = GUINode.int_to_string_suffixed( + _province_info.get(_province_info_rgo_total_employees_key, 0) + ) _rgo_employment_population_label.set_tooltip_string(rgo_employment_tooltip) if _rgo_employment_percentage_label: - _rgo_employment_percentage_label.text = "%d%%" % _province_info.get(_province_info_rgo_employment_percentage_key, 0) + _rgo_employment_percentage_label.text = ( + "%d%%" % _province_info.get(_province_info_rgo_employment_percentage_key, 0) + ) _rgo_employment_percentage_label.set_tooltip_string(rgo_employment_tooltip) if _crime_name_label: @@ -339,7 +465,9 @@ func _update_info() -> void: pass if _total_population_label: - _total_population_label.text = GUINode.int_to_string_suffixed(_province_info.get(_province_info_total_population_key, 0)) + _total_population_label.text = GUINode.int_to_string_suffixed( + _province_info.get(_province_info_total_population_key, 0) + ) if _migration_label: pass @@ -348,31 +476,43 @@ func _update_info() -> void: pass if _pop_types_piechart: - _pop_types_piechart.set_slices_array(_province_info.get(_province_info_pop_types_key, [])) + _pop_types_piechart.set_slices_array( + _province_info.get(_province_info_pop_types_key, []) + ) if _pop_ideologies_piechart: - _pop_ideologies_piechart.set_slices_array(_province_info.get(_province_info_pop_ideologies_key, [])) + _pop_ideologies_piechart.set_slices_array( + _province_info.get(_province_info_pop_ideologies_key, []) + ) if _pop_cultures_piechart: - _pop_cultures_piechart.set_slices_array(_province_info.get(_province_info_pop_cultures_key, [])) + _pop_cultures_piechart.set_slices_array( + _province_info.get(_province_info_pop_cultures_key, []) + ) if _supply_limit_label: pass if _cores_overlapping_elements_box: - var cores : PackedStringArray = _province_info.get(_province_info_cores_key, []) + var cores: PackedStringArray = _province_info.get(_province_info_cores_key, []) _cores_overlapping_elements_box.set_child_count(cores.size()) - for core_index : int in min(cores.size(), _cores_overlapping_elements_box.get_child_count()): + for core_index: int in min( + cores.size(), _cores_overlapping_elements_box.get_child_count() + ): _set_core_flag(core_index, cores[core_index]) - for core_index : int in range(cores.size(), _cores_overlapping_elements_box.get_child_count()): + for core_index: int in range( + cores.size(), _cores_overlapping_elements_box.get_child_count() + ): _set_core_flag(core_index, "") # Buildings if _buildings_panel: - var buildings : Array[Dictionary] = _province_info.get(_province_info_buildings_key, [] as Array[Dictionary]) - for slot_index : int in min(buildings.size(), _building_slots.size()): + var buildings: Array[Dictionary] = _province_info.get( + _province_info_buildings_key, [] as Array[Dictionary] + ) + for slot_index: int in min(buildings.size(), _building_slots.size()): _building_slots[slot_index].update_info(buildings[slot_index]) - for slot_index : int in range(buildings.size(), _building_slots.size()): + for slot_index: int in range(buildings.size(), _building_slots.size()): _building_slots[slot_index].update_info({}) show() @@ -380,8 +520,10 @@ func _update_info() -> void: hide() mouse_exited.emit() -func _on_province_selected(index : int) -> void: + +func _on_province_selected(index: int) -> void: _selected_index = index + func _on_close_button_pressed() -> void: GameSingleton.unset_selected_province() diff --git a/game/src/Game/GameSession/SearchPanel.gd b/game/src/Game/GameSession/SearchPanel.gd index 3d96367f..96dec876 100644 --- a/game/src/Game/GameSession/SearchPanel.gd +++ b/game/src/Game/GameSession/SearchPanel.gd @@ -1,14 +1,15 @@ extends GUINode -@export var _map_view : MapView +@export var _map_view: MapView -var _search_panel : Panel -var _search_line_edit : LineEdit -var _results_list_box : GUIListBox -var _result_buttons : Array[GUIIconButton] +var _search_panel: Panel +var _search_line_edit: LineEdit +var _results_list_box: GUIListBox +var _result_buttons: Array[GUIIconButton] + +var _drag_active: bool = false +var _drag_anchor: Vector2 -var _drag_active : bool = false -var _drag_anchor : Vector2 func _ready() -> void: MenuSingleton.search_cache_changed.connect(_update_results_base) @@ -21,11 +22,11 @@ func _ready() -> void: set_click_mask_from_nodepaths([^"./goto_box/goto_box"]) - var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./goto_box/cancel") + var close_button: GUIIconButton = get_gui_icon_button_from_nodepath(^"./goto_box/cancel") if close_button: close_button.pressed.connect(hide) - var panel_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./goto_box/goto_box") + var panel_button: GUIIconButton = get_gui_icon_button_from_nodepath(^"./goto_box/goto_box") if panel_button: panel_button.button_down.connect(_start_drag) panel_button.button_up.connect(_end_drag) @@ -49,6 +50,7 @@ func _ready() -> void: MenuSingleton.generate_search_cache() + func toggle_visibility() -> void: if is_visible(): hide() @@ -57,49 +59,56 @@ func toggle_visibility() -> void: if _search_line_edit: _search_line_edit.grab_focus() + func _start_drag() -> void: if _search_panel: _drag_anchor = _search_panel.get_position() - get_window().get_mouse_position() _drag_active = true + func _end_drag() -> void: _drag_active = false -func _input(event : InputEvent) -> void: + +func _input(event: InputEvent) -> void: if _drag_active and event is InputEventMouseMotion: _search_panel.set_position(_drag_anchor + get_window().get_mouse_position()) -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: MenuSingleton.generate_search_cache() -func _search_string_updated(search_string : String) -> void: + +func _search_string_updated(search_string: String) -> void: MenuSingleton.update_search_results(search_string) _update_results_base() + func _update_results_base() -> void: if not _results_list_box: return - var result_count : int = MenuSingleton.get_search_result_row_count() + var result_count: int = MenuSingleton.get_search_result_row_count() - var result_height : float = 0.0 + var result_height: float = 0.0 if result_count > 0 and (_results_list_box.get_child_count() > 0 or _add_result_button()): result_height = _results_list_box.get_child(0).get_size().y _results_list_box.set_fixed(result_count, result_height, false) _update_results_scroll() + func _add_result_button() -> bool: if not _results_list_box: return false - var child : Panel = GUINode.generate_gui_element("menubar", "save_game_entry") + var child: Panel = GUINode.generate_gui_element("menubar", "save_game_entry") if not child: return false - var button : GUIIconButton = GUINode.get_gui_icon_button_from_node(child.get_node(^"./game")) + var button: GUIIconButton = GUINode.get_gui_icon_button_from_node(child.get_node(^"./game")) if not button: child.queue_free() return false @@ -113,7 +122,8 @@ func _add_result_button() -> bool: return true -func _update_results_scroll(scroll_index : int = -1) -> void: + +func _update_results_scroll(scroll_index: int = -1) -> void: if not _results_list_box: return @@ -122,19 +132,22 @@ func _update_results_scroll(scroll_index : int = -1) -> void: scroll_index = _results_list_box.get_scroll_index() - var results : PackedStringArray = MenuSingleton.get_search_result_rows(scroll_index, _results_list_box.get_fixed_visible_items()) + var results: PackedStringArray = MenuSingleton.get_search_result_rows( + scroll_index, _results_list_box.get_fixed_visible_items() + ) if results.size() < _result_buttons.size(): _result_buttons.resize(results.size()) _results_list_box.clear_children(results.size()) else: while _result_buttons.size() < results.size() and _add_result_button(): - pass # Button is added in the loop condition + pass # Button is added in the loop condition - for index : int in min(results.size(), _result_buttons.size()): + for index: int in min(results.size(), _result_buttons.size()): _result_buttons[index].set_text(results[index]) -func _result_selected(index : int) -> void: + +func _result_selected(index: int) -> void: if _map_view: _map_view.look_at_map_position(MenuSingleton.get_search_result_position(index)) else: diff --git a/game/src/Game/GameSession/Tooltip.gd b/game/src/Game/GameSession/Tooltip.gd index f079e4c5..ce84ed0a 100644 --- a/game/src/Game/GameSession/Tooltip.gd +++ b/game/src/Game/GameSession/Tooltip.gd @@ -1,6 +1,7 @@ extends GUINode -var _tooltip_label : GUILabel +var _tooltip_label: GUILabel + func _ready() -> void: add_gui_element("core", "ToolTip") @@ -14,34 +15,39 @@ func _ready() -> void: hide() -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_RESIZED: _update_tooltip_max_size() + func _update_tooltip_max_size() -> void: if _tooltip_label: - var max_size : Vector2 = _tooltip_label.get_base_max_size() - var window_size : Vector2 = get_size() + var max_size: Vector2 = _tooltip_label.get_base_max_size() + var window_size: Vector2 = get_size() _tooltip_label.set_max_size(Vector2(min(max_size.x, window_size.x), window_size.y)) -func update_tooltip(text : String, substitution_dict : Dictionary, position : Vector2) -> void: + +func update_tooltip(text: String, substitution_dict: Dictionary, position: Vector2) -> void: if text and _tooltip_label: _tooltip_label.set_text(text) _tooltip_label.set_substitution_dict(substitution_dict) _tooltip_label.force_update_lines() - var adjusted_rect : Rect2 = _tooltip_label.get_adjusted_rect() + var adjusted_rect: Rect2 = _tooltip_label.get_adjusted_rect() # Shift position so that the tooltip doesn't go past the bottom or right sides of the window - var bottom_right : Vector2 = position + adjusted_rect.position + adjusted_rect.size - get_size() + var bottom_right: Vector2 = ( + position + adjusted_rect.position + adjusted_rect.size - get_size() + ) if bottom_right.x > 0: position.x -= bottom_right.x if bottom_right.y > 0: position.y -= bottom_right.y # Shift position so that the tooltip doesn't go past the top or left sides of the window - var top_left : Vector2 = position + adjusted_rect.position + var top_left: Vector2 = position + adjusted_rect.position if top_left.x < 0: position.x -= top_left.x if top_left.y < 0: diff --git a/game/src/Game/GameSession/Topbar.gd b/game/src/Game/GameSession/Topbar.gd index 11e584cd..a9659599 100644 --- a/game/src/Game/GameSession/Topbar.gd +++ b/game/src/Game/GameSession/Topbar.gd @@ -1,78 +1,79 @@ extends GUINode # Country info -var _country_flag_button : GUIMaskedFlagButton -var _country_flag_overlay_icon : GUIIcon -var _country_name_label : GUILabel -var _country_rank_label : GUILabel -var _country_prestige_label : GUILabel -var _country_prestige_rank_label : GUILabel -var _country_industrial_power_label : GUILabel -var _country_industrial_power_rank_label : GUILabel -var _country_military_power_label : GUILabel -var _country_military_power_rank_label : GUILabel -var _country_colonial_power_label : GUILabel +var _country_flag_button: GUIMaskedFlagButton +var _country_flag_overlay_icon: GUIIcon +var _country_name_label: GUILabel +var _country_rank_label: GUILabel +var _country_prestige_label: GUILabel +var _country_prestige_rank_label: GUILabel +var _country_industrial_power_label: GUILabel +var _country_industrial_power_rank_label: GUILabel +var _country_military_power_label: GUILabel +var _country_military_power_rank_label: GUILabel +var _country_colonial_power_label: GUILabel # Time controls -var _speed_up_button : GUIIconButton -var _speed_down_button : GUIIconButton -var _pause_bg_button : GUIButton -var _speed_indicator_button : GUIIconButton -var _date_label : GUILabel +var _speed_up_button: GUIIconButton +var _speed_down_button: GUIIconButton +var _pause_bg_button: GUIButton +var _speed_indicator_button: GUIIconButton +var _date_label: GUILabel # NationManagement.Screen-GUIIconButton -var _nation_management_buttons : Dictionary +var _nation_management_buttons: Dictionary # Production -var _production_top_goods_icons : Array[GUIIcon] -var _production_alert_building_icon : GUIIcon -var _production_alert_closed_icon : GUIIcon -var _production_alert_unemployment_icon : GUIIcon +var _production_top_goods_icons: Array[GUIIcon] +var _production_alert_building_icon: GUIIcon +var _production_alert_closed_icon: GUIIcon +var _production_alert_unemployment_icon: GUIIcon # Budget # TODO - line chart -var _budget_funds_label : GUILabel +var _budget_funds_label: GUILabel # Technology -var _technology_progress_bar : GUIProgressBar -var _technology_current_research_label : GUILabel -var _technology_literacy_label : GUILabel -var _technology_research_points_label : GUILabel +var _technology_progress_bar: GUIProgressBar +var _technology_current_research_label: GUILabel +var _technology_literacy_label: GUILabel +var _technology_research_points_label: GUILabel # Politics -var _politics_party_icon : GUIIcon -var _politics_party_label : GUILabel -var _politics_suppression_points_label : GUILabel -var _politics_infamy_label : GUILabel -var _politics_reforms_button : GUIButton -var _politics_decisions_button : GUIIconButton -var _politics_election_icon : GUIIcon -var _politics_rebels_button : GUIIconButton +var _politics_party_icon: GUIIcon +var _politics_party_label: GUILabel +var _politics_suppression_points_label: GUILabel +var _politics_infamy_label: GUILabel +var _politics_reforms_button: GUIButton +var _politics_decisions_button: GUIIconButton +var _politics_election_icon: GUIIcon +var _politics_rebels_button: GUIIconButton # Population -var _population_total_size_label : GUILabel -var _population_national_foci_label : GUILabel -var _population_militancy_label : GUILabel -var _population_consciousness_label : GUILabel +var _population_total_size_label: GUILabel +var _population_national_foci_label: GUILabel +var _population_militancy_label: GUILabel +var _population_consciousness_label: GUILabel # Trade -var _trade_imported_icons : Array[GUIIcon] -var _trade_exported_icons : Array[GUIIcon] +var _trade_imported_icons: Array[GUIIcon] +var _trade_exported_icons: Array[GUIIcon] # Diplomacy -var _diplomacy_peace_label : GUILabel -var _diplomacy_war_enemies_overlapping_elements_box : GUIOverlappingElementsBox -var _diplomacy_diplomatic_points_label : GUILabel -var _diplomacy_alert_colony_button : GUIIconButton -var _diplomacy_alert_crisis_icon : GUIIcon -var _diplomacy_alert_sphere_icon : GUIIcon -var _diplomacy_alert_great_power_icon : GUIIcon +var _diplomacy_peace_label: GUILabel +var _diplomacy_war_enemies_overlapping_elements_box: GUIOverlappingElementsBox +var _diplomacy_diplomatic_points_label: GUILabel +var _diplomacy_alert_colony_button: GUIIconButton +var _diplomacy_alert_crisis_icon: GUIIcon +var _diplomacy_alert_sphere_icon: GUIIcon +var _diplomacy_alert_great_power_icon: GUIIcon # Military -var _military_army_size_label : GUILabel -var _military_navy_size_label : GUILabel -var _military_mobilisation_size_label : GUILabel -var _military_leadership_points_label : GUILabel +var _military_army_size_label: GUILabel +var _military_navy_size_label: GUILabel +var _military_mobilisation_size_label: GUILabel +var _military_leadership_points_label: GUILabel + func _ready() -> void: GameSingleton.gamestate_updated.connect(_update_info) @@ -80,10 +81,7 @@ func _ready() -> void: add_gui_element("topbar", "topbar") - hide_nodes([ - ^"./topbar/topbar_outlinerbutton_bg", - ^"./topbar/topbar_outlinerbutton" - ]) + hide_nodes([^"./topbar/topbar_outlinerbutton_bg", ^"./topbar/topbar_outlinerbutton"]) set_click_mask_from_nodepaths([^"./topbar/topbar_bg", ^"./topbar/topbar_paper"]) @@ -93,7 +91,9 @@ func _ready() -> void: _country_flag_button.pressed.connect( func() -> void: # TODO - open the diplomacy menu on the Wars tab - Events.NationManagementScreens.open_nation_management_screen(NationManagement.Screen.DIPLOMACY) + Events.NationManagementScreens.open_nation_management_screen( + NationManagement.Screen.DIPLOMACY + ) ) _country_flag_overlay_icon = get_gui_icon_from_nodepath(^"./topbar/topbar_flag_overlay") _country_name_label = get_gui_label_from_nodepath(^"./topbar/CountryName") @@ -101,9 +101,13 @@ func _ready() -> void: _country_prestige_label = get_gui_label_from_nodepath(^"./topbar/country_prestige") _country_prestige_rank_label = get_gui_label_from_nodepath(^"./topbar/selected_prestige_rank") _country_industrial_power_label = get_gui_label_from_nodepath(^"./topbar/country_economic") - _country_industrial_power_rank_label = get_gui_label_from_nodepath(^"./topbar/selected_industry_rank") + _country_industrial_power_rank_label = get_gui_label_from_nodepath( + ^"./topbar/selected_industry_rank" + ) _country_military_power_label = get_gui_label_from_nodepath(^"./topbar/country_military") - _country_military_power_rank_label = get_gui_label_from_nodepath(^"./topbar/selected_military_rank") + _country_military_power_rank_label = get_gui_label_from_nodepath( + ^"./topbar/selected_military_rank" + ) _country_colonial_power_label = get_gui_label_from_nodepath(^"./topbar/country_colonial_power") # Time controls @@ -136,18 +140,18 @@ func _ready() -> void: _date_label = get_gui_label_from_nodepath(^"./topbar/DateText") # Nation management screens - const screen_nodepaths : Dictionary = { - NationManagement.Screen.PRODUCTION : ^"./topbar/topbarbutton_production", - NationManagement.Screen.BUDGET : ^"./topbar/topbarbutton_budget", - NationManagement.Screen.TECHNOLOGY : ^"./topbar/topbarbutton_tech", - NationManagement.Screen.POLITICS : ^"./topbar/topbarbutton_politics", - NationManagement.Screen.POPULATION : ^"./topbar/topbarbutton_pops", - NationManagement.Screen.TRADE : ^"./topbar/topbarbutton_trade", - NationManagement.Screen.DIPLOMACY : ^"./topbar/topbarbutton_diplomacy", - NationManagement.Screen.MILITARY : ^"./topbar/topbarbutton_military" + const screen_nodepaths: Dictionary = { + NationManagement.Screen.PRODUCTION: ^"./topbar/topbarbutton_production", + NationManagement.Screen.BUDGET: ^"./topbar/topbarbutton_budget", + NationManagement.Screen.TECHNOLOGY: ^"./topbar/topbarbutton_tech", + NationManagement.Screen.POLITICS: ^"./topbar/topbarbutton_politics", + NationManagement.Screen.POPULATION: ^"./topbar/topbarbutton_pops", + NationManagement.Screen.TRADE: ^"./topbar/topbarbutton_trade", + NationManagement.Screen.DIPLOMACY: ^"./topbar/topbarbutton_diplomacy", + NationManagement.Screen.MILITARY: ^"./topbar/topbarbutton_military" } - for screen : NationManagement.Screen in screen_nodepaths: - var button : GUIIconButton = get_gui_icon_button_from_nodepath(screen_nodepaths[screen]) + for screen: NationManagement.Screen in screen_nodepaths: + var button: GUIIconButton = get_gui_icon_button_from_nodepath(screen_nodepaths[screen]) if button: button.pressed.connect( Events.NationManagementScreens.toggle_nation_management_screen.bind(screen) @@ -160,56 +164,78 @@ func _ready() -> void: ) # Production - const PRODUCED_GOOD_COUNT : int = 5 - for idx : int in PRODUCED_GOOD_COUNT: - _production_top_goods_icons.push_back(get_gui_icon_from_nodepath("./topbar/topbar_produced%d" % idx)) - _production_alert_building_icon = get_gui_icon_from_nodepath(^"./topbar/alert_building_factories") + const PRODUCED_GOOD_COUNT: int = 5 + for idx: int in PRODUCED_GOOD_COUNT: + _production_top_goods_icons.push_back( + get_gui_icon_from_nodepath("./topbar/topbar_produced%d" % idx) + ) + _production_alert_building_icon = get_gui_icon_from_nodepath( + ^"./topbar/alert_building_factories" + ) _production_alert_closed_icon = get_gui_icon_from_nodepath(^"./topbar/alert_closed_factories") - _production_alert_unemployment_icon = get_gui_icon_from_nodepath(^"./topbar/alert_unemployed_workers") + _production_alert_unemployment_icon = get_gui_icon_from_nodepath( + ^"./topbar/alert_unemployed_workers" + ) # Budget _budget_funds_label = get_gui_label_from_nodepath(^"./topbar/budget_funds") # Technology - var tech_button : GUIIconButton = _nation_management_buttons[NationManagement.Screen.TECHNOLOGY] + var tech_button: GUIIconButton = _nation_management_buttons[NationManagement.Screen.TECHNOLOGY] _technology_progress_bar = get_gui_progress_bar_from_nodepath(^"./topbar/topbar_tech_progress") if _technology_progress_bar and tech_button: _technology_progress_bar.reparent(tech_button) - _technology_current_research_label = get_gui_label_from_nodepath(^"./topbar/tech_current_research") + _technology_current_research_label = get_gui_label_from_nodepath( + ^"./topbar/tech_current_research" + ) if _technology_current_research_label and tech_button: _technology_current_research_label.reparent(tech_button) _technology_literacy_label = get_gui_label_from_nodepath(^"./topbar/tech_literacy_value") if _technology_literacy_label and tech_button: _technology_literacy_label.reparent(tech_button) - _technology_research_points_label = get_gui_label_from_nodepath(^"./topbar/topbar_researchpoints_value") + _technology_research_points_label = get_gui_label_from_nodepath( + ^"./topbar/topbar_researchpoints_value" + ) if _technology_research_points_label and tech_button: _technology_research_points_label.reparent(tech_button) # Politics _politics_party_icon = get_gui_icon_from_nodepath(^"./topbar/politics_party_icon") _politics_party_label = get_gui_label_from_nodepath(^"./topbar/politics_ruling_party") - var politics_suppression_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./topbar/topbar_supression_icon") + var politics_suppression_button: GUIIconButton = get_gui_icon_button_from_nodepath( + ^"./topbar/topbar_supression_icon" + ) if politics_suppression_button: politics_suppression_button.pressed.connect( func() -> void: # TODO - open the politics menu on the Movements tab - Events.NationManagementScreens.toggle_nation_management_screen(NationManagement.Screen.POLITICS) + Events.NationManagementScreens.toggle_nation_management_screen( + NationManagement.Screen.POLITICS + ) ) - _politics_suppression_points_label = get_gui_label_from_nodepath(^"./topbar/politics_supressionpoints_value") + _politics_suppression_points_label = get_gui_label_from_nodepath( + ^"./topbar/politics_supressionpoints_value" + ) _politics_infamy_label = get_gui_label_from_nodepath(^"./topbar/politics_infamy_value") _politics_reforms_button = get_gui_icon_button_from_nodepath(^"./topbar/alert_can_do_reforms") if _politics_reforms_button: _politics_reforms_button.pressed.connect( func() -> void: # TODO - open the politics menu on the Reforms tab - Events.NationManagementScreens.toggle_nation_management_screen(NationManagement.Screen.POLITICS) + Events.NationManagementScreens.toggle_nation_management_screen( + NationManagement.Screen.POLITICS + ) ) - _politics_decisions_button = get_gui_icon_button_from_nodepath(^"./topbar/alert_can_do_decisions") + _politics_decisions_button = get_gui_icon_button_from_nodepath( + ^"./topbar/alert_can_do_decisions" + ) if _politics_decisions_button: _politics_decisions_button.pressed.connect( func() -> void: # TODO - open the politics menu on the Decisions tab - Events.NationManagementScreens.toggle_nation_management_screen(NationManagement.Screen.POLITICS) + Events.NationManagementScreens.toggle_nation_management_screen( + NationManagement.Screen.POLITICS + ) ) _politics_election_icon = get_gui_icon_from_nodepath(^"./topbar/alert_is_in_election") _politics_rebels_button = get_gui_icon_button_from_nodepath(^"./topbar/alert_have_rebels") @@ -217,34 +243,50 @@ func _ready() -> void: _politics_rebels_button.pressed.connect( func() -> void: # TODO - open the politics menu on the Movements tab - Events.NationManagementScreens.toggle_nation_management_screen(NationManagement.Screen.POLITICS) + Events.NationManagementScreens.toggle_nation_management_screen( + NationManagement.Screen.POLITICS + ) ) # Population _population_total_size_label = get_gui_label_from_nodepath(^"./topbar/population_total_value") _population_national_foci_label = get_gui_label_from_nodepath(^"./topbar/topbar_focus_value") _population_militancy_label = get_gui_label_from_nodepath(^"./topbar/population_avg_mil_value") - _population_consciousness_label = get_gui_label_from_nodepath(^"./topbar/population_avg_con_value") + _population_consciousness_label = get_gui_label_from_nodepath( + ^"./topbar/population_avg_con_value" + ) # Trade - const TRADE_GOOD_COUNT : int = 3 + const TRADE_GOOD_COUNT: int = 3 for idx in TRADE_GOOD_COUNT: - _trade_imported_icons.push_back(get_gui_icon_from_nodepath("./topbar/topbar_import%d" % idx)) - _trade_exported_icons.push_back(get_gui_icon_from_nodepath("./topbar/topbar_export%d" % idx)) + _trade_imported_icons.push_back( + get_gui_icon_from_nodepath("./topbar/topbar_import%d" % idx) + ) + _trade_exported_icons.push_back( + get_gui_icon_from_nodepath("./topbar/topbar_export%d" % idx) + ) # Diplomacy _diplomacy_peace_label = get_gui_label_from_nodepath(^"./topbar/diplomacy_status") - _diplomacy_war_enemies_overlapping_elements_box = get_gui_overlapping_elements_box_from_nodepath(^"./topbar/diplomacy_at_war") - _diplomacy_diplomatic_points_label = get_gui_label_from_nodepath(^"./topbar/diplomacy_diplopoints_value") + _diplomacy_war_enemies_overlapping_elements_box = get_gui_overlapping_elements_box_from_nodepath( + ^"./topbar/diplomacy_at_war" + ) + _diplomacy_diplomatic_points_label = get_gui_label_from_nodepath( + ^"./topbar/diplomacy_diplopoints_value" + ) _diplomacy_alert_colony_button = get_gui_icon_button_from_nodepath(^"./topbar/alert_colony") if _diplomacy_alert_colony_button: _diplomacy_alert_colony_button.pressed.connect( func() -> void: # TODO - move to and select province in upgradable colony if any exist - Events.NationManagementScreens.open_nation_management_screen(NationManagement.Screen.DIPLOMACY) + Events.NationManagementScreens.open_nation_management_screen( + NationManagement.Screen.DIPLOMACY + ) ) _diplomacy_alert_crisis_icon = get_gui_icon_from_nodepath(^"./topbar/alert_crisis") - _diplomacy_alert_sphere_icon = get_gui_icon_from_nodepath(^"./topbar/alert_can_increase_opinion") + _diplomacy_alert_sphere_icon = get_gui_icon_from_nodepath( + ^"./topbar/alert_can_increase_opinion" + ) _diplomacy_alert_great_power_icon = get_gui_icon_from_nodepath(^"./topbar/alert_loosing_gp") # Military @@ -253,52 +295,54 @@ func _ready() -> void: _military_army_size_label.set_text("§Y$CURR$/$MAX$") _military_army_size_label.set_tooltip_string("TOPBAR_ARMY_TOOLTIP") _military_navy_size_label = get_gui_label_from_nodepath(^"./topbar/military_navy_value") - _military_mobilisation_size_label = get_gui_label_from_nodepath(^"./topbar/military_manpower_value") - _military_leadership_points_label = get_gui_label_from_nodepath(^"./topbar/military_leadership_value") + _military_mobilisation_size_label = get_gui_label_from_nodepath( + ^"./topbar/military_manpower_value" + ) + _military_leadership_points_label = get_gui_label_from_nodepath( + ^"./topbar/military_leadership_value" + ) _update_info() _update_speed_controls() -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: _update_info() _update_speed_controls() + enum CountryStatus { - GREAT_POWER, - SECONDARY_POWER, - CIVILISED, - PARTIALLY_CIVILISED, - UNCIVILISED, - PRIMITIVE + GREAT_POWER, SECONDARY_POWER, CIVILISED, PARTIALLY_CIVILISED, UNCIVILISED, PRIMITIVE } + func _update_info() -> void: - var topbar_info : Dictionary = MenuSingleton.get_topbar_info() + var topbar_info: Dictionary = MenuSingleton.get_topbar_info() ## Country info - const country_key : StringName = &"country" - const country_status_key : StringName = &"country_status" - const total_rank_key : StringName = &"total_rank" + const country_key: StringName = &"country" + const country_status_key: StringName = &"country_status" + const total_rank_key: StringName = &"total_rank" - const prestige_key : StringName = &"prestige" - const prestige_rank_key : StringName = &"prestige_rank" - const prestige_tooltip_key : StringName = &"prestige_tooltip" + const prestige_key: StringName = &"prestige" + const prestige_rank_key: StringName = &"prestige_rank" + const prestige_tooltip_key: StringName = &"prestige_tooltip" - const industrial_power_key : StringName = &"industrial_power" - const industrial_rank_key : StringName = &"industrial_rank" - const industrial_power_tooltip_key : StringName = &"industrial_power_tooltip" + const industrial_power_key: StringName = &"industrial_power" + const industrial_rank_key: StringName = &"industrial_rank" + const industrial_power_tooltip_key: StringName = &"industrial_power_tooltip" - const military_power_key : StringName = &"military_power" - const military_rank_key : StringName = &"military_rank" - const military_power_tooltip_key : StringName = &"military_power_tooltip" + const military_power_key: StringName = &"military_power" + const military_rank_key: StringName = &"military_rank" + const military_power_tooltip_key: StringName = &"military_power_tooltip" - const colonial_power_available_key : StringName = &"colonial_power_available" - const colonial_power_max_key : StringName = &"colonial_power_max" - const colonial_power_tooltip_key : StringName = &"colonial_power_tooltip" + const colonial_power_available_key: StringName = &"colonial_power_available" + const colonial_power_max_key: StringName = &"colonial_power_max" + const colonial_power_tooltip_key: StringName = &"colonial_power_tooltip" - const COUNTRY_STATUS_NAMES : PackedStringArray = [ + const COUNTRY_STATUS_NAMES: PackedStringArray = [ "DIPLOMACY_GREATNATION_STATUS", "DIPLOMACY_COLONIALNATION_STATUS", "DIPLOMACY_CIVILIZEDNATION_STATUS", @@ -307,35 +351,49 @@ func _update_info() -> void: "DIPLOMACY_PRIMITIVENATION_STATUS" ] - var country_identifier : String = topbar_info.get(country_key, "") - var country_name : String = MenuSingleton.get_country_name_from_identifier(country_identifier) - var country_status : int = topbar_info.get(country_status_key, CountryStatus.UNCIVILISED) + var country_identifier: String = topbar_info.get(country_key, "") + var country_name: String = MenuSingleton.get_country_name_from_identifier(country_identifier) + var country_status: int = topbar_info.get(country_status_key, CountryStatus.UNCIVILISED) - var country_name_rank_tooltip : String = tr("PLAYER_COUNTRY_TOPBAR_RANK") + MenuSingleton.get_tooltip_separator() + tr("RANK_TOTAL_D") - var country_name_rank_dict : Dictionary = { - "NAME": country_name, - "RANK": COUNTRY_STATUS_NAMES[country_status] + var country_name_rank_tooltip: String = ( + tr("PLAYER_COUNTRY_TOPBAR_RANK") + + MenuSingleton.get_tooltip_separator() + + tr("RANK_TOTAL_D") + ) + var country_name_rank_dict: Dictionary = { + "NAME": country_name, "RANK": COUNTRY_STATUS_NAMES[country_status] } if _country_flag_button: _country_flag_button.set_flag_country_name(country_identifier) - _country_flag_button.set_tooltip_string_and_substitution_dict(country_name_rank_tooltip, country_name_rank_dict) + _country_flag_button.set_tooltip_string_and_substitution_dict( + country_name_rank_tooltip, country_name_rank_dict + ) if _country_flag_overlay_icon: # 1 - Great Power # 2 - Secondary Power # 3 - Civilised # 4 - All Uncivilised - _country_flag_overlay_icon.set_icon_index(1 + min(country_status, CountryStatus.PARTIALLY_CIVILISED)) + _country_flag_overlay_icon.set_icon_index( + 1 + min(country_status, CountryStatus.PARTIALLY_CIVILISED) + ) if _country_name_label: _country_name_label.set_text(country_name) if _country_rank_label: _country_rank_label.set_text(str(topbar_info.get(total_rank_key, 0))) - _country_rank_label.set_tooltip_string_and_substitution_dict(country_name_rank_tooltip, country_name_rank_dict) + _country_rank_label.set_tooltip_string_and_substitution_dict( + country_name_rank_tooltip, country_name_rank_dict + ) - var prestige_tooltip : String = tr("RANK_PRESTIGE") + topbar_info.get(prestige_tooltip_key, "") + MenuSingleton.get_tooltip_separator() + tr("RANK_PRESTIGE_D") + var prestige_tooltip: String = ( + tr("RANK_PRESTIGE") + + topbar_info.get(prestige_tooltip_key, "") + + MenuSingleton.get_tooltip_separator() + + tr("RANK_PRESTIGE_D") + ) if _country_prestige_label: _country_prestige_label.set_text(str(topbar_info.get(prestige_key, 0))) @@ -345,7 +403,12 @@ func _update_info() -> void: _country_prestige_rank_label.set_text(str(topbar_info.get(prestige_rank_key, 0))) _country_prestige_rank_label.set_tooltip_string(prestige_tooltip) - var industrial_power_tooltip : String = tr("RANK_INDUSTRY") + MenuSingleton.get_tooltip_separator() + tr("RANK_INDUSTRY_D") + topbar_info.get(industrial_power_tooltip_key, "") + var industrial_power_tooltip: String = ( + tr("RANK_INDUSTRY") + + MenuSingleton.get_tooltip_separator() + + tr("RANK_INDUSTRY_D") + + topbar_info.get(industrial_power_tooltip_key, "") + ) if _country_industrial_power_label: _country_industrial_power_label.set_text(str(topbar_info.get(industrial_power_key, 0))) @@ -355,7 +418,12 @@ func _update_info() -> void: _country_industrial_power_rank_label.set_text(str(topbar_info.get(industrial_rank_key, 0))) _country_industrial_power_rank_label.set_tooltip_string(industrial_power_tooltip) - var military_power_tooltip : String = tr("RANK_MILITARY") + MenuSingleton.get_tooltip_separator() + tr("RANK_MILITARY_D") + topbar_info.get(military_power_tooltip_key, "") + var military_power_tooltip: String = ( + tr("RANK_MILITARY") + + MenuSingleton.get_tooltip_separator() + + tr("RANK_MILITARY_D") + + topbar_info.get(military_power_tooltip_key, "") + ) if _country_military_power_label: _country_military_power_label.set_text(str(topbar_info.get(military_power_key, 0))) @@ -366,21 +434,36 @@ func _update_info() -> void: _country_military_power_rank_label.set_tooltip_string(military_power_tooltip) if _country_colonial_power_label: - var available_colonial_power : int = topbar_info.get(colonial_power_available_key, 0) - var max_colonial_power : int = topbar_info.get(colonial_power_max_key, 0) + var available_colonial_power: int = topbar_info.get(colonial_power_available_key, 0) + var max_colonial_power: int = topbar_info.get(colonial_power_max_key, 0) _country_colonial_power_label.set_text( - "§%s%s§!/%s" % ["W" if available_colonial_power > 0 else "R", available_colonial_power, max_colonial_power] + ( + "§%s%s§!/%s" + % [ + "W" if available_colonial_power > 0 else "R", + available_colonial_power, + max_colonial_power + ] + ) + ) + _country_colonial_power_label.set_tooltip_string( + ( + tr("COLONIAL_POINTS") + + MenuSingleton.get_tooltip_separator() + + ( + topbar_info.get(colonial_power_tooltip_key, "") + if country_status <= CountryStatus.SECONDARY_POWER + else tr("NON_COLONIAL_POWER") + ) + ) ) - _country_colonial_power_label.set_tooltip_string(tr("COLONIAL_POINTS") + MenuSingleton.get_tooltip_separator() + ( - topbar_info.get(colonial_power_tooltip_key, "") if country_status <= CountryStatus.SECONDARY_POWER else tr("NON_COLONIAL_POWER") - )) ## Time control if _date_label: _date_label.text = MenuSingleton.get_longform_date() ## Production - for idx : int in _production_top_goods_icons.size(): + for idx: int in _production_top_goods_icons.size(): if _production_top_goods_icons[idx]: _production_top_goods_icons[idx].set_icon_index(idx + 2) @@ -395,17 +478,22 @@ func _update_info() -> void: ## Budget if _budget_funds_label: - var cash : float = 0.0 - var earnings : float = 0.0 - _budget_funds_label.set_text("§Y%s§!¤(§%s%s§!¤)" % [ - GUINode.float_to_string_suffixed(cash), - "G+" if earnings > 0.0 else "R" if earnings < 0.0 else "Y+", - GUINode.float_to_string_suffixed(earnings) - ]) + var cash: float = 0.0 + var earnings: float = 0.0 + _budget_funds_label.set_text( + ( + "§Y%s§!¤(§%s%s§!¤)" + % [ + GUINode.float_to_string_suffixed(cash), + "G+" if earnings > 0.0 else "R" if earnings < 0.0 else "Y+", + GUINode.float_to_string_suffixed(earnings) + ] + ) + ) ## Technology if _technology_progress_bar: - pass # TODO - set tech progress + pass # TODO - set tech progress if _technology_current_research_label: # TODO - set current research or "unciv_nation" (in red) if uncivilised @@ -413,18 +501,25 @@ func _update_info() -> void: _technology_current_research_label.set_tooltip_string("TECHNOLOGYVIEW_NO_RESEARCH_TOOLTIP") if _technology_literacy_label: - var literacy_float : float = 80.0 - var literacy_string : String = GUINode.float_to_string_dp(80.0, 1) + var literacy_float: float = 80.0 + var literacy_string: String = GUINode.float_to_string_dp(80.0, 1) _technology_literacy_label.set_text("§Y%s§W%%" % literacy_string) - _technology_literacy_label.set_tooltip_string_and_substitution_dict("TOPBAR_AVG_LITERACY", { "AVG": literacy_string }) + _technology_literacy_label.set_tooltip_string_and_substitution_dict( + "TOPBAR_AVG_LITERACY", {"AVG": literacy_string} + ) if _technology_research_points_label: _technology_research_points_label.set_text("§Y%s" % GUINode.float_to_string_dp(10.0, 2)) # TODO - test tooltip, replace with actual values from the simulation - _technology_research_points_label.set_tooltip_string_and_substitution_dict("TECH_DAILY_RESEARCHPOINTS_TOOLTIP", { - "POPTYPE": "Clergymen", "VALUE": GUINode.float_to_string_dp(1.42, 2), - "FRACTION": GUINode.float_to_string_dp(0.95, 2), "OPTIMAL": GUINode.float_to_string_dp(2, 2) - }) + _technology_research_points_label.set_tooltip_string_and_substitution_dict( + "TECH_DAILY_RESEARCHPOINTS_TOOLTIP", + { + "POPTYPE": "Clergymen", + "VALUE": GUINode.float_to_string_dp(1.42, 2), + "FRACTION": GUINode.float_to_string_dp(0.95, 2), + "OPTIMAL": GUINode.float_to_string_dp(2, 2) + } + ) ## Politics if _politics_party_icon: @@ -454,18 +549,28 @@ func _update_info() -> void: ## Population if _population_total_size_label: # TODO - suffixes on both numbers should be white! - var total_population : int = 16000000 - var growth : int = 1500 - _population_total_size_label.set_text("§Y%s§!(§%s%s§!)" % [ - GUINode.int_to_string_suffixed(total_population), - "G" if growth >= 0 else "R", - GUINode.int_to_string_suffixed(growth), - ]) + var total_population: int = 16000000 + var growth: int = 1500 + ( + _population_total_size_label + . set_text( + ( + "§Y%s§!(§%s%s§!)" + % [ + GUINode.int_to_string_suffixed(total_population), + "G" if growth >= 0 else "R", + GUINode.int_to_string_suffixed(growth), + ] + ) + ) + ) if _population_national_foci_label: - var foci_used : int = 1 - var max_foci : int = 1 - _population_national_foci_label.set_text("§%s%d/%d" % ["R" if foci_used < max_foci else "G", foci_used, max_foci]) + var foci_used: int = 1 + var max_foci: int = 1 + _population_national_foci_label.set_text( + "§%s%d/%d" % ["R" if foci_used < max_foci else "G", foci_used, max_foci] + ) if _population_militancy_label: _population_militancy_label.set_text("§Y%s" % GUINode.float_to_string_dp(1.5, 2)) @@ -474,13 +579,15 @@ func _update_info() -> void: _population_consciousness_label.set_text("§Y%s" % GUINode.float_to_string_dp(0.05, 2)) ## Trade - for idx : int in _trade_imported_icons.size(): + for idx: int in _trade_imported_icons.size(): if _trade_imported_icons[idx]: _trade_imported_icons[idx].set_icon_index(idx + 2 + _production_top_goods_icons.size()) - for idx : int in _trade_exported_icons.size(): + for idx: int in _trade_exported_icons.size(): if _trade_exported_icons[idx]: - _trade_exported_icons[idx].set_icon_index(idx + 2 + _production_top_goods_icons.size() + _trade_imported_icons.size()) + _trade_exported_icons[idx].set_icon_index( + idx + 2 + _production_top_goods_icons.size() + _trade_imported_icons.size() + ) ## Diplomacy if _diplomacy_peace_label: @@ -504,13 +611,13 @@ func _update_info() -> void: _diplomacy_alert_great_power_icon.set_icon_index(2) ## Military - const regiment_count_key : StringName = &"regiment_count"; - const max_supported_regiments_key : StringName = &"max_supported_regiments"; + const regiment_count_key: StringName = &"regiment_count" + const max_supported_regiments_key: StringName = &"max_supported_regiments" - var regiment_count : String = str(topbar_info.get(regiment_count_key, 0)) + var regiment_count: String = str(topbar_info.get(regiment_count_key, 0)) if _military_army_size_label: - var army_size_dict : Dictionary = { + var army_size_dict: Dictionary = { "CURR": regiment_count, "MAX": str(topbar_info.get(max_supported_regiments_key, 0)) } _military_army_size_label.set_substitution_dict(army_size_dict) @@ -520,26 +627,37 @@ func _update_info() -> void: _military_navy_size_label.set_text("§Y%d/%d" % [0, 0]) # TODO - navy size tooltip - const mobilised_key : StringName = &"mobilised" - const mobilisation_regiments_key : StringName = &"mobilisation_regiments" - const mobilisation_impact_key : StringName = &"mobilisation_impact" - const war_policy_key : StringName = &"war_policy" - const mobilisation_max_regiments_key : StringName = &"mobilisation_max_regiments" + const mobilised_key: StringName = &"mobilised" + const mobilisation_regiments_key: StringName = &"mobilisation_regiments" + const mobilisation_impact_key: StringName = &"mobilisation_impact" + const war_policy_key: StringName = &"war_policy" + const mobilisation_max_regiments_key: StringName = &"mobilisation_max_regiments" if _military_mobilisation_size_label: if topbar_info.get(mobilised_key, false): _military_mobilisation_size_label.set_text("§R-") _military_mobilisation_size_label.set_tooltip_string("TOPBAR_MOBILIZED") else: - var mobilisation_regiments : String = str(topbar_info.get(mobilisation_regiments_key, 0)) - var mobilisation_impact : String = GUINode.float_to_string_dp(topbar_info.get(mobilisation_impact_key, 0), 1) + "%" + var mobilisation_regiments: String = str(topbar_info.get(mobilisation_regiments_key, 0)) + var mobilisation_impact: String = ( + GUINode.float_to_string_dp(topbar_info.get(mobilisation_impact_key, 0), 1) + "%" + ) _military_mobilisation_size_label.set_text("§Y" + mobilisation_regiments) _military_mobilisation_size_label.set_tooltip_string_and_substitution_dict( - tr("TOPBAR_MOBILIZE_TOOLTIP") + "\n\n" + tr("MOBILIZATION_IMPACT_LIMIT_DESC") + "\n" + tr("MOBILIZATION_IMPACT_LIMIT_DESC2").replace("$CURR$", "$CURR2$"), + ( + tr("TOPBAR_MOBILIZE_TOOLTIP") + + "\n\n" + + tr("MOBILIZATION_IMPACT_LIMIT_DESC") + + "\n" + + tr("MOBILIZATION_IMPACT_LIMIT_DESC2").replace("$CURR$", "$CURR2$") + ), { - "CURR": mobilisation_regiments, "IMPACT": mobilisation_impact, "POLICY": topbar_info.get(war_policy_key, ""), - "UNITS": str(topbar_info.get(mobilisation_max_regiments_key, 0)), "CURR2": regiment_count + "CURR": mobilisation_regiments, + "IMPACT": mobilisation_impact, + "POLICY": topbar_info.get(war_policy_key, ""), + "UNITS": str(topbar_info.get(mobilisation_max_regiments_key, 0)), + "CURR2": regiment_count } ) @@ -547,9 +665,10 @@ func _update_info() -> void: _military_leadership_points_label.set_text("§Y%d" % 0) # TODO - leadership points tooltip + func _update_speed_controls() -> void: - var paused : bool = MenuSingleton.is_paused() - var speed : int = MenuSingleton.get_speed() + var paused: bool = MenuSingleton.is_paused() + var speed: int = MenuSingleton.get_speed() # TODO - decide whether to disable these or not # (they don't appear to get disabled in the base game) @@ -563,41 +682,42 @@ func _update_speed_controls() -> void: _pause_bg_button.set_tooltip_string("TOPBAR_DATE_IS_PAUSED" if paused else "TOPBAR_DATE") if _speed_indicator_button: - var index : int = 1 + var index: int = 1 if paused: _speed_indicator_button.set_tooltip_string("TOPBAR_PAUSE_INDICATOR") else: index += speed + 1 - const SPEED_NAMES : PackedStringArray = [ - "SLOWEST_SPEED", - "SLOW_SPEED", - "NORMAL_SPEED", - "FAST_SPEED", - "FASTEST_SPEED" + const SPEED_NAMES: PackedStringArray = [ + "SLOWEST_SPEED", "SLOW_SPEED", "NORMAL_SPEED", "FAST_SPEED", "FASTEST_SPEED" ] _speed_indicator_button.set_tooltip_string_and_substitution_dict( - "TOPBAR_SPEED_INDICATOR", { "SPEED": SPEED_NAMES[speed] if speed < SPEED_NAMES.size() else str(speed) } + "TOPBAR_SPEED_INDICATOR", + {"SPEED": SPEED_NAMES[speed] if speed < SPEED_NAMES.size() else str(speed)} ) _speed_indicator_button.set_icon_index(index) + # REQUIREMENTS: # * UIFUN-71 func _on_play_pause_button_pressed() -> void: print("Toggling pause!") MenuSingleton.toggle_paused() + # REQUIREMENTS: # * UIFUN-72 func _on_increase_speed_button_pressed() -> void: print("Speed up!") MenuSingleton.increase_speed() + # REQUIREMENTS: # * UIFUN-73 func _on_decrease_speed_button_pressed() -> void: print("Speed down!") MenuSingleton.decrease_speed() -func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: - for screen : NationManagement.Screen in _nation_management_buttons: + +func _on_update_active_nation_management_screen(active_screen: NationManagement.Screen) -> void: + for screen: NationManagement.Screen in _nation_management_buttons: _nation_management_buttons[screen].set_icon_index(1 + int(screen == active_screen)) diff --git a/game/src/Game/GameStart.gd b/game/src/Game/GameStart.gd index 760da7a5..70632ba0 100644 --- a/game/src/Game/GameStart.gd +++ b/game/src/Game/GameStart.gd @@ -5,20 +5,22 @@ const SoundTabScene := preload("res://src/Game/Menu/OptionMenu/SoundTab.tscn") const GameMenuScene := preload("res://src/Game/GameMenu.tscn") @export_subgroup("Nodes") -@export var loading_screen : LoadingScreen -@export var vic2_dir_dialog : FileDialog +@export var loading_screen: LoadingScreen +@export var vic2_dir_dialog: FileDialog @export_subgroup("") -@export var section_name : String = "general" -@export var setting_name : String = "base_defines_path" +@export var section_name: String = "general" +@export var setting_name: String = "base_defines_path" + +var _settings_base_path: String = "" +var _compatibility_path_list: PackedStringArray = [] -var _settings_base_path : String = "" -var _compatibility_path_list : PackedStringArray = [] func _enter_tree() -> void: - Keychain.keep_binding_check = func(action_name : StringName) -> bool: + Keychain.keep_binding_check = func(action_name: StringName) -> bool: return action_name.begins_with("button_") and action_name.ends_with("_hotkey") + func _ready() -> void: Keychain.actions = { # Map Group @@ -68,25 +70,35 @@ func _ready() -> void: await _setup_compatibility_mode_paths() await loading_screen.start_loading_screen(_initialize_game) -func _load_setting(file : ConfigFile) -> void: - if file == null: return + +func _load_setting(file: ConfigFile) -> void: + if file == null: + return _settings_base_path = file.get_value(section_name, setting_name, "") -func _save_setting(file : ConfigFile) -> void: - if file == null: return + +func _save_setting(file: ConfigFile) -> void: + if file == null: + return file.set_value(section_name, setting_name, _settings_base_path) + func _setup_compatibility_mode_paths() -> void: # To test mods, set your base path to Victoria II and then pass mods in reverse order with --mod="mod" for each mod. - var arg_base_path : String = ArgumentParser.get_argument(&"base-path", "") - var arg_search_path : String = ArgumentParser.get_argument(&"search-path", "") + var arg_base_path: String = ArgumentParser.get_argument(&"base-path", "") + var arg_search_path: String = ArgumentParser.get_argument(&"search-path", "") - var actual_base_path : String = "" + var actual_base_path: String = "" if arg_base_path: if arg_search_path: - push_warning("Exact base path and search base path arguments both used:\nBase: ", arg_base_path, "\nSearch: ", arg_search_path) + push_warning( + "Exact base path and search base path arguments both used:\nBase: ", + arg_base_path, + "\nSearch: ", + arg_search_path + ) actual_base_path = arg_base_path elif arg_search_path: # This will also search for a Steam install if the hint doesn't help @@ -130,10 +142,11 @@ func _setup_compatibility_mode_paths() -> void: _compatibility_path_list = [actual_base_path] # Add mod paths - var settings_mod_names : PackedStringArray = ArgumentParser.get_argument(&"mod", "") - for mod_name : String in settings_mod_names: + var settings_mod_names: PackedStringArray = ArgumentParser.get_argument(&"mod", "") + for mod_name: String in settings_mod_names: _compatibility_path_list.push_back(actual_base_path + "/mod/" + mod_name) + func _load_compatibility_mode() -> void: if GameSingleton.set_compatibility_mode_roots(_compatibility_path_list) != OK: push_error("Errors setting game roots!") @@ -147,6 +160,7 @@ func _load_compatibility_mode() -> void: SoundSingleton.load_music() MusicConductor.add_compat_songs() + func setup_title_theme() -> void: SoundSingleton.load_title_theme() @@ -155,12 +169,13 @@ func setup_title_theme() -> void: var song_paths = MusicConductor.get_all_song_paths() var title_index = song_paths.find(SoundSingleton.title_theme) if title_index != -1: - MusicConductor.call_deferred("start_song_by_index",title_index) + MusicConductor.call_deferred("start_song_by_index", title_index) if len(MusicConductor._available_songs) <= 0: push_error("No song available to play") else: MusicConductor.call_deferred("start_current_song") + # REQUIREMENTS # * FS-333, FS-334, FS-335, FS-341 func _initialize_game() -> void: @@ -181,5 +196,6 @@ func _initialize_game() -> void: # change scene in a thread-safe way get_tree().change_scene_to_packed.call_deferred(GameMenuScene) + func _on_splash_container_splash_end() -> void: loading_screen.show() diff --git a/game/src/Game/GlobalClass/GameDebug.gd b/game/src/Game/GlobalClass/GameDebug.gd index 08d2b8b8..1959ba57 100644 --- a/game/src/Game/GlobalClass/GameDebug.gd +++ b/game/src/Game/GlobalClass/GameDebug.gd @@ -1,26 +1,31 @@ class_name GameDebug extends RefCounted -static var _singleton : GameDebug +static var _singleton: GameDebug -static var debug_mode : bool: - get = is_debug_mode, set = set_debug_mode +static var debug_mode: bool: + get = is_debug_mode, + set = set_debug_mode -static func set_debug_mode(value : bool) -> void: + +static func set_debug_mode(value: bool) -> void: if _singleton == null: push_warning("Debug mode could not be set.") return _singleton._set_debug_mode(value) + static func is_debug_mode() -> bool: if _singleton == null: push_warning("Could not get debug mode, returning false.") return false return _singleton._is_debug_mode() -func _set_debug_mode(value : bool) -> void: + +func _set_debug_mode(value: bool) -> void: ArgumentParser.set_argument(&"game-debug", value) print("Set debug mode to: ", value) + func _is_debug_mode() -> bool: return ArgumentParser.get_argument(&"game-debug", false) diff --git a/game/src/Game/GlobalClass/Localisation.gd b/game/src/Game/GlobalClass/Localisation.gd index 25232ef6..d21280c2 100644 --- a/game/src/Game/GlobalClass/Localisation.gd +++ b/game/src/Game/GlobalClass/Localisation.gd @@ -1,34 +1,40 @@ class_name Localisation extends RefCounted + # REQUIREMENTS # * SS-59, SS-60, SS-61 static func get_default_locale() -> String: - var locales : PackedStringArray = TranslationServer.get_loaded_locales() + var locales: PackedStringArray = TranslationServer.get_loaded_locales() var default_locale := OS.get_locale() if default_locale in locales: return default_locale var default_language := OS.get_locale_language() - for locale : String in locales: + for locale: String in locales: if locale.begins_with(default_language): return default_language return ProjectSettings.get_setting("internationalization/locale/fallback", "en_GB") -static func load_localisation(dir_path : String) -> void: + +static func load_localisation(dir_path: String) -> void: if LoadLocalisation.load_localisation_dir(dir_path) != OK: push_error("Error loading localisation directory: ", dir_path) - var loaded_locales : PackedStringArray = TranslationServer.get_loaded_locales() + var loaded_locales: PackedStringArray = TranslationServer.get_loaded_locales() print("Loaded ", loaded_locales.size(), " locales: ", loaded_locales) + # REQUIREMENTS # * SS-57 # * FS-17 static func initialize() -> void: - var localisation_dir_path : String = ProjectSettings.get_setting("internationalization/locale/localisation_path", "") + var localisation_dir_path: String = ProjectSettings.get_setting( + "internationalization/locale/localisation_path", "" + ) if localisation_dir_path.is_empty(): push_error("internationalization/locale/localisation_path setting is empty!") else: Localisation.load_localisation(localisation_dir_path) -static func tr_number(num : Variant) -> String: + +static func tr_number(num: Variant) -> String: return TextServerManager.get_primary_interface().format_number(str(num)) diff --git a/game/src/Game/GlobalClass/NationManagement.gd b/game/src/Game/GlobalClass/NationManagement.gd index 3b73bdee..3c42f85d 100644 --- a/game/src/Game/GlobalClass/NationManagement.gd +++ b/game/src/Game/GlobalClass/NationManagement.gd @@ -1,13 +1,3 @@ class_name NationManagement -enum Screen { - NONE, - PRODUCTION, - BUDGET, - TECHNOLOGY, - POLITICS, - POPULATION, - TRADE, - DIPLOMACY, - MILITARY -} +enum Screen {NONE, PRODUCTION, BUDGET, TECHNOLOGY, POLITICS, POPULATION, TRADE, DIPLOMACY, MILITARY} diff --git a/game/src/Game/GlobalClass/ShaderManager.gd b/game/src/Game/GlobalClass/ShaderManager.gd index 7e409d3b..dae443f3 100644 --- a/game/src/Game/GlobalClass/ShaderManager.gd +++ b/game/src/Game/GlobalClass/ShaderManager.gd @@ -1,27 +1,31 @@ class_name ShaderManagerClass extends RefCounted -const param_province_shape_tex : StringName = &"province_shape_tex" -const param_province_shape_subdivisions : StringName = &"province_shape_subdivisions" -const param_province_colour_tex : StringName = &"province_colour_tex" -const param_hover_index : StringName = &"hover_index" -const param_selected_index : StringName = &"selected_index" -const param_parchment_mix : StringName = &"parchment_mix" -const param_terrain_tex : StringName = &"terrain_tex" -const param_terrain_tile_factor : StringName = &"terrain_tile_factor" -const param_stripe_tex : StringName = &"stripe_tex" -const param_stripe_tile_factor : StringName = &"stripe_tile_factor" -const param_overlay_tex : StringName = &"overlay_tex" -const param_overlay_tile_factor : StringName = &"overlay_tile_factor" -const param_colormap_land_tex : StringName = &"colormap_land_tex" -const param_colormap_water_tex : StringName = &"colormap_water_tex" -const param_colormap_overlay_tex : StringName = &"colormap_overlay_tex" +const param_province_shape_tex: StringName = &"province_shape_tex" +const param_province_shape_subdivisions: StringName = &"province_shape_subdivisions" +const param_province_colour_tex: StringName = &"province_colour_tex" +const param_hover_index: StringName = &"hover_index" +const param_selected_index: StringName = &"selected_index" +const param_parchment_mix: StringName = &"parchment_mix" +const param_terrain_tex: StringName = &"terrain_tex" +const param_terrain_tile_factor: StringName = &"terrain_tile_factor" +const param_stripe_tex: StringName = &"stripe_tex" +const param_stripe_tile_factor: StringName = &"stripe_tile_factor" +const param_overlay_tex: StringName = &"overlay_tex" +const param_overlay_tile_factor: StringName = &"overlay_tile_factor" +const param_colormap_land_tex: StringName = &"colormap_land_tex" +const param_colormap_water_tex: StringName = &"colormap_water_tex" +const param_colormap_overlay_tex: StringName = &"colormap_overlay_tex" + func _set_shader_texture( - shader_material : ShaderMaterial, texture_param : StringName, texture : Texture, - tile_factor_param : StringName = &"", pixels_per_tile : float = 0.0 + shader_material: ShaderMaterial, + texture_param: StringName, + texture: Texture, + tile_factor_param: StringName = &"", + pixels_per_tile: float = 0.0 ) -> Error: - var err : Error = OK + var err: Error = OK if texture != null: shader_material.set_shader_parameter(texture_param, texture) else: @@ -34,15 +38,24 @@ func _set_shader_texture( shader_material.set_shader_parameter(tile_factor_param, 1.0 / pixels_per_tile) return err + func _set_shader_asset_texture( - shader_material : ShaderMaterial, texture_param : StringName, texture_path : StringName, - tile_factor_param : StringName = &"", pixels_per_tile : float = 0.0 + shader_material: ShaderMaterial, + texture_param: StringName, + texture_path: StringName, + tile_factor_param: StringName = &"", + pixels_per_tile: float = 0.0 ) -> Error: return _set_shader_texture( - shader_material, texture_param, AssetManager.get_texture(texture_path), tile_factor_param, pixels_per_tile + shader_material, + texture_param, + AssetManager.get_texture(texture_path), + tile_factor_param, + pixels_per_tile ) -func set_up_shader(material : Material, add_cosmetic_textures : bool) -> Error: + +func set_up_shader(material: Material, add_cosmetic_textures: bool) -> Error: # Shader Material if material == null: push_error("material is null!") @@ -50,69 +63,114 @@ func set_up_shader(material : Material, add_cosmetic_textures : bool) -> Error: if not material is ShaderMaterial: push_error("Invalid map mesh material class: ", material.get_class()) return FAILED - var shader_material : ShaderMaterial = material + var shader_material: ShaderMaterial = material - var ret : Error = OK + var ret: Error = OK # Province shape texture - if _set_shader_texture(shader_material, param_province_shape_tex, GameSingleton.get_province_shape_texture()) != OK: + if ( + _set_shader_texture( + shader_material, param_province_shape_tex, GameSingleton.get_province_shape_texture() + ) + != OK + ): push_error("Failed to set province shape shader texture array!") ret = FAILED - var subdivisions : Vector2i = GameSingleton.get_province_shape_image_subdivisions() + var subdivisions: Vector2i = GameSingleton.get_province_shape_image_subdivisions() if subdivisions.x >= 1 and subdivisions.y >= 1: - shader_material.set_shader_parameter(param_province_shape_subdivisions, Vector2(subdivisions)) + shader_material.set_shader_parameter( + param_province_shape_subdivisions, Vector2(subdivisions) + ) else: - push_error("Invalid province shape image subdivision: ", subdivisions.x, "x", subdivisions.y) + push_error( + "Invalid province shape image subdivision: ", subdivisions.x, "x", subdivisions.y + ) ret = FAILED if add_cosmetic_textures: - # Province colour texture - if _set_shader_texture(shader_material, param_province_colour_tex, GameSingleton.get_province_colour_texture()) != OK: + if ( + _set_shader_texture( + shader_material, + param_province_colour_tex, + GameSingleton.get_province_colour_texture() + ) + != OK + ): push_error("Failed to set province colour shader texture!") ret = FAILED # Terrain texture - const pixels_per_terrain_tile : float = 16.0 - if _set_shader_texture( - shader_material, - param_terrain_tex, GameSingleton.get_terrain_texture(), - param_terrain_tile_factor, pixels_per_terrain_tile - ) != OK: + const pixels_per_terrain_tile: float = 16.0 + if ( + _set_shader_texture( + shader_material, + param_terrain_tex, + GameSingleton.get_terrain_texture(), + param_terrain_tile_factor, + pixels_per_terrain_tile + ) + != OK + ): push_error("Failed to set terrain shader texture array!") ret = FAILED # Stripe texture - const pixels_per_stripe_tile : float = 8.0 - if _set_shader_asset_texture( - shader_material, - param_stripe_tex, &"map/terrain/stripes.dds", - param_stripe_tile_factor, pixels_per_stripe_tile - ) != OK: + const pixels_per_stripe_tile: float = 8.0 + if ( + _set_shader_asset_texture( + shader_material, + param_stripe_tex, + &"map/terrain/stripes.dds", + param_stripe_tile_factor, + pixels_per_stripe_tile + ) + != OK + ): push_error("Failed to set stripe shader texture!") ret = FAILED # Overlay texture - const pixels_per_overlay_tile : float = 512.0 - if _set_shader_asset_texture( - shader_material, - param_overlay_tex, &"map/terrain/map_overlay_tile.dds", - param_overlay_tile_factor, pixels_per_overlay_tile - ) != OK: + const pixels_per_overlay_tile: float = 512.0 + if ( + _set_shader_asset_texture( + shader_material, + param_overlay_tex, + &"map/terrain/map_overlay_tile.dds", + param_overlay_tile_factor, + pixels_per_overlay_tile + ) + != OK + ): push_error("Failed to set overlay shader texture!") ret = FAILED # Land colormap - if _set_shader_asset_texture(shader_material, param_colormap_land_tex, &"map/terrain/colormap.dds") != OK: + if ( + _set_shader_asset_texture( + shader_material, param_colormap_land_tex, &"map/terrain/colormap.dds" + ) + != OK + ): push_error("Failed to set land colormap shader texture!") ret = FAILED # Water colormap - if _set_shader_asset_texture(shader_material, param_colormap_water_tex, &"map/terrain/colormap_water.dds") != OK: + if ( + _set_shader_asset_texture( + shader_material, param_colormap_water_tex, &"map/terrain/colormap_water.dds" + ) + != OK + ): push_error("Failed to set water colormap shader texture!") ret = FAILED # Overlay colormap - if _set_shader_asset_texture(shader_material, param_colormap_overlay_tex, &"map/terrain/colormap_political.dds") != OK: + if ( + _set_shader_asset_texture( + shader_material, param_colormap_overlay_tex, &"map/terrain/colormap_political.dds" + ) + != OK + ): push_error("Failed to set overlay colormap shader texture!") ret = FAILED diff --git a/game/src/Game/LoadingScreen.gd b/game/src/Game/LoadingScreen.gd index 2b96bed5..fa4eb4c4 100644 --- a/game/src/Game/LoadingScreen.gd +++ b/game/src/Game/LoadingScreen.gd @@ -1,6 +1,6 @@ extends Control -@export var quote_file_path : String = "res://assets/localisation/quotes.txt" +@export var quote_file_path: String = "res://assets/localisation/quotes.txt" @export_subgroup("Nodes") @export var progress_bar: ProgressBar @@ -10,7 +10,8 @@ extends Control var thread: Thread var quotes: PackedStringArray = [] -func start_loading_screen(thread_safe_function : Callable) -> void: + +func start_loading_screen(thread_safe_function: Callable) -> void: if not is_node_ready(): await ready # set first quote @@ -25,6 +26,7 @@ func start_loading_screen(thread_safe_function : Callable) -> void: thread.start(thread_safe_function) + func try_update_loading_screen(percent_complete: float, quote_should_change := false) -> void: # forces the function to behave as if deferred await get_tree().process_frame @@ -32,8 +34,10 @@ func try_update_loading_screen(percent_complete: float, quote_should_change := f if quote_should_change and quotes.size() > 0: quote_label.text = quotes[randi() % quotes.size()] + func _ready() -> void: - if Engine.is_editor_hint(): return + if Engine.is_editor_hint(): + return thread = Thread.new() # FS-3, UI-30, UIFUN-35 var quotes_file := FileAccess.open(quote_file_path, FileAccess.READ).get_as_text() @@ -42,6 +46,7 @@ func _ready() -> void: quotes = [""] animation_player.play("loadingscreen_gear") + func _exit_tree() -> void: if thread != null and thread.is_started(): thread.wait_to_finish() diff --git a/game/src/Game/LocaleButton.gd b/game/src/Game/LocaleButton.gd index 8dc6b062..e5e96d28 100644 --- a/game/src/Game/LocaleButton.gd +++ b/game/src/Game/LocaleButton.gd @@ -1,19 +1,22 @@ extends OptionButton -const section_name : String = "localisation" -const setting_name : String = "locale" +const section_name: String = "localisation" +const setting_name: String = "locale" + +var _default_locale_index: int -var _default_locale_index : int func _ready() -> void: - var locales_country_rename : Dictionary = ProjectSettings.get_setting("internationalization/locale/country_short_name", {}) + var locales_country_rename: Dictionary = ProjectSettings.get_setting( + "internationalization/locale/country_short_name", {} + ) var locales_list := TranslationServer.get_loaded_locales() var default_locale := Localisation.get_default_locale() if default_locale not in locales_list: locales_list.push_back(default_locale) - for locale : String in locales_list: + for locale: String in locales_list: # locale_name consists of a compulsory language name and optional script # and country names, in the format: "[ (script)][, country]" var locale_name := TranslationServer.get_locale_name(locale) @@ -33,46 +36,59 @@ func _ready() -> void: Events.Options.load_settings.connect(load_setting) Events.Options.save_settings.connect(save_setting) -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: _select_locale_by_string(TranslationServer.get_locale()) -func _valid_index(index : int) -> bool: + +func _valid_index(index: int) -> bool: return 0 <= index and index < item_count -func load_setting(file : ConfigFile) -> void: - if file == null: return - var load_value : Variant = file.get_value(section_name, setting_name, Localisation.get_default_locale()) + +func load_setting(file: ConfigFile) -> void: + if file == null: + return + var load_value: Variant = file.get_value( + section_name, setting_name, Localisation.get_default_locale() + ) match typeof(load_value): TYPE_STRING, TYPE_STRING_NAME: if _select_locale_by_string(load_value as String): item_selected.emit(selected) return - push_error("Setting value '%s' invalid for setting [%s] %s" % [load_value, section_name, setting_name]) + push_error( + "Setting value '%s' invalid for setting [%s] %s" % [load_value, section_name, setting_name] + ) reset_setting() -func _select_locale_by_string(locale : String) -> bool: - for idx : int in item_count: + +func _select_locale_by_string(locale: String) -> bool: + for idx: int in item_count: if get_item_metadata(idx) == locale: selected = idx return true selected = _default_locale_index return false + # REQUIREMENTS: # * UIFUN-74 -func save_setting(file : ConfigFile) -> void: - if file == null: return +func save_setting(file: ConfigFile) -> void: + if file == null: + return file.set_value(section_name, setting_name, get_item_metadata(selected)) + func reset_setting() -> void: _select_locale_by_string(TranslationServer.get_locale()) + # REQUIREMENTS: # * SS-58 # * UIFUN-323 -func _on_item_selected(index : int) -> void: +func _on_item_selected(index: int) -> void: if _valid_index(index): TranslationServer.set_locale(get_item_metadata(index)) Events.Options.save_settings_to_file.call_deferred() diff --git a/game/src/Game/Menu/CreditsMenu/CreditsMenu.gd b/game/src/Game/Menu/CreditsMenu/CreditsMenu.gd index 2f1e867a..4085d1a0 100644 --- a/game/src/Game/Menu/CreditsMenu/CreditsMenu.gd +++ b/game/src/Game/Menu/CreditsMenu/CreditsMenu.gd @@ -14,38 +14,35 @@ signal back_button_pressed # ... ############### -@export_file("*.csv") -var core_credits_path : String +@export_file("*.csv") var core_credits_path: String -@export -var godot_engine_scene : PackedScene +@export var godot_engine_scene: PackedScene @export_group("Label Variants", "label_variants_") -@export -var label_variants_project : StringName +@export var label_variants_project: StringName -@export -var label_variants_role : StringName +@export var label_variants_role: StringName -@export -var label_variants_person : StringName +@export var label_variants_person: StringName -@export -var credits_list: VBoxContainer +@export var credits_list: VBoxContainer -const title_key : String = "TITLE" +const title_key: String = "TITLE" # REQUIREMENTS: # * 1.5 Credits Menu # * SS-17 + # REQUIREMENTS # * FS-4 -func _load_credit_file(path : String) -> Dictionary: +func _load_credit_file(path: String) -> Dictionary: var roles := {} var core_credits := FileAccess.open(path, FileAccess.READ) if core_credits == null: - push_error("Failed to open credits file %s (error code %d)" % [path, FileAccess.get_open_error()]) + push_error( + "Failed to open credits file %s (error code %d)" % [path, FileAccess.get_open_error()] + ) return roles while not core_credits.eof_reached(): @@ -79,36 +76,40 @@ func _load_credit_file(path : String) -> Dictionary: roles[title_key] = [roles[title_key][0]] else: push_warning("Credits file %s missing %s" % [path, title_key]) - for role_list : Array in roles.values(): - role_list.sort_custom(func(a : String, b : String) -> bool: return a.naturalnocasecmp_to(b) < 0) + for role_list: Array in roles.values(): + role_list.sort_custom( + func(a: String, b: String) -> bool: return a.naturalnocasecmp_to(b) < 0 + ) return roles -func _add_label(node : Node, text : String, type_variation : StringName) -> void: + +func _add_label(node: Node, text: String, type_variation: StringName) -> void: var label := Label.new() - label.name = 'Label' + text + label.name = "Label" + text label.text = text label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER label.theme_type_variation = type_variation node.add_child(label) + # REQUIREMENTS: # * UI-34, UI-35 -func _add_project_credits(project : Dictionary) -> void: +func _add_project_credits(project: Dictionary) -> void: var project_credits_list := VBoxContainer.new() - project_credits_list.name = 'Credits' + project_credits_list.name = "Credits" if title_key in project: - var title : String = project[title_key][0] + var title: String = project[title_key][0] project_credits_list.name += title _add_label(project_credits_list, title, label_variants_project) project_credits_list.add_child(HSeparator.new()) - for role : String in project: + for role: String in project: if role == title_key: continue var role_parent := VBoxContainer.new() - for person : String in project[role]: + for person: String in project[role]: _add_label(role_parent, person, label_variants_person) _add_label(project_credits_list, role, label_variants_role) @@ -117,9 +118,10 @@ func _add_project_credits(project : Dictionary) -> void: credits_list.add_child(project_credits_list) + func _add_godot_credits() -> void: var godot_credits_list := VBoxContainer.new() - godot_credits_list.name = 'CreditsGodot' + godot_credits_list.name = "CreditsGodot" var godot_engine := godot_engine_scene.instantiate() godot_credits_list.add_child(godot_engine) godot_credits_list.add_child(HSeparator.new()) @@ -127,10 +129,10 @@ func _add_godot_credits() -> void: var author_dict := Engine.get_author_info() _add_label(godot_credits_list, "Contributors", label_variants_role) - for role : String in author_dict: + for role: String in author_dict: var role_parent := VBoxContainer.new() - for person : String in author_dict[role]: + for person: String in author_dict[role]: _add_label(role_parent, person, label_variants_person) _add_label(godot_credits_list, role.replace("_", " ").capitalize(), label_variants_role) @@ -140,11 +142,12 @@ func _add_godot_credits() -> void: var donor_dict := Engine.get_donor_info() _add_label(godot_credits_list, "Donors", label_variants_role) - for role : String in donor_dict: - if donor_dict[role].size() == 0 or donor_dict[role][0].begins_with("None"): continue + for role: String in donor_dict: + if donor_dict[role].size() == 0 or donor_dict[role][0].begins_with("None"): + continue var role_parent := VBoxContainer.new() - for person : String in donor_dict[role]: + for person: String in donor_dict[role]: _add_label(role_parent, person, label_variants_person) _add_label(godot_credits_list, role.replace("_", " ").capitalize(), label_variants_role) @@ -153,34 +156,42 @@ func _add_godot_credits() -> void: credits_list.add_child(godot_credits_list) -func _add_link_button(node : Node, text : String, url: String, type_variation : StringName) -> void: + +func _add_link_button(node: Node, text: String, url: String, type_variation: StringName) -> void: var button := LinkButton.new() - button.name = 'LinkButton' + text + button.name = "LinkButton" + text button.text = text button.uri = url button.size_flags_horizontal = SIZE_SHRINK_CENTER button.theme_type_variation = type_variation node.add_child(button) + func _add_licenses() -> void: var license_list := VBoxContainer.new() - license_list.name = 'Licenses' + license_list.name = "Licenses" _add_label(license_list, "Third-Party Licenses", label_variants_project) license_list.add_child(HSeparator.new()) var license_info := { "OpenVic": ["GPLv3", "https://github.com/OpenVicProject/OpenVic/blob/main/LICENSE.md"], "Godot": ["MIT", "https://github.com/godotengine/godot/blob/master/LICENSE.txt"], - "FreeType": ["FreeType License", "https://gitlab.freedesktop.org/freetype/freetype/-/blob/master/docs/FTL.TXT"], + "FreeType": + [ + "FreeType License", + "https://gitlab.freedesktop.org/freetype/freetype/-/blob/master/docs/FTL.TXT" + ], "ENet": ["MIT", "http://enet.bespin.org/License.html"], "mbed TLS": ["APLv2", "https://github.com/Mbed-TLS/mbedtls/blob/development/LICENSE"] } # Add additional licenses required for attribution here # These licenses should also either be displayed or exported alongside this project - for project : String in license_info: + for project: String in license_info: _add_label(license_list, project, label_variants_role) - _add_link_button(license_list, license_info[project][0], license_info[project][1], label_variants_person) + _add_link_button( + license_list, license_info[project][0], license_info[project][1], label_variants_person + ) license_list.add_child(HSeparator.new()) credits_list.add_child(license_list) @@ -193,11 +204,13 @@ func _ready() -> void: _add_godot_credits() _add_licenses() -func _input(event : InputEvent) -> void: + +func _input(event: InputEvent) -> void: if self.is_visible_in_tree(): if event.is_action_pressed("ui_cancel"): _on_back_button_pressed() + # REQUIREMENTS: # * UI-38 # * UIFUN-37 diff --git a/game/src/Game/Menu/CreditsMenu/GodotEngineButton.gd b/game/src/Game/Menu/CreditsMenu/GodotEngineButton.gd index f8d6dd31..31f22654 100644 --- a/game/src/Game/Menu/CreditsMenu/GodotEngineButton.gd +++ b/game/src/Game/Menu/CreditsMenu/GodotEngineButton.gd @@ -1,4 +1,5 @@ extends Button + func _on_pressed() -> void: OS.shell_open("https://godotengine.org") diff --git a/game/src/Game/Menu/LobbyMenu/LobbyMenu.gd b/game/src/Game/Menu/LobbyMenu/LobbyMenu.gd index ca6b3fb9..215a39c5 100644 --- a/game/src/Game/Menu/LobbyMenu/LobbyMenu.gd +++ b/game/src/Game/Menu/LobbyMenu/LobbyMenu.gd @@ -5,23 +5,24 @@ extends HBoxContainer # * SS-12 signal back_button_pressed -signal save_game_selected(save : SaveResource) -signal start_date_selected(index : int) +signal save_game_selected(save: SaveResource) +signal start_date_selected(index: int) -@export var lobby_panel_button : PackedScene -@export var save_scene : PackedScene +@export var lobby_panel_button: PackedScene +@export var save_scene: PackedScene @export_group("Nodes") -@export var game_select_start_date : BoxContainer -@export var game_select_save_tab : TabBar -@export var game_select_save_list : BoxContainer -@export var start_button : BaseButton -@export var session_tag_line_edit : LineEdit -@export var session_tag_dialog : ConfirmationDialog -@export var delete_dialog : ConfirmationDialog - -func filter_for_tag(tag : StringName) -> void: - for child : Control in game_select_save_list.get_children(): +@export var game_select_start_date: BoxContainer +@export var game_select_save_tab: TabBar +@export var game_select_save_list: BoxContainer +@export var start_button: BaseButton +@export var session_tag_line_edit: LineEdit +@export var session_tag_dialog: ConfirmationDialog +@export var delete_dialog: ConfirmationDialog + + +func filter_for_tag(tag: StringName) -> void: + for child: Control in game_select_save_list.get_children(): if tag == &"": child.show() else: @@ -30,6 +31,7 @@ func filter_for_tag(tag : StringName) -> void: else: child.hide() + func _build_date_list() -> void: var start_date := lobby_panel_button.instantiate() start_date.set_text(&"1836") @@ -40,35 +42,40 @@ func _build_date_list() -> void: start_date.pressed.connect(_on_start_date_panel_button_pressed.bind(start_date)) game_select_start_date.add_child(start_date) -var _id_to_tag : Array[StringName] = [] + +var _id_to_tag: Array[StringName] = [] + # Requirements # * FS-8 func _build_save_list() -> void: game_select_save_tab.add_tab("GAMELOBBY_SELECT_ALL") - for save_name : StringName in SaveManager._save_dictionary: - var save : SaveResource = SaveManager._save_dictionary[save_name] + for save_name: StringName in SaveManager._save_dictionary: + var save: SaveResource = SaveManager._save_dictionary[save_name] var save_node := _create_save_node(save) game_select_save_list.add_child(save_node) if not _id_to_tag.has(save.session_tag): _id_to_tag.append(save.session_tag) game_select_save_tab.add_tab(save.session_tag) -func _create_save_node(resource : SaveResource) -> Control: + +func _create_save_node(resource: SaveResource) -> Control: var save_node := save_scene.instantiate() save_node.resource = resource save_node.pressed.connect(_on_save_node_pressed.bind(save_node)) save_node.request_to_delete.connect(_on_save_node_delete_requested.bind(save_node)) return save_node + func _queue_clear_lists() -> void: var full_list := game_select_start_date.get_children() full_list.append_array(game_select_save_list.get_children()) - for child : Node in full_list: + for child: Node in full_list: child.queue_free() game_select_save_tab.clear_tabs() _id_to_tag.clear() + # REQUIREMENTS: # * SS-16 # * UIFUN-40 @@ -78,6 +85,7 @@ func _on_back_button_button_down() -> void: SaveManager.current_save = null back_button_pressed.emit() + # REQUIREMENTS: # * SS-21 func _on_start_button_pressed() -> void: @@ -85,36 +93,47 @@ func _on_start_button_pressed() -> void: if SaveManager.current_session_tag == "": # TODO: Get country tag as well var datetime := Time.get_datetime_dict_from_system() - SaveManager.current_session_tag = "%s/%s/%s-%s:%s:%s" % [ - datetime["day"], - datetime["month"], - datetime["year"], - datetime["hour"], - datetime["minute"], - datetime["second"] - ] + SaveManager.current_session_tag = ( + "%s/%s/%s-%s:%s:%s" + % [ + datetime["day"], + datetime["month"], + datetime["year"], + datetime["hour"], + datetime["minute"], + datetime["second"] + ] + ) if SaveManager.current_save == null and SaveManager.current_session_tag in _id_to_tag: - session_tag_dialog.dialog_text = tr("GAMELOBBY_SESSIONTAG_DIALOG_TEXT").format({ "session_tag": SaveManager.current_session_tag }) - session_tag_dialog.title = tr("GAMELOBBY_SESSIONTAG_DIALOG_TITLE").format({ "session_tag": SaveManager.current_session_tag }) + session_tag_dialog.dialog_text = tr("GAMELOBBY_SESSIONTAG_DIALOG_TEXT").format( + {"session_tag": SaveManager.current_session_tag} + ) + session_tag_dialog.title = tr("GAMELOBBY_SESSIONTAG_DIALOG_TITLE").format( + {"session_tag": SaveManager.current_session_tag} + ) session_tag_dialog.popup_centered() else: _on_session_tag_dialog_confirmed() + # REQUIREMENTS: # * SS-19 func _on_game_select_list_item_selected(index) -> void: print("Selected save game: ", index) save_game_selected.emit(index) + # If the date is double-clicked, start the game! func _on_game_select_list_item_activated(index) -> void: _on_game_select_list_item_selected(index) _on_start_button_pressed() -func _on_session_tag_edit_text_submitted(new_text : String) -> void: + +func _on_session_tag_edit_text_submitted(new_text: String) -> void: SaveManager.current_session_tag = new_text _on_start_button_pressed() + func _on_session_tag_dialog_confirmed() -> void: # TODO - get bookmarks from SIM and generated corresponding buttons, # then use the selected button's bookmark instead of always using 0 @@ -124,15 +143,25 @@ func _on_session_tag_dialog_confirmed() -> void: push_error("Failed to setup game") get_tree().change_scene_to_file("res://src/Game/GameSession/GameSession.tscn") -var _requested_node_to_delete : Control -func _on_save_node_delete_requested(node : Control) -> void: + +var _requested_node_to_delete: Control + + +func _on_save_node_delete_requested(node: Control) -> void: _requested_node_to_delete = node - delete_dialog.dialog_text = tr("GAMELOBBY_DELETE_DIALOG_TEXT").format({ "file_name": _requested_node_to_delete.resource.save_name }) - delete_dialog.title = tr("GAMELOBBY_DELETE_DIALOG_TITLE").format({ "file_name": _requested_node_to_delete.resource.save_name }) + delete_dialog.dialog_text = tr("GAMELOBBY_DELETE_DIALOG_TEXT").format( + {"file_name": _requested_node_to_delete.resource.save_name} + ) + delete_dialog.title = tr("GAMELOBBY_DELETE_DIALOG_TITLE").format( + {"file_name": _requested_node_to_delete.resource.save_name} + ) delete_dialog.popup_centered() + var _start_date_index := -1 -func _on_start_date_panel_button_pressed(node : Control) -> void: + + +func _on_start_date_panel_button_pressed(node: Control) -> void: if node is LobbyPanelButton and node.get_index(true) == _start_date_index: _on_start_button_pressed() return @@ -140,7 +169,8 @@ func _on_start_date_panel_button_pressed(node : Control) -> void: start_button.disabled = false start_date_selected.emit(_start_date_index) -func _on_save_node_pressed(node : Control) -> void: + +func _on_save_node_pressed(node: Control) -> void: if SaveManager.current_save != null and SaveManager.current_save == node.resource: SaveManager.current_session_tag = SaveManager.current_save.session_tag _on_start_button_pressed() @@ -153,16 +183,19 @@ func _on_save_node_pressed(node : Control) -> void: start_button.disabled = false save_game_selected.emit(SaveManager.current_save) -func _on_game_select_save_tab_tab_changed(tab : int) -> void: + +func _on_game_select_save_tab_tab_changed(tab: int) -> void: if tab == 0: filter_for_tag(&"") else: filter_for_tag(_id_to_tag[tab - 1]) + func _on_delete_dialog_confirmed() -> void: _requested_node_to_delete.resource.delete() _requested_node_to_delete.queue_free() + func _on_visibility_changed() -> void: if visible: _build_date_list() diff --git a/game/src/Game/Menu/LobbyMenu/LobbyPanelButton.gd b/game/src/Game/Menu/LobbyMenu/LobbyPanelButton.gd index b50ee28b..9eea03d1 100644 --- a/game/src/Game/Menu/LobbyMenu/LobbyPanelButton.gd +++ b/game/src/Game/Menu/LobbyMenu/LobbyPanelButton.gd @@ -5,37 +5,42 @@ extends Container signal button_down signal button_up signal pressed -signal toggled(button_pressed : bool) +signal toggled(button_pressed: bool) -var is_start_date : bool: +var is_start_date: bool: get = _is_start_date + func _is_start_date() -> bool: return true + @export_group("Nodes") -@export var background_button : BaseButton -@export var name_label : Label +@export var background_button: BaseButton +@export var name_label: Label -var text : StringName: +var text: StringName: get = get_text, set = set_text + func get_text() -> StringName: return name_label.text -func set_text(value : StringName) -> void: + +func set_text(value: StringName) -> void: name_label.text = value + func _get_minimum_size() -> Vector2: var result := Vector2() - for child : Control in get_children(): + for child: Control in get_children(): if child == null or not child.visible: continue if child.top_level: continue - var minsize : Vector2 = child.get_combined_minimum_size() + var minsize: Vector2 = child.get_combined_minimum_size() result.x = max(result.x, minsize.x) result.y = max(result.y, minsize.y) @@ -45,34 +50,47 @@ func _get_minimum_size() -> Vector2: return result -func _get_draw_mode_name(support_rtl : bool = true) -> StringName: + +func _get_draw_mode_name(support_rtl: bool = true) -> StringName: var rtl := support_rtl and background_button != null and background_button.is_layout_rtl() - match background_button.get_draw_mode() if background_button != null else BaseButton.DrawMode.DRAW_NORMAL: + match ( + background_button.get_draw_mode() + if background_button != null + else BaseButton.DrawMode.DRAW_NORMAL + ): BaseButton.DrawMode.DRAW_NORMAL: - if rtl: return &"normal_mirrored" + if rtl: + return &"normal_mirrored" return &"normal" BaseButton.DrawMode.DRAW_PRESSED: - if rtl: return &"pressed_mirrored" + if rtl: + return &"pressed_mirrored" return &"pressed" BaseButton.DrawMode.DRAW_HOVER: - if rtl: return &"hover_mirrored" + if rtl: + return &"hover_mirrored" return &"hover" BaseButton.DrawMode.DRAW_DISABLED: - if rtl: return &"disabled_mirrored" + if rtl: + return &"disabled_mirrored" return &"disabled" BaseButton.DrawMode.DRAW_HOVER_PRESSED: - if rtl: return &"hover_pressed_mirrored" + if rtl: + return &"hover_pressed_mirrored" return &"hover_pressed" return &"" + func _get_draw_mode_style() -> StyleBox: - if background_button == null: return null + if background_button == null: + return null var result := background_button.get_theme_stylebox(_get_draw_mode_name()) if result == null: return background_button.get_theme_stylebox(_get_draw_mode_name(false)) return result -func _notification(what : int) -> void: + +func _notification(what: int) -> void: if what == NOTIFICATION_SORT_CHILDREN: var _size := size var offset := Vector2() @@ -81,20 +99,24 @@ func _notification(what : int) -> void: _size -= style.get_minimum_size() offset += style.get_offset() - for child : Control in get_children(): + for child: Control in get_children(): if child == null or not child.is_visible_in_tree() or child.top_level: continue fit_child_in_rect(child, Rect2(offset, _size)) + func _on_background_button_button_down() -> void: button_down.emit() + func _on_background_button_button_up() -> void: button_up.emit() + func _on_background_button_pressed() -> void: pressed.emit() -func _on_background_button_toggled(button_pressed : bool) -> void: + +func _on_background_button_toggled(button_pressed: bool) -> void: toggled.emit(button_pressed) diff --git a/game/src/Game/Menu/MainMenu/MainMenu.gd b/game/src/Game/Menu/MainMenu/MainMenu.gd index cc8841f9..0dfd7334 100644 --- a/game/src/Game/Menu/MainMenu/MainMenu.gd +++ b/game/src/Game/Menu/MainMenu/MainMenu.gd @@ -4,14 +4,15 @@ signal options_button_pressed signal new_game_button_pressed signal credits_button_pressed -@export -var _new_game_button : BaseButton +@export var _new_game_button: BaseButton + # REQUIREMENTS: # * SS-3 func _ready() -> void: _on_new_game_button_visibility_changed() + # REQUIREMENTS: # * SS-14 # * UIFUN-32 @@ -32,12 +33,14 @@ func _on_options_button_pressed() -> void: print("Check out some options!") options_button_pressed.emit() + # REQUIREMENTS # * UI-32 # * UIFUN-36 func _on_credits_button_pressed() -> void: credits_button_pressed.emit() + # REQUIREMENTS # * SS-4 # * UIFUN-3 @@ -45,6 +48,7 @@ func _on_exit_button_pressed() -> void: print("See you later!") get_tree().quit() + func _on_new_game_button_visibility_changed() -> void: if visible: _new_game_button.grab_focus.call_deferred() diff --git a/game/src/Game/Menu/MainMenu/ReleaseInfoBox.gd b/game/src/Game/Menu/MainMenu/ReleaseInfoBox.gd index 15291296..360ed6a2 100644 --- a/game/src/Game/Menu/MainMenu/ReleaseInfoBox.gd +++ b/game/src/Game/Menu/MainMenu/ReleaseInfoBox.gd @@ -1,46 +1,54 @@ extends HBoxContainer -@export -var _version_label : Button +@export var _version_label: Button -@export -var _commit_label : Button +@export var _commit_label: Button -@export -var _checksum_label : Button +@export var _checksum_label: Button + +var _checksum: String = "????" -var _checksum : String = "????" # REQUIREMENTS: # * SS-104, SS-105, SS-106, SS-107 # * UIFUN-97, UIFUN-297, UIFUN-299 func _ready() -> void: - _version_label.text = tr("MAIMENU_LATEST_RELEASE_NAME").format({ "release_name": _GIT_INFO_.release_name }) + _version_label.text = tr("MAIMENU_LATEST_RELEASE_NAME").format( + {"release_name": _GIT_INFO_.release_name} + ) _version_label.tooltip_text = _GIT_INFO_.tag - _commit_label.text = tr("MAIMENU_COMMIT").format({ "short_hash": _GIT_INFO_.short_hash }) + _commit_label.text = tr("MAIMENU_COMMIT").format({"short_hash": _GIT_INFO_.short_hash}) _commit_label.tooltip_text = _GIT_INFO_.commit_hash # UI-111 _checksum = Checksum.get_checksum_text() _update_checksum_label_text() -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: _update_checksum_label_text() + func _update_checksum_label_text() -> void: - _checksum_label.tooltip_text = tr("MAINMENU_CHECKSUM_TOOLTIP").format({ "checksum": _checksum }) - _checksum_label.text = tr("MAINMENU_CHECKSUM").format({ "short_checksum": _checksum.substr(0, 4) }) + _checksum_label.tooltip_text = tr("MAINMENU_CHECKSUM_TOOLTIP").format({"checksum": _checksum}) + _checksum_label.text = tr("MAINMENU_CHECKSUM").format( + {"short_checksum": _checksum.substr(0, 4)} + ) + func _on_version_label_pressed() -> void: DisplayServer.clipboard_set(_GIT_INFO_.tag) + func _on_commit_label_pressed() -> void: DisplayServer.clipboard_set(_GIT_INFO_.commit_hash) + func _on_checksum_label_pressed() -> void: DisplayServer.clipboard_set(_checksum) + func _on_game_info_button_pressed() -> void: var project_name := ProjectSettings.get_setting("application/config/name") as String var tag_name := _GIT_INFO_.tag @@ -53,5 +61,21 @@ func _on_game_info_button_pressed() -> void: var gpu_api_version := RenderingServer.get_video_adapter_api_version() var cpu_name := OS.get_processor_name() var cpu_processor_count := OS.get_processor_count() - DisplayServer.clipboard_set("%s %s (%s) [Godot %s] - %s %s - %s - %s (API: %s) - %s (%s Threads)" - % [project_name, tag_name, commit_sha, godot_version, os_name, date_str, display_server, gpu_name, gpu_api_version, cpu_name, cpu_processor_count]) + DisplayServer.clipboard_set( + ( + "%s %s (%s) [Godot %s] - %s %s - %s - %s (API: %s) - %s (%s Threads)" + % [ + project_name, + tag_name, + commit_sha, + godot_version, + os_name, + date_str, + display_server, + gpu_name, + gpu_api_version, + cpu_name, + cpu_processor_count + ] + ) + ) diff --git a/game/src/Game/Menu/OptionMenu/AutosaveIntervalSelector.gd b/game/src/Game/Menu/OptionMenu/AutosaveIntervalSelector.gd index 2c558621..c90dcc6f 100644 --- a/game/src/Game/Menu/OptionMenu/AutosaveIntervalSelector.gd +++ b/game/src/Game/Menu/OptionMenu/AutosaveIntervalSelector.gd @@ -1,2 +1 @@ extends SettingOptionButton - diff --git a/game/src/Game/Menu/OptionMenu/GeneralTab.gd b/game/src/Game/Menu/OptionMenu/GeneralTab.gd index 3d98678e..eff9f839 100644 --- a/game/src/Game/Menu/OptionMenu/GeneralTab.gd +++ b/game/src/Game/Menu/OptionMenu/GeneralTab.gd @@ -2,8 +2,9 @@ extends HBoxContainer @export var initial_focus: Control -func _notification(what : int) -> void: - match(what): + +func _notification(what: int) -> void: + match what: NOTIFICATION_VISIBILITY_CHANGED: if visible and is_inside_tree(): initial_focus.grab_focus() diff --git a/game/src/Game/Menu/OptionMenu/GuiScaleSelector.gd b/game/src/Game/Menu/OptionMenu/GuiScaleSelector.gd index f3c7b22f..fa8a977c 100644 --- a/game/src/Game/Menu/OptionMenu/GuiScaleSelector.gd +++ b/game/src/Game/Menu/OptionMenu/GuiScaleSelector.gd @@ -4,20 +4,21 @@ extends SettingOptionButton # * UIFUN-24 # * UIFUN-31 -@export -var default_value : float = GuiScale.error_guiscale +@export var default_value: float = GuiScale.error_guiscale -func _find_guiscale_index_by_value(value : float) -> int: - for item_index : int in item_count: + +func _find_guiscale_index_by_value(value: float) -> int: + for item_index: int in item_count: if get_item_metadata(item_index) == value: return item_index return -1 -func _sync_guiscales(to_select : float = GuiScale.get_current_guiscale()) -> void: + +func _sync_guiscales(to_select: float = GuiScale.get_current_guiscale()) -> void: clear() default_selected = -1 selected = -1 - for guiscale_value : float in GuiScale.get_guiscale_value_list(): + for guiscale_value: float in GuiScale.get_guiscale_value_list(): add_item(GuiScale.get_guiscale_display_name(guiscale_value)) set_item_metadata(item_count - 1, guiscale_value) @@ -33,30 +34,37 @@ func _sync_guiscales(to_select : float = GuiScale.get_current_guiscale()) -> voi if selected == -1: selected = default_selected + func _setup_button() -> void: if default_value <= 0: default_value = ProjectSettings.get_setting("display/window/stretch/scale") GuiScale.add_guiscale(default_value, &"default") _sync_guiscales() -func _get_value_for_file(select_value : int): + +func _get_value_for_file(select_value: int): if _valid_index(select_value): return get_item_metadata(select_value) else: return null -func _set_value_from_file(load_value : Variant) -> void: + +func _set_value_from_file(load_value: Variant) -> void: if typeof(load_value) == TYPE_FLOAT: - var target_guiscale : float = load_value + var target_guiscale: float = load_value selected = _find_guiscale_index_by_value(target_guiscale) - if selected != -1: return + if selected != -1: + return if GuiScale.add_guiscale(target_guiscale): _sync_guiscales(target_guiscale) return - push_error("Setting value '%s' invalid for setting [%s] %s" % [load_value, section_name, setting_name]) + push_error( + "Setting value '%s' invalid for setting [%s] %s" % [load_value, section_name, setting_name] + ) selected = default_selected -func _on_option_selected(index : int, by_user : bool) -> void: + +func _on_option_selected(index: int, by_user: bool) -> void: if _valid_index(index): GuiScale.set_guiscale(get_item_metadata(index)) else: diff --git a/game/src/Game/Menu/OptionMenu/MonitorDisplaySelector.gd b/game/src/Game/Menu/OptionMenu/MonitorDisplaySelector.gd index 44f89f06..56965f54 100644 --- a/game/src/Game/Menu/OptionMenu/MonitorDisplaySelector.gd +++ b/game/src/Game/Menu/OptionMenu/MonitorDisplaySelector.gd @@ -1,23 +1,29 @@ extends SettingRevertButton + func _setup_button() -> void: clear() - for screen_index : int in DisplayServer.get_screen_count(): + for screen_index: int in DisplayServer.get_screen_count(): # Placeholder option text awaiting _update_monitor_options_text() add_item(str(screen_index + 1)) _update_monitor_options_text() default_selected = Resolution.get_current_monitor() -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: _update_monitor_options_text() + func _update_monitor_options_text() -> void: - for index : int in get_item_count(): - set_item_text(index, tr("OPTIONS_VIDEO_MONITOR").format({ "index": Localisation.tr_number(index + 1) })) + for index: int in get_item_count(): + set_item_text( + index, tr("OPTIONS_VIDEO_MONITOR").format({"index": Localisation.tr_number(index + 1)}) + ) + -func _on_option_selected(index : int, by_user : bool) -> void: +func _on_option_selected(index: int, by_user: bool) -> void: if _valid_index(index): if by_user: print("Start Revert Countdown!") diff --git a/game/src/Game/Menu/OptionMenu/OptionsMenu.gd b/game/src/Game/Menu/OptionMenu/OptionsMenu.gd index c487fb46..57ea85c9 100644 --- a/game/src/Game/Menu/OptionMenu/OptionsMenu.gd +++ b/game/src/Game/Menu/OptionMenu/OptionsMenu.gd @@ -5,7 +5,8 @@ extends Control signal back_button_pressed -@export var _tab_container : TabContainer +@export var _tab_container: TabContainer + func _ready() -> void: _tab_container.set_tab_title(0, "OPTIONS_GENERAL") @@ -15,30 +16,32 @@ func _ready() -> void: _tab_container.set_tab_title(4, "OPTIONS_OTHER") # Setup Keychain for Hotkeys - for action : StringName in InputMap.get_actions(): + for action: StringName in InputMap.get_actions(): if not Keychain.keep_binding_check.call(action): continue Keychain.actions[action] = Keychain.InputAction.new( - action.erase(0, "button_".length()).left(-"_hotkey".length()).capitalize(), - "Hotkeys") - var display_name : String = Keychain.actions[action].display_name + action.erase(0, "button_".length()).left(-"_hotkey".length()).capitalize(), "Hotkeys" + ) + var display_name: String = Keychain.actions[action].display_name if display_name.begins_with("Mapmode"): var mapmode_index := display_name.replace("Mapmode", "").to_int() display_name = tr(GameSingleton.get_mapmode_localisation_key(mapmode_index)) if mapmode_index <= 10: - display_name = display_name\ - .replace(" Mapmode", "")\ - .replace("Mode de carte ", "")\ - .replace("-Kartenmodus", "")\ - .replace("Modo de mapa de ", "")\ - .replace("Modo mapa de ", "")\ - .replace("Modo mapa ", "") + display_name = ( + display_name + . replace(" Mapmode", "") + . replace("Mode de carte ", "") + . replace("-Kartenmodus", "") + . replace("Modo de mapa de ", "") + . replace("Modo mapa de ", "") + . replace("Modo mapa ", "") + ) display_name = tr("Mapmode %s") % display_name.capitalize() Keychain.actions[action].display_name = display_name Keychain.profiles[0].bindings[action] = InputMap.action_get_events(action) # Prepare options menu before loading user settings - var tab_bar : TabBar = _tab_container.get_child(0, true) + var tab_bar: TabBar = _tab_container.get_child(0, true) # This ends up easier to manage then trying to manually recreate the TabContainer's behavior # These buttons can be accessed regardless of the tab @@ -64,36 +67,47 @@ func _ready() -> void: button_list.add_child(back_button) get_viewport().get_window().close_requested.connect(_on_window_close_requested) _save_overrides.call_deferred() - Events.Options.save_settings.connect(func(_f : ConfigFile) -> void: self._save_overrides.call_deferred()) + Events.Options.save_settings.connect( + func(_f: ConfigFile) -> void: self._save_overrides.call_deferred() + ) + -func _notification(what : int) -> void: +func _notification(what: int) -> void: match what: NOTIFICATION_CRASH: _on_window_close_requested() -func _input(event : InputEvent) -> void: + +func _input(event: InputEvent) -> void: if self.is_visible_in_tree(): if event.is_action_pressed("ui_cancel"): _on_back_button_pressed() + func _on_back_button_pressed() -> void: Events.Options.save_settings_to_file() back_button_pressed.emit() + func _on_window_close_requested() -> void: if visible: Events.Options.save_settings_to_file() + func _save_overrides() -> void: - var override_path : String = ProjectSettings.get_setting("application/config/project_settings_override", "") + var override_path: String = ProjectSettings.get_setting( + "application/config/project_settings_override", "" + ) if override_path.is_empty(): - override_path = ProjectSettings.get_setting(Events.Options.settings_file_path_setting, Events.Options.settings_file_path_default) + override_path = ProjectSettings.get_setting( + Events.Options.settings_file_path_setting, Events.Options.settings_file_path_default + ) var file := ConfigFile.new() if FileAccess.file_exists(override_path): if file.load(override_path) != OK: push_error("Failed to load overrides from %s" % override_path) file.set_value("display", "window/size/mode", Resolution.get_current_window_mode()) - var resolution : Vector2i = Resolution.get_current_resolution() + var resolution: Vector2i = Resolution.get_current_resolution() file.set_value("display", "window/size/viewport_width", resolution.x) file.set_value("display", "window/size/viewport_height", resolution.y) if file.save(override_path) != OK: diff --git a/game/src/Game/Menu/OptionMenu/QualityPresetSelector.gd b/game/src/Game/Menu/OptionMenu/QualityPresetSelector.gd index 4fb02a63..d66833e3 100644 --- a/game/src/Game/Menu/OptionMenu/QualityPresetSelector.gd +++ b/game/src/Game/Menu/OptionMenu/QualityPresetSelector.gd @@ -1,4 +1,5 @@ extends SettingOptionButton + func _setup_button() -> void: pass diff --git a/game/src/Game/Menu/OptionMenu/ResolutionSelector.gd b/game/src/Game/Menu/OptionMenu/ResolutionSelector.gd index 7ab7c973..2bf96348 100644 --- a/game/src/Game/Menu/OptionMenu/ResolutionSelector.gd +++ b/game/src/Game/Menu/OptionMenu/ResolutionSelector.gd @@ -3,20 +3,22 @@ extends SettingRevertButton # REQUIREMENTS # * UIFUN-21, UIFUN-28, UIFUN-301, UIFUN-302 -@export var default_value : Vector2i = Resolution.error_resolution +@export var default_value: Vector2i = Resolution.error_resolution -func _find_resolution_index_by_value(value : Vector2i) -> int: - for item_index : int in item_count: + +func _find_resolution_index_by_value(value: Vector2i) -> int: + for item_index: int in item_count: if get_item_metadata(item_index) == value: return item_index return -1 + func _sync_resolutions() -> void: clear() default_selected = -1 selected = -1 var current_resolution := Resolution.get_current_resolution() - for resolution_value : Vector2i in Resolution.get_resolution_value_list(): + for resolution_value: Vector2i in Resolution.get_resolution_value_list(): # Placeholder option text awaiting _update_resolution_options_text() add_item(str(resolution_value)) set_item_metadata(item_count - 1, resolution_value) @@ -34,18 +36,21 @@ func _sync_resolutions() -> void: selected = default_selected _update_resolution_options_text() -func _notification(what : int) -> void: + +func _notification(what: int) -> void: match what: NOTIFICATION_TRANSLATION_CHANGED: if is_node_ready(): _update_resolution_options_text() + func _update_resolution_options_text() -> void: - for index : int in get_item_count(): - var resolution_value : Vector2i = get_item_metadata(index) - var format_dict := { "width": resolution_value.x, "height": resolution_value.y } + for index: int in get_item_count(): + var resolution_value: Vector2i = get_item_metadata(index) + var format_dict := {"width": resolution_value.x, "height": resolution_value.y} format_dict["name"] = tr("OPTIONS_VIDEO_RESOLUTION_{width}x{height}".format(format_dict)) - if format_dict["name"].begins_with("OPTIONS"): format_dict["name"] = "" + if format_dict["name"].begins_with("OPTIONS"): + format_dict["name"] = "" var display_name := "OPTIONS_VIDEO_RESOLUTION_DIMS" if format_dict["name"]: display_name += "_NAMED" @@ -56,8 +61,9 @@ func _update_resolution_options_text() -> void: display_name = tr(display_name).format(format_dict) set_item_text(index, display_name) + func _setup_button() -> void: - Resolution.resolution_added.connect(func (_value : Vector2i) -> void: _sync_resolutions()) + Resolution.resolution_added.connect(func(_value: Vector2i) -> void: _sync_resolutions()) if default_value.x <= 0: default_value.x = ProjectSettings.get_setting("display/window/size/viewport_width") if default_value.y <= 0: @@ -67,29 +73,37 @@ func _setup_button() -> void: else: _sync_resolutions() -func _get_value_for_file(select_value : int): + +func _get_value_for_file(select_value: int): if _valid_index(select_value): return get_item_metadata(select_value) else: return null + # REQUIREMENTS: # * SS-25 -func _set_value_from_file(load_value : Variant) -> void: +func _set_value_from_file(load_value: Variant) -> void: var target_resolution := Resolution.error_resolution match typeof(load_value): - TYPE_VECTOR2I: target_resolution = load_value - TYPE_STRING, TYPE_STRING_NAME: target_resolution = Resolution.get_resolution_value_from_string(load_value) + TYPE_VECTOR2I: + target_resolution = load_value + TYPE_STRING, TYPE_STRING_NAME: + target_resolution = Resolution.get_resolution_value_from_string(load_value) if target_resolution != Resolution.error_resolution: selected = _find_resolution_index_by_value(target_resolution) - if selected != -1: return + if selected != -1: + return if Resolution.add_resolution(target_resolution): Resolution.set_resolution(target_resolution) return - push_error("Setting value '%s' invalid for setting [%s] %s" % [load_value, section_name, setting_name]) + push_error( + "Setting value '%s' invalid for setting [%s] %s" % [load_value, section_name, setting_name] + ) selected = default_selected -func _on_option_selected(index : int, by_user : bool) -> void: + +func _on_option_selected(index: int, by_user: bool) -> void: if _valid_index(index): if by_user: print("Start Revert Countdown!") diff --git a/game/src/Game/Menu/OptionMenu/ScreenModeSelector.gd b/game/src/Game/Menu/OptionMenu/ScreenModeSelector.gd index 84ec9c9e..622984d2 100644 --- a/game/src/Game/Menu/OptionMenu/ScreenModeSelector.gd +++ b/game/src/Game/Menu/OptionMenu/ScreenModeSelector.gd @@ -6,7 +6,8 @@ extends SettingRevertButton enum ScreenMode { Unknown = -1, Fullscreen, Borderless, Windowed } -func get_screen_mode_from_window_mode(window_mode : Window.Mode) -> ScreenMode: + +func get_screen_mode_from_window_mode(window_mode: Window.Mode) -> ScreenMode: match window_mode: Window.MODE_EXCLUSIVE_FULLSCREEN: return ScreenMode.Fullscreen @@ -17,7 +18,8 @@ func get_screen_mode_from_window_mode(window_mode : Window.Mode) -> ScreenMode: _: return ScreenMode.Unknown -func get_window_mode_from_screen_mode(screen_mode : ScreenMode) -> Window.Mode: + +func get_window_mode_from_screen_mode(screen_mode: ScreenMode) -> Window.Mode: match screen_mode: ScreenMode.Fullscreen: return Window.MODE_EXCLUSIVE_FULLSCREEN @@ -28,11 +30,13 @@ func get_window_mode_from_screen_mode(screen_mode : ScreenMode) -> Window.Mode: _: return Window.MODE_EXCLUSIVE_FULLSCREEN + func _setup_button() -> void: default_selected = get_screen_mode_from_window_mode(Resolution.get_current_window_mode()) selected = default_selected -func _on_option_selected(index : int, by_user : bool) -> void: + +func _on_option_selected(index: int, by_user: bool) -> void: if _valid_index(index): if by_user: print("Start Revert Countdown!") diff --git a/game/src/Game/Menu/OptionMenu/SettingNodes/SettingCheckBox.gd b/game/src/Game/Menu/OptionMenu/SettingNodes/SettingCheckBox.gd index 46fe4d75..37f23eff 100644 --- a/game/src/Game/Menu/OptionMenu/SettingNodes/SettingCheckBox.gd +++ b/game/src/Game/Menu/OptionMenu/SettingNodes/SettingCheckBox.gd @@ -1,28 +1,28 @@ extends CheckBox class_name SettingCheckBox -signal option_selected(pressed : bool, by_user : bool) +signal option_selected(pressed: bool, by_user: bool) -@export -var section_name : String = "setting" +@export var section_name: String = "setting" -@export -var setting_name : String = "setting_checkbox" +@export var setting_name: String = "setting_checkbox" + +@export var default_pressed: bool = true -@export -var default_pressed : bool = true func _setup_button() -> void: pass + func _ready() -> void: Events.Options.load_settings.connect(load_setting) Events.Options.save_settings.connect(save_setting) Events.Options.reset_settings.connect(reset_setting) - toggled.connect(func(p : bool) -> void: option_selected.emit(p, true)) + toggled.connect(func(p: bool) -> void: option_selected.emit(p, true)) _setup_button() -func _set_value_from_file(load_value : Variant) -> void: + +func _set_value_from_file(load_value: Variant) -> void: match typeof(load_value): TYPE_BOOL, TYPE_INT: set_pressed_no_signal(load_value as bool) @@ -35,19 +35,29 @@ func _set_value_from_file(load_value : Variant) -> void: if load_str.begins_with("t") or load_str.begins_with("y"): set_pressed_no_signal(true) return - push_error("Setting value '%s' invalid for setting [%s] \"%s\"" % [load_value, section_name, setting_name]) + push_error( + ( + "Setting value '%s' invalid for setting [%s] \"%s\"" + % [load_value, section_name, setting_name] + ) + ) set_pressed_no_signal(default_pressed) -func load_setting(file : ConfigFile) -> void: - if file == null: return + +func load_setting(file: ConfigFile) -> void: + if file == null: + return _set_value_from_file(file.get_value(section_name, setting_name, default_pressed)) option_selected.emit(button_pressed, false) -func save_setting(file : ConfigFile) -> void: - if file == null: return + +func save_setting(file: ConfigFile) -> void: + if file == null: + return file.set_value(section_name, setting_name, button_pressed) -func reset_setting(no_emit : bool = false) -> void: + +func reset_setting(no_emit: bool = false) -> void: set_pressed_no_signal(default_pressed) if not no_emit: option_selected.emit(button_pressed, false) diff --git a/game/src/Game/Menu/OptionMenu/SettingNodes/SettingHSlider.gd b/game/src/Game/Menu/OptionMenu/SettingNodes/SettingHSlider.gd index a728ba0b..1eaa8cc1 100644 --- a/game/src/Game/Menu/OptionMenu/SettingNodes/SettingHSlider.gd +++ b/game/src/Game/Menu/OptionMenu/SettingNodes/SettingHSlider.gd @@ -1,41 +1,51 @@ extends HSlider class_name SettingHSlider -@export -var section_name : String = "setting" +@export var section_name: String = "setting" -@export -var setting_name : String = "setting_hslider" +@export var setting_name: String = "setting_hslider" + +@export var default_value: float = 0 -@export -var default_value : float = 0 func _ready() -> void: Events.Options.load_settings.connect(load_setting) Events.Options.save_settings.connect(save_setting) Events.Options.reset_settings.connect(reset_setting) -func load_setting(file : ConfigFile) -> void: - if file == null: return - var load_value : Variant = file.get_value(section_name, setting_name, default_value) + +func load_setting(file: ConfigFile) -> void: + if file == null: + return + var load_value: Variant = file.get_value(section_name, setting_name, default_value) match typeof(load_value): TYPE_FLOAT, TYPE_INT: - if value == load_value: value_changed.emit(value) + if value == load_value: + value_changed.emit(value) value = load_value return TYPE_STRING, TYPE_STRING_NAME: var load_string := load_value as String if load_string.is_valid_float(): load_value = load_string.to_float() - if value == load_value: value_changed.emit(value) + if value == load_value: + value_changed.emit(value) value = load_value return - push_error("Setting value '%s' invalid for setting [%s] \"%s\"" % [load_value, section_name, setting_name]) + push_error( + ( + "Setting value '%s' invalid for setting [%s] \"%s\"" + % [load_value, section_name, setting_name] + ) + ) value = default_value -func save_setting(file : ConfigFile) -> void: - if file == null: return + +func save_setting(file: ConfigFile) -> void: + if file == null: + return file.set_value(section_name, setting_name, value) + func reset_setting() -> void: value = default_value diff --git a/game/src/Game/Menu/OptionMenu/SettingNodes/SettingOptionButton.gd b/game/src/Game/Menu/OptionMenu/SettingNodes/SettingOptionButton.gd index 44bcada7..da448ccd 100644 --- a/game/src/Game/Menu/OptionMenu/SettingNodes/SettingOptionButton.gd +++ b/game/src/Game/Menu/OptionMenu/SettingNodes/SettingOptionButton.gd @@ -1,33 +1,34 @@ extends OptionButton class_name SettingOptionButton -signal option_selected(index : int, by_user : bool) +signal option_selected(index: int, by_user: bool) -@export -var section_name : String = "setting" +@export var section_name: String = "setting" -@export -var setting_name : String = "setting_optionbutton" +@export var setting_name: String = "setting_optionbutton" -@export -var default_selected : int = -1: - get: return default_selected +@export var default_selected: int = -1: + get: + return default_selected set(v): if v < 0 or item_count == 0: default_selected = -1 return default_selected = v % item_count -func _valid_index(index : int) -> bool: + +func _valid_index(index: int) -> bool: return 0 <= index and index < item_count -func _get_value_for_file(select_value : int) -> Variant: + +func _get_value_for_file(select_value: int) -> Variant: if _valid_index(select_value): return select_value else: return null -func _set_value_from_file(load_value : Variant) -> void: + +func _set_value_from_file(load_value: Variant) -> void: match typeof(load_value): TYPE_INT: if _valid_index(load_value): @@ -40,21 +41,28 @@ func _set_value_from_file(load_value : Variant) -> void: if _valid_index(load_int): selected = load_int return - for item_index : int in item_count: + for item_index: int in item_count: if load_string == get_item_text(item_index): selected = item_index return - push_error("Setting value '%s' invalid for setting [%s] \"%s\"" % [load_value, section_name, setting_name]) + push_error( + ( + "Setting value '%s' invalid for setting [%s] \"%s\"" + % [load_value, section_name, setting_name] + ) + ) selected = default_selected + func _setup_button() -> void: pass + func _ready() -> void: Events.Options.load_settings.connect(load_setting) Events.Options.save_settings.connect(save_setting) Events.Options.reset_settings.connect(reset_setting) - item_selected.connect(func(index : int) -> void: option_selected.emit(index, true)) + item_selected.connect(func(index: int) -> void: option_selected.emit(index, true)) _setup_button() if not _valid_index(default_selected) or selected == -1: var msg := "Failed to generate any valid %s %s options." % [setting_name, section_name] @@ -62,16 +70,23 @@ func _ready() -> void: OS.alert(msg, "Options Error: %s / %s" % [section_name, setting_name]) get_tree().quit() -func load_setting(file : ConfigFile) -> void: - if file == null: return - _set_value_from_file(file.get_value(section_name, setting_name, _get_value_for_file(default_selected))) + +func load_setting(file: ConfigFile) -> void: + if file == null: + return + _set_value_from_file( + file.get_value(section_name, setting_name, _get_value_for_file(default_selected)) + ) option_selected.emit(selected, false) -func save_setting(file : ConfigFile) -> void: - if file == null: return + +func save_setting(file: ConfigFile) -> void: + if file == null: + return file.set_value(section_name, setting_name, _get_value_for_file(selected)) -func reset_setting(no_emit : bool = false) -> void: + +func reset_setting(no_emit: bool = false) -> void: selected = default_selected if not no_emit: option_selected.emit(selected, false) diff --git a/game/src/Game/Menu/OptionMenu/SettingNodes/SettingRevertButton.gd b/game/src/Game/Menu/OptionMenu/SettingNodes/SettingRevertButton.gd index 6785f73c..ab760ac3 100644 --- a/game/src/Game/Menu/OptionMenu/SettingNodes/SettingRevertButton.gd +++ b/game/src/Game/Menu/OptionMenu/SettingNodes/SettingRevertButton.gd @@ -2,9 +2,10 @@ extends SettingOptionButton class_name SettingRevertButton @export_group("Nodes") -@export var revert_dialog : SettingRevertDialog +@export var revert_dialog: SettingRevertDialog + +var previous_index: int = -1 -var previous_index : int = -1 func _ready() -> void: super() @@ -13,15 +14,20 @@ func _ready() -> void: revert_dialog.dialog_accepted.connect(_on_accepted) revert_dialog.dialog_reverted.connect(_on_reverted) + func _on_revert_dialog_visibility_changed() -> void: disabled = revert_dialog.visible if not revert_dialog.visible: previous_index = -1 -func _on_reverted(button : SettingRevertButton) -> void: - if button != self: return + +func _on_reverted(button: SettingRevertButton) -> void: + if button != self: + return selected = previous_index option_selected.emit(selected, false) -func _on_accepted(button : SettingRevertButton) -> void: - if button != self: return + +func _on_accepted(button: SettingRevertButton) -> void: + if button != self: + return diff --git a/game/src/Game/Menu/OptionMenu/SettingRevertDialog.gd b/game/src/Game/Menu/OptionMenu/SettingRevertDialog.gd index 7928d152..a748a51b 100644 --- a/game/src/Game/Menu/OptionMenu/SettingRevertDialog.gd +++ b/game/src/Game/Menu/OptionMenu/SettingRevertDialog.gd @@ -1,37 +1,44 @@ extends ConfirmationDialog class_name SettingRevertDialog -signal dialog_accepted(button : SettingRevertButton) -signal dialog_reverted(button : SettingRevertButton) +signal dialog_accepted(button: SettingRevertButton) +signal dialog_reverted(button: SettingRevertButton) -@export var dialog_text_key : String = "< reverting in {time} seconds >" +@export var dialog_text_key: String = "< reverting in {time} seconds >" @export_group("Nodes") -@export var timer : Timer +@export var timer: Timer -var _revert_node : SettingRevertButton = null +var _revert_node: SettingRevertButton = null -func show_dialog(button : SettingRevertButton, time : float = 0) -> void: + +func show_dialog(button: SettingRevertButton, time: float = 0) -> void: timer.start(time) - popup_centered(Vector2(1,1)) + popup_centered(Vector2(1, 1)) _revert_node = button -func _notification(what : int) -> void: + +func _notification(what: int) -> void: if what == NOTIFICATION_VISIBILITY_CHANGED: set_process(visible) - if not visible: _revert_node = null + if not visible: + _revert_node = null + + +func _process(_delta: float) -> void: + dialog_text = tr(dialog_text_key).format({"time": Localisation.tr_number(int(timer.time_left))}) -func _process(_delta : float) -> void: - dialog_text = tr(dialog_text_key).format({ "time": Localisation.tr_number(int(timer.time_left)) }) func _on_canceled_or_close_requested() -> void: timer.stop() dialog_reverted.emit(_revert_node) + func _on_confirmed() -> void: timer.stop() dialog_accepted.emit(_revert_node) + func _on_resolution_revert_timer_timeout() -> void: dialog_reverted.emit(_revert_node) hide() diff --git a/game/src/Game/Menu/OptionMenu/SoundTab.gd b/game/src/Game/Menu/OptionMenu/SoundTab.gd index a84af70f..a0bab700 100644 --- a/game/src/Game/Menu/OptionMenu/SoundTab.gd +++ b/game/src/Game/Menu/OptionMenu/SoundTab.gd @@ -1,6 +1,9 @@ extends HBoxContainer -@export var _startup_music_button : SettingCheckBox +@export var _startup_music_button: SettingCheckBox + func _ready() -> void: - _startup_music_button.option_selected.connect(func (pressed : bool, _by_user : bool) -> void: MusicConductor.set_startup_music(pressed)) + _startup_music_button.option_selected.connect( + func(pressed: bool, _by_user: bool) -> void: MusicConductor.set_startup_music(pressed) + ) diff --git a/game/src/Game/Menu/OptionMenu/VideoTab.gd b/game/src/Game/Menu/OptionMenu/VideoTab.gd index 3d98678e..eff9f839 100644 --- a/game/src/Game/Menu/OptionMenu/VideoTab.gd +++ b/game/src/Game/Menu/OptionMenu/VideoTab.gd @@ -2,8 +2,9 @@ extends HBoxContainer @export var initial_focus: Control -func _notification(what : int) -> void: - match(what): + +func _notification(what: int) -> void: + match what: NOTIFICATION_VISIBILITY_CHANGED: if visible and is_inside_tree(): initial_focus.grab_focus() diff --git a/game/src/Game/Menu/OptionMenu/VolumeGrid.gd b/game/src/Game/Menu/OptionMenu/VolumeGrid.gd index e9c59d5c..9fa8f00f 100644 --- a/game/src/Game/Menu/OptionMenu/VolumeGrid.gd +++ b/game/src/Game/Menu/OptionMenu/VolumeGrid.gd @@ -1,20 +1,23 @@ extends GridContainer -const RATIO_FOR_LINEAR : float = 100 +const RATIO_FOR_LINEAR: float = 100 -var _slider_dictionary : Dictionary +var _slider_dictionary: Dictionary -var initial_focus : Control +var initial_focus: Control -func get_db_as_volume_value(db : float) -> float: + +func get_db_as_volume_value(db: float) -> float: # db_to_linear produces a float between 0 and 1 from a db value return db_to_linear(db) * RATIO_FOR_LINEAR -func get_volume_value_as_db(value : float) -> float: + +func get_volume_value_as_db(value: float) -> float: # linear_to_db consumes a float between 0 and 1 to produce the db value return linear_to_db(value / RATIO_FOR_LINEAR) -func add_volume_row(bus_name : String, bus_index : int) -> HSlider: + +func add_volume_row(bus_name: String, bus_index: int) -> HSlider: var volume_label := Label.new() if bus_name == "Master": volume_label.text = "MASTER_BUS" @@ -29,42 +32,48 @@ func add_volume_row(bus_name : String, bus_index : int) -> HSlider: volume_slider.size_flags_vertical = Control.SIZE_FILL volume_slider.min_value = 0 volume_slider.default_value = 100 - volume_slider.max_value = 120 # 120 so volume can be boosted somewhat + volume_slider.max_value = 120 # 120 so volume can be boosted somewhat volume_slider.value_changed.connect(_on_slider_value_changed.bind(bus_index)) add_child(volume_slider) _slider_dictionary[volume_label.text] = volume_slider - if not initial_focus: initial_focus = volume_slider + if not initial_focus: + initial_focus = volume_slider return volume_slider + # REQUIREMENTS # * UI-22 func _ready() -> void: - for bus_index : int in AudioServer.bus_count: + for bus_index: int in AudioServer.bus_count: add_volume_row(AudioServer.get_bus_name(bus_index), bus_index) -func _notification(what : int) -> void: - match(what): + +func _notification(what: int) -> void: + match what: NOTIFICATION_VISIBILITY_CHANGED: - if visible and is_inside_tree() and initial_focus: initial_focus.grab_focus() + if visible and is_inside_tree() and initial_focus: + initial_focus.grab_focus() + # REQUIREMENTS # * UIFUN-30 -func _on_slider_value_changed(value : float, bus_index : int) -> void: +func _on_slider_value_changed(value: float, bus_index: int) -> void: AudioServer.set_bus_volume_db(bus_index, get_volume_value_as_db(value)) -func _on_options_menu_load_settings(load_file : ConfigFile) -> void: - for volume_slider : SettingHSlider in _slider_dictionary.values(): +func _on_options_menu_load_settings(load_file: ConfigFile) -> void: + for volume_slider: SettingHSlider in _slider_dictionary.values(): volume_slider.load_setting(load_file) + # REQUIREMENTS # * UIFUN-23 -func _on_options_menu_save_settings(save_file : ConfigFile) -> void: - for volume_slider : SettingHSlider in _slider_dictionary.values(): +func _on_options_menu_save_settings(save_file: ConfigFile) -> void: + for volume_slider: SettingHSlider in _slider_dictionary.values(): volume_slider.save_setting(save_file) func _on_options_menu_reset_settings() -> void: - for volume_slider : SettingHSlider in _slider_dictionary.values(): + for volume_slider: SettingHSlider in _slider_dictionary.values(): volume_slider.reset_setting() diff --git a/game/src/Game/Menu/SaveLoadMenu/SaveLoadMenu.gd b/game/src/Game/Menu/SaveLoadMenu/SaveLoadMenu.gd index 66706b99..3993c6dd 100644 --- a/game/src/Game/Menu/SaveLoadMenu/SaveLoadMenu.gd +++ b/game/src/Game/Menu/SaveLoadMenu/SaveLoadMenu.gd @@ -1,21 +1,22 @@ extends Control -@export var _save_scene : PackedScene +@export var _save_scene: PackedScene @export_group("Nodes") -@export var _label : Label -@export var _scroll_list : BoxContainer -@export var _save_line_edit : LineEdit -@export var _save_load_button : Button -@export var _tag_selection_tab : TabBar -@export var _delete_dialog : ConfirmationDialog -@export var _overwrite_dialog : ConfirmationDialog - -var is_save_menu : bool = true -var _id_to_tag : Array[StringName] = [] - -func filter_for_tag(tag : StringName) -> void: - for child : Control in _scroll_list.get_children(): +@export var _label: Label +@export var _scroll_list: BoxContainer +@export var _save_line_edit: LineEdit +@export var _save_load_button: Button +@export var _tag_selection_tab: TabBar +@export var _delete_dialog: ConfirmationDialog +@export var _overwrite_dialog: ConfirmationDialog + +var is_save_menu: bool = true +var _id_to_tag: Array[StringName] = [] + + +func filter_for_tag(tag: StringName) -> void: + for child: Control in _scroll_list.get_children(): if tag == &"": child.show() else: @@ -24,6 +25,7 @@ func filter_for_tag(tag : StringName) -> void: else: child.hide() + # Requirements # * UIFUN-78 func show_for_load() -> void: @@ -33,6 +35,7 @@ func show_for_load() -> void: is_save_menu = false show() + # Requirements # * UIFUN-77 func show_for_save() -> void: @@ -42,79 +45,103 @@ func show_for_save() -> void: is_save_menu = true show() + func _build_save_list() -> void: _tag_selection_tab.add_tab("SAVELOADMENU_TABSELECTIONTABBAR_ALL") - for save_name : StringName in SaveManager._save_dictionary: - var save : SaveResource = SaveManager._save_dictionary[save_name] + for save_name: StringName in SaveManager._save_dictionary: + var save: SaveResource = SaveManager._save_dictionary[save_name] var save_node := _create_save_node(save) _scroll_list.add_child(save_node) if not _id_to_tag.has(save.session_tag): _id_to_tag.append(save.session_tag) _tag_selection_tab.add_tab(save.session_tag) -func _create_save_node(resource : SaveResource) -> Control: + +func _create_save_node(resource: SaveResource) -> Control: var save_node = _save_scene.instantiate() save_node.resource = resource save_node.pressed.connect(_on_save_node_pressed.bind(save_node)) save_node.request_to_delete.connect(_on_save_node_delete_requested.bind(save_node)) return save_node + func _queue_clear_scroll_list() -> void: - for child : Node in _scroll_list.get_children(): + for child: Node in _scroll_list.get_children(): child.queue_free() _tag_selection_tab.clear_tabs() _id_to_tag.clear() + # REQUIREMENTS: # * UIFUN-84 # * UIFUN-89 func _on_close_button_pressed() -> void: hide() + func _on_delete_dialog_confirmed() -> void: _requested_node_to_delete.resource.delete() _requested_node_to_delete.queue_free() + # REQUIREMENTS: # * UIFUN-83 func _on_overwrite_dialog_confirmed() -> void: SaveManager.add_or_replace_save(SaveManager.make_new_save(_submitted_text)) _on_close_button_pressed() -var _submitted_text : String = "" + +var _submitted_text: String = "" + + func _on_save_line_edit_text_submitted(new_text) -> void: _submitted_text = new_text if SaveManager.has_save(new_text): - _overwrite_dialog.dialog_text = tr("SAVELOADMENU_OVERWRITE_DIALOG_TEXT").format({ "file_name": _submitted_text }) - _overwrite_dialog.title = tr("SAVELOADMENU_OVERWRITE_DIALOG_TITLE").format({ "file_name": _submitted_text }) + _overwrite_dialog.dialog_text = tr("SAVELOADMENU_OVERWRITE_DIALOG_TEXT").format( + {"file_name": _submitted_text} + ) + _overwrite_dialog.title = tr("SAVELOADMENU_OVERWRITE_DIALOG_TITLE").format( + {"file_name": _submitted_text} + ) _overwrite_dialog.popup_centered() return _on_overwrite_dialog_confirmed() + func _on_save_load_button_pressed() -> void: if is_save_menu: _save_line_edit.text_submitted.emit(_save_line_edit.text) -var _requested_node_to_delete : Control -func _on_save_node_delete_requested(node : Control) -> void: + +var _requested_node_to_delete: Control + + +func _on_save_node_delete_requested(node: Control) -> void: _requested_node_to_delete = node - _delete_dialog.dialog_text = tr("SAVELOADMENU_DELETE_DIALOG_TEXT").format({ "file_name": _requested_node_to_delete.resource.save_name }) - _delete_dialog.title = tr("SAVELOADMENU_DELETE_DIALOG_TITLE").format({ "file_name": _requested_node_to_delete.resource.save_name }) + _delete_dialog.dialog_text = tr("SAVELOADMENU_DELETE_DIALOG_TEXT").format( + {"file_name": _requested_node_to_delete.resource.save_name} + ) + _delete_dialog.title = tr("SAVELOADMENU_DELETE_DIALOG_TITLE").format( + {"file_name": _requested_node_to_delete.resource.save_name} + ) _delete_dialog.popup_centered() + # REQUIREMENTS: # * UIFUN-81 # * UIFUN-86 -func _on_save_node_pressed(node : Control) -> void: +func _on_save_node_pressed(node: Control) -> void: if is_save_menu: _save_line_edit.text = node.resource.save_name + func _on_tag_selection_tab_bar_tab_changed(tab) -> void: if tab == 0: filter_for_tag(&"") else: filter_for_tag(_id_to_tag[tab - 1]) + func _on_visibility_changed() -> void: if visible: _build_save_list() diff --git a/game/src/Game/Menu/SaveLoadMenu/SavePanelButton.gd b/game/src/Game/Menu/SaveLoadMenu/SavePanelButton.gd index 6dc43c9a..6deb7266 100644 --- a/game/src/Game/Menu/SaveLoadMenu/SavePanelButton.gd +++ b/game/src/Game/Menu/SaveLoadMenu/SavePanelButton.gd @@ -4,11 +4,11 @@ extends LobbyPanelButton signal request_to_delete @export_group("Nodes") -@export var country_flag : TextureRect -@export var date_label : Label -@export var delete_button : BaseButton +@export var country_flag: TextureRect +@export var date_label: Label +@export var delete_button: BaseButton -var resource : SaveResource: +var resource: SaveResource: get: return resource set(value): @@ -19,23 +19,30 @@ var resource : SaveResource: resource.changed.connect(_resource_changed) _resource_changed() + func get_text() -> StringName: return resource.save_name -func set_text(value : StringName) -> void: + +func set_text(value: StringName) -> void: if resource != null: resource.save_name = value + func _ready() -> void: _resource_changed() + func _is_start_date() -> bool: return false + func _resource_changed() -> void: - if resource == null: return + if resource == null: + return name_label.text = resource.save_name date_label.text = Time.get_datetime_string_from_unix_time(resource.get_save_file_time(), true) + func _on_delete_button_pressed() -> void: request_to_delete.emit() diff --git a/game/src/Game/Menu/SaveLoadMenu/SaveResource.gd b/game/src/Game/Menu/SaveLoadMenu/SaveResource.gd index 63cfd7fe..c4a0099f 100644 --- a/game/src/Game/Menu/SaveLoadMenu/SaveResource.gd +++ b/game/src/Game/Menu/SaveLoadMenu/SaveResource.gd @@ -1,43 +1,49 @@ extends Resource class_name SaveResource -signal file_flushed(path : String) +signal file_flushed(path: String) signal file_loaded signal file_moved_to_trash signal file_deleted signal trash_moved signal deleted -var save_name : StringName: - get: return save_name +var save_name: StringName: + get: + return save_name set(v): save_name = v file.set_value("Save", "name", save_name) emit_changed() -var session_tag : StringName: - get: return session_tag +var session_tag: StringName: + get: + return session_tag set(v): session_tag = v file.set_value("Save", "session_tag", v) emit_changed() -var file_path : String: - get: return file_path +var file_path: String: + get: + return file_path set(v): file_path = v emit_changed() -var file : ConfigFile = ConfigFile.new() +var file: ConfigFile = ConfigFile.new() -func set_file_path(name : StringName, path : String) -> void: + +func set_file_path(name: StringName, path: String) -> void: file_path = path save_name = name + func flush_save() -> Error: file_flushed.emit(file_path) var result := file.save(file_path) file.clear() return result -func load_save(path : String = file_path) -> Error: + +func load_save(path: String = file_path) -> Error: file_loaded.emit() var result := file.load(path) session_tag = file.get_value("Save", "session_tag", session_tag) @@ -45,14 +51,17 @@ func load_save(path : String = file_path) -> Error: set_file_path(file.get_value("Save", "name", save_name), path) return result + func get_save_file_time() -> int: return FileAccess.get_modified_time(file_path) + func move_to_trash() -> Error: trash_moved.emit() file_moved_to_trash.emit() return OS.move_to_trash(file_path) + func delete() -> Error: deleted.emit() file_deleted.emit() diff --git a/game/src/Game/Model/FileAccessUtils.gd b/game/src/Game/Model/FileAccessUtils.gd index f5e02e13..0bfbe0af 100644 --- a/game/src/Game/Model/FileAccessUtils.gd +++ b/game/src/Game/Model/FileAccessUtils.gd @@ -1,58 +1,70 @@ class_name FileAccessUtils -static func read_vec2(file : FileAccess) -> Vector2: + +static func read_vec2(file: FileAccess) -> Vector2: return Vector2(file.get_float(), file.get_float()) -static func read_vec3(file : FileAccess) -> Vector3: + +static func read_vec3(file: FileAccess) -> Vector3: return Vector3(file.get_float(), file.get_float(), file.get_float()) -static func read_pos(file : FileAccess) -> Vector3: - var pos : Vector3 = read_vec3(file) + +static func read_pos(file: FileAccess) -> Vector3: + var pos: Vector3 = read_vec3(file) pos.x = -pos.x return pos -static func read_vec4(file : FileAccess) -> Vector4: + +static func read_vec4(file: FileAccess) -> Vector4: return Vector4(file.get_float(), file.get_float(), file.get_float(), file.get_float()) + # Because paradox may or may not be consistent with the xsm spec depending on if its Tuesday or not -static func read_quat(file : FileAccess, int16 : bool = false) -> Quaternion: +static func read_quat(file: FileAccess, int16: bool = false) -> Quaternion: if int16: return Quaternion(read_f16(file), -read_f16(file), -read_f16(file), read_f16(file)) else: return Quaternion(file.get_float(), -file.get_float(), -file.get_float(), file.get_float()) -static func read_f16(file : FileAccess) -> float: + +static func read_f16(file: FileAccess) -> float: # 32767 or 0x7FFF is the max magnitude of a signed int16 return float(read_int16(file)) / 32767.0 -static func replace_chars(string : String) -> String: + +static func replace_chars(string: String) -> String: return string.replace(":", "_").replace("\\", "_").replace("/", "_") -static func read_xac_str(file : FileAccess) -> String: - var length : int = file.get_32() - var buffer : PackedByteArray = file.get_buffer(length) + +static func read_xac_str(file: FileAccess) -> String: + var length: int = file.get_32() + var buffer: PackedByteArray = file.get_buffer(length) return buffer.get_string_from_ascii() -static func read_int32(file : FileAccess) -> int: - var bytes : int = file.get_32() - var negative : bool = bytes >> 31 - var val : int = bytes & 0x7FFFFFFF + +static func read_int32(file: FileAccess) -> int: + var bytes: int = file.get_32() + var negative: bool = bytes >> 31 + var val: int = bytes & 0x7FFFFFFF if negative: val = -((val ^ 0x7FFFFFFF) + 1) return val -static func read_int16(file : FileAccess) -> int: - var bytes : int = file.get_16() - var negative : bool = bytes >> 15 - var val : int = bytes & 0x7FFF + +static func read_int16(file: FileAccess) -> int: + var bytes: int = file.get_16() + var negative: bool = bytes >> 15 + var val: int = bytes & 0x7FFF if negative: val = -((val ^ 0x7FFF) + 1) return val -static func read_Color32(file : FileAccess) -> Color: + +static func read_Color32(file: FileAccess) -> Color: return Color8(file.get_8(), file.get_8(), file.get_8(), file.get_8()) -static func read_Color128(file : FileAccess) -> Color: + +static func read_Color128(file: FileAccess) -> Color: return Color( file.get_32() / 0xFFFFFFFF, file.get_32() / 0xFFFFFFFF, @@ -60,17 +72,19 @@ static func read_Color128(file : FileAccess) -> Color: file.get_32() / 0xFFFFFFFF ) -static func read_mat4x4(file : FileAccess) -> xac_mat4x4: + +static func read_mat4x4(file: FileAccess) -> xac_mat4x4: return xac_mat4x4.new(read_vec4(file), read_vec4(file), read_vec4(file), read_vec4(file)) + # This datatype is only ever used to hold a transform for nodes (bones) class xac_mat4x4: - var col1 : Vector4 - var col2 : Vector4 - var col3 : Vector4 - var col4 : Vector4 + var col1: Vector4 + var col2: Vector4 + var col3: Vector4 + var col4: Vector4 - func _init(col1 : Vector4, col2 : Vector4, col3 : Vector4, col4 : Vector4) -> void: + func _init(col1: Vector4, col2: Vector4, col3: Vector4, col4: Vector4) -> void: self.col1 = col1 self.col2 = col2 self.col3 = col3 @@ -79,7 +93,7 @@ class xac_mat4x4: func debugPrint() -> void: print("\t\tMat4x4 col1:", col1, " col2:", col2, " col3:", col3, " col4:", col4) - func getAsTransform() -> Transform3D: # godot wants 3x4 matrix + func getAsTransform() -> Transform3D: # godot wants 3x4 matrix return Transform3D( Vector3(col1.x, col1.y, col1.z), Vector3(col2.x, col2.y, col2.z), diff --git a/game/src/Game/Model/UnitModel.gd b/game/src/Game/Model/UnitModel.gd index e98d22a4..10c7538e 100644 --- a/game/src/Game/Model/UnitModel.gd +++ b/game/src/Game/Model/UnitModel.gd @@ -1,62 +1,62 @@ class_name UnitModel extends Node3D -var skeleton : Skeleton3D = null -var anim_player : AnimationPlayer = null -var anim_lib : AnimationLibrary = null -var sub_units : Array[UnitModel] -var meshes : Array[MeshInstance3D] +var skeleton: Skeleton3D = null +var anim_player: AnimationPlayer = null +var anim_lib: AnimationLibrary = null +var sub_units: Array[UnitModel] +var meshes: Array[MeshInstance3D] # COLOUR VARIABLES @export_group("Colors") -@export var primary_colour : Color: +@export var primary_colour: Color: set(col_in): primary_colour = col_in _set_shader_parameter(&"colour_primary", primary_colour) - for unit : UnitModel in sub_units: + for unit: UnitModel in sub_units: unit.primary_colour = col_in @export var secondary_colour: Color: set(col_in): secondary_colour = col_in _set_shader_parameter(&"colour_secondary", secondary_colour) - for unit : UnitModel in sub_units: + for unit: UnitModel in sub_units: unit.secondary_colour = col_in -@export var tertiary_colour : Color: +@export var tertiary_colour: Color: set(col_in): tertiary_colour = col_in _set_shader_parameter(&"colour_tertiary", tertiary_colour) - for unit : UnitModel in sub_units: + for unit: UnitModel in sub_units: unit.tertiary_colour = col_in # ANIMATION VARIABLES @export_group("Animation") -@export var idle_anim : Animation: +@export var idle_anim: Animation: set(anim_in): load_animation("idle", anim_in) idle_anim = anim_in -@export var move_anim : Animation: +@export var move_anim: Animation: set(anim_in): load_animation("move", anim_in) move_anim = anim_in -@export var attack_anim : Animation: +@export var attack_anim: Animation: set(anim_in): load_animation("attack", anim_in) attack_anim = anim_in enum Anim { NONE, IDLE, MOVE, ATTACK } -const ANIMATION_LIBRARY : StringName = &"default_lib" -const ANIMATION_IDLE : String = ANIMATION_LIBRARY + "/idle" -const ANIMATION_MOVE : String = ANIMATION_LIBRARY + "/move" -const ANIMATION_ATTACK : String = ANIMATION_LIBRARY + "/attack" +const ANIMATION_LIBRARY: StringName = &"default_lib" +const ANIMATION_IDLE: String = ANIMATION_LIBRARY + "/idle" +const ANIMATION_MOVE: String = ANIMATION_LIBRARY + "/move" +const ANIMATION_ATTACK: String = ANIMATION_LIBRARY + "/attack" -@export var current_anim : Anim: +@export var current_anim: Anim: set(anim_in): - for unit : UnitModel in sub_units: + for unit: UnitModel in sub_units: unit.current_anim = anim_in if anim_player: @@ -79,7 +79,7 @@ const ANIMATION_ATTACK : String = ANIMATION_LIBRARY + "/attack" _set_tex_scroll(scroll_speed_attack) current_anim = Anim.ATTACK return - _: #None + _: #None pass anim_player.stop() @@ -89,31 +89,33 @@ const ANIMATION_ATTACK : String = ANIMATION_LIBRARY + "/attack" # TEXTURE SCROLL SPEEDS (TANKS TRACKS AND SMOKE) @export_subgroup("Texture_Scroll") -@export var scroll_speed_idle : float: +@export var scroll_speed_idle: float: set(speed_in): scroll_speed_idle = speed_in - for unit : UnitModel in sub_units: + for unit: UnitModel in sub_units: unit.scroll_speed_idle = speed_in -@export var scroll_speed_move : float: +@export var scroll_speed_move: float: set(speed_in): scroll_speed_move = speed_in - for unit : UnitModel in sub_units: + for unit: UnitModel in sub_units: unit.scroll_speed_move = speed_in -@export var scroll_speed_attack : float: +@export var scroll_speed_attack: float: set(speed_in): scroll_speed_attack = speed_in - for unit : UnitModel in sub_units: + for unit: UnitModel in sub_units: unit.scroll_speed_attack = speed_in + func unit_init() -> void: - for child : Node in get_children(): + for child: Node in get_children(): if child is MeshInstance3D: meshes.append(child) elif child is Skeleton3D: skeleton = child + func add_anim_player() -> void: anim_player = AnimationPlayer.new() anim_player.name = "anim_player" @@ -124,21 +126,41 @@ func add_anim_player() -> void: add_child(anim_player) -func has_bone(bone_name : String) -> bool: + +func has_bone(bone_name: String) -> bool: return skeleton and skeleton.find_bone(bone_name) > -1 -func attach_model(bone_name : String, model : Node3D) -> Error: + +func attach_model(bone_name: String, model: Node3D) -> Error: if not model: - push_error("Cannot attach null model to bone \"", bone_name, "\" of UnitModel ", get_name()) + push_error('Cannot attach null model to bone "', bone_name, '" of UnitModel ', get_name()) return FAILED if not skeleton: - push_error("Cannot attach model \"", model.get_name(), "\" to bone \"", bone_name, "\" of UnitModel ", get_name(), " - has no skeleton!") + push_error( + 'Cannot attach model "', + model.get_name(), + '" to bone "', + bone_name, + '" of UnitModel ', + get_name(), + " - has no skeleton!" + ) return FAILED - var bone_idx : int = skeleton.find_bone(bone_name) + var bone_idx: int = skeleton.find_bone(bone_name) if bone_idx < 0 or bone_idx >= skeleton.get_bone_count(): - push_error("Invalid bone \"", bone_name, "\" (index ", bone_idx, ") for attachment \"", model.get_name(), "\" to UnitModel \"", get_name(), "\"") + push_error( + 'Invalid bone "', + bone_name, + '" (index ', + bone_idx, + ') for attachment "', + model.get_name(), + '" to UnitModel "', + get_name(), + '"' + ) return FAILED var bone_attachment := BoneAttachment3D.new() @@ -156,19 +178,23 @@ func attach_model(bone_name : String, model : Node3D) -> Error: return OK -func _set_shader_parameter(param_name : StringName, param_val : Variant) -> void: - for mesh : MeshInstance3D in meshes: + +func _set_shader_parameter(param_name: StringName, param_val: Variant) -> void: + for mesh: MeshInstance3D in meshes: mesh.set_instance_shader_parameter(param_name, param_val) -func _set_tex_scroll(speed : float) -> void: + +func _set_tex_scroll(speed: float) -> void: _set_shader_parameter(&"scroll_speed", speed) -func set_flag_index(index : int) -> void: + +func set_flag_index(index: int) -> void: _set_shader_parameter(&"flag_index", index) -func load_animation(prop_name : String, animIn : Animation) -> void: + +func load_animation(prop_name: String, animIn: Animation) -> void: if not animIn: return if not anim_player: add_anim_player() - anim_lib.add_animation(prop_name,animIn) + anim_lib.add_animation(prop_name, animIn) diff --git a/game/src/Game/Model/XACLoader.gd b/game/src/Game/Model/XACLoader.gd index 423c6222..18c21e5b 100644 --- a/game/src/Game/Model/XACLoader.gd +++ b/game/src/Game/Model/XACLoader.gd @@ -1,75 +1,78 @@ class_name XACLoader -static var unit_shader : ShaderMaterial = preload("res://src/Game/Model/unit_colours_mat.tres") -const MAX_UNIT_TEXTURES : int = 32 # max number of textures supported by the shader -const EXTRA_CULL_MARGIN : int = 2 # extra margin to stop sub-meshes from being culled near the edges of screens -static var added_unit_textures_spec : PackedStringArray -static var added_unit_textures_diffuse : PackedStringArray - -static var flag_shader : ShaderMaterial = preload("res://src/Game/Model/flag_mat.tres") - -static var scrolling_shader : ShaderMaterial = preload("res://src/Game/Model/scrolling_mat.tres") -const MAX_SCROLLING_TEXTURES : int = 32 # max number of textures supported by the shader -static var added_scrolling_textures_diffuse : PackedStringArray -const SCROLLING_MATERIAL_FACTORS : Dictionary = { - "TexAnim" : 2.5, # Tank tracks - "Smoke" : 0.3 # Buildings, factories, steam ships, sieges -} +static var unit_shader: ShaderMaterial = preload("res://src/Game/Model/unit_colours_mat.tres") +const MAX_UNIT_TEXTURES: int = 32 # max number of textures supported by the shader +const EXTRA_CULL_MARGIN: int = 2 # extra margin to stop sub-meshes from being culled near the edges of screens +static var added_unit_textures_spec: PackedStringArray +static var added_unit_textures_diffuse: PackedStringArray + +static var flag_shader: ShaderMaterial = preload("res://src/Game/Model/flag_mat.tres") + +static var scrolling_shader: ShaderMaterial = preload("res://src/Game/Model/scrolling_mat.tres") +const MAX_SCROLLING_TEXTURES: int = 32 # max number of textures supported by the shader +static var added_scrolling_textures_diffuse: PackedStringArray +const SCROLLING_MATERIAL_FACTORS: Dictionary = {"TexAnim": 2.5, "Smoke": 0.3} # Tank tracks # Buildings, factories, steam ships, sieges + static func setup_flag_shader() -> void: flag_shader.set_shader_parameter(&"flag_dims", GameSingleton.get_flag_dims()) - flag_shader.set_shader_parameter(&"texture_flag_sheet_diffuse", GameSingleton.get_flag_sheet_texture()) + flag_shader.set_shader_parameter( + &"texture_flag_sheet_diffuse", GameSingleton.get_flag_sheet_texture() + ) + # Keys: source_file (String) # Values: loaded model (UnitModel or Node3D) or LOAD_FAILED_MARKER (StringName) -static var xac_cache : Dictionary +static var xac_cache: Dictionary + +const LOAD_FAILED_MARKER: StringName = &"XAC LOAD FAILED" -const LOAD_FAILED_MARKER : StringName = &"XAC LOAD FAILED" -static func get_xac_model(source_file : String, is_unit : bool) -> Node3D: - var cached : Variant = xac_cache.get(source_file) +static func get_xac_model(source_file: String, is_unit: bool) -> Node3D: + var cached: Variant = xac_cache.get(source_file) if not cached: cached = _load_xac_model(source_file, is_unit) if cached: xac_cache[source_file] = cached else: xac_cache[source_file] = LOAD_FAILED_MARKER - push_error("Failed to get XAC model \"", source_file, "\" (current load failed)") + push_error('Failed to get XAC model "', source_file, '" (current load failed)') return null if not cached is Node3D: - push_error("Failed to get XAC model \"", source_file, "\" (previous load failed)") + push_error('Failed to get XAC model "', source_file, '" (previous load failed)') return null - var node : Node3D = cached.duplicate() + var node: Node3D = cached.duplicate() if node is UnitModel: node.unit_init() return node -static func _load_xac_model(source_file : String, is_unit : bool) -> Node3D: - var source_path : String = GameSingleton.lookup_file_path(source_file) - var file : FileAccess = FileAccess.open(source_path, FileAccess.READ) + +static func _load_xac_model(source_file: String, is_unit: bool) -> Node3D: + var source_path: String = GameSingleton.lookup_file_path(source_file) + var file: FileAccess = FileAccess.open(source_path, FileAccess.READ) if file == null: push_error("Failed to load XAC ", source_file, " from looked up path ", source_path) return null - var metaDataChunk : MetadataChunk - var nodeHierarchyChunk : NodeHierarchyChunk - var materialTotalsChunk : MaterialTotalsChunk - var materialDefinitionChunks : Array[MaterialDefinitionChunk] = [] - var mesh_chunks : Array[MeshChunk] = [] - var skinningChunks : Array[SkinningChunk] = [] - var chunkType6s : Array[ChunkType6] = [] - var nodeChunks : Array[NodeChunk] = [] - var chunkType4s : Array[ChunkTypeUnknown] = [] - var chunkUnknowns : Array[ChunkTypeUnknown] = [] + var metaDataChunk: MetadataChunk + var nodeHierarchyChunk: NodeHierarchyChunk + var materialTotalsChunk: MaterialTotalsChunk + var materialDefinitionChunks: Array[MaterialDefinitionChunk] = [] + var mesh_chunks: Array[MeshChunk] = [] + var skinningChunks: Array[SkinningChunk] = [] + var chunkType6s: Array[ChunkType6] = [] + var nodeChunks: Array[NodeChunk] = [] + var chunkType4s: Array[ChunkTypeUnknown] = [] + var chunkUnknowns: Array[ChunkTypeUnknown] = [] readHeader(file) while file.get_position() < file.get_length(): - var type : int = FileAccessUtils.read_int32(file) - var length : int = FileAccessUtils.read_int32(file) - var version : int = FileAccessUtils.read_int32(file) + var type: int = FileAccessUtils.read_int32(file) + var length: int = FileAccessUtils.read_int32(file) + var version: int = FileAccessUtils.read_int32(file) match type: 0x7: metaDataChunk = readMetaDataChunk(file) @@ -79,21 +82,21 @@ static func _load_xac_model(source_file : String, is_unit : bool) -> Node3D: materialTotalsChunk = readMaterialTotalsChunk(file) 0x3: # Ver=1 Appears on old version of format - var chunk : MaterialDefinitionChunk = readMaterialDefinitionChunk(file, version==1) + var chunk: MaterialDefinitionChunk = readMaterialDefinitionChunk(file, version == 1) if chunk.has_specular(): is_unit = true materialDefinitionChunks.push_back(chunk) 0x1: mesh_chunks.push_back(readMeshChunk(file)) 0x2: - skinningChunks.push_back(readSkinningChunk(file,mesh_chunks, version==2)) + skinningChunks.push_back(readSkinningChunk(file, mesh_chunks, version == 2)) 0x6: chunkType6s.push_back(readChunkType6(file)) - 0x0: # Appears on old version of format + 0x0: # Appears on old version of format nodeChunks.push_back(readNodeChunk(file)) - 0xA: # Appears on old version of format + 0xA: # Appears on old version of format chunkUnknowns.push_back(readChunkTypeUnknown(file, length)) - 0x4: # Appears on old version of format + 0x4: # Appears on old version of format chunkType4s.push_back(readChunkTypeUnknown(file, length)) 0x8: push_warning("XAC model ", source_file, " contains junk data chunk 0x8 (skipping)") @@ -103,19 +106,21 @@ static func _load_xac_model(source_file : String, is_unit : bool) -> Node3D: break #BUILD THE GODOT MATERIALS - var materials : Array[MaterialDefinition] = make_materials(materialDefinitionChunks) + var materials: Array[MaterialDefinition] = make_materials(materialDefinitionChunks) #BUILD THE MESH - var node : Node3D = null + var node: Node3D = null if is_unit: node = UnitModel.new() else: node = Node3D.new() - node.name = metaDataChunk.origFileName.replace("\\", "/").split("/", false)[-1].get_slice(".", 0) + node.name = metaDataChunk.origFileName.replace("\\", "/").split("/", false)[-1].get_slice( + ".", 0 + ) - var skeleton : Skeleton3D = null + var skeleton: Skeleton3D = null # build the skeleton hierarchy if nodeHierarchyChunk: @@ -128,54 +133,54 @@ static func _load_xac_model(source_file : String, is_unit : bool) -> Node3D: else: push_warning("MODEL HAS NO SKELETON: ", source_file) - var st : SurfaceTool = SurfaceTool.new() + var st: SurfaceTool = SurfaceTool.new() - for chunk : MeshChunk in mesh_chunks: - var mesh_chunk_name : String + for chunk: MeshChunk in mesh_chunks: + var mesh_chunk_name: String if nodeHierarchyChunk: mesh_chunk_name = nodeHierarchyChunk.nodes[chunk.nodeId].name elif not nodeChunks.is_empty(): mesh_chunk_name = nodeChunks[chunk.nodeId].name - const INVALID_MESHES : PackedStringArray = ["polySurface95"] + const INVALID_MESHES: PackedStringArray = ["polySurface95"] if mesh_chunk_name in INVALID_MESHES: - push_warning("Skipping unused mesh \"", mesh_chunk_name, "\" in model \"", node.name, "\"") + push_warning('Skipping unused mesh "', mesh_chunk_name, '" in model "', node.name, '"') continue - var mesh : ArrayMesh = null - var verts : PackedVector3Array - var normals : PackedVector3Array - var tangents : Array[Vector4] - var uvs : Array[PackedVector2Array] = [] - var influenceRangeInd : PackedInt64Array + var mesh: ArrayMesh = null + var verts: PackedVector3Array + var normals: PackedVector3Array + var tangents: Array[Vector4] + var uvs: Array[PackedVector2Array] = [] + var influenceRangeInd: PackedInt64Array # vert attributes could be in any order, so search for them - for vertAttrib : VerticesAttribute in chunk.VerticesAttributes: + for vertAttrib: VerticesAttribute in chunk.VerticesAttributes: match vertAttrib.type: - 0: # position + 0: # position verts = vertAttrib.data - 1: # normals vec3 + 1: # normals vec3 normals = vertAttrib.data - 2: # tangents vec4 + 2: # tangents vec4 tangents = vertAttrib.data - 3: # uv coords vec2 - uvs.push_back(vertAttrib.data) #can have multiple sets of uv data - 5: # influence range, uint32 + 3: # uv coords vec2 + uvs.push_back(vertAttrib.data) #can have multiple sets of uv data + 5: # influence range, uint32 influenceRangeInd = vertAttrib.data - _: # type 4 32bit colours and type 6 128bit colours aren't used + _: # type 4 32bit colours and type 6 128bit colours aren't used pass #FIXME: find a better solution if possible #pCube1 hardcoding is to fix the cruiser which doesn't properly mark its collision mesh if chunk.bIsCollisionMesh or mesh_chunk_name == "pCube1": - var ar3d : Area3D = Area3D.new() + var ar3d: Area3D = Area3D.new() node.add_child(ar3d) ar3d.owner = node - for submesh : SubMesh in chunk.SubMeshes: - var shape : ConvexPolygonShape3D = ConvexPolygonShape3D.new() + for submesh: SubMesh in chunk.SubMeshes: + var shape: ConvexPolygonShape3D = ConvexPolygonShape3D.new() shape.points = verts - var col : CollisionShape3D = CollisionShape3D.new() + var col: CollisionShape3D = CollisionShape3D.new() col.shape = shape ar3d.add_child(col) @@ -183,9 +188,9 @@ static func _load_xac_model(source_file : String, is_unit : bool) -> Node3D: continue #TODO will this produce correct results? - var applyVertexWeights : bool = true - var skinning_chunk_ind : int = 0 - for skin : SkinningChunk in skinningChunks: + var applyVertexWeights: bool = true + var skinning_chunk_ind: int = 0 + for skin: SkinningChunk in skinningChunks: if skin.nodeId == chunk.nodeId: break skinning_chunk_ind += 1 @@ -197,13 +202,19 @@ static func _load_xac_model(source_file : String, is_unit : bool) -> Node3D: # but only in cases where it isn't an attachment # problem, this is also the body of the S-P infantry # so this should only be valid if inside an attachment or makes use of bone weights - const INVALID_IF_NOT_ONLY_MESH : PackedStringArray = ["polySurface97"] + const INVALID_IF_NOT_ONLY_MESH: PackedStringArray = ["polySurface97"] if influenceRangeInd.is_empty() or skinningChunks.is_empty() or not applyVertexWeights: if mesh_chunks.size() != 1 and mesh_chunk_name in INVALID_IF_NOT_ONLY_MESH: - push_warning("Skipping unused mesh \"", mesh_chunk_name, "\" in model \"", node.name, "\" because it was not the only mesh chunk in its file") + push_warning( + 'Skipping unused mesh "', + mesh_chunk_name, + '" in model "', + node.name, + '" because it was not the only mesh chunk in its file' + ) break - var meshInstance : MeshInstance3D = MeshInstance3D.new() + var meshInstance: MeshInstance3D = MeshInstance3D.new() node.add_child(meshInstance) meshInstance.owner = node @@ -217,53 +228,65 @@ static func _load_xac_model(source_file : String, is_unit : bool) -> Node3D: meshInstance.skeleton = meshInstance.get_path_to(skeleton) if not verts.is_empty(): - var vert_total : int = 0 - var surfaceIndex : int = 0 + var vert_total: int = 0 + var surfaceIndex: int = 0 - for submesh : SubMesh in chunk.SubMeshes: + for submesh: SubMesh in chunk.SubMeshes: st.begin(Mesh.PRIMITIVE_TRIANGLES) - for i : int in submesh.relativeIndices.size(): - var rel_index : int = vert_total + submesh.relativeIndices[i] + for i: int in submesh.relativeIndices.size(): + var rel_index: int = vert_total + submesh.relativeIndices[i] if not normals.is_empty(): st.set_normal(normals[rel_index]) if not tangents.is_empty(): - st.set_tangent(Plane( - -tangents[rel_index].x, - tangents[rel_index].y, - tangents[rel_index].z, - tangents[rel_index].w - )) + st.set_tangent( + Plane( + -tangents[rel_index].x, + tangents[rel_index].y, + tangents[rel_index].z, + tangents[rel_index].w + ) + ) if not uvs.is_empty(): st.set_uv(uvs[0][rel_index]) - if not influenceRangeInd.is_empty() and not skinningChunks.is_empty() and applyVertexWeights: + if ( + not influenceRangeInd.is_empty() + and not skinningChunks.is_empty() + and applyVertexWeights + ): #TODO: Which skinning Chunk? # likely look at the skinning chunk's nodeId, see if it matches our mesh's id - var vert_inf_range_ind : int = influenceRangeInd[rel_index] - var skin_chunk : SkinningChunk = skinningChunks[skinning_chunk_ind] - var influenceRange : InfluenceRange = skin_chunk.influenceRange[vert_inf_range_ind] - var boneWeights : Array[InfluenceData] = skinningChunks[skinning_chunk_ind].influenceData.slice( - influenceRange.firstInfluenceIndex, - influenceRange.firstInfluenceIndex + influenceRange.numInfluences + var vert_inf_range_ind: int = influenceRangeInd[rel_index] + var skin_chunk: SkinningChunk = skinningChunks[skinning_chunk_ind] + var influenceRange: InfluenceRange = ( + skin_chunk.influenceRange[vert_inf_range_ind] + ) + var boneWeights: Array[InfluenceData] = ( + skinningChunks[skinning_chunk_ind] + . influenceData + . slice( + influenceRange.firstInfluenceIndex, + influenceRange.firstInfluenceIndex + influenceRange.numInfluences + ) ) if len(boneWeights) > 4: push_error("num BONE WEIGHTS WAS > 4, GODOT DOESNT LIKE THIS") # TODO: Less hacky fix? - boneWeights = boneWeights.slice(0,4) + boneWeights = boneWeights.slice(0, 4) - var godotBoneIds : PackedInt32Array = PackedInt32Array() - var godotBoneWeights : PackedFloat32Array = PackedFloat32Array() + var godotBoneIds: PackedInt32Array = PackedInt32Array() + var godotBoneWeights: PackedFloat32Array = PackedFloat32Array() godotBoneIds.resize(4) godotBoneIds.fill(0) godotBoneWeights.resize(4) godotBoneWeights.fill(0) - var index : int = 0 - for bone : InfluenceData in boneWeights: + var index: int = 0 + for bone: InfluenceData in boneWeights: godotBoneIds.set(index, bone.boneId) godotBoneWeights.set(index, bone.fWeight) index += 1 @@ -276,7 +299,7 @@ static func _load_xac_model(source_file : String, is_unit : bool) -> Node3D: vert_total += submesh.numVertices - mesh = st.commit(mesh) # add a new surface to the mesh + mesh = st.commit(mesh) # add a new surface to the mesh meshInstance.mesh = mesh st.clear() @@ -285,66 +308,93 @@ static func _load_xac_model(source_file : String, is_unit : bool) -> Node3D: surfaceIndex += 1 if materials[submesh.materialId].spec_index != -1: - meshInstance.set_instance_shader_parameter(&"tex_index_specular", materials[submesh.materialId].spec_index) + meshInstance.set_instance_shader_parameter( + &"tex_index_specular", materials[submesh.materialId].spec_index + ) if materials[submesh.materialId].diffuse_index != -1: - meshInstance.set_instance_shader_parameter(&"tex_index_diffuse", materials[submesh.materialId].diffuse_index) + meshInstance.set_instance_shader_parameter( + &"tex_index_diffuse", materials[submesh.materialId].diffuse_index + ) if materials[submesh.materialId].scroll_index != -1: - meshInstance.set_instance_shader_parameter(&"scroll_tex_index_diffuse", materials[submesh.materialId].scroll_index) + meshInstance.set_instance_shader_parameter( + &"scroll_tex_index_diffuse", materials[submesh.materialId].scroll_index + ) return node + # Information needed to set up a material # Leave the indices -1 if not using the unit shader class MaterialDefinition: - var spec_index : int = -1 - var diffuse_index : int = -1 - var scroll_index : int = -1 - var mat : Material + var spec_index: int = -1 + var diffuse_index: int = -1 + var scroll_index: int = -1 + var mat: Material - func _init(mat : Material, diffuse_ind : int = -1, spec_ind : int = -1, scroll_ind : int = -1) -> void: + func _init( + mat: Material, diffuse_ind: int = -1, spec_ind: int = -1, scroll_ind: int = -1 + ) -> void: self.mat = mat self.diffuse_index = diffuse_ind self.spec_index = spec_ind self.scroll_index = scroll_ind -static func make_materials(materialDefinitionChunks : Array[MaterialDefinitionChunk]) -> Array[MaterialDefinition]: - const TEXTURES_PATH : String = "gfx/anims/%s.dds" - var materials : Array[MaterialDefinition] = [] +static func make_materials( + materialDefinitionChunks: Array[MaterialDefinitionChunk] +) -> Array[MaterialDefinition]: + const TEXTURES_PATH: String = "gfx/anims/%s.dds" + + var materials: Array[MaterialDefinition] = [] - for matdef : MaterialDefinitionChunk in materialDefinitionChunks: - var diffuse_name : String - var specular_name : String - var normal_name : String + for matdef: MaterialDefinitionChunk in materialDefinitionChunks: + var diffuse_name: String + var specular_name: String + var normal_name: String # Find important textures - for layer : Layer in matdef.Layers: + for layer: Layer in matdef.Layers: if layer.texture in ["nospec", "unionjacksquare", "test256texture"]: continue match layer.mapType: - 2: # diffuse + 2: # diffuse if not diffuse_name: diffuse_name = layer.texture else: - push_error("Multiple diffuse layers in material: ", diffuse_name, " and ", layer.texture) + push_error( + "Multiple diffuse layers in material: ", + diffuse_name, + " and ", + layer.texture + ) - 3: # specular + 3: # specular if not specular_name: specular_name = layer.texture else: - push_error("Multiple specular layers in material: ", specular_name, " and ", layer.texture) + push_error( + "Multiple specular layers in material: ", + specular_name, + " and ", + layer.texture + ) - 4: # currently unused + 4: # currently unused pass - 5: # normal + 5: # normal if not normal_name: normal_name = layer.texture else: - push_error("Multiple normal layers in material: ", normal_name, " and ", layer.texture) + push_error( + "Multiple normal layers in material: ", + normal_name, + " and ", + layer.texture + ) _: push_error("Unknown layer type: ", layer.mapType) @@ -355,52 +405,68 @@ static func make_materials(materialDefinitionChunks : Array[MaterialDefinitionCh if normal_name: push_error("Normal texture present in unit colours material: ", normal_name) - var textures_index_spec : int = added_unit_textures_spec.find(specular_name) + var textures_index_spec: int = added_unit_textures_spec.find(specular_name) if textures_index_spec < 0: - var unit_colours_mask_texture : ImageTexture = AssetManager.get_texture(TEXTURES_PATH % specular_name) + var unit_colours_mask_texture: ImageTexture = AssetManager.get_texture( + TEXTURES_PATH % specular_name + ) if unit_colours_mask_texture: added_unit_textures_spec.push_back(specular_name) # Should we still attempt to add the texture to the shader? if len(added_unit_textures_spec) >= MAX_UNIT_TEXTURES: - push_error("Colour masks have exceeded max number of textures supported by unit shader!") + push_error( + "Colour masks have exceeded max number of textures supported by unit shader!" + ) - const param_texture_nation_colors_mask : StringName = &"texture_nation_colors_mask" + const param_texture_nation_colors_mask: StringName = &"texture_nation_colors_mask" - var colour_masks : Array = unit_shader.get_shader_parameter(param_texture_nation_colors_mask) + var colour_masks: Array = unit_shader.get_shader_parameter( + param_texture_nation_colors_mask + ) colour_masks.push_back(unit_colours_mask_texture) textures_index_spec = len(colour_masks) - 1 unit_shader.set_shader_parameter(param_texture_nation_colors_mask, colour_masks) else: push_error("Failed to load specular texture: ", specular_name) - var textures_index_diffuse : int = added_unit_textures_diffuse.find(diffuse_name) + var textures_index_diffuse: int = added_unit_textures_diffuse.find(diffuse_name) if textures_index_diffuse < 0: - var diffuse_texture : ImageTexture = AssetManager.get_texture(TEXTURES_PATH % diffuse_name) + var diffuse_texture: ImageTexture = AssetManager.get_texture( + TEXTURES_PATH % diffuse_name + ) if diffuse_texture: added_unit_textures_diffuse.push_back(diffuse_name) # Should we still attempt to add the texture to the shader? if len(added_unit_textures_diffuse) >= MAX_UNIT_TEXTURES: - push_error("Diffuse textures have exceeded max number supported by unit shader!") + push_error( + "Diffuse textures have exceeded max number supported by unit shader!" + ) - const param_texture_diffuse : StringName = &"texture_diffuse" + const param_texture_diffuse: StringName = &"texture_diffuse" - var diffuse_textures : Array = unit_shader.get_shader_parameter(param_texture_diffuse) + var diffuse_textures: Array = unit_shader.get_shader_parameter( + param_texture_diffuse + ) diffuse_textures.push_back(diffuse_texture) textures_index_diffuse = len(diffuse_textures) - 1 unit_shader.set_shader_parameter(param_texture_diffuse, diffuse_textures) else: push_error("Failed to load diffuse texture: ", diffuse_name) - materials.push_back(MaterialDefinition.new(unit_shader, textures_index_diffuse, textures_index_spec)) + materials.push_back( + MaterialDefinition.new(unit_shader, textures_index_diffuse, textures_index_spec) + ) # Flag (diffuse is unionjacksquare which is ignored) elif normal_name and not diffuse_name: if specular_name: push_error("Specular texture present in flag material: ", specular_name) - var flag_normal_texture : ImageTexture = AssetManager.get_texture(TEXTURES_PATH % normal_name) + var flag_normal_texture: ImageTexture = AssetManager.get_texture( + TEXTURES_PATH % normal_name + ) if flag_normal_texture: flag_shader.set_shader_parameter(&"texture_normal", flag_normal_texture) else: @@ -415,50 +481,68 @@ static func make_materials(materialDefinitionChunks : Array[MaterialDefinitionCh if normal_name: push_error("Normal texture present in scrolling material: ", normal_name) - var scroll_textures_index_diffuse : int = added_scrolling_textures_diffuse.find(diffuse_name) + var scroll_textures_index_diffuse: int = added_scrolling_textures_diffuse.find( + diffuse_name + ) if scroll_textures_index_diffuse < 0: - var diffuse_texture : ImageTexture = AssetManager.get_texture(TEXTURES_PATH % diffuse_name) + var diffuse_texture: ImageTexture = AssetManager.get_texture( + TEXTURES_PATH % diffuse_name + ) if diffuse_texture: added_scrolling_textures_diffuse.push_back(diffuse_name) # Should we still attempt to add the texture to the shader? if len(added_scrolling_textures_diffuse) >= MAX_SCROLLING_TEXTURES: - push_error("Diffuse textures have exceeded max number supported by scrolling shader!") + push_error( + "Diffuse textures have exceeded max number supported by scrolling shader!" + ) - const param_scroll_texture_diffuse : StringName = &"scroll_texture_diffuse" + const param_scroll_texture_diffuse: StringName = &"scroll_texture_diffuse" - var scroll_diffuse_textures : Array = scrolling_shader.get_shader_parameter(param_scroll_texture_diffuse) + var scroll_diffuse_textures: Array = scrolling_shader.get_shader_parameter( + param_scroll_texture_diffuse + ) scroll_diffuse_textures.push_back(diffuse_texture) scroll_textures_index_diffuse = len(scroll_diffuse_textures) - 1 - scrolling_shader.set_shader_parameter(param_scroll_texture_diffuse, scroll_diffuse_textures) + scrolling_shader.set_shader_parameter( + param_scroll_texture_diffuse, scroll_diffuse_textures + ) - const param_scroll_factor : StringName = &"scroll_factor" + const param_scroll_factor: StringName = &"scroll_factor" - var scroll_factors : Array = scrolling_shader.get_shader_parameter(param_scroll_factor) + var scroll_factors: Array = scrolling_shader.get_shader_parameter( + param_scroll_factor + ) scroll_factors.push_back(SCROLLING_MATERIAL_FACTORS[matdef.name]) scrolling_shader.set_shader_parameter(param_scroll_factor, scroll_factors) else: push_error("Failed to load diffuse texture: ", diffuse_name) - materials.push_back(MaterialDefinition.new(scrolling_shader, -1, -1, scroll_textures_index_diffuse)) + materials.push_back( + MaterialDefinition.new(scrolling_shader, -1, -1, scroll_textures_index_diffuse) + ) # Standard material else: if specular_name: push_error("Specular texture present in standard material: ", specular_name) - var mat : StandardMaterial3D = StandardMaterial3D.new() + var mat: StandardMaterial3D = StandardMaterial3D.new() mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA_DEPTH_PRE_PASS if diffuse_name: - var diffuse_texture : ImageTexture = AssetManager.get_texture(TEXTURES_PATH % diffuse_name) + var diffuse_texture: ImageTexture = AssetManager.get_texture( + TEXTURES_PATH % diffuse_name + ) if diffuse_texture: mat.set_texture(BaseMaterial3D.TEXTURE_ALBEDO, diffuse_texture) else: push_error("Failed to load diffuse texture: ", diffuse_name) if normal_name: - var normal_texture : ImageTexture = AssetManager.get_texture(TEXTURES_PATH % normal_name) + var normal_texture: ImageTexture = AssetManager.get_texture( + TEXTURES_PATH % normal_name + ) if normal_texture: mat.normal_enabled = true mat.set_texture(BaseMaterial3D.TEXTURE_NORMAL, normal_texture) @@ -473,17 +557,20 @@ static func make_materials(materialDefinitionChunks : Array[MaterialDefinitionCh return materials -static func build_armature(hierarchy_chunk : NodeHierarchyChunk) -> Skeleton3D: - var skeleton : Skeleton3D = Skeleton3D.new() + +static func build_armature(hierarchy_chunk: NodeHierarchyChunk) -> Skeleton3D: + var skeleton: Skeleton3D = Skeleton3D.new() skeleton.name = "skeleton" - var cur_id : int = 0 - for node : NodeData in hierarchy_chunk.nodes: + var cur_id: int = 0 + for node: NodeData in hierarchy_chunk.nodes: # godot doesn't like the ':' in bone names unlike paradox skeleton.add_bone(FileAccessUtils.replace_chars(node.name)) skeleton.set_bone_parent(cur_id, node.parentNodeId) #For now assume rest and current position are the same - skeleton.set_bone_rest(cur_id, Transform3D(Basis(node.rotation).scaled(node.scale), node.position)) + skeleton.set_bone_rest( + cur_id, Transform3D(Basis(node.rotation).scaled(node.scale), node.position) + ) skeleton.set_bone_pose_position(cur_id, node.position) skeleton.set_bone_pose_rotation(cur_id, node.rotation) @@ -496,17 +583,20 @@ static func build_armature(hierarchy_chunk : NodeHierarchyChunk) -> Skeleton3D: # it might be that one is a current position and the other is a rest position? return skeleton -static func build_armature_chunk0(nodeChunks : Array[NodeChunk]) -> Skeleton3D: - var skeleton : Skeleton3D = Skeleton3D.new() + +static func build_armature_chunk0(nodeChunks: Array[NodeChunk]) -> Skeleton3D: + var skeleton: Skeleton3D = Skeleton3D.new() skeleton.name = "skeleton" - var cur_id : int = 0 - for node : NodeChunk in nodeChunks: + var cur_id: int = 0 + for node: NodeChunk in nodeChunks: # godot doesn't like the ':' in bone names unlike paradox skeleton.add_bone(FileAccessUtils.replace_chars(node.name)) skeleton.set_bone_parent(cur_id, node.parentBone) # For now assume rest and current position are the same - skeleton.set_bone_rest(cur_id, Transform3D(Basis(node.rotation).scaled(node.scale), node.position)) + skeleton.set_bone_rest( + cur_id, Transform3D(Basis(node.rotation).scaled(node.scale), node.position) + ) skeleton.set_bone_pose_position(cur_id, node.position) skeleton.set_bone_pose_rotation(cur_id, node.rotation) @@ -515,45 +605,54 @@ static func build_armature_chunk0(nodeChunks : Array[NodeChunk]) -> Skeleton3D: cur_id += 1 return skeleton -static func readHeader(file : FileAccess) -> void: - var magic_bytes : PackedByteArray = [file.get_8(), file.get_8(), file.get_8(), file.get_8()] - var magic : String = magic_bytes.get_string_from_ascii() - var version : String = "%d.%d" % [file.get_8(), file.get_8()] - var bBigEndian : bool = file.get_8() - var multiplyOrder : int = file.get_8() + +static func readHeader(file: FileAccess) -> void: + var magic_bytes: PackedByteArray = [file.get_8(), file.get_8(), file.get_8(), file.get_8()] + var magic: String = magic_bytes.get_string_from_ascii() + var version: String = "%d.%d" % [file.get_8(), file.get_8()] + var bBigEndian: bool = file.get_8() + var multiplyOrder: int = file.get_8() #print(magic, ", version: ", version, ", bigEndian: ", bBigEndian, " multiplyOrder: ", multiplyOrder) -static func readMetaDataChunk(file : FileAccess) -> MetadataChunk: + +static func readMetaDataChunk(file: FileAccess) -> MetadataChunk: return MetadataChunk.new( - file.get_32(), FileAccessUtils.read_int32(file), file.get_8(), file.get_8(), - Vector2i(file.get_8(), file.get_8()), file.get_float(), - FileAccessUtils.read_xac_str(file), FileAccessUtils.read_xac_str(file), - FileAccessUtils.read_xac_str(file), FileAccessUtils.read_xac_str(file) + file.get_32(), + FileAccessUtils.read_int32(file), + file.get_8(), + file.get_8(), + Vector2i(file.get_8(), file.get_8()), + file.get_float(), + FileAccessUtils.read_xac_str(file), + FileAccessUtils.read_xac_str(file), + FileAccessUtils.read_xac_str(file), + FileAccessUtils.read_xac_str(file) ) + class MetadataChunk: - var repositionMask : int # uint32 - var repositioningNode : int # int32 - var exporterMajorVersion : int # byte - var exporterMinorVersion : int # byte - var unused : Vector2i # 2x byte - var retargetRootOffset : float - var sourceApp : String - var origFileName : String - var exportDate : String - var actorName : String + var repositionMask: int # uint32 + var repositioningNode: int # int32 + var exporterMajorVersion: int # byte + var exporterMinorVersion: int # byte + var unused: Vector2i # 2x byte + var retargetRootOffset: float + var sourceApp: String + var origFileName: String + var exportDate: String + var actorName: String func _init( - repMask : int, - repNode : int, - exMajV : int, - exMinV : int, - un : Vector2i, - retRootOff : float, - sourceApp : String, - origFile : String, - date : String, - actorName : String + repMask: int, + repNode: int, + exMajV: int, + exMinV: int, + un: Vector2i, + retRootOff: float, + sourceApp: String, + origFile: String, + date: String, + actorName: String ) -> void: self.repositionMask = repMask self.repositioningNode = repNode @@ -567,52 +666,70 @@ class MetadataChunk: self.actorName = actorName func debugPrint() -> void: - print("Ver: %d.%d, exported: %s, fileName: %s, sourceApp: %s" % - [exporterMajorVersion, exporterMinorVersion, exportDate, origFileName, sourceApp]) - print("Actor: %s, retargetRootOffset: %d, repositionMask: %d, repositionNode: %d" % - [actorName, retargetRootOffset, repositionMask, repositioningNode]) + print( + ( + "Ver: %d.%d, exported: %s, fileName: %s, sourceApp: %s" + % [exporterMajorVersion, exporterMinorVersion, exportDate, origFileName, sourceApp] + ) + ) + print( + ( + "Actor: %s, retargetRootOffset: %d, repositionMask: %d, repositionNode: %d" + % [actorName, retargetRootOffset, repositionMask, repositioningNode] + ) + ) + # HIERARCHY -static func readNodeData(file : FileAccess) -> NodeData: + +static func readNodeData(file: FileAccess) -> NodeData: return NodeData.new( - FileAccessUtils.read_quat(file), FileAccessUtils.read_quat(file), - FileAccessUtils.read_pos(file), FileAccessUtils.read_vec3(file), - FileAccessUtils.read_vec3(file), # 3x unused floats - FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file), - FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file), - FileAccessUtils.read_mat4x4(file), file.get_float(), FileAccessUtils.read_xac_str(file) + FileAccessUtils.read_quat(file), + FileAccessUtils.read_quat(file), + FileAccessUtils.read_pos(file), + FileAccessUtils.read_vec3(file), + FileAccessUtils.read_vec3(file), # 3x unused floats + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + FileAccessUtils.read_mat4x4(file), + file.get_float(), + FileAccessUtils.read_xac_str(file) ) + class NodeData: - var rotation : Quaternion - var scaleRotation : Quaternion - var position : Vector3 - var scale : Vector3 - var unused : Vector3 # 3x unused floats - var unknown : int # int32 - var unknown2 : int # int32 - var parentNodeId : int # int32 - var numChildNodes : int # int32 - var bIncludeInBoundsCalc : bool # int32 - var transform : FileAccessUtils.xac_mat4x4 - var fImportanceFactor : float - var name : String + var rotation: Quaternion + var scaleRotation: Quaternion + var position: Vector3 + var scale: Vector3 + var unused: Vector3 # 3x unused floats + var unknown: int # int32 + var unknown2: int # int32 + var parentNodeId: int # int32 + var numChildNodes: int # int32 + var bIncludeInBoundsCalc: bool # int32 + var transform: FileAccessUtils.xac_mat4x4 + var fImportanceFactor: float + var name: String func _init( - rot : Quaternion, - scaleRot : Quaternion, - pos : Vector3, - scale : Vector3, - unused : Vector3, - unknown : int, - unknown2 : int, - parentNodeId : int, - numChildNodes : int, - incInBoundsCalc : bool, - transform : FileAccessUtils.xac_mat4x4, - fImportanceFactor : float, - name : String + rot: Quaternion, + scaleRot: Quaternion, + pos: Vector3, + scale: Vector3, + unused: Vector3, + unknown: int, + unknown2: int, + parentNodeId: int, + numChildNodes: int, + incInBoundsCalc: bool, + transform: FileAccessUtils.xac_mat4x4, + fImportanceFactor: float, + name: String ) -> void: self.rotation = rot self.scaleRotation = scaleRot @@ -629,93 +746,127 @@ class NodeData: self.name = name func debugPrint() -> void: - print("\tparentNodeId: %d,\t numChildNodes: %d,\t Node Name: %s" % [parentNodeId, numChildNodes, name]) - print("\tunused %s,%s,%s, -1: %s, -1: %s" % [unused[0], unused[1], unused[2], unknown, unknown2]) - -static func readNodeHierarchyChunk(file : FileAccess) -> NodeHierarchyChunk: - var numNodes : int = FileAccessUtils.read_int32(file) - var numRootNodes : int = FileAccessUtils.read_int32(file) - var nodes : Array[NodeData] = [] - for i : int in numNodes: + print( + ( + "\tparentNodeId: %d,\t numChildNodes: %d,\t Node Name: %s" + % [parentNodeId, numChildNodes, name] + ) + ) + print( + ( + "\tunused %s,%s,%s, -1: %s, -1: %s" + % [unused[0], unused[1], unused[2], unknown, unknown2] + ) + ) + + +static func readNodeHierarchyChunk(file: FileAccess) -> NodeHierarchyChunk: + var numNodes: int = FileAccessUtils.read_int32(file) + var numRootNodes: int = FileAccessUtils.read_int32(file) + var nodes: Array[NodeData] = [] + for i: int in numNodes: nodes.push_back(readNodeData(file)) return NodeHierarchyChunk.new(numNodes, numRootNodes, nodes) + class NodeHierarchyChunk: - var numNodes : int # int32 - var numRootNodes : int # int32 - var nodes : Array[NodeData] + var numNodes: int # int32 + var numRootNodes: int # int32 + var nodes: Array[NodeData] - func _init(numNodes : int, numRootNodes : int, nodes : Array[NodeData]) -> void: + func _init(numNodes: int, numRootNodes: int, nodes: Array[NodeData]) -> void: self.numNodes = numNodes self.numRootNodes = numRootNodes self.nodes = nodes func debugPrint() -> void: print("numNodes: %d, numRootNodes: %d" % [numNodes, numRootNodes]) - for node : NodeData in nodes: + for node: NodeData in nodes: node.debugPrint() + # MATERIAL TOTALS -static func readMaterialTotalsChunk(file : FileAccess) -> MaterialTotalsChunk: - return MaterialTotalsChunk.new(FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file)) + +static func readMaterialTotalsChunk(file: FileAccess) -> MaterialTotalsChunk: + return MaterialTotalsChunk.new( + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file) + ) + class MaterialTotalsChunk: - var numTotalMaterials : int # int32 - var numStandMaterials : int # int32 - var numFxMaterials : int # int32 + var numTotalMaterials: int # int32 + var numStandMaterials: int # int32 + var numFxMaterials: int # int32 - func _init(numTotalMaterials : int, numStandMaterials : int, numFxMaterials : int) -> void: + func _init(numTotalMaterials: int, numStandMaterials: int, numFxMaterials: int) -> void: self.numTotalMaterials = numTotalMaterials self.numStandMaterials = numStandMaterials self.numFxMaterials = numFxMaterials func debugPrint() -> void: - print("totalMaterials: %d, standardMaterials: %d, fxMaterials: %d" % - [numTotalMaterials, numStandMaterials, numFxMaterials]) + print( + ( + "totalMaterials: %d, standardMaterials: %d, fxMaterials: %d" + % [numTotalMaterials, numStandMaterials, numFxMaterials] + ) + ) + # MATERIAL DEFINITION -static func readLayer(file : FileAccess, isV1 : bool) -> Layer: - var unknown : Vector3i + +static func readLayer(file: FileAccess, isV1: bool) -> Layer: + var unknown: Vector3i if isV1: unknown = Vector3i( FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file) ) - var layer : Layer = Layer.new( - file.get_float(), file.get_float(), file.get_float(), file.get_float(), - file.get_float(), file.get_float(), FileAccessUtils.read_int16(file), - file.get_8(), file.get_8(), FileAccessUtils.read_xac_str(file), unknown + var layer: Layer = Layer.new( + file.get_float(), + file.get_float(), + file.get_float(), + file.get_float(), + file.get_float(), + file.get_float(), + FileAccessUtils.read_int16(file), + file.get_8(), + file.get_8(), + FileAccessUtils.read_xac_str(file), + unknown ) return layer + class Layer: - var amount : float - var uOffset : float - var vOffset : float - var uTiling : float - var vTiling : float - var rotInRad : float - var matId : int # int16 - var mapType : int # byte - var unused : int # byte - var texture : String - var unknown : Vector3i # Unknown 3 integers present in v1 of the chunk + var amount: float + var uOffset: float + var vOffset: float + var uTiling: float + var vTiling: float + var rotInRad: float + var matId: int # int16 + var mapType: int # byte + var unused: int # byte + var texture: String + var unknown: Vector3i # Unknown 3 integers present in v1 of the chunk func _init( - amount : float, - uOffset : float, - vOffset : float, - uTiling : float, - vTiling : float, - rotInRad : float, - matId : int, - mapType : int, - unused : int, - texture : String, - unknown : Vector3i + amount: float, + uOffset: float, + vOffset: float, + uTiling: float, + vTiling: float, + rotInRad: float, + matId: int, + mapType: int, + unused: int, + texture: String, + unknown: Vector3i ) -> void: self.amount = amount self.uOffset = uOffset @@ -730,58 +881,72 @@ class Layer: self.unknown = unknown func debugPrint() -> void: - print("\tLayer MatId:%d,\t UVOffset:%d,%d,\t UVTiling %d,%d mapType: %d,\t Texture Name: %s" % - [matId, uOffset, vOffset, uTiling, vTiling, mapType, texture]) + print( + ( + "\tLayer MatId:%d,\t UVOffset:%d,%d,\t UVTiling %d,%d mapType: %d,\t Texture Name: %s" + % [matId, uOffset, vOffset, uTiling, vTiling, mapType, texture] + ) + ) print("\t amount:%s,\t rot:%s,\t unused:%d" % [amount, rotInRad, unused]) func is_specular() -> bool: return mapType == 3 + # TODO: Might want to change this from vec4d to colours where appropriate -static func readMaterialDefinitionChunk(file : FileAccess, isV1 : bool) -> MaterialDefinitionChunk: - var chunk : MaterialDefinitionChunk = MaterialDefinitionChunk.new( - FileAccessUtils.read_vec4(file), FileAccessUtils.read_vec4(file), - FileAccessUtils.read_vec4(file), FileAccessUtils.read_vec4(file), - file.get_float(), file.get_float(), file.get_float(), file.get_float(), - file.get_8(), file.get_8(), file.get_8(), file.get_8(), +static func readMaterialDefinitionChunk(file: FileAccess, isV1: bool) -> MaterialDefinitionChunk: + var chunk: MaterialDefinitionChunk = MaterialDefinitionChunk.new( + FileAccessUtils.read_vec4(file), + FileAccessUtils.read_vec4(file), + FileAccessUtils.read_vec4(file), + FileAccessUtils.read_vec4(file), + file.get_float(), + file.get_float(), + file.get_float(), + file.get_float(), + file.get_8(), + file.get_8(), + file.get_8(), + file.get_8(), FileAccessUtils.read_xac_str(file) ) - var layers : Array[Layer] = [] - for i : int in chunk.numLayers: + var layers: Array[Layer] = [] + for i: int in chunk.numLayers: layers.push_back(readLayer(file, isV1)) chunk.setLayers(layers) return chunk + class MaterialDefinitionChunk: - var ambientColor : Vector4 - var diffuseColor : Vector4 - var specularColor : Vector4 - var emissiveColor : Vector4 - var shine : float - var shineStrength : float - var opacity : float - var ior : float - var bDoubleSided : bool # byte - var bWireframe : bool # byte - var unused : int # 1 byte - var numLayers : int # byte - var name : String - var Layers : Array[Layer] + var ambientColor: Vector4 + var diffuseColor: Vector4 + var specularColor: Vector4 + var emissiveColor: Vector4 + var shine: float + var shineStrength: float + var opacity: float + var ior: float + var bDoubleSided: bool # byte + var bWireframe: bool # byte + var unused: int # 1 byte + var numLayers: int # byte + var name: String + var Layers: Array[Layer] func _init( - ambientColor : Vector4, - diffuseColor : Vector4, - specularColor : Vector4, - emissiveColor : Vector4, - shine : float, - shineStrength : float, - opacity : float, - ior : float, - bDoubleSided : bool, - bWireframe : bool, - unused : int, - numLayers : int, - name : String + ambientColor: Vector4, + diffuseColor: Vector4, + specularColor: Vector4, + emissiveColor: Vector4, + shine: float, + shineStrength: float, + opacity: float, + ior: float, + bDoubleSided: bool, + bWireframe: bool, + unused: int, + numLayers: int, + name: String ) -> void: self.ambientColor = ambientColor self.diffuseColor = diffuseColor @@ -797,81 +962,89 @@ class MaterialDefinitionChunk: self.numLayers = numLayers self.name = name - func setLayers(layers : Array[Layer]) -> void: + func setLayers(layers: Array[Layer]) -> void: self.Layers = layers # Specular textures are used for country-specific unit colours, # which need a UnitModel to be set through func has_specular() -> bool: - for layer : Layer in Layers: + for layer: Layer in Layers: if layer.is_specular(): return true return false func debugPrint() -> void: print("Material Name: %s, num layers: %d, doubleSided %s" % [name, numLayers, bDoubleSided]) - print("\tshine:%s\tshineStrength:%s\t,opacity:%s,\tior:%s,\tunused:%s" % [shine, shineStrength, opacity, ior, unused]) - for layer : Layer in Layers: + print( + ( + "\tshine:%s\tshineStrength:%s\t,opacity:%s,\tior:%s,\tunused:%s" + % [shine, shineStrength, opacity, ior, unused] + ) + ) + for layer: Layer in Layers: layer.debugPrint() + # MESH -static func readVerticesAttribute(file : FileAccess, numVerts : int) -> VerticesAttribute: - var vertAttrib : VerticesAttribute = VerticesAttribute.new( - FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file), - file.get_8(), file.get_8(), Vector2i(file.get_8(), file.get_8())) - var data : Variant + +static func readVerticesAttribute(file: FileAccess, numVerts: int) -> VerticesAttribute: + var vertAttrib: VerticesAttribute = VerticesAttribute.new( + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + file.get_8(), + file.get_8(), + Vector2i(file.get_8(), file.get_8()) + ) + var data: Variant match vertAttrib.type: - 0: # position + 0: # position data = PackedVector3Array() - for i : int in numVerts: + for i: int in numVerts: data.push_back(FileAccessUtils.read_pos(file)) - 1: # normals + 1: # normals data = PackedVector3Array() - for i : int in numVerts: + for i: int in numVerts: data.push_back(FileAccessUtils.read_pos(file)) - 2: # tangents + 2: # tangents data = [] as Array[Vector4] - for i : int in numVerts: - var tangent : Vector4 = FileAccessUtils.read_vec4(file) + for i: int in numVerts: + var tangent: Vector4 = FileAccessUtils.read_vec4(file) #tangent.w *= -1 data.push_back(tangent) - 3: # uvs + 3: # uvs data = PackedVector2Array() - for i : int in numVerts: + for i: int in numVerts: data.push_back(FileAccessUtils.read_vec2(file)) - 4: # 32bit colors + 4: # 32bit colors data = PackedColorArray() - for i : int in numVerts: + for i: int in numVerts: data.push_back(FileAccessUtils.read_Color32(file)) - 5: # influence range indices + 5: # influence range indices data = PackedInt64Array() - for i : int in numVerts: + for i: int in numVerts: data.push_back(file.get_32()) - 6: # 128bit colors + 6: # 128bit colors data = PackedColorArray() - for i : int in numVerts: + for i: int in numVerts: data.push_back(FileAccessUtils.read_Color128(file)) _: push_error("INVALID XAC VERTATTRIBUTE TYPE %d" % vertAttrib.type) vertAttrib.setData(data) return vertAttrib + # mesh has one of these for each vertex property (position, normals, etc) class VerticesAttribute: - var type : int # int32 - var attribSize : int # int32 - var bKeepOriginals : bool # byte - var bIsScaleFactor : bool # byte - var pad : Vector2i # 2x byte - var data : Variant # numVerts * attribSize + var type: int # int32 + var attribSize: int # int32 + var bKeepOriginals: bool # byte + var bIsScaleFactor: bool # byte + var pad: Vector2i # 2x byte + var data: Variant # numVerts * attribSize func _init( - type : int, - attribSize : int, - bKeepOriginals : bool, - bIsScaleFactor : bool, - pad : Vector2i + type: int, attribSize: int, bKeepOriginals: bool, bIsScaleFactor: bool, pad: Vector2i ) -> void: self.type = type self.attribSize = attribSize @@ -879,11 +1052,11 @@ class VerticesAttribute: self.bIsScaleFactor = bIsScaleFactor self.pad = pad - func setData(data : Variant) -> void: + func setData(data: Variant) -> void: self.data = data func debugPrint() -> void: - var typeStr : String + var typeStr: String match type: 0: typeStr = "Positions" @@ -901,87 +1074,105 @@ class VerticesAttribute: typeStr = "128bit Colors" _: typeStr = "invalid type %d" % type - print("\tattribSize:%d (bytes),\t keepOriginals:%s,\t isScaleFactor:%s,\t VertAttrib: type:%s" % - [attribSize, bKeepOriginals, bIsScaleFactor, typeStr]) + print( + ( + "\tattribSize:%d (bytes),\t keepOriginals:%s,\t isScaleFactor:%s,\t VertAttrib: type:%s" + % [attribSize, bKeepOriginals, bIsScaleFactor, typeStr] + ) + ) print("\tpad: %s" % pad) -static func readSubMesh(file : FileAccess) -> SubMesh: - var subMesh : SubMesh = SubMesh.new( - FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file), - FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file) + +static func readSubMesh(file: FileAccess) -> SubMesh: + var subMesh: SubMesh = SubMesh.new( + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file) ) - var relIndices : PackedInt32Array = PackedInt32Array() - var boneIds : PackedInt32Array = PackedInt32Array() - for i : int in subMesh.numIndices: + var relIndices: PackedInt32Array = PackedInt32Array() + var boneIds: PackedInt32Array = PackedInt32Array() + for i: int in subMesh.numIndices: relIndices.push_back(FileAccessUtils.read_int32(file)) - for i : int in subMesh.numBones: + for i: int in subMesh.numBones: boneIds.push_back(FileAccessUtils.read_int32(file)) subMesh.setBoneIds(boneIds) subMesh.setRelIndices(relIndices) return subMesh + class SubMesh: - var numIndices : int # int32 - var numVertices : int # int32 - var materialId : int # int32 - var numBones : int # int32 - var relativeIndices : PackedInt32Array # int32 [numIndices] - var boneIds : PackedInt32Array # int32 [numBones], unused - - func _init(numIndices : int, numVertices : int, materialId : int, numBones : int) -> void: + var numIndices: int # int32 + var numVertices: int # int32 + var materialId: int # int32 + var numBones: int # int32 + var relativeIndices: PackedInt32Array # int32 [numIndices] + var boneIds: PackedInt32Array # int32 [numBones], unused + + func _init(numIndices: int, numVertices: int, materialId: int, numBones: int) -> void: self.numIndices = numIndices self.numVertices = numVertices self.materialId = materialId self.numBones = numBones - func setRelIndices(relativeIndices : PackedInt32Array) -> void: + func setRelIndices(relativeIndices: PackedInt32Array) -> void: self.relativeIndices = relativeIndices - func setBoneIds(boneIds : PackedInt32Array) -> void: + func setBoneIds(boneIds: PackedInt32Array) -> void: self.boneIds = boneIds func debugPrint() -> void: - print("\tSubMesh:\t numIndices:%d,\t numVerts:%d,\t matId:%d,\t numBones:%d" % - [numIndices, numVertices, materialId, numBones]) - -static func readMeshChunk(file : FileAccess) -> MeshChunk: - var mesh : MeshChunk = MeshChunk.new( - FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file), - FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file), - FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file), file.get_8(), + print( + ( + "\tSubMesh:\t numIndices:%d,\t numVerts:%d,\t matId:%d,\t numBones:%d" + % [numIndices, numVertices, materialId, numBones] + ) + ) + + +static func readMeshChunk(file: FileAccess) -> MeshChunk: + var mesh: MeshChunk = MeshChunk.new( + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + file.get_8(), Vector3i(file.get_8(), file.get_8(), file.get_8()) ) - var vertAttribs : Array[VerticesAttribute] = [] - var submeshes : Array[SubMesh] = [] - for i : int in mesh.numAttribLayers: - vertAttribs.push_back(readVerticesAttribute(file,mesh.numVertices)) - for i : int in mesh.numSubMeshes: + var vertAttribs: Array[VerticesAttribute] = [] + var submeshes: Array[SubMesh] = [] + for i: int in mesh.numAttribLayers: + vertAttribs.push_back(readVerticesAttribute(file, mesh.numVertices)) + for i: int in mesh.numSubMeshes: submeshes.push_back(readSubMesh(file)) mesh.setVerticesAttributes(vertAttribs) mesh.setSubMeshes(submeshes) return mesh + class MeshChunk: - var nodeId : int # int32 - var numInfluenceRanges : int # int32 - var numVertices : int # int32 - var numIndices : int # int32 - var numSubMeshes : int # int32 - var numAttribLayers : int # int32 - var bIsCollisionMesh : bool # byte - var pad : Vector3i # 3x byte - var VerticesAttributes : Array[VerticesAttribute] - var SubMeshes : Array[SubMesh] + var nodeId: int # int32 + var numInfluenceRanges: int # int32 + var numVertices: int # int32 + var numIndices: int # int32 + var numSubMeshes: int # int32 + var numAttribLayers: int # int32 + var bIsCollisionMesh: bool # byte + var pad: Vector3i # 3x byte + var VerticesAttributes: Array[VerticesAttribute] + var SubMeshes: Array[SubMesh] func _init( - nodeId : int, - numInfluenceRanges : int, - numVertices : int, - numIndices : int, - numSubMeshes : int, - numAttribLayers : int, - bIsCollisionMesh : bool, - pad : Vector3i + nodeId: int, + numInfluenceRanges: int, + numVertices: int, + numIndices: int, + numSubMeshes: int, + numAttribLayers: int, + bIsCollisionMesh: bool, + pad: Vector3i ) -> void: self.nodeId = nodeId self.numInfluenceRanges = numInfluenceRanges @@ -992,30 +1183,38 @@ class MeshChunk: self.bIsCollisionMesh = bIsCollisionMesh self.pad = pad - func setVerticesAttributes(VerticesAttributes : Array[VerticesAttribute]) -> void: + func setVerticesAttributes(VerticesAttributes: Array[VerticesAttribute]) -> void: self.VerticesAttributes = VerticesAttributes - func setSubMeshes(SubMeshes : Array[SubMesh]) -> void: + func setSubMeshes(SubMeshes: Array[SubMesh]) -> void: self.SubMeshes = SubMeshes func debugPrint() -> void: - print("Mesh: nodeId:%d, numVerts:%d, numSubMeshes:%d, numVertAttribs:%d, isCollisionMesh:%s" % - [nodeId, numVertices, numSubMeshes, numAttribLayers, bIsCollisionMesh]) + print( + ( + "Mesh: nodeId:%d, numVerts:%d, numSubMeshes:%d, numVertAttribs:%d, isCollisionMesh:%s" + % [nodeId, numVertices, numSubMeshes, numAttribLayers, bIsCollisionMesh] + ) + ) for vertAttrib in VerticesAttributes: vertAttrib.debugPrint() - for subMesh : SubMesh in SubMeshes: + for subMesh: SubMesh in SubMeshes: subMesh.debugPrint() + # SKINNING -static func readInfluenceData(file : FileAccess) -> InfluenceData: - return InfluenceData.new(file.get_float(), FileAccessUtils.read_int16(file), Vector2i(file.get_8(), file.get_8())) +static func readInfluenceData(file: FileAccess) -> InfluenceData: + return InfluenceData.new( + file.get_float(), FileAccessUtils.read_int16(file), Vector2i(file.get_8(), file.get_8()) + ) + class InfluenceData: - var fWeight : float # (0..1) - var boneId : int # int16 - var pad : Vector2i # 2x byte + var fWeight: float # (0..1) + var boneId: int # int16 + var pad: Vector2i # 2x byte - func _init(fWeight : float, boneId : int, pad : Vector2i) -> void: + func _init(fWeight: float, boneId: int, pad: Vector2i) -> void: self.fWeight = fWeight self.boneId = boneId self.pad = pad @@ -1023,59 +1222,77 @@ class InfluenceData: func debugPrint() -> void: print("\tInfluenceData:\t boneId: %d,\t Weight: %s" % [boneId, fWeight]) + # For some reason influenceRange isn't being loaded, needs investigation # Weird data on the flag -static func readInfluenceRange(file : FileAccess) -> InfluenceRange: + +static func readInfluenceRange(file: FileAccess) -> InfluenceRange: return InfluenceRange.new(FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file)) + class InfluenceRange: - var firstInfluenceIndex : int # int32 - var numInfluences : int # int32 + var firstInfluenceIndex: int # int32 + var numInfluences: int # int32 - func _init(firstInfluenceIndex : int, numInfluences : int) -> void: + func _init(firstInfluenceIndex: int, numInfluences: int) -> void: self.firstInfluenceIndex = firstInfluenceIndex self.numInfluences = numInfluences func debugPrint() -> void: - print("\tInfluenceRange:\t firstIndex: %d,\t numInfluences: %d" % [firstInfluenceIndex, numInfluences]) + print( + ( + "\tInfluenceRange:\t firstIndex: %d,\t numInfluences: %d" + % [firstInfluenceIndex, numInfluences] + ) + ) + -static func readSkinningChunk(file : FileAccess, meshChunks : Array[MeshChunk], isV2 : bool) -> SkinningChunk: - var skinning : SkinningChunk = null +static func readSkinningChunk( + file: FileAccess, meshChunks: Array[MeshChunk], isV2: bool +) -> SkinningChunk: + var skinning: SkinningChunk = null skinning = SkinningChunk.new( - FileAccessUtils.read_int32(file), -1 if isV2 else FileAccessUtils.read_int32(file), - FileAccessUtils.read_int32(file), file.get_8(), Vector3i(file.get_8(), file.get_8(), file.get_8()) + FileAccessUtils.read_int32(file), + -1 if isV2 else FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), + file.get_8(), + Vector3i(file.get_8(), file.get_8(), file.get_8()) ) - var influenceData : Array[InfluenceData] = [] - var influenceRange : Array[InfluenceRange] = [] - for i : int in skinning.numInfluences: + var influenceData: Array[InfluenceData] = [] + var influenceRange: Array[InfluenceRange] = [] + for i: int in skinning.numInfluences: influenceData.push_back(readInfluenceData(file)) # search the list of mesh chunks for the one which matches IsCollisionMesh and NodeId? # documentation is a little unclear about this (lists the mesh accessing by node, which isn't possible) - for chunk : MeshChunk in meshChunks: - if chunk.nodeId == skinning.nodeId and chunk.bIsCollisionMesh == skinning.bIsForCollisionMesh: - for i : int in chunk.numInfluenceRanges: + for chunk: MeshChunk in meshChunks: + if ( + chunk.nodeId == skinning.nodeId + and chunk.bIsCollisionMesh == skinning.bIsForCollisionMesh + ): + for i: int in chunk.numInfluenceRanges: influenceRange.push_back(readInfluenceRange(file)) break skinning.setInfluenceData(influenceData) skinning.setInfluenceRange(influenceRange) return skinning + class SkinningChunk: - var nodeId : int # int32 - var numLocalBones : int # int32, of bones in the influence data - var numInfluences : int # int32 - var bIsForCollisionMesh : bool # byte boolean - var pad : Vector3i # 3x pad - var influenceData : Array[InfluenceData] - var influenceRange : Array[InfluenceRange] + var nodeId: int # int32 + var numLocalBones: int # int32, of bones in the influence data + var numInfluences: int # int32 + var bIsForCollisionMesh: bool # byte boolean + var pad: Vector3i # 3x pad + var influenceData: Array[InfluenceData] + var influenceRange: Array[InfluenceRange] func _init( - nodeId : int, - numLocalBones : int, - numInfluences : int, - bIsForCollisionMesh : bool, - pad : Vector3i + nodeId: int, + numLocalBones: int, + numInfluences: int, + bIsForCollisionMesh: bool, + pad: Vector3i ) -> void: self.nodeId = nodeId self.numLocalBones = numLocalBones @@ -1083,84 +1300,106 @@ class SkinningChunk: self.bIsForCollisionMesh = bIsForCollisionMesh self.pad = pad - func setInfluenceData(influenceData : Array[InfluenceData]) -> void: + func setInfluenceData(influenceData: Array[InfluenceData]) -> void: self.influenceData = influenceData - func setInfluenceRange(influenceRange : Array[InfluenceRange]) -> void: + func setInfluenceRange(influenceRange: Array[InfluenceRange]) -> void: self.influenceRange = influenceRange func debugPrint() -> void: - print("Skinning: nodeId:%d, numInfluencedBones: %d, numInfluences: %d, CollisionMesh?: %d" % - [nodeId, numLocalBones, numInfluences, bIsForCollisionMesh]) - for infDat : InfluenceData in influenceData: + print( + ( + "Skinning: nodeId:%d, numInfluencedBones: %d, numInfluences: %d, CollisionMesh?: %d" + % [nodeId, numLocalBones, numInfluences, bIsForCollisionMesh] + ) + ) + for infDat: InfluenceData in influenceData: infDat.debugPrint() - for infRange : InfluenceRange in influenceRange: + for infRange: InfluenceRange in influenceRange: infRange.debugPrint() + # TODO: What is chunk type6, figure out what the plausible datatypes are # Currently, since XACs tend to use int32s and float (32bit) + strings, and no strings # are evident in chunk type 6, to load these as arrays of int32 -static func readChunkType6(file : FileAccess) -> ChunkType6: - var intArr : PackedInt32Array = [] - var floatArr : PackedFloat32Array = [] - for i : int in 12: + +static func readChunkType6(file: FileAccess) -> ChunkType6: + var intArr: PackedInt32Array = [] + var floatArr: PackedFloat32Array = [] + for i: int in 12: intArr.push_back(FileAccessUtils.read_int32(file)) - for i : int in 9: + for i: int in 9: floatArr.push_back(file.get_float()) return ChunkType6.new(intArr, floatArr, FileAccessUtils.read_int32(file)) + class ChunkType6: - var unknown : PackedInt32Array - var unknown_floats : PackedFloat32Array - var maybe_node_id : int + var unknown: PackedInt32Array + var unknown_floats: PackedFloat32Array + var maybe_node_id: int - func _init(unknown : PackedInt32Array, unknown_floats : PackedFloat32Array, maybe_node_id : int) -> void: + func _init( + unknown: PackedInt32Array, unknown_floats: PackedFloat32Array, maybe_node_id: int + ) -> void: self.unknown = unknown self.unknown_floats = unknown_floats self.maybe_node_id = maybe_node_id func debugPrint() -> void: - print("\tUnknown: %s\n\tFloats: %s\n\tPerhaps NodeId? %s" % [self.unknown, self.unknown_floats, self.maybe_node_id]) + print( + ( + "\tUnknown: %s\n\tFloats: %s\n\tPerhaps NodeId? %s" + % [self.unknown, self.unknown_floats, self.maybe_node_id] + ) + ) + # Chunk type 0x0 -static func readNodeChunk(file : FileAccess) -> NodeChunk: +static func readNodeChunk(file: FileAccess) -> NodeChunk: return NodeChunk.new( - FileAccessUtils.read_quat(file), FileAccessUtils.read_quat(file), - FileAccessUtils.read_pos(file), FileAccessUtils.read_vec3(file), - FileAccessUtils.read_vec3(file), # unused 3 floats - FileAccessUtils.read_int32(file), FileAccessUtils.read_int32(file), #-1-1 + FileAccessUtils.read_quat(file), + FileAccessUtils.read_quat(file), + FileAccessUtils.read_pos(file), + FileAccessUtils.read_vec3(file), + FileAccessUtils.read_vec3(file), # unused 3 floats + FileAccessUtils.read_int32(file), + FileAccessUtils.read_int32(file), #-1-1 # 17 x 32bit unknowns, likely matrix and some other info # last 32bit unknown is likely fImportanceFactor, (float 1f). Rest is likely matrix - (func() -> PackedInt32Array: - var array : PackedInt32Array = PackedInt32Array() - for i : int in 17: - array.push_back(FileAccessUtils.read_int32(file)) - return array).call(), + ( + (func() -> PackedInt32Array: + var array: PackedInt32Array = PackedInt32Array() + for i: int in 17: + array.push_back(FileAccessUtils.read_int32(file)) + return array) + . call() + ), FileAccessUtils.read_xac_str(file) ) + class NodeChunk: - var rotation : Quaternion - var scaleRotation : Quaternion - var position : Vector3 - var scale : Vector3 - var unused : Vector3 # 3x unused floats - var unknown : int # int32 - var parentBone : int # int32 - var unknown2 : PackedInt32Array # 17x int32 sized numbers - var name : String + var rotation: Quaternion + var scaleRotation: Quaternion + var position: Vector3 + var scale: Vector3 + var unused: Vector3 # 3x unused floats + var unknown: int # int32 + var parentBone: int # int32 + var unknown2: PackedInt32Array # 17x int32 sized numbers + var name: String func _init( - rot : Quaternion, - scaleRot : Quaternion, - pos : Vector3, - scale : Vector3, - unused : Vector3, - unknown : int, - parentBone : int, - unknown2 : PackedInt32Array, - name : String + rot: Quaternion, + scaleRot: Quaternion, + pos: Vector3, + scale: Vector3, + unused: Vector3, + unknown: int, + parentBone: int, + unknown2: PackedInt32Array, + name: String ) -> void: self.rotation = rot self.scaleRotation = scaleRot @@ -1177,13 +1416,15 @@ class NodeChunk: print("\tunused (%s) unknown: %s" % [unused, unknown]) print("\tunknown after -1-1: %s" % unknown2) -static func readChunkTypeUnknown(file : FileAccess, length : int) -> ChunkTypeUnknown: + +static func readChunkTypeUnknown(file: FileAccess, length: int) -> ChunkTypeUnknown: return ChunkTypeUnknown.new(file.get_buffer(length)) + class ChunkTypeUnknown: - var unknown : PackedByteArray + var unknown: PackedByteArray - func _init(unknown : PackedByteArray) -> void: + func _init(unknown: PackedByteArray) -> void: self.unknown = unknown func debugPrint() -> void: diff --git a/game/src/Game/Model/XSMLoader.gd b/game/src/Game/Model/XSMLoader.gd index e1706ae6..a1632636 100644 --- a/game/src/Game/Model/XSMLoader.gd +++ b/game/src/Game/Model/XSMLoader.gd @@ -2,91 +2,96 @@ class_name XSMLoader # Keys: source_file (String) # Values: loaded animation (Animation) or LOAD_FAILED_MARKER (StringName) -static var xsm_cache : Dictionary +static var xsm_cache: Dictionary -const LOAD_FAILED_MARKER : StringName = &"XSM LOAD FAILED" +const LOAD_FAILED_MARKER: StringName = &"XSM LOAD FAILED" -static func get_xsm_animation(source_file : String) -> Animation: - var cached : Variant = xsm_cache.get(source_file) + +static func get_xsm_animation(source_file: String) -> Animation: + var cached: Variant = xsm_cache.get(source_file) if not cached: cached = _load_xsm_animation(source_file) if cached: xsm_cache[source_file] = cached else: xsm_cache[source_file] = LOAD_FAILED_MARKER - push_error("Failed to get XSM model \"", source_file, "\" (current load failed)") + push_error('Failed to get XSM model "', source_file, '" (current load failed)') return null if not cached is Animation: - push_error("Failed to get XSM model \"", source_file, "\" (previous load failed)") + push_error('Failed to get XSM model "', source_file, '" (previous load failed)') return null return cached -const SKELETON_PATH : String = "./skeleton:%s" -static func _load_xsm_animation(source_file : String) -> Animation: - var source_path : String = GameSingleton.lookup_file_path(source_file) - var file : FileAccess = FileAccess.open(source_path, FileAccess.READ) +const SKELETON_PATH: String = "./skeleton:%s" + + +static func _load_xsm_animation(source_file: String) -> Animation: + var source_path: String = GameSingleton.lookup_file_path(source_file) + var file: FileAccess = FileAccess.open(source_path, FileAccess.READ) if file == null: push_error("Failed to load XSM ", source_file, " from looked up path ", source_path) return null readHeader(file) - var metadataChunk : MetadataChunk = null - var boneAnimationChunks : Array[BoneAnimationChunk] = [] + var metadataChunk: MetadataChunk = null + var boneAnimationChunks: Array[BoneAnimationChunk] = [] while file.get_position() < file.get_length(): - var type : int = FileAccessUtils.read_int32(file) - var length : int = FileAccessUtils.read_int32(file) - var version : int = FileAccessUtils.read_int32(file) + var type: int = FileAccessUtils.read_int32(file) + var length: int = FileAccessUtils.read_int32(file) + var version: int = FileAccessUtils.read_int32(file) match type: - 0xC9: #Metadata + 0xC9: #Metadata metadataChunk = readMetadataChunk(file) - 0xCA: #Bone Animation + 0xCA: #Bone Animation # v1 is float32 quaternions, v2 is int16 quaternions boneAnimationChunks.push_back(readBoneAnimationChunk(file, version == 2)) _: push_error(">> INVALID XSM CHUNK TYPE %X" % type) break - var animLength : float = 0.0 - var anim : Animation = Animation.new() - for anim_Chunk : BoneAnimationChunk in boneAnimationChunks: - for submotion : SkeletalSubMotion in anim_Chunk.SkeletalSubMotions: + var animLength: float = 0.0 + var anim: Animation = Animation.new() + for anim_Chunk: BoneAnimationChunk in boneAnimationChunks: + for submotion: SkeletalSubMotion in anim_Chunk.SkeletalSubMotions: # NOTE: godot uses ':' to specify properties, so we replace such characters with '_' - var skeleton_path : String = SKELETON_PATH % FileAccessUtils.replace_chars(submotion.nodeName) + var skeleton_path: String = ( + SKELETON_PATH % FileAccessUtils.replace_chars(submotion.nodeName) + ) if submotion.numPosKeys > 0: - var id : int = anim.add_track(Animation.TYPE_POSITION_3D) + var id: int = anim.add_track(Animation.TYPE_POSITION_3D) anim.track_set_path(id, skeleton_path) - for key : PosKey in submotion.PosKeys: + for key: PosKey in submotion.PosKeys: anim.position_track_insert_key(id, key.fTime, key.pos) if key.fTime > animLength: animLength = key.fTime - else: # EXPERIMENTAL: see if setting posePos fixes idle3 - var id : int = anim.add_track(Animation.TYPE_POSITION_3D) + else: # EXPERIMENTAL: see if setting posePos fixes idle3 + var id: int = anim.add_track(Animation.TYPE_POSITION_3D) anim.track_set_path(id, skeleton_path) anim.position_track_insert_key(id, 0, submotion.posePos) if submotion.numRotKeys > 0: - var id : int = anim.add_track(Animation.TYPE_ROTATION_3D) + var id: int = anim.add_track(Animation.TYPE_ROTATION_3D) anim.track_set_path(id, skeleton_path) - for key : RotKey in submotion.RotKeys: + for key: RotKey in submotion.RotKeys: anim.rotation_track_insert_key(id, key.fTime, key.rot) if key.fTime > animLength: animLength = key.fTime - else: # EXPERIMENTAL: see if setting posePos fixes idle3 - var id : int = anim.add_track(Animation.TYPE_ROTATION_3D) + else: # EXPERIMENTAL: see if setting posePos fixes idle3 + var id: int = anim.add_track(Animation.TYPE_ROTATION_3D) anim.track_set_path(id, skeleton_path) anim.rotation_track_insert_key(id, 0, submotion.poseRot) if submotion.numScaleKeys > 0: - var id : int = anim.add_track(Animation.TYPE_SCALE_3D) + var id: int = anim.add_track(Animation.TYPE_SCALE_3D) anim.track_set_path(id, skeleton_path) - for key : ScaleKey in submotion.ScaleKeys: + for key: ScaleKey in submotion.ScaleKeys: anim.scale_track_insert_key(id, key.fTime, key.scale) if key.fTime > animLength: animLength = key.fTime @@ -99,48 +104,59 @@ static func _load_xsm_animation(source_file : String) -> Animation: xsm_cache[source_file] = anim return anim -static func readHeader(file : FileAccess) -> void: - var magic_bytes : PackedByteArray = [file.get_8(), file.get_8(), file.get_8(), file.get_8()] - var magic : String = magic_bytes.get_string_from_ascii() - var version : String = "%d.%d" % [file.get_8(), file.get_8()] - var bBigEndian : bool = file.get_8() - var pad : int = file.get_8() + +static func readHeader(file: FileAccess) -> void: + var magic_bytes: PackedByteArray = [file.get_8(), file.get_8(), file.get_8(), file.get_8()] + var magic: String = magic_bytes.get_string_from_ascii() + var version: String = "%d.%d" % [file.get_8(), file.get_8()] + var bBigEndian: bool = file.get_8() + var pad: int = file.get_8() #print(magic, ", version: ", version, ", bigEndian: ", bBigEndian, " pad: ", pad) + # NOTE: the "pad" variable is actually very important! # It seems to have something to do with whether paradox uses int16 or int32 # for quaternions (it's "pad" or version number, can't tell) -static func readMetadataChunk(file : FileAccess) -> MetadataChunk: + +static func readMetadataChunk(file: FileAccess) -> MetadataChunk: return MetadataChunk.new( - file.get_float(), file.get_float(), FileAccessUtils.read_int32(file), - file.get_8(), file.get_8(), file.get_16(), - FileAccessUtils.read_xac_str(file), FileAccessUtils.read_xac_str(file), FileAccessUtils.read_xac_str(file), FileAccessUtils.read_xac_str(file) + file.get_float(), + file.get_float(), + FileAccessUtils.read_int32(file), + file.get_8(), + file.get_8(), + file.get_16(), + FileAccessUtils.read_xac_str(file), + FileAccessUtils.read_xac_str(file), + FileAccessUtils.read_xac_str(file), + FileAccessUtils.read_xac_str(file) ) + class MetadataChunk: - var unused : float - var fMaxAcceptableError : float - var fps : int # int32 - var exporterMajorVersion : int # byte - var exporterMinorVersion : int # byte - var pad : int # 2x byte - var sourceApp : String - var origFileName : String - var exportDate : String - var motionName : String + var unused: float + var fMaxAcceptableError: float + var fps: int # int32 + var exporterMajorVersion: int # byte + var exporterMinorVersion: int # byte + var pad: int # 2x byte + var sourceApp: String + var origFileName: String + var exportDate: String + var motionName: String func _init( - unused : float, - fMaxAcceptableError : float, - fps : int, - exporterMajorVersion : int, - exporterMinorVersion : int, - pad : int, - sourceApp : String, - origFileName : String, - exportDate : String, - motionName : String + unused: float, + fMaxAcceptableError: float, + fps: int, + exporterMajorVersion: int, + exporterMinorVersion: int, + pad: int, + sourceApp: String, + origFileName: String, + exportDate: String, + motionName: String ) -> void: self.unused = unused self.fMaxAcceptableError = fMaxAcceptableError @@ -154,105 +170,114 @@ class MetadataChunk: self.motionName = motionName func debugPrint() -> void: - print("FileName: %s, sourceApp: %s, exportDate: %s, ExporterV:%d.%d" % - [origFileName, sourceApp, exportDate, exporterMajorVersion, exporterMinorVersion]) - print("MotionName: %s, fps: %d, MaxError: %s" % - [motionName, fps, fMaxAcceptableError]) + print( + ( + "FileName: %s, sourceApp: %s, exportDate: %s, ExporterV:%d.%d" + % [origFileName, sourceApp, exportDate, exporterMajorVersion, exporterMinorVersion] + ) + ) + print("MotionName: %s, fps: %d, MaxError: %s" % [motionName, fps, fMaxAcceptableError]) + -static func readPosKey(file : FileAccess) -> PosKey: +static func readPosKey(file: FileAccess) -> PosKey: return PosKey.new(FileAccessUtils.read_pos(file), file.get_float()) + class PosKey: - var pos : Vector3 - var fTime : float + var pos: Vector3 + var fTime: float - func _init(pos : Vector3, fTime : float) -> void: + func _init(pos: Vector3, fTime: float) -> void: self.pos = pos self.fTime = fTime func debugPrint() -> void: print("\t\tPos:%s, time:%s" % [pos, fTime]) -static func readRotKey(file : FileAccess, use_quat16 : bool) -> RotKey: + +static func readRotKey(file: FileAccess, use_quat16: bool) -> RotKey: return RotKey.new(FileAccessUtils.read_quat(file, use_quat16), file.get_float()) + class RotKey: - var rot : Quaternion - var fTime : float + var rot: Quaternion + var fTime: float - func _init(rot : Quaternion, fTime : float) -> void: + func _init(rot: Quaternion, fTime: float) -> void: self.rot = rot self.fTime = fTime func debugPrint() -> void: print("\t\tRot:%s, time:%s" % [rot, fTime]) -static func readScaleKey(file : FileAccess) -> ScaleKey: + +static func readScaleKey(file: FileAccess) -> ScaleKey: return ScaleKey.new(FileAccessUtils.read_vec3(file), file.get_float()) + class ScaleKey: - var scale : Vector3 - var fTime : float + var scale: Vector3 + var fTime: float - func _init(scale : Vector3, fTime : float) -> void: + func _init(scale: Vector3, fTime: float) -> void: self.scale = scale self.fTime = fTime func debugPrint() -> void: print("\t\tScale:%s, time:%s" % [scale, fTime]) -static func readScaleRotKey(file : FileAccess, use_quat16 : bool) -> ScaleRotKey: + +static func readScaleRotKey(file: FileAccess, use_quat16: bool) -> ScaleRotKey: return ScaleRotKey.new(FileAccessUtils.read_quat(file, use_quat16), file.get_float()) + class ScaleRotKey: - var rot : Quaternion - var fTime : float + var rot: Quaternion + var fTime: float - func _init(rot : Quaternion, fTime : float) -> void: + func _init(rot: Quaternion, fTime: float) -> void: self.rot = rot self.fTime = fTime func debugPrint() -> void: print("\t\tScaleRot:%s, time:%s" % [rot, fTime]) -static func readSkeletalSubMotion(file : FileAccess, use_quat16 : bool) -> SkeletalSubMotion: - var a : Quaternion = FileAccessUtils.read_quat(file, use_quat16) - var b : Quaternion = FileAccessUtils.read_quat(file, use_quat16) - var c : Quaternion = FileAccessUtils.read_quat(file, use_quat16) - var d : Quaternion = FileAccessUtils.read_quat(file, use_quat16) - - var e : Vector3 = FileAccessUtils.read_pos(file) - var f : Vector3 = FileAccessUtils.read_vec3(file) - var g : Vector3 = FileAccessUtils.read_pos(file) - var h : Vector3 = FileAccessUtils.read_vec3(file) - - var p : int = FileAccessUtils.read_int32(file) - var j : int = FileAccessUtils.read_int32(file) - var k : int = FileAccessUtils.read_int32(file) - var l : int = FileAccessUtils.read_int32(file) - - var m : float = file.get_float() - var n : String = FileAccessUtils.read_xac_str(file) - - var submotion : SkeletalSubMotion = SkeletalSubMotion.new( - a, b, c, d, # quats - e, f, g, h, # vec3 - p, j, k, l, # ints - m, n + +static func readSkeletalSubMotion(file: FileAccess, use_quat16: bool) -> SkeletalSubMotion: + var a: Quaternion = FileAccessUtils.read_quat(file, use_quat16) + var b: Quaternion = FileAccessUtils.read_quat(file, use_quat16) + var c: Quaternion = FileAccessUtils.read_quat(file, use_quat16) + var d: Quaternion = FileAccessUtils.read_quat(file, use_quat16) + + var e: Vector3 = FileAccessUtils.read_pos(file) + var f: Vector3 = FileAccessUtils.read_vec3(file) + var g: Vector3 = FileAccessUtils.read_pos(file) + var h: Vector3 = FileAccessUtils.read_vec3(file) + + var p: int = FileAccessUtils.read_int32(file) + var j: int = FileAccessUtils.read_int32(file) + var k: int = FileAccessUtils.read_int32(file) + var l: int = FileAccessUtils.read_int32(file) + + var m: float = file.get_float() + var n: String = FileAccessUtils.read_xac_str(file) + + var submotion: SkeletalSubMotion = SkeletalSubMotion.new( + a, b, c, d, e, f, g, h, p, j, k, l, m, n # quats # vec3 # ints ) - var poskeys : Array[PosKey] = [] - var rotkeys : Array[RotKey] = [] - var scalekeys : Array[ScaleKey] = [] - var scalerotkeys : Array[ScaleRotKey] = [] + var poskeys: Array[PosKey] = [] + var rotkeys: Array[RotKey] = [] + var scalekeys: Array[ScaleKey] = [] + var scalerotkeys: Array[ScaleRotKey] = [] #FIXME: Did paradox store the number of pos keys as a float instead of int? - for i : int in submotion.numPosKeys: + for i: int in submotion.numPosKeys: poskeys.push_back(readPosKey(file)) - for i : int in submotion.numRotKeys: + for i: int in submotion.numRotKeys: rotkeys.push_back(readRotKey(file, use_quat16)) - for i : int in submotion.numScaleKeys: + for i: int in submotion.numScaleKeys: scalekeys.push_back(readScaleKey(file)) - for i : int in submotion.numScaleRotKeys: + for i: int in submotion.numScaleRotKeys: scalerotkeys.push_back(readScaleRotKey(file, use_quat16)) submotion.setPosKeys(poskeys) submotion.setRotKeys(rotkeys) @@ -260,42 +285,43 @@ static func readSkeletalSubMotion(file : FileAccess, use_quat16 : bool) -> Skele submotion.setScaleRotKeys(scalerotkeys) return submotion + class SkeletalSubMotion: - var poseRot : Quaternion - var bindPoseRot : Quaternion - var poseScaleRot : Quaternion - var bindPoseScaleRot : Quaternion - var posePos : Vector3 - var poseScale : Vector3 - var bindPosePos : Vector3 - var bindPoseScale : Vector3 - var numPosKeys : int # int32 - var numRotKeys : int # int32 - var numScaleKeys : int # int32 - var numScaleRotKeys : int # int32 - var fMaxError : float - var nodeName : String - - var PosKeys : Array[PosKey] - var RotKeys : Array[RotKey] - var ScaleKeys : Array[ScaleKey] - var ScaleRotKeys : Array[ScaleRotKey] + var poseRot: Quaternion + var bindPoseRot: Quaternion + var poseScaleRot: Quaternion + var bindPoseScaleRot: Quaternion + var posePos: Vector3 + var poseScale: Vector3 + var bindPosePos: Vector3 + var bindPoseScale: Vector3 + var numPosKeys: int # int32 + var numRotKeys: int # int32 + var numScaleKeys: int # int32 + var numScaleRotKeys: int # int32 + var fMaxError: float + var nodeName: String + + var PosKeys: Array[PosKey] + var RotKeys: Array[RotKey] + var ScaleKeys: Array[ScaleKey] + var ScaleRotKeys: Array[ScaleRotKey] func _init( - poseRot : Quaternion, - bindPoseRot : Quaternion, - poseScaleRot : Quaternion, - bindPoseScaleRot : Quaternion, - posePos : Vector3, - poseScale : Vector3, - bindPosePos : Vector3, - bindPoseScale : Vector3, - numPosKeys : int, - numRotKeys : int, - numScaleKeys : int, - numScaleRotKeys : int, - fMaxError : float, - nodeName : String + poseRot: Quaternion, + bindPoseRot: Quaternion, + poseScaleRot: Quaternion, + bindPoseScaleRot: Quaternion, + posePos: Vector3, + poseScale: Vector3, + bindPosePos: Vector3, + bindPoseScale: Vector3, + numPosKeys: int, + numRotKeys: int, + numScaleKeys: int, + numScaleRotKeys: int, + fMaxError: float, + nodeName: String ) -> void: self.poseRot = poseRot self.bindPoseRot = bindPoseRot @@ -312,50 +338,62 @@ class SkeletalSubMotion: self.fMaxError = fMaxError self.nodeName = nodeName - func setPosKeys(PosKeys : Array[PosKey]) -> void: + func setPosKeys(PosKeys: Array[PosKey]) -> void: self.PosKeys = PosKeys - func setRotKeys(RotKeys : Array[RotKey]) -> void: + func setRotKeys(RotKeys: Array[RotKey]) -> void: self.RotKeys = RotKeys - func setScaleKeys(ScaleKeys : Array[ScaleKey]) -> void: + func setScaleKeys(ScaleKeys: Array[ScaleKey]) -> void: self.ScaleKeys = ScaleKeys - func setScaleRotKeys(ScaleRotKeys : Array[ScaleRotKey]) -> void: + func setScaleRotKeys(ScaleRotKeys: Array[ScaleRotKey]) -> void: self.ScaleRotKeys = ScaleRotKeys func debugPrint() -> void: - print("Node: %s, #PosKeys %d, #RotKeys %d, #ScaleKeys %d, #ScaleRotKeys %d" % [nodeName, numPosKeys, numRotKeys, numScaleKeys, numScaleRotKeys]) - print("\tposeScaleRot %s,\tbindPoseScaleRot %s,\tposeScale %s,\tbindPoseScale %s" % [poseScaleRot, bindPoseScaleRot, poseScale, bindPoseScale]) - for key : PosKey in PosKeys: + print( + ( + "Node: %s, #PosKeys %d, #RotKeys %d, #ScaleKeys %d, #ScaleRotKeys %d" + % [nodeName, numPosKeys, numRotKeys, numScaleKeys, numScaleRotKeys] + ) + ) + print( + ( + "\tposeScaleRot %s,\tbindPoseScaleRot %s,\tposeScale %s,\tbindPoseScale %s" + % [poseScaleRot, bindPoseScaleRot, poseScale, bindPoseScale] + ) + ) + for key: PosKey in PosKeys: key.debugPrint() - for key : RotKey in RotKeys: + for key: RotKey in RotKeys: key.debugPrint() - for key : ScaleKey in ScaleKeys: + for key: ScaleKey in ScaleKeys: key.debugPrint() - for key : ScaleRotKey in ScaleRotKeys: + for key: ScaleRotKey in ScaleRotKeys: key.debugPrint() -static func readBoneAnimationChunk(file : FileAccess, use_quat16 : bool) -> BoneAnimationChunk: - var numSubMotions : int = FileAccessUtils.read_int32(file) - var animChunk : BoneAnimationChunk = BoneAnimationChunk.new(numSubMotions) - var submotions : Array[SkeletalSubMotion] = [] - for i : int in animChunk.numSubMotions: + +static func readBoneAnimationChunk(file: FileAccess, use_quat16: bool) -> BoneAnimationChunk: + var numSubMotions: int = FileAccessUtils.read_int32(file) + var animChunk: BoneAnimationChunk = BoneAnimationChunk.new(numSubMotions) + var submotions: Array[SkeletalSubMotion] = [] + for i: int in animChunk.numSubMotions: submotions.push_back(readSkeletalSubMotion(file, use_quat16)) animChunk.setSkeletalSubMotions(submotions) return animChunk + class BoneAnimationChunk: - var numSubMotions : int # int32 - var SkeletalSubMotions : Array[SkeletalSubMotion] + var numSubMotions: int # int32 + var SkeletalSubMotions: Array[SkeletalSubMotion] - func _init(numSubMotions : int) -> void: + func _init(numSubMotions: int) -> void: self.numSubMotions = numSubMotions - func setSkeletalSubMotions(SkeletalSubMotions : Array[SkeletalSubMotion]) -> void: + func setSkeletalSubMotions(SkeletalSubMotions: Array[SkeletalSubMotion]) -> void: self.SkeletalSubMotions = SkeletalSubMotions func debugPrint() -> void: print("Number of Submotions: %d" % numSubMotions) - for submotion : SkeletalSubMotion in SkeletalSubMotions: + for submotion: SkeletalSubMotion in SkeletalSubMotions: submotion.debugPrint() diff --git a/game/src/Game/MusicConductor/MusicConductor.gd b/game/src/Game/MusicConductor/MusicConductor.gd index ade8fb4d..3e14a0d2 100644 --- a/game/src/Game/MusicConductor/MusicConductor.gd +++ b/game/src/Game/MusicConductor/MusicConductor.gd @@ -1,81 +1,95 @@ extends Node -signal song_paused(paused : bool) -signal song_started(track_id : int) +signal song_paused(paused: bool) +signal song_started(track_id: int) ## Only triggers when song naturally ends -signal song_finished(track_id : int) -signal song_scrubbed(percentage : float, seconds : float) +signal song_finished(track_id: int) +signal song_scrubbed(percentage: float, seconds: float) # REQUIREMENTS # * SS-67 -@export_dir var music_directory : String -@export var first_song_name : String +@export_dir var music_directory: String +@export var first_song_name: String -@export var _audio_stream_player : AudioStreamPlayer +@export var _audio_stream_player: AudioStreamPlayer var _selected_track := 0 -var _available_songs : Array[SongInfo] = [] -var _auto_play_next_song : bool = true +var _available_songs: Array[SongInfo] = [] +var _auto_play_next_song: bool = true var playlist: Array[int] = [] -var playlist_index:int = 0 +var playlist_index: int = 0 var preferred_playlist_len: int = 7 var last_played: int = -1 - ## True if music player should be visible. ## Used to keep keep consistency between scene changes -var is_music_player_visible : bool = true +var is_music_player_visible: bool = true + +var _has_startup_happened: bool = false -var _has_startup_happened : bool = false func get_all_song_names() -> PackedStringArray: - var songNames : PackedStringArray = [] - for si : SongInfo in _available_songs: + var songNames: PackedStringArray = [] + for si: SongInfo in _available_songs: songNames.append(si.song_name) return songNames + func get_all_song_paths() -> PackedStringArray: - var songPaths : PackedStringArray = [] - for si : SongInfo in _available_songs: + var songPaths: PackedStringArray = [] + for si: SongInfo in _available_songs: songPaths.append(si.song_path) return songPaths + func get_current_song_index() -> int: return _selected_track + func get_current_song_name() -> String: return _available_songs[_selected_track].song_name + func scrub_song_by_percentage(percentage: float) -> void: - var percentInSeconds : float = (percentage / 100.0) * _audio_stream_player.stream.get_length() + var percentInSeconds: float = (percentage / 100.0) * _audio_stream_player.stream.get_length() _audio_stream_player.play(percentInSeconds) song_scrubbed.emit(percentage, percentInSeconds) + func get_current_song_progress_percentage() -> float: - return 100 * (_audio_stream_player.get_playback_position() / _audio_stream_player.stream.get_length()) + return ( + 100 + * (_audio_stream_player.get_playback_position() / _audio_stream_player.stream.get_length()) + ) + func is_paused() -> bool: return _audio_stream_player.stream_paused -func set_paused(paused : bool) -> void: + +func set_paused(paused: bool) -> void: _audio_stream_player.stream_paused = paused song_paused.emit(paused) + func toggle_play_pause() -> void: set_paused(not is_paused()) + func start_current_song() -> void: _audio_stream_player.stream = _available_songs[_selected_track].song_stream _audio_stream_player.play() song_started.emit(_selected_track) + # REQUIREMENTS # * SS-70 func start_song_by_index(id: int) -> void: _selected_track = id start_current_song() + # REQUIREMENTS # * SS-69 func select_next_song() -> void: @@ -88,10 +102,14 @@ func select_next_song() -> void: last_played = playlist_index start_current_song() + func select_previous_song() -> void: - _selected_track = (len(_available_songs) - 1) if (_selected_track == 0) else (_selected_track - 1) + _selected_track = ( + (len(_available_songs) - 1) if (_selected_track == 0) else (_selected_track - 1) + ) start_current_song() + func setup_compat_song(file_name) -> void: var song = SongInfo.new() var stream = SoundSingleton.get_song(file_name) @@ -107,16 +125,18 @@ func setup_compat_song(file_name) -> void: if title == "": #use the file name without the extension if there's no metadata title = file_name.split(".")[0] - song.init_stream(file_name,title,stream) + song.init_stream(file_name, title, stream) _available_songs.append(song) + func add_compat_songs() -> void: - for file_name : String in SoundSingleton.song_list: + for file_name: String in SoundSingleton.song_list: setup_compat_song(file_name) + func add_ootb_music() -> void: var dir := DirAccess.open(music_directory) - for fname : String in dir.get_files(): + for fname: String in dir.get_files(): if fname.ends_with(".import"): fname = fname.get_basename() if fname.get_basename() == first_song_name: @@ -125,14 +145,15 @@ func add_ootb_music() -> void: song.init_file_path(music_directory, fname) _available_songs.append(song) + func generate_playlist() -> void: var song_names = MusicConductor.get_all_song_paths() - var possible_indices = range(len(song_names)-1) + var possible_indices = range(len(song_names) - 1) var title_index = song_names.find(SoundSingleton.title_theme) possible_indices.remove_at(title_index) - var actual_playlist_len = min(preferred_playlist_len,len(possible_indices)) + var actual_playlist_len = min(preferred_playlist_len, len(possible_indices)) #if the playlist size is too large or small, make it the same size as what we #need to support @@ -146,14 +167,15 @@ func generate_playlist() -> void: #essentially shuffle-bag randomness, picking from a list of song indices for i in range(actual_playlist_len): - var ind = randi_range(0,len(possible_indices)-1) + var ind = randi_range(0, len(possible_indices) - 1) #add back the last song we just played as an option - if i==2: + if i == 2: possible_indices.append(last_played) playlist[i] = possible_indices[ind] possible_indices.remove_at(ind) + # REQUIREMENTS # * SND-2, SND-3 func _ready() -> void: @@ -161,11 +183,13 @@ func _ready() -> void: #don't start the current song for compat mode, do that from #GameStart so we can wait until the music is loaded -func set_startup_music(play : bool) -> void: + +func set_startup_music(play: bool) -> void: if not _has_startup_happened: _has_startup_happened = true set_paused(not play) + func _on_audio_stream_player_finished() -> void: song_finished.emit(_selected_track) if _auto_play_next_song: diff --git a/game/src/Game/MusicConductor/MusicPlayer.gd b/game/src/Game/MusicConductor/MusicPlayer.gd index 0db44ca9..8a9db2fd 100644 --- a/game/src/Game/MusicConductor/MusicPlayer.gd +++ b/game/src/Game/MusicConductor/MusicPlayer.gd @@ -1,16 +1,17 @@ extends Control -@export var _song_selector_button : OptionButton -@export var _progress_slider : HSlider -@export var _previous_song_button : Button -@export var _play_pause_button : Button -@export var _next_song_button : Button -@export var _visbility_button : Button +@export var _song_selector_button: OptionButton +@export var _progress_slider: HSlider +@export var _previous_song_button: Button +@export var _play_pause_button: Button +@export var _next_song_button: Button +@export var _visbility_button: Button + +var _is_user_dragging_progress_slider: bool = false -var _is_user_dragging_progress_slider : bool = false func _ready() -> void: - for songName : String in MusicConductor.get_all_song_names(): + for songName: String in MusicConductor.get_all_song_names(): _song_selector_button.add_item(songName, _song_selector_button.item_count) _on_song_set(MusicConductor.get_current_song_index()) MusicConductor.song_started.connect(_on_song_set) @@ -18,43 +19,53 @@ func _ready() -> void: MusicConductor.song_scrubbed.connect(_update_play_pause_button) _set_music_player_visible(MusicConductor.is_music_player_visible) -func _on_song_set(track_id : int) -> void: + +func _on_song_set(track_id: int) -> void: _song_selector_button.selected = track_id _update_play_pause_button() -func _process(_delta : float) -> void: + +func _process(_delta: float) -> void: if !_is_user_dragging_progress_slider: _progress_slider.value = MusicConductor.get_current_song_progress_percentage() -func _update_play_pause_button(_arg1 : Variant = null, _arg2 : Variant = null) -> void: + +func _update_play_pause_button(_arg1: Variant = null, _arg2: Variant = null) -> void: _play_pause_button.text = "▶️" if MusicConductor.is_paused() else "❚❚" + func _on_play_pause_button_pressed() -> void: MusicConductor.toggle_play_pause() + # REQUIREMENTS # * UIFUN-93 func _on_next_song_button_pressed() -> void: MusicConductor.select_next_song() + # REQUIREMENTS # * UIFUN-94 func _on_previous_song_button_pressed() -> void: MusicConductor.select_previous_song() + # REQUIREMENTS # * UIFUN-95 -func _on_option_button_item_selected(index : int) -> void: +func _on_option_button_item_selected(index: int) -> void: MusicConductor.start_song_by_index(index) + func _on_progress_slider_drag_started() -> void: _is_user_dragging_progress_slider = true -func _on_progress_slider_drag_ended(_value_changed : bool) -> void: + +func _on_progress_slider_drag_ended(_value_changed: bool) -> void: MusicConductor.scrub_song_by_percentage(_progress_slider.value) _is_user_dragging_progress_slider = false -func _set_music_player_visible(is_player_visible : bool) -> void: + +func _set_music_player_visible(is_player_visible: bool) -> void: MusicConductor.is_music_player_visible = is_player_visible _visbility_button.text = "⬆️" if is_player_visible else "⬇" _song_selector_button.visible = is_player_visible @@ -63,6 +74,7 @@ func _set_music_player_visible(is_player_visible : bool) -> void: _play_pause_button.visible = is_player_visible _next_song_button.visible = is_player_visible + # REQUIREMENTS # * UIFUN-91 func _on_music_ui_visibility_button_pressed() -> void: diff --git a/game/src/Game/MusicConductor/SongInfo.gd b/game/src/Game/MusicConductor/SongInfo.gd index 527f618e..e4b2f43a 100644 --- a/game/src/Game/MusicConductor/SongInfo.gd +++ b/game/src/Game/MusicConductor/SongInfo.gd @@ -1,18 +1,20 @@ extends Resource class_name SongInfo -var song_path : String = "" -var song_name : String = "" -var song_stream : AudioStream +var song_path: String = "" +var song_name: String = "" +var song_stream: AudioStream + #Initialize from a file path -func init_file_path(dirname : String, fname : String) -> void: - song_path = dirname.path_join(fname) - song_name = fname.get_basename().replace("_", " ") - song_stream = load(song_path) +func init_file_path(dirname: String, fname: String) -> void: + song_path = dirname.path_join(fname) + song_name = fname.get_basename().replace("_", " ") + song_stream = load(song_path) + #Initialize from an audio stream -func init_stream(dirpath : String, name : String, stream : AudioStream) -> void: - song_path = dirpath - song_name = name - song_stream = stream +func init_stream(dirpath: String, name: String, stream: AudioStream) -> void: + song_path = dirpath + song_name = name + song_stream = stream diff --git a/game/src/Game/SplashContainer.gd b/game/src/Game/SplashContainer.gd index e74620b2..7e67b47a 100644 --- a/game/src/Game/SplashContainer.gd +++ b/game/src/Game/SplashContainer.gd @@ -2,26 +2,34 @@ extends Control signal splash_end -@export var _splash_finish : TextureRect -@export var _splash_image : TextureRect -@export var _splash_video : VideoStreamPlayer +@export var _splash_finish: TextureRect +@export var _splash_image: TextureRect +@export var _splash_video: VideoStreamPlayer -func _process(_delta : float) -> void: + +func _process(_delta: float) -> void: var stream_texture := _splash_video.get_video_texture() if stream_texture != null and not stream_texture.get_image().is_invisible(): _splash_image.hide() _splash_finish.show() set_process(false) -func _input(event : InputEvent) -> void: - if (event is InputEventKey\ - or event is InputEventMouse\ - or event is InputEventScreenTouch\ - or event is InputEventJoypadButton) and event.is_pressed(): + +func _input(event: InputEvent) -> void: + if ( + ( + event is InputEventKey + or event is InputEventMouse + or event is InputEventScreenTouch + or event is InputEventJoypadButton + ) + and event.is_pressed() + ): _splash_finish.hide() _on_splash_startup_finished() accept_event() + func _on_splash_startup_finished() -> void: set_process_input(false) splash_end.emit() diff --git a/game/src/Game/Theme/StyleBoxCombinedTexture.gd b/game/src/Game/Theme/StyleBoxCombinedTexture.gd index 1d68363b..092ba188 100644 --- a/game/src/Game/Theme/StyleBoxCombinedTexture.gd +++ b/game/src/Game/Theme/StyleBoxCombinedTexture.gd @@ -2,18 +2,19 @@ extends StyleBox class_name StyleBoxCombinedTexture -@export -var texture_settings : Array[TextureSetting] = []: - get: return texture_settings.duplicate() +@export var texture_settings: Array[TextureSetting] = []: + get: + return texture_settings.duplicate() set(v): texture_settings = v - for setting : TextureSetting in texture_settings: + for setting: TextureSetting in texture_settings: setting.changed.connect(emit_changed) emit_changed() -func _get_draw_rect(rect : Rect2) -> Rect2: - var combined_rect : Rect2 = Rect2() - for setting : TextureSetting in texture_settings: + +func _get_draw_rect(rect: Rect2) -> Rect2: + var combined_rect: Rect2 = Rect2() + for setting: TextureSetting in texture_settings: if combined_rect.position.x > setting.expand_margin_left: combined_rect.position.x = setting.expand_margin_left if combined_rect.position.y > setting.expand_margin_top: @@ -22,13 +23,16 @@ func _get_draw_rect(rect : Rect2) -> Rect2: combined_rect.end.x = setting.expand_margin_right if combined_rect.end.y < setting.expand_margin_bottom: combined_rect.end.y = setting.expand_margin_bottom - return rect.grow_individual(combined_rect.position.x, combined_rect.position.y, combined_rect.end.x, combined_rect.end.y) + return rect.grow_individual( + combined_rect.position.x, combined_rect.position.y, combined_rect.end.x, combined_rect.end.y + ) + -func _draw(to_canvas_item : RID, rect : Rect2) -> void: - for setting : TextureSetting in texture_settings: +func _draw(to_canvas_item: RID, rect: Rect2) -> void: + for setting: TextureSetting in texture_settings: if setting == null or setting.texture == null: continue - var inner_rect : Rect2 = rect + var inner_rect: Rect2 = rect inner_rect.position.x -= setting.expand_margin_left inner_rect.position.y -= setting.expand_margin_top inner_rect.size.x += setting.expand_margin_left + setting.expand_margin_right diff --git a/game/src/Game/Theme/StyleBoxWithSound.gd b/game/src/Game/Theme/StyleBoxWithSound.gd index 75a181a7..fd93a59c 100644 --- a/game/src/Game/Theme/StyleBoxWithSound.gd +++ b/game/src/Game/Theme/StyleBoxWithSound.gd @@ -3,25 +3,28 @@ extends StyleBox class_name StyleBoxWithSound -@export -var style_box : StyleBox: - get: return style_box +@export var style_box: StyleBox: + get: + return style_box set(v): style_box = v emit_changed() -@export -var sound : AudioStream: - get: return sound +@export var sound: AudioStream: + get: + return sound set(v): sound = v emit_changed() -func _get_draw_rect(rect : Rect2) -> Rect2: - if style_box == null: return Rect2() + +func _get_draw_rect(rect: Rect2) -> Rect2: + if style_box == null: + return Rect2() return style_box._get_draw_rect(rect) -func _draw(to_canvas_item : RID, rect : Rect2) -> void: + +func _draw(to_canvas_item: RID, rect: Rect2) -> void: # This is a hack # Works fine for simple non-normal style cases # Normal styles being drawn immediately tho will trigger sound on startup @@ -29,6 +32,6 @@ func _draw(to_canvas_item : RID, rect : Rect2) -> void: # Is there any other reason aside from release sounds (might be useful for toggles?) # This should be fast enough to not cause draw issues if sound != null: - SoundManager.play_effect_compat("click",sound) + SoundManager.play_effect_compat("click", sound) if style_box != null: style_box.draw(to_canvas_item, rect) diff --git a/game/src/Game/Theme/TextureSetting.gd b/game/src/Game/Theme/TextureSetting.gd index da9b1854..225a8b4b 100644 --- a/game/src/Game/Theme/TextureSetting.gd +++ b/game/src/Game/Theme/TextureSetting.gd @@ -1,123 +1,125 @@ extends Resource class_name TextureSetting -@export -var texture : Texture2D: - get: return texture +@export var texture: Texture2D: + get: + return texture set(v): texture = v emit_changed() -@export -var draw_center : bool = true: - get: return draw_center +@export var draw_center: bool = true: + get: + return draw_center set(v): draw_center = v emit_changed() @export_group("Texture Margins", "texture_margin_") -@export -var texture_margin_left : float = 0: - get: return texture_margin_left +@export var texture_margin_left: float = 0: + get: + return texture_margin_left set(v): texture_margin_left = v emit_changed() -@export -var texture_margin_top : float = 0: - get: return texture_margin_top +@export var texture_margin_top: float = 0: + get: + return texture_margin_top set(v): texture_margin_top = v emit_changed() -@export -var texture_margin_right : float = 0: - get: return texture_margin_right +@export var texture_margin_right: float = 0: + get: + return texture_margin_right set(v): texture_margin_right = v emit_changed() -@export -var texture_margin_bottom : float = 0: - get: return texture_margin_bottom +@export var texture_margin_bottom: float = 0: + get: + return texture_margin_bottom set(v): texture_margin_bottom = v emit_changed() @export_group("Expand Margins", "expand_margin_") -@export -var expand_margin_left : float = 0: - get: return expand_margin_left +@export var expand_margin_left: float = 0: + get: + return expand_margin_left set(v): expand_margin_left = v emit_changed() -@export -var expand_margin_top : float = 0: - get: return expand_margin_top +@export var expand_margin_top: float = 0: + get: + return expand_margin_top set(v): expand_margin_top = v emit_changed() -@export -var expand_margin_right : float = 0: - get: return expand_margin_right +@export var expand_margin_right: float = 0: + get: + return expand_margin_right set(v): expand_margin_right = v emit_changed() -@export -var expand_margin_bottom : float = 0: - get: return expand_margin_bottom +@export var expand_margin_bottom: float = 0: + get: + return expand_margin_bottom set(v): expand_margin_bottom = v emit_changed() @export_group("Axis Stretch", "axis_stretch_") @export -var axis_stretch_horizontal : RenderingServer.NinePatchAxisMode = RenderingServer.NINE_PATCH_STRETCH: - get: return axis_stretch_horizontal +var axis_stretch_horizontal: RenderingServer.NinePatchAxisMode = RenderingServer.NINE_PATCH_STRETCH: + get: + return axis_stretch_horizontal set(v): axis_stretch_horizontal = v emit_changed() @export -var axis_stretch_vertical : RenderingServer.NinePatchAxisMode = RenderingServer.NINE_PATCH_STRETCH: - get: return axis_stretch_vertical +var axis_stretch_vertical: RenderingServer.NinePatchAxisMode = RenderingServer.NINE_PATCH_STRETCH: + get: + return axis_stretch_vertical set(v): axis_stretch_vertical = v emit_changed() @export_group("Sub-Region", "region_") -@export -var region_rect : Rect2 = Rect2(0, 0, 0, 0): - get: return region_rect +@export var region_rect: Rect2 = Rect2(0, 0, 0, 0): + get: + return region_rect set(v): region_rect = v emit_changed() @export_group("Modulate", "modulate_") -@export -var modulate_color : Color = Color(1, 1, 1, 1): - get: return modulate_color +@export var modulate_color: Color = Color(1, 1, 1, 1): + get: + return modulate_color set(v): modulate_color = v emit_changed() @export_group("Content Margins", "content_margin_") -@export -var content_margin_left : float = -1: - get: return content_margin_left +@export var content_margin_left: float = -1: + get: + return content_margin_left set(v): content_margin_left = v emit_changed() -@export -var content_margin_top : float = -1: - get: return content_margin_top +@export var content_margin_top: float = -1: + get: + return content_margin_top set(v): content_margin_top = v emit_changed() -@export -var content_margin_right : float = -1: - get: return content_margin_right +@export var content_margin_right: float = -1: + get: + return content_margin_right set(v): content_margin_right = v emit_changed() -@export -var content_margin_bottom : float = -1: - get: return content_margin_bottom +@export var content_margin_bottom: float = -1: + get: + return content_margin_bottom set(v): content_margin_bottom = v emit_changed()