diff --git a/addons/pandora/api.gd b/addons/pandora/api.gd index a9cb333b..f54e6898 100644 --- a/addons/pandora/api.gd +++ b/addons/pandora/api.gd @@ -13,6 +13,7 @@ signal import_failed(reason: String) signal import_calculation_ended(import_info: Dictionary) signal import_calculation_failed(reason: String) signal import_progress +signal update_fields_settings(type: String) var _context_manager: PandoraContextManager var _storage: PandoraDataStorage diff --git a/addons/pandora/icons/ExtensionsSettings.svg b/addons/pandora/icons/ExtensionsSettings.svg new file mode 100644 index 00000000..948b6316 --- /dev/null +++ b/addons/pandora/icons/ExtensionsSettings.svg @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/addons/pandora/icons/ExtensionsSettings.svg.import b/addons/pandora/icons/ExtensionsSettings.svg.import new file mode 100644 index 00000000..ff60eb2c --- /dev/null +++ b/addons/pandora/icons/ExtensionsSettings.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cqxxv5pilfslw" +path="res://.godot/imported/ExtensionsSettings.svg-7b09f161a7fd97a3789aaef5788d6005.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/pandora/icons/ExtensionsSettings.svg" +dest_files=["res://.godot/imported/ExtensionsSettings.svg-7b09f161a7fd97a3789aaef5788d6005.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/pandora/model/entity.gd b/addons/pandora/model/entity.gd index ca8d1331..c578541b 100644 --- a/addons/pandora/model/entity.gd +++ b/addons/pandora/model/entity.gd @@ -111,7 +111,15 @@ class OverridingProperty: var value = _parent_entity._property_overrides[_property.get_property_name()] if value is PandoraReference: return value.get_entity() - return value + # Parse the value through the property type to handle conversions + # (e.g., String paths to Resources) + var parsed_value = _property.get_property_type().parse_value(value, {}) + # Duplicate RefCounted objects (custom classes like Pandora+, etc.) + # to avoid reference sharing between entities. + # Don't duplicate Resources (Texture, AudioStream, etc.) as they are shared assets. + if parsed_value != null and parsed_value is RefCounted and parsed_value.has_method("duplicate"): + return parsed_value.duplicate() + return parsed_value return _property.get_default_value() func get_property_id() -> String: diff --git a/addons/pandora/model/property.gd b/addons/pandora/model/property.gd index 301e2c85..f4c7c068 100644 --- a/addons/pandora/model/property.gd +++ b/addons/pandora/model/property.gd @@ -37,7 +37,7 @@ func _init(id: String, name: String, type_name: String) -> void: func get_setting(key: String) -> Variant: if has_setting_override(key): return _setting_overrides[key] - elif _type != null: + elif _type != null and _type.get_settings().has(key): return _type.get_settings()[key]["value"] else: return null @@ -95,6 +95,10 @@ func get_property_type() -> PandoraPropertyType: func get_default_value() -> Variant: if _default_value is PandoraReference: return _default_value.get_entity() + # If the default value has a duplicate() method, use it to avoid reference sharing. This is important for complex types. + # Only Objects have has_method(), so check type first + if _default_value != null and _default_value is Object and _default_value.has_method("duplicate"): + return _default_value.duplicate() return _default_value diff --git a/addons/pandora/model/types/resource.gd b/addons/pandora/model/types/resource.gd index dc912c27..f25a5933 100644 --- a/addons/pandora/model/types/resource.gd +++ b/addons/pandora/model/types/resource.gd @@ -11,15 +11,27 @@ func _init() -> void: func parse_value(variant: Variant, settings: Dictionary = {}) -> Variant: if variant is String: - return load(variant) + # Handle empty strings as null to avoid "res://" loading errors + if variant == "": + return null + # Load the resource and handle potential errors + var resource = load(variant) + if resource == null: + push_warning("Failed to load resource: " + variant) + return resource return variant func write_value(variant: Variant) -> Variant: + if variant == null: + return null if variant is Resource: return variant.resource_path return variant func is_valid(variant: Variant) -> bool: - return variant is Resource + # Allow null as valid value for optional resources + # Allow String (resource paths) as they will be converted to Resources + # Allow Resource objects directly + return variant == null or variant is Resource or variant is String diff --git a/addons/pandora/plugin.gd b/addons/pandora/plugin.gd index acd96b1e..b95fc051 100644 --- a/addons/pandora/plugin.gd +++ b/addons/pandora/plugin.gd @@ -13,6 +13,12 @@ var _exporter: PandoraExportPlugin func _init() -> void: self.name = 'PandoraPlugin' +func _ready() -> void: + if not DirAccess.dir_exists_absolute("res://pandora/extensions/"): + DirAccess.make_dir_recursive_absolute("res://pandora/extensions/") + if not FileAccess.file_exists("res://pandora/extensions/configuration.json"): + var extensionsDir = DirAccess.open("res://pandora/extensions/") + extensionsDir.copy("res://addons/pandora/util/configuration_template.json", "res://pandora/extensions/configuration.json") func _enter_tree() -> void: Engine.set_meta("PandoraEditorPlugin", self) @@ -37,7 +43,6 @@ func _enter_tree() -> void: _make_visible(false) - func _apply_changes() -> void: if Engine.is_editor_hint() and is_instance_valid(editor_view): if editor_view.has_method("apply_changes"): diff --git a/addons/pandora/settings/pandora_settings.gd b/addons/pandora/settings/pandora_settings.gd index 2eae6865..7bc40227 100644 --- a/addons/pandora/settings/pandora_settings.gd +++ b/addons/pandora/settings/pandora_settings.gd @@ -25,6 +25,8 @@ const DEFAULT_PANDORA_EXTENSIONS_DIR: Array[StringName] = ["res://pandora/extens static var extensions_models: Dictionary[String, RefCounted] = {} static var extensions_types: Dictionary[String, String] = {} +static var extensions_configurations: Array[Dictionary] = [] +static var extensions_confs_map: Dictionary[String, int] = {} static func initialize() -> void: init_setting( @@ -75,6 +77,7 @@ static func init_setting( "hint_string": hint_string, } ProjectSettings.add_property_info(info) + _load_all_extensions_configuration() _check_new_extensions_models() static func get_id_type() -> IDType: @@ -110,10 +113,36 @@ static func get_extensions_dirs() -> Array: DEFAULT_PANDORA_EXTENSIONS_DIR ) +static func get_extensions_configurations() -> Array[Dictionary]: + return extensions_configurations + +static func get_extensions_confs_map() -> Dictionary: + return extensions_confs_map + static func set_extensions_dir(array: Array) -> void: ProjectSettings.set_setting(SETTINGS_PANDORA_EXTENSIONS_DIR, array) + _load_all_extensions_configuration() _check_new_extensions_models() +static func find_extension_configuration_property(type: String) -> Dictionary: + for conf in extensions_configurations: + for property in conf["properties"]: + if property and property.has("dir_name") and property["dir_name"] == type: + return property + return {} + +static func _load_all_extensions_configuration() -> void: + var extensions_dirs = PandoraSettings.get_extensions_dirs() + for extensions_dir in extensions_dirs: + var configuration_file = FileAccess.open(extensions_dir + "/configuration.json", FileAccess.READ) + if not configuration_file: + push_error("Impossible to load the configuration from " + extensions_dir) + else: + var configuration_dic = JSON.parse_string(configuration_file.get_as_text()) + if not extensions_configurations.has(configuration_dic): + extensions_configurations.append(configuration_dic) + extensions_confs_map[extensions_dir] = extensions_configurations.size() - 1 + static func _check_new_extensions_models() -> void: var extensions_dirs = PandoraSettings.get_extensions_dirs() for extensions_dir in extensions_dirs: @@ -146,6 +175,30 @@ static func compare_with_extensions_models(value) -> bool: return true return false +static func save_extensions_configurations() -> void: + var extensions_dirs = PandoraSettings.get_extensions_dirs() + var extensions_confs_map = PandoraSettings.get_extensions_confs_map() + var extensions_configurations = PandoraSettings.get_extensions_configurations() + for extensions_dir in extensions_dirs: + var configuration_file = FileAccess.open(extensions_dir + "/configuration.json", FileAccess.WRITE) + var extensions_confs_idx: int = extensions_confs_map[extensions_dir] as int + var extensions_configuration = extensions_configurations[extensions_confs_idx] + configuration_file.store_string(JSON.stringify(extensions_configuration, "\t")) + configuration_file.close() + +static func get_property_dependencies_by(current_property: Dictionary) -> Array[Dictionary]: + var extensions_configurations = PandoraSettings.get_extensions_configurations() + var property_dependencies : Array[Dictionary] = [] + var current_dependencies := current_property["dependencies"] as Array + var current_prop_dependencies = current_dependencies.filter(func(dep: Dictionary): return dep["type"] == "PROPERTY") + for current_dependency in current_prop_dependencies: + for ext_configuration in extensions_configurations: + var ext_conf_properties := ext_configuration["properties"] as Array + var property_dependency := ext_conf_properties.filter(func(p: Dictionary): return p["name"] == current_dependency["name"]) + if property_dependency: + property_dependencies.append(property_dependency[0]) + return property_dependencies + static func get_lookup_property_name(value) -> String: for emodel in extensions_models: if not value is Dictionary and not value is Color: diff --git a/addons/pandora/ui/components/properties/property_control.gd b/addons/pandora/ui/components/properties/property_control.gd index bf09bf6b..e5a659f0 100644 --- a/addons/pandora/ui/components/properties/property_control.gd +++ b/addons/pandora/ui/components/properties/property_control.gd @@ -8,11 +8,31 @@ signal unfocused @export var type: String var _property: PandoraProperty +var _fields_settings: Array = [] +func _notification(what: int) -> void: + if what == NOTIFICATION_PARENTED: + var ext_conf_property := PandoraSettings.find_extension_configuration_property(type) + if ext_conf_property.has("enabled") and not ext_conf_property["enabled"]: + push_error("You are trying to instantiate/add a scene that is part of a property disabled by Pandora's configurations. Are you sure you want to continue?") func init(property: PandoraProperty) -> void: self._property = property - + print("init ", property) + _load_fields_settings() func refresh() -> void: pass + +func update_field_settings(field_settings: Dictionary) -> void: + _load_fields_settings() + var fs := _fields_settings.filter(func(dic: Dictionary): return dic["name"] == field_settings["name"])[0] as Dictionary + var fs_idx := _fields_settings.find(fs) + _fields_settings[fs_idx] = field_settings + Pandora.update_fields_settings.emit(type) + +func _load_fields_settings() -> void: + if _fields_settings.is_empty(): + var extension_configuration := PandoraSettings.find_extension_configuration_property(type) + if not extension_configuration.is_empty(): + _fields_settings = extension_configuration["fields"] as Array diff --git a/addons/pandora/ui/components/properties/resource/resource_property.gd b/addons/pandora/ui/components/properties/resource/resource_property.gd index 97074aa9..7bbd1563 100644 --- a/addons/pandora/ui/components/properties/resource/resource_property.gd +++ b/addons/pandora/ui/components/properties/resource/resource_property.gd @@ -11,12 +11,29 @@ func _ready() -> void: resource_picker.focus_entered.connect(func(): focused.emit()) resource_picker.resource_changed.connect( func(resource_path:String): - _property.set_default_value(load(resource_path)) + # Store the path as string, not the loaded resource + # The type system will handle conversion via parse_value/write_value + _property.set_default_value(resource_path) + refresh() property_value_changed.emit(resource_path)) func refresh() -> void: if _property != null: - var default_value = _property.get_default_value() as Resource - if default_value != null: - resource_picker.set_resource_path(default_value.resource_path) + # Get the raw value from overrides to avoid parse_value conversion + var raw_value = null + if _property is PandoraEntity.OverridingProperty: + var prop_name = _property.get_property_name() + if _property._parent_entity._property_overrides.has(prop_name): + raw_value = _property._parent_entity._property_overrides[prop_name] + + if raw_value == null: + raw_value = _property.get_default_value() + + # Handle both String paths and Resource objects + if raw_value is String and raw_value != "": + resource_picker.set_resource_path(raw_value) + elif raw_value is Resource and raw_value.resource_path != "": + resource_picker.set_resource_path(raw_value.resource_path) + else: + resource_picker.set_resource_path("") diff --git a/addons/pandora/ui/components/property_bar/property_bar.gd b/addons/pandora/ui/components/property_bar/property_bar.gd index 57f6de28..04a63cb1 100644 --- a/addons/pandora/ui/components/property_bar/property_bar.gd +++ b/addons/pandora/ui/components/property_bar/property_bar.gd @@ -20,13 +20,45 @@ func get_scene_by_type(type: String) -> PackedScene: return type_to_scene[type] func add_extensions_button() -> void: + var extensions_configurations := PandoraSettings.get_extensions_configurations() + var extensions_confs_map := PandoraSettings.get_extensions_confs_map() var extensions_dirs = PandoraSettings.get_extensions_dirs() for extensions_dir in extensions_dirs: + var extensions_configuration_idx := extensions_confs_map[extensions_dir] as int + var extensions_configuration := extensions_configurations[extensions_configuration_idx] as Dictionary + var extension_properties := extensions_configuration["properties"] as Array + var main_dir = DirAccess.open(extensions_dir) for ed_path in main_dir.get_directories(): - var extension_dir = DirAccess.open(extensions_dir + "/" + ed_path) - assert(extension_dir.dir_exists("property_button")) - var property_button_dir = DirAccess.open(extensions_dir + "/" + ed_path + "/property_button/") - var scene_path : String = extensions_dir + "/" + ed_path + "/property_button/property_button.tscn" - var scene = load(scene_path).instantiate() - add_child(scene) + var extension_property = extension_properties.filter(func(property: Dictionary): return property["dir_name"] == ed_path)[0] as Dictionary + if extension_property["enabled"]: + var extension_dir = DirAccess.open(extensions_dir + "/" + ed_path) + assert(extension_dir.dir_exists("property_button")) + var property_button_dir = DirAccess.open(extensions_dir + "/" + ed_path + "/property_button/") + var scene_path : String = extensions_dir + "/" + ed_path + "/property_button/property_button.tscn" + var scene = load(scene_path).instantiate() + scene.visible = extension_property["show_on_top"] + add_child(scene) + +func updates_property_bar_buttons() -> void: + var extensions_configurations := PandoraSettings.get_extensions_configurations() + var extensions_confs_map := PandoraSettings.get_extensions_confs_map() + var extensions_dirs = PandoraSettings.get_extensions_dirs() + for extensions_dir in extensions_dirs: + var extensions_configuration_idx := extensions_confs_map[extensions_dir] as int + var extensions_configuration := extensions_configurations[extensions_configuration_idx] as Dictionary + var extension_properties := extensions_configuration["properties"] as Array + for extension_property in extension_properties: + var btn = get_children().filter(func(node: Node): + var node_instance = node.scene.instantiate() + var check = node_instance.type == extension_property["dir_name"] + node_instance.queue_free() + return check) + if btn: + if extension_property["enabled"]: + if extension_property["show_on_top"]: + btn[0].show() + else: + btn[0].hide() + else: + btn[0].hide() diff --git a/addons/pandora/ui/components/resource_picker/resource_picker.gd b/addons/pandora/ui/components/resource_picker/resource_picker.gd index b4a5d702..b33c130d 100644 --- a/addons/pandora/ui/components/resource_picker/resource_picker.gd +++ b/addons/pandora/ui/components/resource_picker/resource_picker.gd @@ -17,6 +17,12 @@ func _ready() -> void: func set_resource_path(path: String) -> void: + # Handle empty path - clear the field + if path == "": + line_edit.text = "" + self.resource_path = "" + return + var resource = load(path) as Resource if resource != null: line_edit.text = path diff --git a/addons/pandora/ui/editor/pandora_editor.gd b/addons/pandora/ui/editor/pandora_editor.gd index a34e06ae..ebe6d6ab 100644 --- a/addons/pandora/ui/editor/pandora_editor.gd +++ b/addons/pandora/ui/editor/pandora_editor.gd @@ -7,6 +7,7 @@ class_name PandoraEditor extends Control @onready var create_entity_button: Button = %CreateEntityButton @onready var create_category_button: Button = %CreateCategoryButton @onready var import_button: Button = %ImportButton +@onready var settings_button: Button = %SettingsButton @onready var delete_button = %DeleteButton @onready var property_editor = %PropertyEditor @onready var regenerate_id_button: Button = %RegenerateIDButton @@ -14,6 +15,7 @@ class_name PandoraEditor extends Control @onready var version = %Version @onready var save_label = %SaveLabel @onready var import_dialog = %ImportDialog +@onready var settings_dialog = %SettingsDialog @onready var progress_bar = %ProgressBar @onready var data_content = %DataContent @@ -22,7 +24,6 @@ class_name PandoraEditor extends Control var selected_entity: PandoraEntity var _load_error = false - func _ready() -> void: save_button.pressed.connect(_save) tree.entity_selected.connect(_entity_selected) @@ -37,6 +38,7 @@ func _ready() -> void: reset_button.pressed.connect(_reset_to_saved_file) delete_button.pressed.connect(func(): tree.queue_delete(selected_entity.get_entity_id())) import_button.pressed.connect(func(): import_dialog.open()) + settings_button.pressed.connect(func(): settings_dialog.open()) import_dialog.import_started.connect(func(import_count: int): progress_bar.init(import_count)) import_dialog.import_ended.connect(_on_import_ended) diff --git a/addons/pandora/ui/editor/pandora_editor.tscn b/addons/pandora/ui/editor/pandora_editor.tscn index a2c9a1da..f45c2aa9 100644 --- a/addons/pandora/ui/editor/pandora_editor.tscn +++ b/addons/pandora/ui/editor/pandora_editor.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=17 format=3 uid="uid://0bxxjjroysub"] +[gd_scene load_steps=19 format=3 uid="uid://0bxxjjroysub"] [ext_resource type="Script" uid="uid://b4f7fhcompuon" path="res://addons/pandora/ui/editor/pandora_editor.gd" id="1_bowve"] [ext_resource type="Texture2D" uid="uid://dojpd3ptnta4m" path="res://addons/pandora/icons/Object.svg" id="2_aj8uc"] @@ -12,10 +12,12 @@ [ext_resource type="Texture2D" uid="uid://bhcep67ihojnd" path="res://addons/pandora/icons/Reload.svg" id="5_qbvn0"] [ext_resource type="PackedScene" uid="uid://dsqfuyjkcdwvu" path="res://addons/pandora/ui/components/notification_label/notification_label.tscn" id="6_ftkgr"] [ext_resource type="Texture2D" uid="uid://dp8it1xjb8k2g" path="res://addons/pandora/icons/AssetLib.svg" id="8_wruey"] +[ext_resource type="Texture2D" uid="uid://cqxxv5pilfslw" path="res://addons/pandora/icons/ExtensionsSettings.svg" id="9_aw1n3"] [ext_resource type="PackedScene" uid="uid://dibfkp6i5uvgi" path="res://addons/pandora/ui/components/progress_bar/progress_bar.tscn" id="10_xf8wv"] [ext_resource type="PackedScene" uid="uid://dy4xl20q2nq7q" path="res://addons/pandora/ui/components/update_button/update_button.tscn" id="11_cva2e"] [ext_resource type="Texture2D" uid="uid://crgjwaubao8pj" path="res://addons/pandora/icons/icon.png" id="15_3jwvj"] [ext_resource type="PackedScene" uid="uid://ceboo5esbe2ld" path="res://addons/pandora/ui/editor/import_dialog/import_dialog.tscn" id="15_umv0u"] +[ext_resource type="PackedScene" uid="uid://ctp7xnvi5ep0e" path="res://addons/pandora/ui/editor/settings_dialog/settings_dialog.tscn" id="18_yfrlk"] [node name="PandoraEditor" type="MarginContainer"] clip_contents = true @@ -89,6 +91,12 @@ layout_mode = 2 tooltip_text = "Import Data File" icon = ExtResource("8_wruey") +[node name="SettingsButton" type="Button" parent="Contents/HeaderBar/Actions"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Extensions Settings" +icon = ExtResource("9_aw1n3") + [node name="SaveLabel" parent="Contents/HeaderBar/Actions" instance=ExtResource("6_ftkgr")] unique_name_in_owner = true visible = false @@ -130,7 +138,7 @@ unique_name_in_owner = true layout_mode = 2 size_flags_vertical = 1 theme_override_colors/font_color = Color(1, 1, 1, 0.27451) -text = "Pandora v1.0-alpha4" +text = "Pandora v1.0-alpha10-dev" horizontal_alignment = 2 vertical_alignment = 1 justification_flags = 0 @@ -208,3 +216,9 @@ unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 0 size_flags_vertical = 0 + +[node name="SettingsDialog" parent="." instance=ExtResource("18_yfrlk")] +unique_name_in_owner = true +layout_mode = 2 + +[connection signal="update_extensions_configurations" from="SettingsDialog" to="Contents/DataContent/HSplitContainer/PropertyEditor" method="_on_update_extensions_configurations"] diff --git a/addons/pandora/ui/editor/property_editor/property_editor.gd b/addons/pandora/ui/editor/property_editor/property_editor.gd index 715000ac..e7d3219b 100644 --- a/addons/pandora/ui/editor/property_editor/property_editor.gd +++ b/addons/pandora/ui/editor/property_editor/property_editor.gd @@ -100,3 +100,7 @@ func _generate_property_name(type: String, entity: PandoraEntity) -> String: if properties.is_empty() or not entity.has_entity_property(property_name): return property_name return property_name + str(properties.size()) + + +func _on_update_extensions_configurations() -> void: + property_bar.updates_property_bar_buttons() diff --git a/addons/pandora/ui/editor/property_settings_editor/property_settings_editor.gd b/addons/pandora/ui/editor/property_settings_editor/property_settings_editor.gd index e7098d01..6d687244 100644 --- a/addons/pandora/ui/editor/property_settings_editor/property_settings_editor.gd +++ b/addons/pandora/ui/editor/property_settings_editor/property_settings_editor.gd @@ -19,6 +19,7 @@ func set_property(property: PandoraProperty) -> void: self._property = property if property: var property_type = property.get_property_type() + print(property_type.get_settings()) if property_type.get_type_name() == "array": self._default_settings = property_type.get_merged_settings(property) else: diff --git a/addons/pandora/ui/editor/settings_dialog/dependency.gd b/addons/pandora/ui/editor/settings_dialog/dependency.gd new file mode 100644 index 00000000..062d74bc --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/dependency.gd @@ -0,0 +1,16 @@ +@tool +class_name Dependency +extends PanelContainer + +signal removed(dependency: Dictionary) + +@onready var label: Label = $MarginContainer/HBoxContainer/Label + +var dependency: Dictionary + +func _ready() -> void: + label.text = dependency["name"] + +func _on_button_pressed() -> void: + removed.emit(dependency) + queue_free() diff --git a/addons/pandora/ui/editor/settings_dialog/dependency.gd.uid b/addons/pandora/ui/editor/settings_dialog/dependency.gd.uid new file mode 100644 index 00000000..3d2abcb3 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/dependency.gd.uid @@ -0,0 +1 @@ +uid://bo02nc6r2276o diff --git a/addons/pandora/ui/editor/settings_dialog/dependency.tscn b/addons/pandora/ui/editor/settings_dialog/dependency.tscn new file mode 100644 index 00000000..ab774e96 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/dependency.tscn @@ -0,0 +1,29 @@ +[gd_scene load_steps=3 format=3 uid="uid://dn5yxfosec2ta"] + +[ext_resource type="Script" uid="uid://bo02nc6r2276o" path="res://addons/pandora/ui/editor/settings_dialog/dependency.gd" id="1_cka5m"] +[ext_resource type="Texture2D" uid="uid://b2s1ixfakdj1e" path="res://addons/pandora/icons/Remove.svg" id="2_u7abk"] + +[node name="Dependency" type="PanelContainer"] +offset_right = 129.0 +offset_bottom = 28.0 +script = ExtResource("1_cka5m") + +[node name="MarginContainer" type="MarginContainer" parent="."] +layout_mode = 2 +theme_override_constants/margin_left = 15 +theme_override_constants/margin_top = 2 +theme_override_constants/margin_bottom = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"] +layout_mode = 2 +theme_override_constants/separation = 10 + +[node name="Label" type="Label" parent="MarginContainer/HBoxContainer"] +layout_mode = 2 +text = "Dependency" + +[node name="Button" type="Button" parent="MarginContainer/HBoxContainer"] +layout_mode = 2 +icon = ExtResource("2_u7abk") + +[connection signal="pressed" from="MarginContainer/HBoxContainer/Button" to="." method="_on_button_pressed"] diff --git a/addons/pandora/ui/editor/settings_dialog/settings_dialog.gd b/addons/pandora/ui/editor/settings_dialog/settings_dialog.gd new file mode 100644 index 00000000..08aa3d8c --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/settings_dialog.gd @@ -0,0 +1,343 @@ +@tool +extends Control + +signal update_extensions_configurations + +const DependencyScene = preload("uid://dn5yxfosec2ta") +const STRING_FIELD_SETTINGS = preload("uid://bn7da5ljy5mqh") +const RANGE_FIELD_SETTINGS = preload("uid://cyd24jwivayf5") +const ARRAY_FIELD_SETTINGS = preload("uid://cgwd2gdv7xeia") +const REFERENCE_FIELD_SETTINGS = preload("uid://d3a0188wd61px") +const OPTIONS_FIELD_SETTINGS = preload("uid://7c8j3yx3hnr4") +const BOOL_FIELD_SETTINGS = preload("uid://bm6rmjycqduyn") + +@onready var window: Window = $Window +@onready var extensions_list: ItemList = $Window/PanelContainer/HBoxContainer/ExtensionsContainer/ItemList +@onready var extension_label: Label = $Window/PanelContainer/HBoxContainer/VBoxContainer/Label +@onready var select_extension_label: Label = %SelectExtension +@onready var no_properties_label: Label = %NoProperties +@onready var ext_configuration_container: VBoxContainer = %ExtConfigurationContainer + +@onready var ext_properties_list: ItemList = %PropertyItemList +@onready var ext_property_desc: Label = %PropertyDescription +@onready var ext_property_enable_btn: CheckButton = %EnableButton +@onready var ext_property_show_on_top_btn: CheckButton = %ShowPropertyOnTop +@onready var customization_container: FoldableContainer = %CustomizationContainer +@onready var dependencies_container: FoldableContainer = %DependenciesContainer +@onready var properties_dependencies: VBoxContainer = %PropertiesDependencies +@onready var entities_dependencies: VBoxContainer = %EntitiesDependencies +@onready var properties_dependencies_container: GridContainer = %PropertiesDependencies/GridContainer +@onready var entities_dependencies_container: GridContainer = %EntitiesDependencies/GridContainer +@onready var ext_property_details: VBoxContainer = %PropertyContainer + +@onready var creation_dialog: ConfirmationDialog = $Window/CreationDialog +@onready var creation_name_edit: LineEdit = $Window/CreationDialog/VBoxContainer/HBoxContainer/VBoxContainer/LineEdit +@onready var creation_type_edit: LineEdit = $Window/CreationDialog/VBoxContainer/HBoxContainer/VBoxContainer2/LineEdit2 +@onready var creation_description_edit: TextEdit = $Window/CreationDialog/VBoxContainer/VBoxContainer/TextEdit + +@onready var dependency_dialog: ConfirmationDialog = $Window/DependencyDialog +@onready var extensions_properties_selector: OptionButton = $Window/DependencyDialog/VBoxContainer/OptionButton +@onready var dependency_type_edit: LineEdit = $Window/DependencyDialog/VBoxContainer/LineEdit +@onready var enable_dialog: ConfirmationDialog = $Window/EnableDialog +@onready var dependency_check_alert: AcceptDialog = $Window/DependencyCheckAlert + +@onready var property_scene_container: MarginContainer = %PropertySceneContainer +@onready var fields_settings: VBoxContainer = %FieldsSettings + +var _selected_extension_conf_index : int +var _selected_extension_property_index : int +var _selected_dependency : Dictionary + +func _ready() -> void: + window.hide() + hide() + +func _load_configurations() -> void: + extensions_list.clear() + + var extensions_configurations := PandoraSettings.get_extensions_configurations() + for extensions_configuration in extensions_configurations: + var item_name = extensions_configuration["configuration"]["name"] as String + var item_icon = load(extensions_configuration["configuration"]["icon"] as String) + + if item_name == "Pandora": + item_name = "Default" + extensions_list.add_item(item_name, item_icon) + no_properties_label.hide() + ext_configuration_container.hide() + ext_property_details.hide() + select_extension_label.show() + +func open(): + _load_configurations() + + show() + window.show() + +func _on_close_requested() -> void: + _selected_extension_conf_index = -1 + _selected_extension_property_index = -1 + + window.hide() + hide() + +func _on_item_selected(index: int) -> void: + _selected_extension_conf_index = index + var extensions_configurations := PandoraSettings.get_extensions_configurations() + var extensions_configuration := extensions_configurations[index] + extension_label.text = "%s - Extensions Settings" % extensions_configuration["configuration"]["name"] + + no_properties_label.hide() + select_extension_label.hide() + ext_configuration_container.hide() + if not extensions_configuration["properties"]: + no_properties_label.show() + else: + ext_properties_list.clear() + + for extension_property in extensions_configuration["properties"]: + ext_properties_list.add_item(extension_property["name"]) + + ext_configuration_container.show() + +func _on_property_selected(index: int) -> void: + _selected_extension_property_index = index + for child in properties_dependencies_container.get_children(): + child.queue_free() + for child in entities_dependencies_container.get_children(): + child.queue_free() + for child in fields_settings.get_children(): + child.queue_free() + if property_scene_container.get_child_count() > 0: + property_scene_container.get_child(0).queue_free() + + var extensions_configurations := PandoraSettings.get_extensions_configurations() + var extensions_configuration := extensions_configurations[_selected_extension_conf_index] + var extension_property = extensions_configurations[_selected_extension_conf_index]["properties"][index] as Dictionary + + ext_property_desc.text = extension_property["description"] + ext_property_enable_btn.button_pressed = extension_property["enabled"] + ext_property_show_on_top_btn.button_pressed = extension_property["show_on_top"] + var dependencies : Array = extension_property["dependencies"] + var property_dependencies := dependencies.filter(func(dep: Dictionary): return dep["type"] == "PROPERTY") + var model_dependencies := dependencies.filter(func(dep: Dictionary): return dep["type"] == "MODEL") + if property_dependencies: + for dep in property_dependencies: + var dependency_scene : Dependency = DependencyScene.instantiate() + dependency_scene.dependency = dep + properties_dependencies_container.add_child(dependency_scene) + dependency_scene.removed.connect(_on_dependency_removed) + if model_dependencies: + for dep in model_dependencies: + var dependency_scene : Dependency = DependencyScene.instantiate() + dependency_scene.dependency = dep + entities_dependencies_container.add_child(dependency_scene) + dependency_scene.removed.connect(_on_dependency_removed) + var extension_dir = PandoraSettings.get_extensions_confs_map().find_key(_selected_extension_conf_index) + var property_scene := (load(extension_dir + "/" + extension_property["dir_name"] + "/ui_component/" + extension_property["dir_name"] + ".tscn") as PackedScene).instantiate() + property_scene_container.add_child(property_scene) + + if extension_property["fields"]: + for property_field in extension_property["fields"]: + if property_field["type"] == "STRING": + var field_instance := STRING_FIELD_SETTINGS.instantiate() as StringFieldSettings + fields_settings.add_child(field_instance) + field_instance.set_property_field(property_field) + field_instance.updated.connect(_on_field_settings_update) + elif property_field["type"] == "RANGE": + var field_instance := RANGE_FIELD_SETTINGS.instantiate() as RangeFieldSettings + fields_settings.add_child(field_instance) + field_instance.set_property_field(property_field) + field_instance.updated.connect(_on_field_settings_update) + elif property_field["type"] == "ARRAY": + var field_instance := ARRAY_FIELD_SETTINGS.instantiate() as ArrayFieldSettings + fields_settings.add_child(field_instance) + field_instance.set_property_field(property_field) + field_instance.updated.connect(_on_field_settings_update) + elif property_field["type"] == "REFERENCE": + var field_instance := REFERENCE_FIELD_SETTINGS.instantiate() as ReferenceFieldSettings + fields_settings.add_child(field_instance) + field_instance.set_property_field(property_field) + field_instance.updated.connect(_on_field_settings_update) + elif property_field["type"] == "OPTIONS": + var field_instance := OPTIONS_FIELD_SETTINGS.instantiate() as OptionsFieldSettings + fields_settings.add_child(field_instance) + field_instance.set_property_field(property_field) + field_instance.updated.connect(_on_field_settings_update) + elif property_field["type"] == "BOOL": + var field_instance := BOOL_FIELD_SETTINGS.instantiate() as BoolFieldSettings + fields_settings.add_child(field_instance) + field_instance.set_property_field(property_field) + field_instance.updated.connect(_on_field_settings_update) + + if not extension_property["enabled"]: + ext_property_show_on_top_btn.disabled = true + dependencies_container.modulate.a = 0.45 + customization_container.modulate.a = 0.45 + else: + ext_property_show_on_top_btn.disabled = false + dependencies_container.modulate.a = 1 + customization_container.modulate.a = 1 + ext_property_details.show() + +func _on_field_settings_update(property_field: Dictionary) -> void: + var property_control = property_scene_container.get_child(0) as PandoraPropertyControl + property_control.update_field_settings(property_field) + PandoraSettings.save_extensions_configurations() + update_extensions_configurations.emit() + +func _on_enabled(toggled_on: bool) -> void: + var extensions_configurations := PandoraSettings.get_extensions_configurations() + var extensions_configuration := extensions_configurations[_selected_extension_conf_index] + var extension_property = extensions_configurations[_selected_extension_conf_index]["properties"][_selected_extension_property_index] as Dictionary + extension_property["enabled"] = toggled_on + + if not toggled_on: + ext_property_show_on_top_btn.disabled = true + dependencies_container.modulate.a = 0.45 + customization_container.modulate.a = 0.45 + else: + ext_property_show_on_top_btn.disabled = false + dependencies_container.modulate.a = 1 + customization_container.modulate.a = 1 + + PandoraSettings.save_extensions_configurations() + update_extensions_configurations.emit() + +func _on_show_on_top(toggled_on: bool) -> void: + var extensions_configurations := PandoraSettings.get_extensions_configurations() + var extensions_configuration := extensions_configurations[_selected_extension_conf_index] + var extension_property = extensions_configurations[_selected_extension_conf_index]["properties"][_selected_extension_property_index] as Dictionary + extension_property["show_on_top"] = toggled_on + + PandoraSettings.save_extensions_configurations() + update_extensions_configurations.emit() + +func _on_new_property_pressed() -> void: + creation_dialog.popup_centered() + +func _on_creation_dialog_confirmed() -> void: + var property_name = creation_name_edit.text + var property_type = creation_type_edit.text + var property_description = creation_description_edit.text + + if not property_name: + push_error("Property name is mandatory. Please retry.") + if not property_type: + push_error("Property type is mandatory. Please retry.") + + var extensions_configurations := PandoraSettings.get_extensions_configurations() + var extensions_dirs = PandoraSettings.get_extensions_dirs() + + var extensions_dir = extensions_dirs[_selected_extension_conf_index] + var extensions_configuration := extensions_configurations[_selected_extension_conf_index] + + var opened_ext_dir = DirAccess.open(extensions_dir) + opened_ext_dir.make_dir_recursive(property_type + "/icons") + opened_ext_dir.make_dir_recursive(property_type + "/model/types") + opened_ext_dir.make_dir_recursive(property_type + "/property_button") + opened_ext_dir.make_dir_recursive(property_type + "/ui_component") + FileAccess.open(extensions_dir + "/" + property_type + "/model/" + property_type + ".gd", FileAccess.WRITE) + FileAccess.open(extensions_dir + "/" + property_type + "/model/types/" + property_type + ".gd", FileAccess.WRITE) + FileAccess.open(extensions_dir + "/" + property_type + "/ui_component/" + property_type + ".gd", FileAccess.WRITE) + + var ui_component := PandoraPropertyControl.new() + ui_component.type = property_type + + var ui_component_scene := PackedScene.new() + var result = ui_component_scene.pack(ui_component) + if result == OK: + ResourceSaver.save(ui_component_scene, extensions_dir + "/" + property_type + "/ui_component/" + property_type + ".tscn") + + var property_button := PandoraPropertyButton.new() + property_button.scene = load(extensions_dir + "/" + property_type + "/ui_component/" + property_type + ".tscn") + var property_button_scene := PackedScene.new() + result = property_button_scene.pack(property_button) + if result == OK: + ResourceSaver.save(property_button_scene, extensions_dir + "/" + property_type + "/property_button/property_button.tscn") + + var extension_property : Dictionary = { + "name": property_name, + "dir_name": property_type, + "description": property_description, + "enabled": false, + "show_on_top": true, + "dependencies": [] + } + extensions_configurations[_selected_extension_conf_index]["properties"].append(extension_property) + PandoraSettings.save_extensions_configurations() + update_extensions_configurations.emit() + + creation_name_edit.text = "" + creation_type_edit.text = "" + creation_description_edit.text = "" + + _load_configurations() + +func _on_add_prop_dependency_pressed() -> void: + dependency_type_edit.editable = true + dependency_type_edit.text = "PROPERTY" + dependency_type_edit.editable = false + + extensions_properties_selector.clear() + + var extensions_configurations := PandoraSettings.get_extensions_configurations() + var extensions_configuration := extensions_configurations[_selected_extension_conf_index] + for ext_conf_prop in extensions_configuration["properties"]: + if ext_conf_prop["name"] != extensions_configuration["properties"][_selected_extension_property_index]["name"]: + extensions_properties_selector.add_item(ext_conf_prop["name"]) + + dependency_dialog.popup_centered() + +func _on_add_entity_dependency_pressed() -> void: + dependency_type_edit.editable = true + dependency_type_edit.text = "ENTITY" + dependency_type_edit.editable = false + dependency_dialog.popup_centered() + +func _on_dependency_dialog_confirmed() -> void: + var property_name := extensions_properties_selector.get_item_text(extensions_properties_selector.selected) + + var extensions_configurations := PandoraSettings.get_extensions_configurations() + var extensions_configuration := extensions_configurations[_selected_extension_conf_index] + var extension_properties = extensions_configurations[_selected_extension_conf_index]["properties"] + var selected_dependency = extension_properties.filter(func(property: Dictionary): return property["name"] == property_name)[0] as Dictionary + if not selected_dependency["enabled"]: + _selected_dependency = selected_dependency + enable_dialog.popup_centered() + else: + extension_properties[_selected_extension_property_index]["dependencies"].append({"name": selected_dependency["name"], "type": "PROPERTY"}) + PandoraSettings.save_extensions_configurations() + update_extensions_configurations.emit() + +func _on_enable_dialog_confirmed() -> void: + var extensions_configurations := PandoraSettings.get_extensions_configurations() + var extensions_configuration := extensions_configurations[_selected_extension_conf_index] + var extension_properties = extensions_configurations[_selected_extension_conf_index]["properties"] + extension_properties.filter(func(property: Dictionary): return property["name"] == _selected_dependency["name"])[0]["enabled"] = true + extension_properties[_selected_extension_property_index]["dependencies"].append({"name": _selected_dependency["name"], "type": "PROPERTY"}) + PandoraSettings.save_extensions_configurations() + update_extensions_configurations.emit() + +func _on_delete_property_pressed() -> void: + var extensions_configurations := PandoraSettings.get_extensions_configurations() + var extensions_configuration := extensions_configurations[_selected_extension_conf_index] + var current_property_name = extensions_configuration["properties"][_selected_extension_property_index]["name"] + var is_dependency = extensions_configuration["properties"].any(func(property: Dictionary): \ + return property["dependencies"].any(func(dep: Dictionary): \ + return dep["name"] == current_property_name)) + + if is_dependency: + dependency_check_alert.popup_centered() + else: + pass + +func _on_dependency_removed(dep: Dictionary) -> void: + var extensions_configurations := PandoraSettings.get_extensions_configurations() + var extensions_configuration := extensions_configurations[_selected_extension_conf_index] + var extension_properties = extensions_configurations[_selected_extension_conf_index]["properties"] + var property_dependencies = extension_properties[_selected_extension_property_index]["dependencies"] as Array + property_dependencies.erase(dep) + + PandoraSettings.save_extensions_configurations() + update_extensions_configurations.emit() diff --git a/addons/pandora/ui/editor/settings_dialog/settings_dialog.gd.uid b/addons/pandora/ui/editor/settings_dialog/settings_dialog.gd.uid new file mode 100644 index 00000000..760e7b98 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/settings_dialog.gd.uid @@ -0,0 +1 @@ +uid://d4efa7td5f0e0 diff --git a/addons/pandora/ui/editor/settings_dialog/settings_dialog.tscn b/addons/pandora/ui/editor/settings_dialog/settings_dialog.tscn new file mode 100644 index 00000000..7d1a325a --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/settings_dialog.tscn @@ -0,0 +1,388 @@ +[gd_scene load_steps=4 format=3 uid="uid://ctp7xnvi5ep0e"] + +[ext_resource type="Script" uid="uid://d4efa7td5f0e0" path="res://addons/pandora/ui/editor/settings_dialog/settings_dialog.gd" id="1_4vos3"] +[ext_resource type="Texture2D" uid="uid://dmh7pik8vjog8" path="res://addons/pandora/icons/pandora-icon.svg" id="2_4vos3"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_4vos3"] + +[node name="SettingsDialog" type="Control"] +visible = false +layout_mode = 3 +anchors_preset = 0 +script = ExtResource("1_4vos3") + +[node name="Window" type="Window" parent="."] +disable_3d = true +oversampling_override = 1.0 +title = "Extensions Settings" +initial_position = 2 +size = Vector2i(1152, 648) +visible = false +wrap_controls = true +content_scale_mode = 1 +content_scale_aspect = 4 + +[node name="PanelContainer" type="PanelContainer" parent="Window"] +self_modulate = Color(0, 0, 0, 1) +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_4vos3") + +[node name="HBoxContainer" type="HBoxContainer" parent="Window/PanelContainer"] +layout_mode = 2 + +[node name="ExtensionsContainer" type="VBoxContainer" parent="Window/PanelContainer/HBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="Window/PanelContainer/HBoxContainer/ExtensionsContainer"] +layout_mode = 2 +theme_override_colors/font_color = Color(1, 1, 0.69411767, 1) +text = "Extensions list" + +[node name="ItemList" type="ItemList" parent="Window/PanelContainer/HBoxContainer/ExtensionsContainer"] +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 +size_flags_vertical = 3 +item_count = 1 +item_0/text = "Default" +item_0/icon = ExtResource("2_4vos3") + +[node name="VBoxContainer" type="VBoxContainer" parent="Window/PanelContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="Window/PanelContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +theme_override_colors/font_color = Color(0.7882353, 0.3137255, 0.80784315, 1) +text = "Pandora - Extensions Settings" + +[node name="MarginContainer" type="MarginContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +theme_override_constants/margin_left = 5 +theme_override_constants/margin_top = 5 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_bottom = 5 + +[node name="VBoxContainer" type="VBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +text = "Here you can enable/disable any properties added by the extension or change their behaviours." + +[node name="NoProperties" type="Label" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer"] +unique_name_in_owner = true +visible = false +layout_mode = 2 +size_flags_vertical = 3 +theme_override_colors/font_color = Color(0.5489626, 0.5489626, 0.54896253, 1) +text = "This extensions doesn't add custom properties to Pandora." +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="SelectExtension" type="Label" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer"] +unique_name_in_owner = true +visible = false +layout_mode = 2 +size_flags_vertical = 3 +theme_override_colors/font_color = Color(0.5489626, 0.5489626, 0.54896253, 1) +text = "Select an extension to check its configuration" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="ExtConfigurationContainer" type="VBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 + +[node name="Label" type="Label" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer"] +layout_mode = 2 +theme_override_colors/font_color = Color(0.6039216, 0.44313726, 0.4117647, 1) +text = "All Properties" + +[node name="HBoxContainer" type="HBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="Properties" type="VBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer"] +layout_mode = 2 + +[node name="PropertyItemList" type="ItemList" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/Properties"] +unique_name_in_owner = true +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 +size_flags_vertical = 3 +theme_override_colors/font_selected_color = Color(0.64705884, 0.25490198, 0.6627451, 1) +item_count = 1 +item_0/text = "TestProperty" + +[node name="Button" type="Button" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/Properties"] +layout_mode = 2 +text = "New Property" + +[node name="ScrollContainer" type="ScrollContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="PropertyContainer" type="VBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="PropertyDescription" type="Label" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Defines the main attributes of an entity (mob, player, NPC, etc.)." + +[node name="HBoxContainer" type="HBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer"] +layout_mode = 2 + +[node name="EnableButton" type="CheckButton" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 0 +text = "Enable property" + +[node name="ShowPropertyOnTop" type="CheckButton" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 0 +disabled = true +text = "Show property on top (inside Property bar)" + +[node name="CustomizationContainer" type="FoldableContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer"] +unique_name_in_owner = true +modulate = Color(1, 1, 1, 0.47058824) +layout_mode = 2 +title = "Customize Property" + +[node name="PropertyShowcase" type="VBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/CustomizationContainer"] +layout_mode = 2 + +[node name="MarginContainer" type="MarginContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/CustomizationContainer/PropertyShowcase"] +layout_mode = 2 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 0 +theme_override_constants/margin_right = 10 + +[node name="VBoxContainer" type="VBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/CustomizationContainer/PropertyShowcase/MarginContainer"] +layout_mode = 2 + +[node name="PanelContainer" type="PanelContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/CustomizationContainer/PropertyShowcase/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="PropertySceneContainer" type="MarginContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/CustomizationContainer/PropertyShowcase/MarginContainer/VBoxContainer/PanelContainer"] +unique_name_in_owner = true +layout_mode = 2 +mouse_filter = 0 +mouse_behavior_recursive = 1 +mouse_force_pass_scroll_events = false +mouse_default_cursor_shape = 8 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 10 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 10 + +[node name="MarginContainer" type="MarginContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/CustomizationContainer/PropertyShowcase/MarginContainer/VBoxContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 5 +theme_override_constants/margin_top = 5 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_bottom = 5 + +[node name="FieldsSettings" type="VBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/CustomizationContainer/PropertyShowcase/MarginContainer/VBoxContainer/MarginContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="DependenciesContainer" type="FoldableContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer"] +unique_name_in_owner = true +modulate = Color(1, 1, 1, 0.47058824) +layout_mode = 2 +title = "Dependencies" + +[node name="VBoxContainer" type="VBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer"] +layout_mode = 2 + +[node name="PropertiesDependencies" type="VBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="HSeparator" type="HSeparator" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/PropertiesDependencies"] +layout_mode = 2 +theme_override_constants/separation = 10 + +[node name="HBoxContainer" type="HBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/PropertiesDependencies"] +layout_mode = 2 + +[node name="Dependecies" type="Label" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/PropertiesDependencies/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_colors/font_color = Color(1, 0.23921569, 0.2509804, 1) +text = "Dependencies (Properties)" + +[node name="Button" type="Button" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/PropertiesDependencies/HBoxContainer"] +layout_mode = 2 +text = "Add dependency" + +[node name="GridContainer" type="GridContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/PropertiesDependencies"] +layout_mode = 2 +theme_override_constants/h_separation = 30 +columns = 5 + +[node name="EntitiesDependencies" type="VBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer"] +unique_name_in_owner = true +visible = false +layout_mode = 2 + +[node name="HSeparator" type="HSeparator" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/EntitiesDependencies"] +layout_mode = 2 +theme_override_constants/separation = 10 + +[node name="HBoxContainer" type="HBoxContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/EntitiesDependencies"] +layout_mode = 2 + +[node name="Dependecies" type="Label" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/EntitiesDependencies/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_colors/font_color = Color(1, 0.23921569, 0.2509804, 1) +text = "Dependencies (Entities/Models)" + +[node name="Button" type="Button" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/EntitiesDependencies/HBoxContainer"] +layout_mode = 2 +text = "Add dependency" + +[node name="GridContainer" type="GridContainer" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/EntitiesDependencies"] +layout_mode = 2 +theme_override_constants/h_separation = 30 +columns = 5 + +[node name="Label" type="Label" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/EntitiesDependencies/GridContainer"] +layout_mode = 2 +text = "ItemEntity" + +[node name="BottomSpace" type="HSeparator" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/EntitiesDependencies"] +modulate = Color(1, 1, 1, 0) +layout_mode = 2 +theme_override_constants/separation = 10 + +[node name="Button" type="Button" parent="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer"] +custom_minimum_size = Vector2(160, 0) +layout_mode = 2 +size_flags_horizontal = 8 +size_flags_vertical = 10 +theme_override_colors/font_color = Color(0.8745098, 0.24313726, 0, 1) +text = "Delete Property" + +[node name="CreationDialog" type="ConfirmationDialog" parent="Window"] +oversampling_override = 1.0 +title = "New Property" +initial_position = 2 +size = Vector2i(500, 246) +ok_button_text = "Create" + +[node name="VBoxContainer" type="VBoxContainer" parent="Window/CreationDialog"] +offset_left = 8.0 +offset_top = 8.0 +offset_right = 492.0 +offset_bottom = 197.0 + +[node name="HBoxContainer" type="HBoxContainer" parent="Window/CreationDialog/VBoxContainer"] +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="Window/CreationDialog/VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="Window/CreationDialog/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +text = "Property Name" + +[node name="LineEdit" type="LineEdit" parent="Window/CreationDialog/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +placeholder_text = "TestProperty" + +[node name="VBoxContainer2" type="VBoxContainer" parent="Window/CreationDialog/VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label2" type="Label" parent="Window/CreationDialog/VBoxContainer/HBoxContainer/VBoxContainer2"] +layout_mode = 2 +text = "Type" + +[node name="LineEdit2" type="LineEdit" parent="Window/CreationDialog/VBoxContainer/HBoxContainer/VBoxContainer2"] +layout_mode = 2 +placeholder_text = "test_property" + +[node name="VBoxContainer" type="VBoxContainer" parent="Window/CreationDialog/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="Window/CreationDialog/VBoxContainer/VBoxContainer"] +layout_mode = 2 +text = "Description" + +[node name="TextEdit" type="TextEdit" parent="Window/CreationDialog/VBoxContainer/VBoxContainer"] +custom_minimum_size = Vector2(0, 100) +layout_mode = 2 +placeholder_text = "Write here a description of your property" + +[node name="DependencyDialog" type="ConfirmationDialog" parent="Window"] +oversampling_override = 1.0 +title = "Add new dependency" +initial_position = 2 +size = Vector2i(300, 166) +ok_button_text = "Add" + +[node name="VBoxContainer" type="VBoxContainer" parent="Window/DependencyDialog"] +offset_left = 8.0 +offset_top = 8.0 +offset_right = 292.0 +offset_bottom = 117.0 + +[node name="Label" type="Label" parent="Window/DependencyDialog/VBoxContainer"] +layout_mode = 2 +text = "Select a property" + +[node name="OptionButton" type="OptionButton" parent="Window/DependencyDialog/VBoxContainer"] +layout_mode = 2 + +[node name="Label2" type="Label" parent="Window/DependencyDialog/VBoxContainer"] +layout_mode = 2 +text = "Type of dependency" + +[node name="LineEdit" type="LineEdit" parent="Window/DependencyDialog/VBoxContainer"] +layout_mode = 2 +editable = false + +[node name="EnableDialog" type="ConfirmationDialog" parent="Window"] +oversampling_override = 1.0 +title = "Warning" +initial_position = 2 +size = Vector2i(275, 106) +ok_button_text = "Enable" +dialog_text = "The selected property is disabled. +Do you want to enable it?" + +[node name="DependencyCheckAlert" type="AcceptDialog" parent="Window"] +oversampling_override = 1.0 +title = "Warning!" +initial_position = 2 +size = Vector2i(370, 106) +dialog_text = "You can't delete this property because is used +by another property." + +[connection signal="close_requested" from="Window" to="." method="_on_close_requested"] +[connection signal="item_selected" from="Window/PanelContainer/HBoxContainer/ExtensionsContainer/ItemList" to="." method="_on_item_selected"] +[connection signal="item_selected" from="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/Properties/PropertyItemList" to="." method="_on_property_selected"] +[connection signal="pressed" from="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/Properties/Button" to="." method="_on_new_property_pressed"] +[connection signal="toggled" from="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/HBoxContainer/EnableButton" to="." method="_on_enabled"] +[connection signal="toggled" from="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/HBoxContainer/ShowPropertyOnTop" to="." method="_on_show_on_top"] +[connection signal="pressed" from="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/PropertiesDependencies/HBoxContainer/Button" to="." method="_on_add_prop_dependency_pressed"] +[connection signal="pressed" from="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/DependenciesContainer/VBoxContainer/EntitiesDependencies/HBoxContainer/Button" to="." method="_on_add_entity_dependency_pressed"] +[connection signal="pressed" from="Window/PanelContainer/HBoxContainer/VBoxContainer/MarginContainer/VBoxContainer/ExtConfigurationContainer/HBoxContainer/ScrollContainer/PropertyContainer/Button" to="." method="_on_delete_property_pressed"] +[connection signal="confirmed" from="Window/CreationDialog" to="." method="_on_creation_dialog_confirmed"] +[connection signal="confirmed" from="Window/DependencyDialog" to="." method="_on_dependency_dialog_confirmed"] +[connection signal="confirmed" from="Window/EnableDialog" to="." method="_on_enable_dialog_confirmed"] diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/array_field_settings.gd b/addons/pandora/ui/editor/settings_dialog/ui_fields/array_field_settings.gd new file mode 100644 index 00000000..a5534bd3 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/array_field_settings.gd @@ -0,0 +1,41 @@ +@tool +class_name ArrayFieldSettings +extends VBoxContainer + +signal updated(property_field: Dictionary) + +@onready var label: Label = $Label +@onready var check_button: CheckButton = $HBoxContainer/CheckButton +@onready var option_button: OptionButton = $HBoxContainer/OptionButton + +var property_field : Dictionary : set = set_property_field +var property_types_idx: Dictionary + +func _ready() -> void: + option_button.clear() + var idx = 0 + for property_type in PandoraPropertyType.get_all_types(): + if property_type.allow_nesting(): + option_button.add_icon_item( + load(property_type.get_type_icon_path()), property_type.get_type_name(), idx + ) + property_types_idx[idx] = property_type.get_type_name() + idx += 1 + +func set_property_field(field: Dictionary) -> void: + property_field = field + _update_field_settings() + +func _update_field_settings() -> void: + label.text = property_field["name"] + " Settings" + check_button.button_pressed = property_field["enabled"] + var idx = property_types_idx.find_key(property_field["settings"]["type"]) + option_button.select(idx) + +func _on_check_button_toggled(toggled_on: bool) -> void: + property_field["enabled"] = toggled_on + updated.emit(property_field) + +func _on_option_button_item_selected(index: int) -> void: + property_field["settings"]["type"] = property_types_idx[index] + updated.emit(property_field) diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/array_field_settings.gd.uid b/addons/pandora/ui/editor/settings_dialog/ui_fields/array_field_settings.gd.uid new file mode 100644 index 00000000..c5687a37 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/array_field_settings.gd.uid @@ -0,0 +1 @@ +uid://gifa0m2v52h7 diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/array_field_settings.tscn b/addons/pandora/ui/editor/settings_dialog/ui_fields/array_field_settings.tscn new file mode 100644 index 00000000..d826a4b3 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/array_field_settings.tscn @@ -0,0 +1,31 @@ +[gd_scene load_steps=2 format=3 uid="uid://cgwd2gdv7xeia"] + +[ext_resource type="Script" uid="uid://gifa0m2v52h7" path="res://addons/pandora/ui/editor/settings_dialog/ui_fields/array_field_settings.gd" id="1_qtgvu"] + +[node name="ArrayFieldSettings" type="VBoxContainer"] +offset_right = 109.0 +offset_bottom = 23.0 +script = ExtResource("1_qtgvu") + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +theme_override_colors/font_color = Color(0.59607846, 0.43529412, 0.40392157, 1) +text = "Array Settings" + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="CheckButton" type="CheckButton" parent="HBoxContainer"] +layout_mode = 2 +button_pressed = true +text = "Enable field" + +[node name="Label" type="Label" parent="HBoxContainer"] +layout_mode = 2 +text = "Type" + +[node name="OptionButton" type="OptionButton" parent="HBoxContainer"] +layout_mode = 2 + +[connection signal="toggled" from="HBoxContainer/CheckButton" to="." method="_on_check_button_toggled"] +[connection signal="item_selected" from="HBoxContainer/OptionButton" to="." method="_on_option_button_item_selected"] diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/bool_field_settings.gd b/addons/pandora/ui/editor/settings_dialog/ui_fields/bool_field_settings.gd new file mode 100644 index 00000000..5a3fcdec --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/bool_field_settings.gd @@ -0,0 +1,22 @@ +@tool +class_name BoolFieldSettings +extends VBoxContainer + +signal updated(property_field: Dictionary) + +@onready var label: Label = $Label +@onready var check_button: CheckButton = $HBoxContainer/CheckButton + +var property_field : Dictionary : set = set_property_field + +func set_property_field(field: Dictionary) -> void: + property_field = field + _update_field_settings() + +func _update_field_settings() -> void: + label.text = property_field["name"] + " Settings" + check_button.button_pressed = property_field["enabled"] + +func _on_check_button_toggled(toggled_on: bool) -> void: + property_field["enabled"] = toggled_on + updated.emit(property_field) diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/bool_field_settings.gd.uid b/addons/pandora/ui/editor/settings_dialog/ui_fields/bool_field_settings.gd.uid new file mode 100644 index 00000000..9814a5a7 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/bool_field_settings.gd.uid @@ -0,0 +1 @@ +uid://ch5nj1y2dxmjk diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/bool_field_settings.tscn b/addons/pandora/ui/editor/settings_dialog/ui_fields/bool_field_settings.tscn new file mode 100644 index 00000000..9d9c302d --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/bool_field_settings.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=2 format=3 uid="uid://bm6rmjycqduyn"] + +[ext_resource type="Script" uid="uid://ch5nj1y2dxmjk" path="res://addons/pandora/ui/editor/settings_dialog/ui_fields/bool_field_settings.gd" id="1_h648l"] + +[node name="BoolFieldSettings" type="VBoxContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_h648l") + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +theme_override_colors/font_color = Color(0.59607846, 0.43529412, 0.40392157, 1) +text = "Bool Settings" + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="CheckButton" type="CheckButton" parent="HBoxContainer"] +layout_mode = 2 +button_pressed = true +text = "Enable field" + +[connection signal="toggled" from="HBoxContainer/CheckButton" to="." method="_on_check_button_toggled"] diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/options_field_settings.gd b/addons/pandora/ui/editor/settings_dialog/ui_fields/options_field_settings.gd new file mode 100644 index 00000000..c54f1195 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/options_field_settings.gd @@ -0,0 +1,44 @@ +@tool +class_name OptionsFieldSettings +extends VBoxContainer + +signal updated(property_field: Dictionary) + +@onready var label: Label = $Label +@onready var check_button: CheckButton = $HBoxContainer/CheckButton +@onready var edit_button: Button = $HBoxContainer/Button +@onready var options_window: Window = $OptionsWindow +@onready var line_edit: LineEdit = $HBoxContainer/LineEdit + +var property_field : Dictionary : set = set_property_field + +func _ready() -> void: + edit_button.pressed.connect(func(): options_window.open(property_field["settings"]["options"] as Array)) + + options_window.item_added.connect(func(item: Variant): + property_field["settings"]["options"].append(item) + ) + options_window.item_removed.connect(func(item: Variant): + property_field["settings"]["options"].erase(item) + ) + options_window.item_updated.connect(func(idx: int, item: Variant): + property_field["settings"]["options"][idx] = item + ) + +func set_property_field(field: Dictionary) -> void: + property_field = field + _update_field_settings() + +func _update_field_settings() -> void: + label.text = property_field["name"] + " Settings" + check_button.button_pressed = property_field["enabled"] + line_edit.text = str(property_field["settings"]["options"].size()) + " Options" + +func _on_check_button_toggled(toggled_on: bool) -> void: + property_field["enabled"] = toggled_on + updated.emit(property_field) + +func _on_window_close_requested() -> void: + _update_field_settings.call_deferred() + updated.emit(property_field) + options_window.hide() diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/options_field_settings.gd.uid b/addons/pandora/ui/editor/settings_dialog/ui_fields/options_field_settings.gd.uid new file mode 100644 index 00000000..3f4e1f1e --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/options_field_settings.gd.uid @@ -0,0 +1 @@ +uid://qx222rida1tm diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/options_field_settings.tscn b/addons/pandora/ui/editor/settings_dialog/ui_fields/options_field_settings.tscn new file mode 100644 index 00000000..684a6225 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/options_field_settings.tscn @@ -0,0 +1,114 @@ +[gd_scene load_steps=4 format=3 uid="uid://7c8j3yx3hnr4"] + +[ext_resource type="Texture2D" uid="uid://b0mt8ysdc5m4a" path="res://addons/pandora/icons/Edit.svg" id="1_atebi"] +[ext_resource type="Script" uid="uid://qx222rida1tm" path="res://addons/pandora/ui/editor/settings_dialog/ui_fields/options_field_settings.gd" id="1_ceb5e"] +[ext_resource type="Script" uid="uid://1higomb3gr2t" path="res://addons/pandora/ui/editor/settings_dialog/ui_fields/options_window.gd" id="3_xc8d3"] + +[node name="OptionsFieldSettings" type="VBoxContainer"] +script = ExtResource("1_ceb5e") + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +theme_override_colors/font_color = Color(0.59607846, 0.43529412, 0.40392157, 1) +text = "Options Settings" + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="CheckButton" type="CheckButton" parent="HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 0 +size_flags_vertical = 8 +button_pressed = true +text = "Enable field" + +[node name="LineEdit" type="LineEdit" parent="HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "0 Options" +alignment = 1 +editable = false +expand_to_text_length = true +context_menu_enabled = false +virtual_keyboard_enabled = false +shortcut_keys_enabled = false +selecting_enabled = false +flat = true + +[node name="Button" type="Button" parent="HBoxContainer"] +layout_mode = 2 +icon = ExtResource("1_atebi") + +[node name="OptionsWindow" type="Window" parent="."] +disable_3d = true +oversampling_override = 1.0 +title = "Options Manager" +initial_position = 2 +size = Vector2i(134, 100) +visible = false +wrap_controls = true +content_scale_mode = 1 +content_scale_aspect = 4 +script = ExtResource("3_xc8d3") + +[node name="Panel" type="Panel" parent="OptionsWindow"] +self_modulate = Color(0, 0, 0, 1) +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="MarginContainer" type="MarginContainer" parent="OptionsWindow/Panel"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 10 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 10 + +[node name="MainContainer" type="VBoxContainer" parent="OptionsWindow/Panel/MarginContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="ScrollContainer" type="ScrollContainer" parent="OptionsWindow/Panel/MarginContainer/MainContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="VBoxContainer" type="VBoxContainer" parent="OptionsWindow/Panel/MarginContainer/MainContainer/ScrollContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="MarginContainer" type="MarginContainer" parent="OptionsWindow/Panel/MarginContainer/MainContainer/ScrollContainer/VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 8 +theme_override_constants/margin_bottom = 10 + +[node name="NewItemButton" type="Button" parent="OptionsWindow/Panel/MarginContainer/MainContainer/ScrollContainer/VBoxContainer/MarginContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Add New Item +" + +[node name="ArrayItems" type="VBoxContainer" parent="OptionsWindow/Panel/MarginContainer/MainContainer/ScrollContainer/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="CenterContainer" type="CenterContainer" parent="OptionsWindow/Panel/MarginContainer/MainContainer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="OptionsWindow/Panel/MarginContainer/MainContainer/CenterContainer"] +layout_mode = 2 +theme_override_constants/separation = 20 + +[node name="CloseButton" type="Button" parent="OptionsWindow/Panel/MarginContainer/MainContainer/CenterContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Close" + +[connection signal="toggled" from="HBoxContainer/CheckButton" to="." method="_on_check_button_toggled"] +[connection signal="close_requested" from="OptionsWindow" to="." method="_on_window_close_requested"] diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/options_window.gd b/addons/pandora/ui/editor/settings_dialog/ui_fields/options_window.gd new file mode 100644 index 00000000..ce4d956c --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/options_window.gd @@ -0,0 +1,84 @@ +@tool +extends Window + +const ArrayItem = preload("res://addons/pandora/ui/components/array_editor/array_item.tscn") +const PropertyBarScene = "res://addons/pandora/ui/components/property_bar/property_bar.tscn" + +signal item_added(item: Variant) +signal item_removed(item: Variant) +signal item_updated(idx: int, new_item: Variant) + +@onready var close_button: Button = %CloseButton +@onready var new_item_button: Button = %NewItemButton +@onready var items_container: VBoxContainer = %ArrayItems +@onready var main_container: VBoxContainer = %MainContainer + +var property_bar: Node +var _items: Array + +func _ready(): + if owner.get_parent() is SubViewport: + return + + close_button.pressed.connect(_on_close_requested) + new_item_button.pressed.connect(_add_new_item) + +func close(): + _remove_empty_items() + _clear() + +func _add_new_item(): + var scene = property_bar.get_scene_by_type("string") + var control = scene.instantiate() as PandoraPropertyControl + var item_property = PandoraProperty.new("", "array_item", "string") + _items.append(item_property.get_default_value()) + _add_property_control(control, item_property, _items.size() - 1) + item_added.emit(_items[_items.size() - 1]) + +func _add_property_control(control: PandoraPropertyControl, item_property: PandoraProperty, idx: int): + var item = ArrayItem.instantiate() + control.init(item_property) + control.property_value_changed.connect(func(value: Variant): item_updated.emit(idx, value)) + item.item_removal_requested.connect( + func(): item_removed.emit(control._property.get_default_value()) + ) + item.init(item_property, control, Pandora._entity_backend) + items_container.add_child(item) + +func _clear(): + _items.clear() + for child in items_container.get_children(): + child.queue_free() + items_container.get_children().clear() + +func _remove_empty_items(): + for index in range(_items.size()): + if _items[index] == null: + _items.erase(index) + item_removed.emit(_items[index]) + +func _load_items(): + for i in range(_items.size()): + var control = (property_bar.get_scene_by_type("string").instantiate() as PandoraPropertyControl) + var item_property = PandoraProperty.new("", "array_item", "string") + var value = _items[i] + item_property.set_default_value(value) + _add_property_control(control, item_property, i) + +func open(original_items: Array): + popup_centered_clamped(Vector2i(800, 1000), 0.5) + move_to_foreground() + grab_focus() + + var property_bar_scene = load(PropertyBarScene) + property_bar = property_bar_scene.instantiate() + property_bar._ready() + + _items = original_items.duplicate() + _load_items() + +func _on_close_requested(): + close() + hide() + property_bar.queue_free() + close_requested.emit() diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/options_window.gd.uid b/addons/pandora/ui/editor/settings_dialog/ui_fields/options_window.gd.uid new file mode 100644 index 00000000..4ea25cbb --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/options_window.gd.uid @@ -0,0 +1 @@ +uid://1higomb3gr2t diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/range_field_settings.gd b/addons/pandora/ui/editor/settings_dialog/ui_fields/range_field_settings.gd new file mode 100644 index 00000000..5a6e37aa --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/range_field_settings.gd @@ -0,0 +1,38 @@ +@tool +class_name RangeFieldSettings +extends VBoxContainer + +signal updated(property_field: Dictionary) + +@onready var label: Label = $Label +@onready var check_button: CheckButton = $HBoxContainer/CheckButton +@onready var spin_box: SpinBox = $HBoxContainer/SpinBox +@onready var spin_box_2: SpinBox = $HBoxContainer/SpinBox2 + +var property_field : Dictionary : set = set_property_field + +func set_property_field(field: Dictionary) -> void: + property_field = field + _update_field_settings() + +func _update_field_settings() -> void: + label.text = property_field["name"] + " Settings" + check_button.button_pressed = property_field["enabled"] + spin_box_2.value = property_field["settings"]["max_value"] + spin_box_2.max_value = property_field["settings"]["max_value"] + spin_box_2.min_value = property_field["settings"]["min_value"] + spin_box.value = property_field["settings"]["min_value"] + spin_box.min_value = property_field["settings"]["min_value"] + spin_box.max_value = property_field["settings"]["max_value"] + +func _on_check_button_toggled(toggled_on: bool) -> void: + property_field["enabled"] = toggled_on + updated.emit(property_field) + +func _on_spin_box_value_changed(value: float) -> void: + property_field["settings"]["min_value"] = value + updated.emit(property_field) + +func _on_spin_box_2_value_changed(value: float) -> void: + property_field["settings"]["max_value"] = value + updated.emit(property_field) diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/range_field_settings.gd.uid b/addons/pandora/ui/editor/settings_dialog/ui_fields/range_field_settings.gd.uid new file mode 100644 index 00000000..3c8c9c00 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/range_field_settings.gd.uid @@ -0,0 +1 @@ +uid://ba6xr8b575on3 diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/range_field_settings.tscn b/addons/pandora/ui/editor/settings_dialog/ui_fields/range_field_settings.tscn new file mode 100644 index 00000000..9a55b523 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/range_field_settings.tscn @@ -0,0 +1,45 @@ +[gd_scene load_steps=2 format=3 uid="uid://cyd24jwivayf5"] + +[ext_resource type="Script" uid="uid://ba6xr8b575on3" path="res://addons/pandora/ui/editor/settings_dialog/ui_fields/range_field_settings.gd" id="1_oe68r"] + +[node name="RangeFieldSettings" type="VBoxContainer"] +script = ExtResource("1_oe68r") + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +theme_override_colors/font_color = Color(0.59607846, 0.43529412, 0.40392157, 1) +text = "Quantity Settings" + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="CheckButton" type="CheckButton" parent="HBoxContainer"] +layout_mode = 2 +button_pressed = true +text = "Enable field" + +[node name="Label" type="Label" parent="HBoxContainer"] +layout_mode = 2 +text = "Min Value" + +[node name="SpinBox" type="SpinBox" parent="HBoxContainer"] +custom_minimum_size = Vector2(120, 0) +layout_mode = 2 +min_value = -999999999.0 +max_value = 999999999.0 +value = -999999999.0 + +[node name="Label2" type="Label" parent="HBoxContainer"] +layout_mode = 2 +text = "Max Value" + +[node name="SpinBox2" type="SpinBox" parent="HBoxContainer"] +custom_minimum_size = Vector2(120, 0) +layout_mode = 2 +min_value = -999999999.0 +max_value = 999999999.0 +value = 999999999.0 + +[connection signal="toggled" from="HBoxContainer/CheckButton" to="." method="_on_check_button_toggled"] +[connection signal="value_changed" from="HBoxContainer/SpinBox" to="." method="_on_spin_box_value_changed"] +[connection signal="value_changed" from="HBoxContainer/SpinBox2" to="." method="_on_spin_box_2_value_changed"] diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/reference_field_settings.gd b/addons/pandora/ui/editor/settings_dialog/ui_fields/reference_field_settings.gd new file mode 100644 index 00000000..56694ec9 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/reference_field_settings.gd @@ -0,0 +1,39 @@ +@tool +class_name ReferenceFieldSettings +extends VBoxContainer + +signal updated(property_field: Dictionary) + +@onready var label: Label = $Label +@onready var check_button: CheckButton = $HBoxContainer/CheckButton +@onready var category_only: CheckButton = $HBoxContainer/CategoryOnly +@onready var entity_picker: HBoxContainer = $HBoxContainer/EntityPicker + +var property_field : Dictionary : set = set_property_field + +func set_property_field(field: Dictionary) -> void: + property_field = field + _update_field_settings() + +func _update_field_settings() -> void: + label.text = property_field["name"] + " Settings" + check_button.button_pressed = property_field["enabled"] + category_only.button_pressed = property_field["settings"]["category_only"] + entity_picker.categories_only = property_field["settings"]["category_only"] + _pick_entity_or_category.call_deferred(property_field["settings"]["entity_id"]) + +func _pick_entity_or_category(category_id: String) -> void: + var category = Pandora.get_category(category_id) + entity_picker.select(category) + +func _on_check_button_toggled(toggled_on: bool) -> void: + property_field["enabled"] = toggled_on + updated.emit(property_field) + +func _on_category_only_toggled(toggled_on: bool) -> void: + property_field["settings"]["category_only"] = toggled_on + entity_picker.categories_only = toggled_on + updated.emit(property_field) + +func _on_entity_picker_entity_selected(entity: PandoraEntity) -> void: + property_field["settings"]["entity_id"] = entity.get_entity_id() diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/reference_field_settings.gd.uid b/addons/pandora/ui/editor/settings_dialog/ui_fields/reference_field_settings.gd.uid new file mode 100644 index 00000000..4a692830 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/reference_field_settings.gd.uid @@ -0,0 +1 @@ +uid://nt7wcwqkldyq diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/reference_field_settings.tscn b/addons/pandora/ui/editor/settings_dialog/ui_fields/reference_field_settings.tscn new file mode 100644 index 00000000..b2102cb1 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/reference_field_settings.tscn @@ -0,0 +1,39 @@ +[gd_scene load_steps=3 format=3 uid="uid://d3a0188wd61px"] + +[ext_resource type="Script" uid="uid://nt7wcwqkldyq" path="res://addons/pandora/ui/editor/settings_dialog/ui_fields/reference_field_settings.gd" id="1_a0vmf"] +[ext_resource type="PackedScene" uid="uid://bfhqt0xa4a2fh" path="res://addons/pandora/ui/components/entity_picker/entity_picker.tscn" id="1_hcy81"] + +[node name="ReferenceFieldSettings" type="VBoxContainer"] +script = ExtResource("1_a0vmf") + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +theme_override_colors/font_color = Color(0.59607846, 0.43529412, 0.40392157, 1) +text = "Reference Settings" + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="CheckButton" type="CheckButton" parent="HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 0 +size_flags_vertical = 8 +button_pressed = true +text = "Enable field" + +[node name="CategoryOnly" type="CheckButton" parent="HBoxContainer"] +layout_mode = 2 +size_flags_vertical = 8 +text = "Category only" + +[node name="Label" type="Label" parent="HBoxContainer"] +layout_mode = 2 +text = "Category Filter" + +[node name="EntityPicker" parent="HBoxContainer" instance=ExtResource("1_hcy81")] +custom_minimum_size = Vector2(190, 0) +layout_mode = 2 + +[connection signal="toggled" from="HBoxContainer/CheckButton" to="." method="_on_check_button_toggled"] +[connection signal="toggled" from="HBoxContainer/CategoryOnly" to="." method="_on_category_only_toggled"] +[connection signal="entity_selected" from="HBoxContainer/EntityPicker" to="." method="_on_entity_picker_entity_selected"] diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/string_field_settings.gd b/addons/pandora/ui/editor/settings_dialog/ui_fields/string_field_settings.gd new file mode 100644 index 00000000..36854c86 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/string_field_settings.gd @@ -0,0 +1,22 @@ +@tool +class_name StringFieldSettings +extends VBoxContainer + +signal updated(property_field: Dictionary) + +@onready var label: Label = $Label +@onready var check_button: CheckButton = $HBoxContainer/CheckButton + +var property_field : Dictionary : set = set_property_field + +func set_property_field(field: Dictionary) -> void: + property_field = field + _update_field_settings() + +func _update_field_settings() -> void: + label.text = property_field["name"] + " Settings" + check_button.button_pressed = property_field["enabled"] + +func _on_check_button_toggled(toggled_on: bool) -> void: + property_field["enabled"] = toggled_on + updated.emit(property_field) diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/string_field_settings.gd.uid b/addons/pandora/ui/editor/settings_dialog/ui_fields/string_field_settings.gd.uid new file mode 100644 index 00000000..94fb8338 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/string_field_settings.gd.uid @@ -0,0 +1 @@ +uid://ds6adhc4rxiyl diff --git a/addons/pandora/ui/editor/settings_dialog/ui_fields/string_field_settings.tscn b/addons/pandora/ui/editor/settings_dialog/ui_fields/string_field_settings.tscn new file mode 100644 index 00000000..e0bd0a20 --- /dev/null +++ b/addons/pandora/ui/editor/settings_dialog/ui_fields/string_field_settings.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=2 format=3 uid="uid://bn7da5ljy5mqh"] + +[ext_resource type="Script" uid="uid://ds6adhc4rxiyl" path="res://addons/pandora/ui/editor/settings_dialog/ui_fields/string_field_settings.gd" id="1_1ygog"] + +[node name="StringFieldSettings" type="VBoxContainer"] +script = ExtResource("1_1ygog") + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +theme_override_colors/font_color = Color(0.59607846, 0.43529412, 0.40392157, 1) +text = "Item Name Settings" + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="CheckButton" type="CheckButton" parent="HBoxContainer"] +layout_mode = 2 +button_pressed = true +text = "Enable field" + +[connection signal="toggled" from="HBoxContainer/CheckButton" to="." method="_on_check_button_toggled"] diff --git a/addons/pandora/util/configuration_template.json b/addons/pandora/util/configuration_template.json new file mode 100644 index 00000000..959f9a6a --- /dev/null +++ b/addons/pandora/util/configuration_template.json @@ -0,0 +1,7 @@ +{ + "configuration": { + "name": "Pandora", + "icon": "res://addons/pandora/icons/pandora-icon.svg", + }, + "properties": [] +} diff --git a/data.pandora b/data.pandora index 88a137ed..703c9279 100644 --- a/data.pandora +++ b/data.pandora @@ -428,12 +428,19 @@ "_id": "5", "_name": "array property", "_type": "array" + }, + { + "_category_id": "1", + "_default_value": null, + "_id": "17.0", + "_name": "test_property property", + "_type": "test_property" } ] }, "_id_generator": { "_ids_by_context": { - "default": 9.0 + "default": 17.0 } } } \ No newline at end of file diff --git a/pandora/categories.gd b/pandora/categories.gd index 3094c8cd..d1c830c2 100644 --- a/pandora/categories.gd +++ b/pandora/categories.gd @@ -2,11 +2,22 @@ class_name PandoraCategories -const ROOT = "F2e9QCtQ6e" +const ITEMS = "1" +const RARITY = "16" +const QUESTS = "27" +const DIALOGUES = "28" +const SPELLS = "29" +const MOCK__REQUIRED_FOR_TESTING__ = "54" +const NPCS = "2" -class RootCategories: - const ITEMS = "_zMxaAiHqU" - const NPCS = "PXyryU_CUw" +class ItemsArmoryCategories: + const SHIELDS = "8" + + +class ItemsCategories: + const ARMORY = "3" + const TOOLS = "4" + const ORES = "13" diff --git a/pandora/extensions/configuration.json b/pandora/extensions/configuration.json new file mode 100644 index 00000000..4ba57a0a --- /dev/null +++ b/pandora/extensions/configuration.json @@ -0,0 +1,83 @@ +{ + "configuration": { + "icon": "res://addons/pandora/icons/pandora-icon.svg", + "name": "Pandora" + }, + "properties": [ + { + "dependencies": [ + { + "name": "DependencyProperty", + "type": "PROPERTY" + } + ], + "description": "A simple property of test to show how to use new custom extensions.", + "dir_name": "test_property", + "enabled": true, + "fields": [ + { + "enabled": true, + "name": "Item Name", + "settings": { + + }, + "type": "STRING" + }, + { + "enabled": true, + "name": "Quantity", + "settings": { + "max_value": 100.0, + "min_value": 0.0 + }, + "type": "RANGE" + } + ], + "name": "PandoraTestProperty", + "show_on_top": true + }, + { + "dependencies": [], + "description": "", + "dir_name": "dependency_property", + "enabled": true, + "fields": [ + { + "enabled": true, + "name": "Item Name", + "settings": { + "options": [] + }, + "type": "OPTIONS" + }, + { + "enabled": true, + "name": "Quantity", + "settings": { + "max_value": 100.0, + "min_value": 0.0 + }, + "type": "RANGE" + }, + { + "enabled": true, + "name": "Test", + "settings": { + "type": "bool" + }, + "type": "ARRAY" + }, + { + "enabled": true, + "name": "Item Name", + "settings": { + "options": [] + }, + "type": "OPTIONS" + } + ], + "name": "DependencyProperty", + "show_on_top": true + } + ] +} diff --git a/pandora/extensions/dependency_property/model/dependency_property.gd b/pandora/extensions/dependency_property/model/dependency_property.gd new file mode 100644 index 00000000..d2738aa0 --- /dev/null +++ b/pandora/extensions/dependency_property/model/dependency_property.gd @@ -0,0 +1,30 @@ +class_name PandoraDependencyProperty extends RefCounted + +var _item_name : String +var _quantity : int + +func _init(item_name: String, quantity: int) -> void: + _item_name = item_name + _quantity = quantity + +func set_item_name(item_name: String) -> void: + _item_name = item_name + +func set_quantity(quantity: int) -> void: + _quantity = quantity + +func get_item_name() -> String: + return _item_name + +func get_quantity() -> int: + return _quantity + +func load_data(data: Dictionary) -> void: + _item_name = data["item_name"] + _quantity = data["quantity"] + +func save_data() -> Dictionary: + return { "item_name": _item_name, "quantity": _quantity } + +func _to_string() -> String: + return "" diff --git a/pandora/extensions/dependency_property/model/dependency_property.gd.uid b/pandora/extensions/dependency_property/model/dependency_property.gd.uid new file mode 100644 index 00000000..aa885aad --- /dev/null +++ b/pandora/extensions/dependency_property/model/dependency_property.gd.uid @@ -0,0 +1 @@ +uid://dooakeh83r2ai diff --git a/pandora/extensions/dependency_property/model/types/dependency_property.gd b/pandora/extensions/dependency_property/model/types/dependency_property.gd new file mode 100644 index 00000000..713b24ac --- /dev/null +++ b/pandora/extensions/dependency_property/model/types/dependency_property.gd @@ -0,0 +1,27 @@ +extends PandoraPropertyType + +const SETTING_CATEGORY_FILTER = "Category Filter" +const SETTING_MIN_VALUE = "Min Quantity" +const SETTING_MAX_VALUE = "Max Quantity" +const SETTINGS = { + SETTING_MIN_VALUE: {"type": "int", "value": -9999999999}, + SETTING_MAX_VALUE: {"type": "int", "value": 9999999999} +} + +func _init() -> void: + super("dependency_property", SETTINGS, null, "res://pandora/extensions/test_property/icons/icon.png") + +func parse_value(variant: Variant, _s: Dictionary = {}) -> Variant: + if variant is Dictionary: + var item_name = variant["item_name"] + var quantity = variant["quantity"] + return PandoraTestProperty.new(item_name, quantity) + return variant + +func write_value(variant: Variant) -> Variant: + if variant is PandoraTestProperty: + return variant.save_data() + return variant + +func is_valid(variant: Variant) -> bool: + return variant is PandoraDependencyProperty diff --git a/pandora/extensions/dependency_property/model/types/dependency_property.gd.uid b/pandora/extensions/dependency_property/model/types/dependency_property.gd.uid new file mode 100644 index 00000000..2968dcdf --- /dev/null +++ b/pandora/extensions/dependency_property/model/types/dependency_property.gd.uid @@ -0,0 +1 @@ +uid://bv6atsu450c0j diff --git a/pandora/extensions/dependency_property/property_button/property_button.tscn b/pandora/extensions/dependency_property/property_button/property_button.tscn new file mode 100644 index 00000000..20a33f67 --- /dev/null +++ b/pandora/extensions/dependency_property/property_button/property_button.tscn @@ -0,0 +1,12 @@ +[gd_scene load_steps=4 format=3 uid="uid://bm08cj4lcvudv"] + +[ext_resource type="Texture2D" uid="uid://cvktrbp2le3eb" path="res://addons/gdUnit4/src/update/assets/dot1.png" id="1_2jhnd"] +[ext_resource type="Script" uid="uid://crr6rlkqtg6we" path="res://addons/pandora/ui/components/property_bar/property_button.gd" id="2_nq2f7"] +[ext_resource type="PackedScene" uid="uid://byn750powq8to" path="res://pandora/extensions/test_property/ui_component/test_property.tscn" id="3_ovgkr"] + +[node name="AddDependencyPropertyButton" type="Button"] +tooltip_text = "Dependency property" +icon = ExtResource("1_2jhnd") +script = ExtResource("2_nq2f7") +scene = ExtResource("3_ovgkr") +metadata/_custom_type_script = "uid://crr6rlkqtg6we" diff --git a/pandora/extensions/dependency_property/ui_component/dependency_property.gd b/pandora/extensions/dependency_property/ui_component/dependency_property.gd new file mode 100644 index 00000000..18e2a6b6 --- /dev/null +++ b/pandora/extensions/dependency_property/ui_component/dependency_property.gd @@ -0,0 +1,44 @@ +@tool +extends PandoraPropertyControl + +const DependencyPropertyType = preload("../model/types/dependency_property.gd") + +@onready var text_edit: TextEdit = $HBoxContainer/TextEdit +@onready var spin_box: SpinBox = $HBoxContainer/SpinBox +var current_property : PandoraDependencyProperty = PandoraDependencyProperty.new("", 0) + +func _ready() -> void: + refresh() + + if _property != null: + _property.setting_changed.connect(_setting_changed) + _property.setting_cleared.connect(_setting_changed) + text_edit.focus_exited.connect(func(): unfocused.emit()) + text_edit.focus_entered.connect(func(): focused.emit()) + text_edit.text_changed.connect( + func(): + current_property.set_item_name(text_edit.text) + _property.set_default_value(current_property) + property_value_changed.emit(current_property)) + + spin_box.focus_entered.connect(func(): focused.emit()) + spin_box.focus_exited.connect(func(): unfocused.emit()) + spin_box.value_changed.connect( + func(value: float): + current_property.set_quantity(int(value)) + _property.set_default_value(current_property) + property_value_changed.emit(current_property)) + +func refresh() -> void: + if _property != null: + spin_box.min_value = _property.get_setting(DependencyPropertyType.SETTING_MIN_VALUE) as int + spin_box.max_value = _property.get_setting(DependencyPropertyType.SETTING_MAX_VALUE) as int + if _property.get_default_value() != null: + current_property = _property.get_default_value() as PandoraDependencyProperty + text_edit.text = current_property.get_item_name() + text_edit.set_caret_column(text_edit.text.length()) + spin_box.value = current_property.get_quantity() + +func _setting_changed(key:String) -> void: + if key == DependencyPropertyType.SETTING_MIN_VALUE || key == DependencyPropertyType.SETTING_MAX_VALUE: + refresh() diff --git a/pandora/extensions/dependency_property/ui_component/dependency_property.gd.uid b/pandora/extensions/dependency_property/ui_component/dependency_property.gd.uid new file mode 100644 index 00000000..d0ffbce3 --- /dev/null +++ b/pandora/extensions/dependency_property/ui_component/dependency_property.gd.uid @@ -0,0 +1 @@ +uid://cmdhm8gi3l3xv diff --git a/pandora/extensions/dependency_property/ui_component/dependency_property.tscn b/pandora/extensions/dependency_property/ui_component/dependency_property.tscn new file mode 100644 index 00000000..faa024fc --- /dev/null +++ b/pandora/extensions/dependency_property/ui_component/dependency_property.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=2 format=3 uid="uid://sqgw6p1rliv8"] + +[ext_resource type="Script" uid="uid://cmdhm8gi3l3xv" path="res://pandora/extensions/dependency_property/ui_component/dependency_property.gd" id="1_ovono"] + +[node name="DependencyProperty" type="MarginContainer"] +script = ExtResource("1_ovono") +type = "dependency_property" +metadata/_custom_type_script = "uid://bvl8qiojdoihh" + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="TextEdit" type="TextEdit" parent="HBoxContainer"] +custom_minimum_size = Vector2(0, 31) +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "Test Name" + +[node name="SpinBox" type="SpinBox" parent="HBoxContainer"] +layout_mode = 2 +focus_mode = 1 +max_value = 99999.0 +rounded = true +select_all_on_focus = true diff --git a/pandora/extensions/test_property/model/test_property.gd b/pandora/extensions/test_property/model/test_property.gd index b7284e76..aa662d64 100644 --- a/pandora/extensions/test_property/model/test_property.gd +++ b/pandora/extensions/test_property/model/test_property.gd @@ -20,11 +20,20 @@ func get_quantity() -> int: return _quantity func load_data(data: Dictionary) -> void: - _item_name = data["item_name"] - _quantity = data["quantity"] - -func save_data() -> Dictionary: - return { "item_name": _item_name, "quantity": _quantity } + if data.has("item_name"): + _item_name = data["item_name"] + if data.has("quantity"): + _quantity = data["quantity"] + +func save_data(fields_settings: Array[Dictionary]) -> Dictionary: + var result := {} + var itemNameIdx := fields_settings.find(func(dic: Dictionary): return dic["name"] == "Item Name") + var quantityIdx := fields_settings.find(func(dic: Dictionary): return dic["name"] == "Quantity") + if fields_settings[itemNameIdx]["enabled"]: + result["item_name"] = _item_name + if fields_settings[quantityIdx]["enabled"]: + result["quantity"] = _quantity + return result func _to_string() -> String: - return "" + return "" diff --git a/pandora/extensions/test_property/model/types/test_property.gd b/pandora/extensions/test_property/model/types/test_property.gd index d5b9d93e..ac45079c 100644 --- a/pandora/extensions/test_property/model/types/test_property.gd +++ b/pandora/extensions/test_property/model/types/test_property.gd @@ -1,26 +1,47 @@ extends PandoraPropertyType -const SETTING_CATEGORY_FILTER = "Category Filter" const SETTING_MIN_VALUE = "Min Quantity" const SETTING_MAX_VALUE = "Max Quantity" -const SETTINGS = { +var SETTINGS = { SETTING_MIN_VALUE: {"type": "int", "value": -9999999999}, SETTING_MAX_VALUE: {"type": "int", "value": 9999999999} } func _init() -> void: super("test_property", SETTINGS, null, "res://pandora/extensions/test_property/icons/icon.png") + Pandora.update_fields_settings.connect(_on_update_fields_settings) + _update_fields_settings() + +func _on_update_fields_settings(type: String) -> void: + if _type_name == type: + _update_fields_settings() + +func _update_fields_settings() -> void: + var extension_configuration := PandoraSettings.find_extension_configuration_property("test_property") + var fields_settings := extension_configuration["fields"] as Array + for field_settings in fields_settings: + if field_settings["name"] == "Quantity": + if field_settings["enabled"] == false: + SETTINGS.erase(SETTING_MAX_VALUE) + SETTINGS.erase(SETTING_MIN_VALUE) + else: + if !SETTINGS.has(SETTING_MAX_VALUE) or !SETTINGS.has(SETTING_MIN_VALUE): + SETTINGS[SETTING_MAX_VALUE] = {"type": "int", "value": field_settings["settings"]["max_value"]} + SETTINGS[SETTING_MIN_VALUE] = {"type": "int", "value": field_settings["settings"]["min_value"]} + _settings = SETTINGS func parse_value(variant: Variant, _s: Dictionary = {}) -> Variant: if variant is Dictionary: - var item_name = variant["item_name"] - var quantity = variant["quantity"] + var item_name = "" if not variant.has("item_name") else variant["item_name"] + var quantity = 0 if not variant.has("quantity") else variant["quantity"] return PandoraTestProperty.new(item_name, quantity) return variant func write_value(variant: Variant) -> Variant: if variant is PandoraTestProperty: - return variant.save_data() + var extension_configuration := PandoraSettings.find_extension_configuration_property("test_property") + var fields_settings := extension_configuration["fields"] as Array + return variant.save_data(fields_settings) return variant func is_valid(variant: Variant) -> bool: diff --git a/pandora/extensions/test_property/ui_component/test_property.gd b/pandora/extensions/test_property/ui_component/test_property.gd index 023e371c..f6223be8 100644 --- a/pandora/extensions/test_property/ui_component/test_property.gd +++ b/pandora/extensions/test_property/ui_component/test_property.gd @@ -1,7 +1,7 @@ @tool extends PandoraPropertyControl -const ItemRecipeType = preload("../model/types/test_property.gd") +const TestPropertyType = preload("../model/types/test_property.gd") @onready var text_edit: TextEdit = $HBoxContainer/TextEdit @onready var spin_box: SpinBox = $HBoxContainer/SpinBox @@ -9,6 +9,7 @@ var current_property : PandoraTestProperty = PandoraTestProperty.new("", 0) func _ready() -> void: refresh() + Pandora.update_fields_settings.connect(_on_update_fields_settings) if _property != null: _property.setting_changed.connect(_setting_changed) @@ -30,9 +31,17 @@ func _ready() -> void: property_value_changed.emit(current_property)) func refresh() -> void: + for field_settings in _fields_settings: + if field_settings["name"] == "Quantity": + spin_box.visible = field_settings["enabled"] + elif field_settings["name"] == "Item Name": + spin_box.visible = field_settings["enabled"] + if _property != null: - spin_box.min_value = _property.get_setting(ItemRecipeType.SETTING_MIN_VALUE) as int - spin_box.max_value = _property.get_setting(ItemRecipeType.SETTING_MAX_VALUE) as int + if _property.get_setting(TestPropertyType.SETTING_MIN_VALUE): + spin_box.min_value = _property.get_setting(TestPropertyType.SETTING_MIN_VALUE) as int + if _property.get_setting(TestPropertyType.SETTING_MAX_VALUE): + spin_box.max_value = _property.get_setting(TestPropertyType.SETTING_MAX_VALUE) as int if _property.get_default_value() != null: current_property = _property.get_default_value() as PandoraTestProperty text_edit.text = current_property.get_item_name() @@ -40,5 +49,9 @@ func refresh() -> void: spin_box.value = current_property.get_quantity() func _setting_changed(key:String) -> void: - if key == ItemRecipeType.SETTING_MIN_VALUE || key == ItemRecipeType.SETTING_MAX_VALUE: + if key == TestPropertyType.SETTING_MIN_VALUE || key == TestPropertyType.SETTING_MAX_VALUE: + refresh() + +func _on_update_fields_settings(property_type: String) -> void: + if property_type == type: refresh() diff --git a/pandora/extensions/test_property/ui_component/test_property.tscn b/pandora/extensions/test_property/ui_component/test_property.tscn index 6aeb3adf..d7c7e9e5 100644 --- a/pandora/extensions/test_property/ui_component/test_property.tscn +++ b/pandora/extensions/test_property/ui_component/test_property.tscn @@ -11,6 +11,7 @@ metadata/_custom_type_script = "uid://bvl8qiojdoihh" layout_mode = 2 [node name="TextEdit" type="TextEdit" parent="HBoxContainer"] +custom_minimum_size = Vector2(0, 31) layout_mode = 2 size_flags_horizontal = 3 placeholder_text = "Item Name"