Rework player state system to use an event subscription system to avoid directly calling methods on individual state and having to worry about validity
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
[ext_resource type="PackedScene" uid="uid://ddgeo3vwebqeg" path="res://Entities/Map Objects/Mechanisms/shop_item.tscn" id="3_7ftpj"]
|
||||
[ext_resource type="Script" uid="uid://dkcsftcdqtmg" path="res://Maps/Connectors/Scripts/spawn_marker_connector.gd" id="3_t8w5b"]
|
||||
[ext_resource type="Texture2D" uid="uid://hop1gedjh8s4" path="res://Assets/Spritesheets/Player/icons_full_32.png" id="4_r8s0p"]
|
||||
[ext_resource type="PackedScene" uid="uid://6athlweutl2g" path="res://Entities/Characters/Player/player.tscn" id="5_6ky6i"]
|
||||
[ext_resource type="PackedScene" uid="uid://6athlweutl2g" path="res://Entities/Characters/Player/Individual Components/body.tscn" id="5_6ky6i"]
|
||||
[ext_resource type="Texture2D" uid="uid://crebnygky3qv0" path="res://Assets/Sprites/Black Square.png" id="6_kt7c3"]
|
||||
[ext_resource type="PackedScene" uid="uid://bbules4o3xayc" path="res://Entities/Map Objects/Loading Zone/loading_zone_transporter.tscn" id="6_t8w5b"]
|
||||
[ext_resource type="Texture2D" uid="uid://bf6llktwqhs8l" path="res://Assets/Sprites/Door Fade.png" id="7_7ftpj"]
|
||||
@@ -44,7 +44,7 @@ script = ExtResource("2_r8s0p")
|
||||
|
||||
[node name="Spawn Marker Connector" type="Node" parent="." unique_id=2053338893 node_paths=PackedStringArray("player", "markers")]
|
||||
script = ExtResource("3_t8w5b")
|
||||
player = NodePath("../Player")
|
||||
player = NodePath("../Player Body")
|
||||
markers = NodePath("../Spawn Markers")
|
||||
|
||||
[node name="Tilemap" type="Node2D" parent="." unique_id=81778152]
|
||||
@@ -115,7 +115,7 @@ destination_marker_name = "Shop Entrance"
|
||||
[node name="Shop Entrance" type="Marker2D" parent="Spawn Markers" unique_id=122141189]
|
||||
position = Vector2(223, 225)
|
||||
|
||||
[node name="Player" parent="." unique_id=1502234578 instance=ExtResource("5_6ky6i")]
|
||||
[node name="Player Body" parent="." unique_id=1502234578 instance=ExtResource("5_6ky6i")]
|
||||
position = Vector2(289, 174)
|
||||
|
||||
[node name="Camera2D" type="Camera2D" parent="." unique_id=1684491254]
|
||||
@@ -145,6 +145,3 @@ texture = ExtResource("6_kt7c3")
|
||||
position = Vector2(224, 232)
|
||||
scale = Vector2(2, 1)
|
||||
texture = ExtResource("7_7ftpj")
|
||||
|
||||
[connection signal="InteractScannerAreaEntered" from="Player" to="Shop Item Notification Connector" method="OnPlayerInteractScannerAreaEntered"]
|
||||
[connection signal="InteractScannerAreaExited" from="Player" to="Shop Item Notification Connector" method="OnPlayerInteractScannerAreaExited"]
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
extends Node
|
||||
class_name BenchInteractionConnector
|
||||
|
||||
# Signals
|
||||
signal SitOnBenchTriggered(position: Vector2, sitting_direction: Enums.Directions)
|
||||
|
||||
# Exports
|
||||
@export var player: PlayerCharacter
|
||||
|
||||
# Private Variables
|
||||
var _benches_in_range: Array[WoodenBench] = []
|
||||
|
||||
# Private Methods
|
||||
func _ready() -> void:
|
||||
player.interact_scanner.area_entered.connect(_on_interact_scanned)
|
||||
player.interact_scanner.area_exited.connect(_on_interact_unscanned)
|
||||
player.interact_scanner.InteractionActionTriggered.connect(_on_interact_triggered)
|
||||
|
||||
|
||||
func _on_interact_scanned(area: Area2D) -> void:
|
||||
var parent := area.get_parent()
|
||||
if parent == null or parent is not WoodenBench or _benches_in_range.has(parent):
|
||||
return
|
||||
_benches_in_range.append(parent)
|
||||
|
||||
|
||||
func _on_interact_unscanned(area: Area2D) -> void:
|
||||
var parent: Node = area.get_parent()
|
||||
if parent == null or parent is not WoodenBench or !_benches_in_range.has(parent):
|
||||
return
|
||||
_benches_in_range.erase(parent)
|
||||
|
||||
|
||||
func _on_interact_triggered() -> void:
|
||||
if _benches_in_range.is_empty():
|
||||
return
|
||||
|
||||
var bench := _benches_in_range[0]
|
||||
var sitting_spots_container := bench.get_node("Sitting Spots") as Node2D
|
||||
var sitting_spot_markers := sitting_spots_container.get_children()
|
||||
|
||||
var closest_marker: Marker2D
|
||||
var distance_to_player := 9999.0
|
||||
for node in sitting_spot_markers:
|
||||
var marker := node as Marker2D
|
||||
var distance := marker.global_position.distance_to(player.global_position)
|
||||
if distance < distance_to_player:
|
||||
closest_marker = marker
|
||||
distance_to_player = distance
|
||||
|
||||
if !closest_marker:
|
||||
return
|
||||
|
||||
player.SitOnFurnitureTriggered.emit(closest_marker.global_position, Enums.Directions.DOWN)
|
||||
#class_name BenchInteractionConnector
|
||||
#
|
||||
## Signals
|
||||
#signal SitOnBenchTriggered(position: Vector2, sitting_direction: Enums.Directions)
|
||||
#
|
||||
## Exports
|
||||
#@export var player: PlayerBody
|
||||
#
|
||||
## Private Variables
|
||||
#var _benches_in_range: Array[WoodenBench] = []
|
||||
#
|
||||
## Private Methods
|
||||
#func _ready() -> void:
|
||||
#player.interact_scanner.area_entered.connect(_on_interact_scanned)
|
||||
#player.interact_scanner.area_exited.connect(_on_interact_unscanned)
|
||||
#player.interact_scanner.InteractionActionTriggered.connect(_on_interact_triggered)
|
||||
#
|
||||
#
|
||||
#func _on_interact_scanned(area: Area2D) -> void:
|
||||
#var parent := area.get_parent()
|
||||
#if parent == null or parent is not WoodenBench or _benches_in_range.has(parent):
|
||||
#return
|
||||
#_benches_in_range.append(parent)
|
||||
#
|
||||
#
|
||||
#func _on_interact_unscanned(area: Area2D) -> void:
|
||||
#var parent: Node = area.get_parent()
|
||||
#if parent == null or parent is not WoodenBench or !_benches_in_range.has(parent):
|
||||
#return
|
||||
#_benches_in_range.erase(parent)
|
||||
#
|
||||
#
|
||||
#func _on_interact_triggered() -> void:
|
||||
#if _benches_in_range.is_empty():
|
||||
#return
|
||||
#
|
||||
#var bench := _benches_in_range[0]
|
||||
#var sitting_spots_container := bench.get_node("Sitting Spots") as Node2D
|
||||
#var sitting_spot_markers := sitting_spots_container.get_children()
|
||||
#
|
||||
#var closest_marker: Marker2D
|
||||
#var distance_to_player := 9999.0
|
||||
#for node in sitting_spot_markers:
|
||||
#var marker := node as Marker2D
|
||||
#var distance := marker.global_position.distance_to(player.global_position)
|
||||
#if distance < distance_to_player:
|
||||
#closest_marker = marker
|
||||
#distance_to_player = distance
|
||||
#
|
||||
#if !closest_marker:
|
||||
#return
|
||||
#
|
||||
#player.SitOnFurnitureTriggered.emit(closest_marker.global_position, Enums.Directions.DOWN)
|
||||
|
||||
@@ -4,73 +4,65 @@ extends Node
|
||||
signal OpeningOfOpenedChestAttempted
|
||||
|
||||
# Exports
|
||||
@export var player: PlayerCharacter
|
||||
@export var auto_connect_all_chests := true
|
||||
|
||||
# Private Variables
|
||||
var _chests_in_range: Array[BaseChest] = []
|
||||
|
||||
# Private Methods
|
||||
func _ready() -> void:
|
||||
player.interact_scanner.area_entered.connect(_on_interact_scanned)
|
||||
player.interact_scanner.area_exited.connect(_on_interact_unscanned)
|
||||
player.interact_scanner.InteractionActionTriggered.connect(_on_interact_triggered)
|
||||
|
||||
var chests := GroupUtils.GetAllTreasureChests()
|
||||
for chest in chests:
|
||||
chest.OpeningAnimationStarted.connect(_on_chest_opening_animation_started)
|
||||
|
||||
|
||||
func _on_chest_opening_animation_started() -> void:
|
||||
var player := GroupUtils.GetPlayer()
|
||||
var children := player.get_children()
|
||||
|
||||
player.QueueCutsceneState()
|
||||
|
||||
var camera_idx := children.find_custom(func(x): return x is Camera2D)
|
||||
if camera_idx == -1: return
|
||||
|
||||
# Zoom In
|
||||
var camera := children[camera_idx] as Camera2D
|
||||
var current_zoom := camera.zoom
|
||||
await get_tree().create_tween().tween_property(camera, "zoom", current_zoom + Vector2(2, 2), 0.5).finished
|
||||
|
||||
# Player the player's chest opening animation
|
||||
player.state_machine.QueueStateChange(PlayerStateMachine.States.PLAY_ANIMATION, { "animation_name": "opening-chest-down" })
|
||||
await player.state_machine.StateChanged
|
||||
var play_animation_state := player.state_machine.current_state as PlayerPlayAnimationState
|
||||
await play_animation_state.AnimationFinished
|
||||
player.state_machine.QueueStateChange(PlayerStateMachine.States.IDLE)
|
||||
|
||||
# Zoom back out
|
||||
await get_tree().create_tween().tween_property(camera, "zoom", current_zoom, 0.5).finished
|
||||
|
||||
|
||||
func _on_interact_scanned(area: Area2D) -> void:
|
||||
var chest = area.get_parent()
|
||||
if chest == null or chest is not BaseChest:
|
||||
return
|
||||
if _chests_in_range.has(chest):
|
||||
return
|
||||
_chests_in_range.append(chest)
|
||||
|
||||
|
||||
func _on_interact_unscanned(area: Area2D) -> void:
|
||||
var chest = area.get_parent()
|
||||
if chest == null or chest is not BaseChest:
|
||||
return
|
||||
if !_chests_in_range.has(chest):
|
||||
return
|
||||
_chests_in_range.erase(chest)
|
||||
|
||||
|
||||
func _on_interact_triggered() -> void:
|
||||
if _chests_in_range.is_empty():
|
||||
return
|
||||
|
||||
var chest := _chests_in_range[0]
|
||||
if !chest.is_open:
|
||||
chest.Open()
|
||||
else:
|
||||
chest.OpenAlreadyOpened()
|
||||
OpeningOfOpenedChestAttempted.emit()
|
||||
## Private Methods
|
||||
#func _ready() -> void:
|
||||
#var chests := GroupUtils.GetAllTreasureChests()
|
||||
#for chest in chests:
|
||||
#chest.OpeningAnimationStarted.connect(_on_chest_opening_animation_started)
|
||||
#
|
||||
#
|
||||
#func _on_chest_opening_animation_started() -> void:
|
||||
#player.QueueCutsceneState()
|
||||
#
|
||||
#var camera_idx := children.find_custom(func(x): return x is Camera2D)
|
||||
#if camera_idx == -1: return
|
||||
#
|
||||
## Zoom In
|
||||
#var camera := children[camera_idx] as Camera2D
|
||||
#var current_zoom := camera.zoom
|
||||
#await get_tree().create_tween().tween_property(camera, "zoom", current_zoom + Vector2(2, 2), 0.5).finished
|
||||
#
|
||||
## Player the player's chest opening animation
|
||||
#player.state_machine.QueueStateChange(PlayerStateMachine.States.PLAY_ANIMATION, { "animation_name": "opening-chest-down" })
|
||||
#await player.state_machine.StateChanged
|
||||
#var play_animation_state := player.state_machine.current_state as PlayerPlayAnimationState
|
||||
#await play_animation_state.AnimationFinished
|
||||
#player.state_machine.QueueStateChange(PlayerStateMachine.States.IDLE)
|
||||
#
|
||||
## Zoom back out
|
||||
#await get_tree().create_tween().tween_property(camera, "zoom", current_zoom, 0.5).finished
|
||||
#
|
||||
#
|
||||
#func _on_interact_scanned(area: Area2D) -> void:
|
||||
#var chest = area.get_parent()
|
||||
#if chest == null or chest is not BaseChest:
|
||||
#return
|
||||
#if _chests_in_range.has(chest):
|
||||
#return
|
||||
#_chests_in_range.append(chest)
|
||||
#
|
||||
#
|
||||
#func _on_interact_unscanned(area: Area2D) -> void:
|
||||
#var chest = area.get_parent()
|
||||
#if chest == null or chest is not BaseChest:
|
||||
#return
|
||||
#if !_chests_in_range.has(chest):
|
||||
#return
|
||||
#_chests_in_range.erase(chest)
|
||||
#
|
||||
#
|
||||
#func _on_interact_triggered() -> void:
|
||||
#if _chests_in_range.is_empty():
|
||||
#return
|
||||
#
|
||||
#var chest := _chests_in_range[0]
|
||||
#if !chest.is_open:
|
||||
#chest.Open()
|
||||
#else:
|
||||
#chest.OpenAlreadyOpened()
|
||||
#OpeningOfOpenedChestAttempted.emit()
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
extends Node
|
||||
|
||||
@export var player: PlayerCharacter
|
||||
|
||||
# Public Methods
|
||||
func OnPlayerAreaEntered(area: Area2D) -> void:
|
||||
pass
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
extends Node
|
||||
|
||||
# Exports
|
||||
@export var player: PlayerCharacter
|
||||
|
||||
# Private Variables
|
||||
var _zones_in_range: Array[InteractiveLoadingZone] = []
|
||||
|
||||
# Private Methods
|
||||
func _ready() -> void:
|
||||
player.interact_scanner.area_entered.connect(_on_interact_scanned)
|
||||
player.interact_scanner.area_exited.connect(_on_interact_unscanned)
|
||||
player.interact_scanner.InteractionActionTriggered.connect(_on_interact_triggered)
|
||||
|
||||
|
||||
func _on_interact_scanned(area: Area2D) -> void:
|
||||
if area is not InteractiveLoadingZone or _zones_in_range.has(area):
|
||||
return
|
||||
|
||||
_zones_in_range.append(area)
|
||||
|
||||
|
||||
func _on_interact_unscanned(area: Area2D) -> void:
|
||||
if area is not InteractiveLoadingZone or !_zones_in_range.has(area):
|
||||
return
|
||||
|
||||
_zones_in_range.erase(area)
|
||||
|
||||
|
||||
func _on_interact_triggered() -> void:
|
||||
if _zones_in_range.is_empty():
|
||||
return
|
||||
|
||||
var zone := _zones_in_range[0]
|
||||
zone.Activate()
|
||||
#
|
||||
## Exports
|
||||
#@export var player: PlayerBody
|
||||
#
|
||||
## Private Variables
|
||||
#var _zones_in_range: Array[InteractiveLoadingZone] = []
|
||||
#
|
||||
## Private Methods
|
||||
#func _ready() -> void:
|
||||
#player.interact_scanner.area_entered.connect(_on_interact_scanned)
|
||||
#player.interact_scanner.area_exited.connect(_on_interact_unscanned)
|
||||
#player.interact_scanner.InteractionActionTriggered.connect(_on_interact_triggered)
|
||||
#
|
||||
#
|
||||
#func _on_interact_scanned(area: Area2D) -> void:
|
||||
#if area is not InteractiveLoadingZone or _zones_in_range.has(area):
|
||||
#return
|
||||
#
|
||||
#_zones_in_range.append(area)
|
||||
#
|
||||
#
|
||||
#func _on_interact_unscanned(area: Area2D) -> void:
|
||||
#if area is not InteractiveLoadingZone or !_zones_in_range.has(area):
|
||||
#return
|
||||
#
|
||||
#_zones_in_range.erase(area)
|
||||
#
|
||||
#
|
||||
#func _on_interact_triggered() -> void:
|
||||
#if _zones_in_range.is_empty():
|
||||
#return
|
||||
#
|
||||
#var zone := _zones_in_range[0]
|
||||
#zone.Activate()
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
[ext_resource type="TileSet" uid="uid://df0lg5vkqwbbt" path="res://Resources/Tilesets/home_interior.tres" id="1_rf04x"]
|
||||
[ext_resource type="Script" uid="uid://dkcsftcdqtmg" path="res://Maps/Connectors/Scripts/spawn_marker_connector.gd" id="2_16uj4"]
|
||||
[ext_resource type="PackedScene" uid="uid://ca75b65eh7vv8" path="res://Entities/Map Objects/Loading Zone/collision_loading_zone.tscn" id="2_fdso5"]
|
||||
[ext_resource type="PackedScene" uid="uid://6athlweutl2g" path="res://Entities/Characters/Player/player.tscn" id="2_lky26"]
|
||||
[ext_resource type="PackedScene" uid="uid://bbules4o3xayc" path="res://Entities/Map Objects/Loading Zone/loading_zone_transporter.tscn" id="3_7kg22"]
|
||||
[ext_resource type="PackedScene" uid="uid://dl2jpjtbiju34" path="res://Maps/Connectors/chest_interaction_connector.tscn" id="3_ec540"]
|
||||
[ext_resource type="PackedScene" uid="uid://b7u4hlvuqiefn" path="res://Entities/Map Objects/Chests/Item Chests/item_chest_02 (Metal).tscn" id="4_a58cd"]
|
||||
[ext_resource type="PackedScene" uid="uid://b60nr4wfvijpf" path="res://Entities/Map Objects/Dialogue/dialogue_trigger.tscn" id="5_msu6a"]
|
||||
[ext_resource type="Texture2D" uid="uid://bm5ewxv51potl" path="res://Assets/Spritesheets/NPCs/Miner_Mike.png" id="6_x3y8m"]
|
||||
[ext_resource type="Texture2D" uid="uid://bqvnkdyhfa1yq" path="res://Maps/Forest Dungeon Entrance/Interiors/Home_01_Overlay_01.png" id="11_6xfm6"]
|
||||
[ext_resource type="PackedScene" uid="uid://nbkisxm2oekn" path="res://Entities/Characters/Utility/Components/movement_component.tscn" id="11_fqvwb"]
|
||||
[ext_resource type="PackedScene" uid="uid://c65cfm3t0obwq" path="res://Entities/Characters/Player/player_map_entity.tscn" id="11_s4nwa"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_7kg22"]
|
||||
size = Vector2(32, 8)
|
||||
@@ -82,11 +81,11 @@ script = ExtResource("1_18bbf")
|
||||
|
||||
[node name="Spawn Marker Connector" type="Node" parent="Connectors" unique_id=296643918 node_paths=PackedStringArray("player", "markers")]
|
||||
script = ExtResource("2_16uj4")
|
||||
player = NodePath("../../Player")
|
||||
player = NodePath("")
|
||||
markers = NodePath("../../Spawn Markers")
|
||||
|
||||
[node name="Chest Interaction Connector" parent="Connectors" unique_id=625804018 node_paths=PackedStringArray("player") instance=ExtResource("3_ec540")]
|
||||
player = NodePath("../../Player")
|
||||
player = NodePath("")
|
||||
|
||||
[node name="Tilemap" type="Node2D" parent="." unique_id=894627186]
|
||||
y_sort_enabled = true
|
||||
@@ -155,15 +154,13 @@ position = Vector2(-0.5, -4)
|
||||
shape = SubResource("RectangleShape2D_6xfm6")
|
||||
debug_color = Color(0.7930861, 0.42714188, 7.70092e-07, 0.41960785)
|
||||
|
||||
[node name="Player Map Entity" parent="." unique_id=469362016 instance=ExtResource("11_s4nwa")]
|
||||
position = Vector2(176, 133)
|
||||
|
||||
[node name="Camera2D" type="Camera2D" parent="." unique_id=2134984506]
|
||||
position = Vector2(127, 110)
|
||||
zoom = Vector2(3, 3)
|
||||
|
||||
[node name="Player" parent="." unique_id=1502234578 instance=ExtResource("2_lky26")]
|
||||
position = Vector2(108, 139)
|
||||
|
||||
[node name="Movement Component" parent="Player" unique_id=737644583 instance=ExtResource("11_fqvwb")]
|
||||
|
||||
[node name="Overlay" type="Sprite2D" parent="." unique_id=455840170]
|
||||
position = Vector2(124, 217)
|
||||
scale = Vector2(0.25, 0.25)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[ext_resource type="PackedScene" uid="uid://303hbhqetdhy" path="res://Maps/Connectors/arrow_spawner.tscn" id="2_jtncl"]
|
||||
[ext_resource type="PackedScene" uid="uid://divmfeqf10ri1" path="res://Maps/Connectors/bench_interaction_connector.tscn" id="3_x6da4"]
|
||||
[ext_resource type="Script" uid="uid://kfupww4frb1r" path="res://Maps/Connectors/Scripts/camera_limit_connector.gd" id="3_ycf72"]
|
||||
[ext_resource type="PackedScene" uid="uid://6athlweutl2g" path="res://Entities/Characters/Player/player.tscn" id="4_4igim"]
|
||||
[ext_resource type="PackedScene" uid="uid://6athlweutl2g" path="res://Entities/Characters/Player/Individual Components/body.tscn" id="4_4igim"]
|
||||
[ext_resource type="PackedScene" uid="uid://b03s7fw8bxdxs" path="res://Maps/Connectors/interactive_loading_zone_connector.tscn" id="4_4lnhp"]
|
||||
[ext_resource type="PackedScene" uid="uid://byp273amg5ji8" path="res://Entities/Map Objects/Chests/Item Chests/item_chest_01 (Wooden).tscn" id="5_bnsbe"]
|
||||
[ext_resource type="Texture2D" uid="uid://bf6llktwqhs8l" path="res://Assets/Sprites/Door Fade.png" id="5_jett5"]
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
[ext_resource type="Script" uid="uid://qv5i4xr6pldc" path="res://Maps/Live Menus/Scripts/title_screen.gd" id="1_q1wq0"]
|
||||
[ext_resource type="TileSet" uid="uid://cds2lapr3niap" path="res://Resources/Tilesets/forest_exterior.tres" id="1_x5wur"]
|
||||
[ext_resource type="PackedScene" uid="uid://bjufxlsrlcuas" path="res://Entities/Buildings/home_01.tscn" id="2_x4fat"]
|
||||
[ext_resource type="PackedScene" uid="uid://6athlweutl2g" path="res://Entities/Characters/Player/player.tscn" id="3_kqssl"]
|
||||
[ext_resource type="PackedScene" uid="uid://be6xfndyj4ckx" path="res://Entities/Map Objects/Trees/tree_02.tscn" id="4_gs8fo"]
|
||||
[ext_resource type="PackedScene" uid="uid://bcx1d8kvp7o0h" path="res://Entities/Map Objects/Trees/tree_03.tscn" id="5_hgldw"]
|
||||
[ext_resource type="PackedScene" uid="uid://dl4bhu5o71rdv" path="res://Entities/Characters/Player/decorative_player_map_entity.tscn" id="6_gs8fo"]
|
||||
|
||||
[node name="TitleScreen" type="Node2D" unique_id=791312405]
|
||||
y_sort_enabled = true
|
||||
@@ -61,8 +61,8 @@ position = Vector2(773, 425)
|
||||
[node name="Tree 03 - 2" parent="Entities/Map Objects/Trees" unique_id=1648360632 instance=ExtResource("5_hgldw")]
|
||||
position = Vector2(427, 307)
|
||||
|
||||
[node name="Player" parent="." unique_id=1502234578 instance=ExtResource("3_kqssl")]
|
||||
position = Vector2(470, 358)
|
||||
[node name="Decorative Player Map Entity" parent="Entities" unique_id=2077444123 instance=ExtResource("6_gs8fo")]
|
||||
position = Vector2(488, 375)
|
||||
|
||||
[node name="UI" type="CanvasLayer" parent="." unique_id=2020053057]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user