From 1a9d9162930d1e22c102bca33b569586d00faa49 Mon Sep 17 00:00:00 2001 From: Steven Wroblewski Date: Fri, 8 May 2026 22:07:53 +0200 Subject: [PATCH] feat(character): add outfit layer API (set/clear/get_outfit per layer 1-3) --- scripts/characters/character.gd | 42 +++++++++++++++++++++++++++++++++ test/unit/test_character_v2.gd | 39 ++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/scripts/characters/character.gd b/scripts/characters/character.gd index 6a48972..4f53f4d 100644 --- a/scripts/characters/character.gd +++ b/scripts/characters/character.gd @@ -31,6 +31,7 @@ func _ready() -> void: drag.drag_released.connect(_on_drag_released) if data != null: _update_visual_state() + _refresh_outfit_layers() func set_state(new_state: CharacterData.State) -> void: @@ -54,6 +55,38 @@ func get_animation_state() -> String: return _current_anim +func set_outfit(layer: int, item_id: String, texture: Texture2D) -> void: + if layer < 1 or layer > 3: + return + if data != null: + data.outfit[layer - 1] = item_id + var layer_node: Sprite2D = get_node_or_null("OutfitLayer%d" % layer) as Sprite2D + if layer_node == null: + return + layer_node.texture = texture + layer_node.visible = not item_id.is_empty() + + +func clear_outfit(layer: int) -> String: + if layer < 1 or layer > 3: + return "" + var old_id: String = "" + if data != null: + old_id = data.outfit[layer - 1] + data.outfit[layer - 1] = "" + var layer_node: Sprite2D = get_node_or_null("OutfitLayer%d" % layer) as Sprite2D + if layer_node != null: + layer_node.texture = null + layer_node.visible = false + return old_id + + +func get_outfit(layer: int) -> String: + if data == null or layer < 1 or layer > 3: + return "" + return data.outfit[layer - 1] + + func _update_visual_state() -> void: if data == null: return @@ -83,3 +116,12 @@ func _on_drag_released(pos: Vector2) -> void: return GameState.set_character_position(character_id, global_position) character_placed.emit(self, global_position) + + +func _refresh_outfit_layers() -> void: + if data == null: + return + for i: int in range(3): + var layer_node: Sprite2D = get_node_or_null("OutfitLayer%d" % (i + 1)) as Sprite2D + if layer_node != null: + layer_node.visible = not data.outfit[i].is_empty() diff --git a/test/unit/test_character_v2.gd b/test/unit/test_character_v2.gd index 112fb68..f7002ec 100644 --- a/test/unit/test_character_v2.gd +++ b/test/unit/test_character_v2.gd @@ -73,3 +73,42 @@ func test_set_animation_state_happy() -> void: func test_set_animation_state_sleeping() -> void: _char.set_animation_state("sleeping") assert_eq(_char.get_animation_state(), "sleeping") + + +func test_get_outfit_returns_empty_for_all_layers_initially() -> void: + assert_eq(_char.get_outfit(1), "") + assert_eq(_char.get_outfit(2), "") + assert_eq(_char.get_outfit(3), "") + + +func test_set_outfit_stores_item_id() -> void: + _char.set_outfit(1, "white_coat", null) + assert_eq(_char.get_outfit(1), "white_coat") + + +func test_set_outfit_does_not_affect_other_layers() -> void: + _char.set_outfit(1, "white_coat", null) + assert_eq(_char.get_outfit(2), "") + assert_eq(_char.get_outfit(3), "") + + +func test_clear_outfit_returns_item_id() -> void: + _char.set_outfit(2, "cast_arm", null) + var returned: String = _char.clear_outfit(2) + assert_eq(returned, "cast_arm") + + +func test_clear_outfit_empties_layer() -> void: + _char.set_outfit(2, "cast_arm", null) + _char.clear_outfit(2) + assert_eq(_char.get_outfit(2), "") + + +func test_set_outfit_invalid_layer_zero_is_noop() -> void: + _char.set_outfit(0, "white_coat", null) + assert_eq(_char.get_outfit(1), "") + + +func test_set_outfit_invalid_layer_four_is_noop() -> void: + _char.set_outfit(4, "white_coat", null) + assert_eq(_char.get_outfit(3), "")