8const DEFAULT_DIRECTIONS := [
"down",
"left",
"right",
"up"]
12func direction_name(value, fallback:String =
"down") -> String:
14 var text = str(value).to_lower()
15 return text
if DEFAULT_DIRECTIONS.has(text)
else fallback
16 var vector = _vector_from_any(value)
17 if vector.length() <= 0.001:
19 if abs(vector.x) > abs(vector.y):
20 return "right" if vector.x > 0.0
else "left"
21 return "down" if vector.y > 0.0
else "up"
25func get_state_key(entity:Dictionary, options:Dictionary = {}) -> String:
26 var base_state = str(options.get(
"state", entity.get(
"state",
"idle"))).strip_edges().to_lower()
29 var fallback_direction = str(options.get(
"default_direction",
"down"))
30 var direction_value = entity.get(
"facing", entity.get(
"velocity", [0, 0]))
31 if options.has(
"direction"):
32 direction_value = options.get(
"direction")
33 var direction = direction_name(direction_value, fallback_direction)
34 if not bool(options.get(
"directional", true)):
36 return "%s_%s" % [base_state, direction]
40func get_sprite_candidates(entity:Dictionary, options:Dictionary = {}) -> Array:
42 var explicit = str(entity.get(
"sprite_id",
"")).strip_edges()
44 candidates.append(explicit)
45 var base_id = str(options.get(
"base_id", entity.get(
"animation_id", entity.get(
"archetype", entity.get(
"id", entity.get(
"kind",
"entity")))))).strip_edges()
46 var kind = str(entity.get(
"kind", entity.get(
"type",
"entity"))).strip_edges()
47 var state_key = get_state_key(entity, options)
49 candidates.append(
"%s_%s" % [base_id, state_key])
50 var base_state = state_key.split(
"_")[0]
51 candidates.append(
"%s_%s" % [base_id, base_state])
53 candidates.append(
"%s_%s" % [kind, state_key])
54 var kind_base_state = state_key.split(
"_")[0]
55 candidates.append(
"%s_%s" % [kind, kind_base_state])
56 return _unique_non_empty(candidates)
60func required_sprite_ids(base_id:String, states:Array = [], directions:Array = DEFAULT_DIRECTIONS) -> Array:
62 var state_list = states
if not states.is_empty()
else [
"idle",
"move",
"attack",
"hurt",
"death"]
63 for state
in state_list:
64 var state_name = str(state)
67 if state_name ==
"death" or state_name ==
"hurt":
68 ids.append(
"%s_%s" % [base_id, state_name])
70 for direction
in directions:
71 ids.append(
"%s_%s_%s" % [base_id, state_name, str(direction)])
72 return _unique_non_empty(ids)
75func _unique_non_empty(values:Array) -> Array:
78 var text = str(value).strip_edges()
79 if text !=
"" and not result.has(text):
84func _vector_from_any(value) -> Vector2:
88 return Vector2(float(value.x), float(value.y))
89 if value
is Array
and value.size() >= 2:
90 return Vector2(float(value[0]), float(value[1]))
91 if value
is Dictionary
and value.has(
"velocity"):
92 return _vector_from_any(value.get(
"velocity"))
93 if value
is Dictionary
and value.has(
"facing"):
94 return _vector_from_any(value.get(
"facing"))
95 if value
is Dictionary
and value.has(
"x")
and value.has(
"y"):
96 return Vector2(float(value.get(
"x", 0.0)), float(value.get(
"y", 0.0)))