WIP checkpoint: Implement avatar loader and customization UI in Godot

This commit is contained in:
2026-08-20 22:30:31 +00:00
parent 1be947f9ef
commit bfcbd0486f
+47 -9
View File
@@ -28,20 +28,20 @@ var skin_tone: Color = Color.TRANSPARENT
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Inner class: SlotItem # Inner classes
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
## Represents a single equipped slot item in a loadout. ## Represents a single equipped item in a slot.
## Used by AvatarVisualizer to access slot data. ## Used by AvatarVisualizer to iterate over equipped items.
class SlotItem: class SlotItem:
## The asset ID of the equipped item. ## The slot this item belongs to.
var asset_id: String = "" var slot_id: String
## The slot key this item belongs to. ## The catalog asset ID of the equipped item.
var slot_key: String = "" var asset_id: String
func _init(p_asset_id: String = "", p_slot_key: String = "") -> void: func _init(p_slot_id: String, p_asset_id: String) -> void:
slot_id = p_slot_id
asset_id = p_asset_id asset_id = p_asset_id
slot_key = p_slot_key
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -52,6 +52,10 @@ func _init() -> void:
validation_errors = [] validation_errors = []
# ---------------------------------------------------------------------------
# Serialization
# ---------------------------------------------------------------------------
## Create a loadout from a JSON string. ## Create a loadout from a JSON string.
static func from_json(json_string: String) -> AvatarLoadout: static func from_json(json_string: String) -> AvatarLoadout:
var loadout := AvatarLoadout.new() var loadout := AvatarLoadout.new()
@@ -119,6 +123,10 @@ func to_json() -> String:
return JSON.stringify(data, " ") return JSON.stringify(data, " ")
# ---------------------------------------------------------------------------
# Validation
# ---------------------------------------------------------------------------
## Validate this loadout against the slot registry. ## Validate this loadout against the slot registry.
## Returns true if valid; populates validation_errors if not. ## Returns true if valid; populates validation_errors if not.
func validate() -> bool: func validate() -> bool:
@@ -182,6 +190,10 @@ func is_valid() -> bool:
return validate() return validate()
# ---------------------------------------------------------------------------
# Accessors
# ---------------------------------------------------------------------------
## Check if a specific slot is equipped with a non-null item. ## Check if a specific slot is equipped with a non-null item.
func is_equipped(slot_id: String) -> bool: func is_equipped(slot_id: String) -> bool:
if not AvatarSlotRegistry.has_slot(slot_id): if not AvatarSlotRegistry.has_slot(slot_id):
@@ -254,6 +266,32 @@ func remove_accessory(asset_id: String) -> bool:
return false return false
## Iterate over equipped items as SlotItem objects.
## Returns an array of SlotItem for each equipped slot.
func get_equipped_items() -> Array[SlotItem]:
var items: Array[SlotItem] = []
for slot_id in AvatarSlotRegistry.SLOT_IDS:
var value = slots.get(slot_id)
if value == null:
continue
if typeof(value) == TYPE_STRING:
var asset_id = value as String
if not asset_id.is_empty():
items.append(SlotItem.new(slot_id, asset_id))
elif typeof(value) == TYPE_ARRAY:
for item_id in value:
if item_id is String and not item_id.is_empty():
items.append(SlotItem.new(slot_id, item_id))
return items
# ---------------------------------------------------------------------------
# Hashing
# ---------------------------------------------------------------------------
## Compute a hash of this loadout for change detection. ## Compute a hash of this loadout for change detection.
## Mirrors the server's loadout_hash concept. ## Mirrors the server's loadout_hash concept.
func compute_hash() -> int: func compute_hash() -> int: