Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions addons/pandora/api.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
138 changes: 138 additions & 0 deletions addons/pandora/icons/ExtensionsSettings.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 43 additions & 0 deletions addons/pandora/icons/ExtensionsSettings.svg.import
Original file line number Diff line number Diff line change
@@ -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
10 changes: 9 additions & 1 deletion addons/pandora/model/entity.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
6 changes: 5 additions & 1 deletion addons/pandora/model/property.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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


Expand Down
16 changes: 14 additions & 2 deletions addons/pandora/model/types/resource.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 6 additions & 1 deletion addons/pandora/plugin.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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"):
Expand Down
53 changes: 53 additions & 0 deletions addons/pandora/settings/pandora_settings.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
22 changes: 21 additions & 1 deletion addons/pandora/ui/components/properties/property_control.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading