Skip to content

Commit

Permalink
feat: validates for multiple start locations set in an ESCRoom and up…
Browse files Browse the repository at this point in the history
…dates scene tree with configuration warnings next to the offending ESCLocation nodes
  • Loading branch information
BHSDuncan authored and balloonpopper committed Mar 12, 2023
1 parent 14e5625 commit 1f16421
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 9 deletions.
51 changes: 44 additions & 7 deletions addons/escoria-core/game/core-scripts/esc_location.gd
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,23 @@
# automatically use an `ESCLocation` that is a child of the destination node.
# Commands like `turn_to`--which are not movement-based--will ignore child
# `ESCLocation`s and refer to the parent node.
tool
extends Position2D
class_name ESCLocation, "res://addons/escoria-core/design/esc_location.svg"


signal is_start_location_set


const MULTIPLE_START_LOCATIONS_WARNING = \
"Only 1 ESCLocation should have is_start_location set to true in an ESCRoom"


# The global ID of this item
export(String) var global_id

# If true, this ESCLocation is considered as a player start location
export(bool) var is_start_location = false
export(bool) var is_start_location = false setget set_is_start_location

# If true, player orients towards 'interaction_direction' as
# player character arrives.
Expand All @@ -22,6 +30,9 @@ export(bool) var player_orients_on_arrival = true
export(int) var interaction_direction


var _multiple_start_locations_exist: bool = false setget set_multiple_locations_exist


# Used by "is" keyword to check whether a node's class_name
# is the same as p_classname.
#
Expand All @@ -34,10 +45,36 @@ func is_class(p_classname: String) -> bool:

# Ready function
func _ready():
if not self.global_id.empty():
escoria.object_manager.register_object(
ESCObject.new(
self.global_id,
self
if not Engine.is_editor_hint():
if not self.global_id.empty():
escoria.object_manager.register_object(
ESCObject.new(
self.global_id,
self
)
)
)


func _exit_tree():
if Engine.is_editor_hint():
if is_start_location:
emit_signal("is_start_location_set", self)


func _get_configuration_warning():
if _multiple_start_locations_exist:
return MULTIPLE_START_LOCATIONS_WARNING

return ""


func set_multiple_locations_exist(value: bool) -> void:
_multiple_start_locations_exist = value
update_configuration_warning()


func set_is_start_location(value: bool) -> void:
is_start_location = value

if Engine.is_editor_hint() and is_instance_valid(get_owner()):
emit_signal("is_start_location_set")
58 changes: 56 additions & 2 deletions addons/escoria-core/game/core-scripts/esc_room.gd
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,12 @@ func _ready():
) != self.filename:
is_run_directly = true

if not Engine.is_editor_hint():
escoria.room_manager.init_room(self)
if Engine.is_editor_hint():
_connect_location_nodes()
_validate_start_locations()
return

escoria.room_manager.init_room(self)


# Draw the camera limits visualization if enabled
Expand Down Expand Up @@ -97,6 +101,56 @@ func _draw():
camera_limits[i].position.y + 30), str(i), camera_limits_colors[i])


# Listen for any signals from ESCLocation indicating that the is_start_location attribute
# has been set/unset in order to update start location validation.
func _connect_location_nodes() -> void:
_connect_location_nodes_in_tree(self)


func _connect_location_nodes_in_tree(node: Node):
for n in node.get_children():
if n is ESCLocation:
if not n.is_connected("is_start_location_set", self, "_validate_start_locations"):
n.connect("is_start_location_set", self, "_validate_start_locations")

if n.get_child_count() > 0:
_connect_location_nodes_in_tree(n)


# Validate that we only have one start location for this scene. If we don't, call it out in the
# scene tree via configuration warnings.
#
# We may have to ignore a node if it's being removed/deleted from the scene tree.
func _validate_start_locations(to_ignore: ESCLocation = null):
var esc_locations: Array = _find_esc_locations(self)
var num_start_locations: int = 0

for n in esc_locations:
if n == to_ignore:
continue

num_start_locations += 1 if n.is_start_location else 0

for n in esc_locations:
if n == to_ignore:
continue

n.set_multiple_locations_exist(n.is_start_location and num_start_locations > 1)


func _find_esc_locations(node: Node) -> Array:
var esc_locations: Array = []

for n in node.get_children():
if n is ESCLocation:
esc_locations.append(n)

if n.get_child_count() > 0:
esc_locations.append_array(_find_esc_locations(n))

return esc_locations


# Set the camera limits
#
# #### Parameters
Expand Down

0 comments on commit 1f16421

Please sign in to comment.