关卡管理器组件完成
This commit is contained in:
parent
bc848b8526
commit
46f69e2336
|
|
@ -1,21 +1,3 @@
|
||||||
extends Node2D
|
extends Node2D
|
||||||
|
|
||||||
@onready var act_manager: ActManager = $ReedScene/ActManager
|
|
||||||
|
|
||||||
var s := 1
|
var s := 1
|
||||||
|
|
||||||
func _unhandled_input(event: InputEvent) -> void:
|
|
||||||
if act_manager == null:
|
|
||||||
return
|
|
||||||
|
|
||||||
if event.is_action_pressed("ui_right"):
|
|
||||||
s = clampi(s+1,0,2)
|
|
||||||
act_manager.switch_act_with_id(s)
|
|
||||||
|
|
||||||
elif event.is_action_pressed("ui_left"):
|
|
||||||
s = clampi(s-1,0,2)
|
|
||||||
act_manager.switch_act_with_id(s)
|
|
||||||
elif event.is_action_pressed("ui_up"):
|
|
||||||
act_manager.switch_act_with_id(3)
|
|
||||||
elif event.is_action_pressed("ui_down"):
|
|
||||||
act_manager.switch_act_with_id(4)
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
[gd_scene load_steps=4 format=4 uid="uid://3vc8ojbiyy5w"]
|
[gd_scene load_steps=5 format=4 uid="uid://3vc8ojbiyy5w"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" uid="uid://gwhff4qaouxy" path="res://_player/Avatar.tscn" id="1_fdx6o"]
|
[ext_resource type="PackedScene" uid="uid://gwhff4qaouxy" path="res://_player/Avatar.tscn" id="1_fdx6o"]
|
||||||
[ext_resource type="PackedScene" uid="uid://1l06de041i40" path="res://_levels/l_level_1.tscn" id="1_pvnxo"]
|
[ext_resource type="PackedScene" uid="uid://1l06de041i40" path="res://_levels/l_level_1.tscn" id="1_pvnxo"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cvqehvdjpoar4" path="res://_player/player_controller.tscn" id="2_j2xwq"]
|
[ext_resource type="PackedScene" uid="uid://cvqehvdjpoar4" path="res://_player/player_controller.tscn" id="2_j2xwq"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://c3mievyfhx6ni" path="res://_props/coin/coin.tscn" id="4_j2xwq"]
|
||||||
|
|
||||||
[node name="Game" type="Node2D"]
|
[node name="Game" type="Node2D"]
|
||||||
|
|
||||||
|
|
@ -13,5 +14,14 @@ tile_map_data = PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAIAAAAAAAA
|
||||||
auto_controlled_avatar = NodePath("../Avatar")
|
auto_controlled_avatar = NodePath("../Avatar")
|
||||||
|
|
||||||
[node name="Avatar" parent="." instance=ExtResource("1_fdx6o")]
|
[node name="Avatar" parent="." instance=ExtResource("1_fdx6o")]
|
||||||
position = Vector2(312, 195)
|
position = Vector2(349, -271)
|
||||||
collision_mask = 4
|
collision_mask = 4
|
||||||
|
|
||||||
|
[node name="Coin" parent="." instance=ExtResource("4_j2xwq")]
|
||||||
|
position = Vector2(479, -182)
|
||||||
|
|
||||||
|
[node name="Coin2" parent="." instance=ExtResource("4_j2xwq")]
|
||||||
|
position = Vector2(585, -184)
|
||||||
|
|
||||||
|
[node name="Coin3" parent="." instance=ExtResource("4_j2xwq")]
|
||||||
|
position = Vector2(695, -185)
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,184 @@
|
||||||
|
[gd_scene load_steps=28 format=4 uid="uid://bt55vmoc83l6g"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://5e157vdk6175" path="res://addons/reedscene/scene/ReedScene.gd" id="1_wiqi4"]
|
||||||
|
[ext_resource type="Script" uid="uid://bh066o84byplh" path="res://addons/reedscene/scene/ReedSceneID.gd" id="2_1t0dx"]
|
||||||
|
[ext_resource type="Script" uid="uid://43ula8nd3yl7" path="res://_game/scenes/scripts/s_l1_s1.gd" id="3_1t0dx"]
|
||||||
|
[ext_resource type="Script" uid="uid://dsgl7lbyjsiif" path="res://addons/reedscene/act/ActManager.gd" id="4_a224g"]
|
||||||
|
[ext_resource type="Script" uid="uid://fxpk2ot6otfh" path="res://addons/reedscene/act/Act.gd" id="5_a224g"]
|
||||||
|
[ext_resource type="Script" uid="uid://pxjf5vst08eo" path="res://addons/reedscene/prop/PropManager.gd" id="5_fyfyw"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://b5nx4dntm0gyn" path="res://_props/door_manager/event_trigger_door.tscn" id="6_8hwae"]
|
||||||
|
[ext_resource type="Script" uid="uid://baqgorvlumyju" path="res://addons/reedscene/act/SingleAct.gd" id="6_fyfyw"]
|
||||||
|
[ext_resource type="Script" uid="uid://b4menkyub4ce7" path="res://addons/reedscene/prop/PropComponent.gd" id="7_s6kod"]
|
||||||
|
[ext_resource type="Script" uid="uid://di41kt2tj34c2" path="res://addons/reedscene/prop/StateManager.gd" id="8_1dh04"]
|
||||||
|
[ext_resource type="Script" uid="uid://7lml6d1t5xtq" path="res://addons/reedscene/prop/PropState.gd" id="9_648qh"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://1l06de041i40" path="res://_levels/l_level_1.tscn" id="10_25twt"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://c3mievyfhx6ni" path="res://_props/coin/coin.tscn" id="11_1t0dx"]
|
||||||
|
[ext_resource type="Script" uid="uid://cdvgq0xqdbagk" path="res://addons/reedscene/prop/ReedPropEffect.gd" id="12_fyfyw"]
|
||||||
|
[ext_resource type="Script" uid="uid://jeybblac0kg2" path="res://addons/reedscene/prop/ReedTransition.gd" id="13_8hwae"]
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_8hwae"]
|
||||||
|
script = ExtResource("6_fyfyw")
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_s6kod"]
|
||||||
|
script = ExtResource("6_fyfyw")
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_1dh04"]
|
||||||
|
script = ExtResource("5_a224g")
|
||||||
|
prop_state_map = Dictionary[int, ExtResource("6_fyfyw")]({
|
||||||
|
0: SubResource("Resource_8hwae"),
|
||||||
|
1: SubResource("Resource_s6kod")
|
||||||
|
})
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_gu0l6"]
|
||||||
|
script = ExtResource("6_fyfyw")
|
||||||
|
state_id = 1
|
||||||
|
use_trans = true
|
||||||
|
metadata/_custom_type_script = "uid://baqgorvlumyju"
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_648qh"]
|
||||||
|
script = ExtResource("5_a224g")
|
||||||
|
prop_state_map = Dictionary[int, ExtResource("6_fyfyw")]({
|
||||||
|
0: SubResource("Resource_gu0l6")
|
||||||
|
})
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_onwc0"]
|
||||||
|
script = ExtResource("6_fyfyw")
|
||||||
|
use_trans = true
|
||||||
|
metadata/_custom_type_script = "uid://baqgorvlumyju"
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_7tspm"]
|
||||||
|
script = ExtResource("6_fyfyw")
|
||||||
|
state_id = 1
|
||||||
|
use_trans = true
|
||||||
|
metadata/_custom_type_script = "uid://baqgorvlumyju"
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_jh33u"]
|
||||||
|
script = ExtResource("5_a224g")
|
||||||
|
prop_state_map = Dictionary[int, ExtResource("6_fyfyw")]({
|
||||||
|
0: SubResource("Resource_onwc0"),
|
||||||
|
1: SubResource("Resource_7tspm")
|
||||||
|
})
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_fyfyw"]
|
||||||
|
script = ExtResource("12_fyfyw")
|
||||||
|
effect_type = 1
|
||||||
|
value = null
|
||||||
|
func_name = &"reset_door_state_id"
|
||||||
|
func_args = [0]
|
||||||
|
metadata/_custom_type_script = "uid://cdvgq0xqdbagk"
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_bco80"]
|
||||||
|
script = ExtResource("12_fyfyw")
|
||||||
|
effect_type = 1
|
||||||
|
value = null
|
||||||
|
func_name = &"door_close"
|
||||||
|
metadata/_custom_type_script = "uid://cdvgq0xqdbagk"
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_22pon"]
|
||||||
|
script = ExtResource("12_fyfyw")
|
||||||
|
effect_type = 1
|
||||||
|
value = null
|
||||||
|
func_name = &"reset_door_state_id"
|
||||||
|
func_args = [1]
|
||||||
|
metadata/_custom_type_script = "uid://cdvgq0xqdbagk"
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_25twt"]
|
||||||
|
script = ExtResource("12_fyfyw")
|
||||||
|
effect_type = 1
|
||||||
|
value = null
|
||||||
|
func_name = &"door_open"
|
||||||
|
metadata/_custom_type_script = "uid://cdvgq0xqdbagk"
|
||||||
|
|
||||||
|
[node name="l1_s1" type="Node2D"]
|
||||||
|
script = ExtResource("1_wiqi4")
|
||||||
|
metadata/_custom_type_script = "uid://5e157vdk6175"
|
||||||
|
|
||||||
|
[node name="[ID_ 9900001]" type="Node" parent="."]
|
||||||
|
script = ExtResource("2_1t0dx")
|
||||||
|
scene_id = 9900001
|
||||||
|
|
||||||
|
[node name="SceneManager" type="Node" parent="."]
|
||||||
|
script = ExtResource("3_1t0dx")
|
||||||
|
|
||||||
|
[node name="ActManager" type="Node" parent="."]
|
||||||
|
script = ExtResource("4_a224g")
|
||||||
|
prop_state_map = Dictionary[int, ExtResource("5_a224g")]({
|
||||||
|
0: SubResource("Resource_1dh04"),
|
||||||
|
1: SubResource("Resource_648qh"),
|
||||||
|
2: SubResource("Resource_jh33u")
|
||||||
|
})
|
||||||
|
|
||||||
|
[node name="Props" type="Node2D" parent="."]
|
||||||
|
script = ExtResource("5_fyfyw")
|
||||||
|
|
||||||
|
[node name="EventTriggerDoor" parent="Props" instance=ExtResource("6_8hwae")]
|
||||||
|
position = Vector2(656, 268)
|
||||||
|
|
||||||
|
[node name="[Prop_0000]" type="Node" parent="Props/EventTriggerDoor"]
|
||||||
|
script = ExtResource("7_s6kod")
|
||||||
|
prop_id = 0
|
||||||
|
|
||||||
|
[node name="States" type="Node" parent="Props/EventTriggerDoor/[Prop_0000]"]
|
||||||
|
script = ExtResource("8_1dh04")
|
||||||
|
|
||||||
|
[node name="[ID_0] Close" type="Node" parent="Props/EventTriggerDoor/[Prop_0000]/States"]
|
||||||
|
script = ExtResource("9_648qh")
|
||||||
|
state_id = 0
|
||||||
|
effects = Array[ExtResource("12_fyfyw")]([SubResource("Resource_fyfyw")])
|
||||||
|
|
||||||
|
[node name="From1" type="Node" parent="Props/EventTriggerDoor/[Prop_0000]/States/[ID_0] Close"]
|
||||||
|
script = ExtResource("13_8hwae")
|
||||||
|
from_state_id = 1
|
||||||
|
effects = Array[ExtResource("12_fyfyw")]([SubResource("Resource_bco80")])
|
||||||
|
metadata/_custom_type_script = "uid://jeybblac0kg2"
|
||||||
|
|
||||||
|
[node name="[ID_1] Open" type="Node" parent="Props/EventTriggerDoor/[Prop_0000]/States"]
|
||||||
|
script = ExtResource("9_648qh")
|
||||||
|
state_id = 1
|
||||||
|
effects = Array[ExtResource("12_fyfyw")]([SubResource("Resource_22pon")])
|
||||||
|
|
||||||
|
[node name="From0" type="Node" parent="Props/EventTriggerDoor/[Prop_0000]/States/[ID_1] Open"]
|
||||||
|
script = ExtResource("13_8hwae")
|
||||||
|
from_state_id = 0
|
||||||
|
effects = Array[ExtResource("12_fyfyw")]([SubResource("Resource_25twt")])
|
||||||
|
metadata/_custom_type_script = "uid://jeybblac0kg2"
|
||||||
|
|
||||||
|
[node name="EventTriggerDoor2" parent="Props" instance=ExtResource("6_8hwae")]
|
||||||
|
position = Vector2(15, 270)
|
||||||
|
|
||||||
|
[node name="[Prop_0001]" type="Node" parent="Props/EventTriggerDoor2"]
|
||||||
|
script = ExtResource("7_s6kod")
|
||||||
|
prop_id = 1
|
||||||
|
|
||||||
|
[node name="States" type="Node" parent="Props/EventTriggerDoor2/[Prop_0001]"]
|
||||||
|
script = ExtResource("8_1dh04")
|
||||||
|
|
||||||
|
[node name="[ID_0] Close" type="Node" parent="Props/EventTriggerDoor2/[Prop_0001]/States"]
|
||||||
|
script = ExtResource("9_648qh")
|
||||||
|
state_id = 0
|
||||||
|
effects = Array[ExtResource("12_fyfyw")]([SubResource("Resource_fyfyw")])
|
||||||
|
|
||||||
|
[node name="From1" type="Node" parent="Props/EventTriggerDoor2/[Prop_0001]/States/[ID_0] Close"]
|
||||||
|
script = ExtResource("13_8hwae")
|
||||||
|
from_state_id = 1
|
||||||
|
effects = Array[ExtResource("12_fyfyw")]([SubResource("Resource_bco80")])
|
||||||
|
metadata/_custom_type_script = "uid://jeybblac0kg2"
|
||||||
|
|
||||||
|
[node name="[ID_1] Open" type="Node" parent="Props/EventTriggerDoor2/[Prop_0001]/States"]
|
||||||
|
script = ExtResource("9_648qh")
|
||||||
|
state_id = 1
|
||||||
|
effects = Array[ExtResource("12_fyfyw")]([SubResource("Resource_22pon")])
|
||||||
|
|
||||||
|
[node name="From0" type="Node" parent="Props/EventTriggerDoor2/[Prop_0001]/States/[ID_1] Open"]
|
||||||
|
script = ExtResource("13_8hwae")
|
||||||
|
from_state_id = 0
|
||||||
|
effects = Array[ExtResource("12_fyfyw")]([SubResource("Resource_25twt")])
|
||||||
|
metadata/_custom_type_script = "uid://jeybblac0kg2"
|
||||||
|
|
||||||
|
[node name="l1_s1_tile" parent="." instance=ExtResource("10_25twt")]
|
||||||
|
tile_map_data = PackedByteArray("AAAAAAQAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAwAAAAAAAAAAAAAABQAAAAAAAAAAAAAABUAAAAAAAAAAAAAABYAAAAAAAAAAAABAAQAAAAAAAAAAAABAAUAAAAAAAAAAAABAAYAAAAAAAAAAAABAAcAAAAAAAAAAAABAAgAAAAAAAAAAAABAAkAAAAAAAAAAAABAAoAAAAAAAAAAAABAAsAAAAAAAAAAAABAAwAAAAAAAAAAAABABQAAAAAAAAAAAABABUAAAAAAAAAAAABABYAAAAAAAAAAAACABQAAAAAAAAAAAACABUAAAAAAAAAAAACABYAAAAAAAAAAAADAAAAAAAAAAAAAAADAAEAAAAAAAAAAAADAAIAAAAAAAAAAAADABQAAAAAAAAAAAADABUAAAAAAAAAAAADABYAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAEAAAAAAAAAAAAEAAIAAAAAAAAAAAAEABQAAAAAAAAAAAAEABUAAAAAAAAAAAAEABYAAAAAAAAAAAAFAAAAAAAAAAAAAAAFAAEAAAAAAAAAAAAFAAIAAAAAAAAAAAAFABQAAAAAAAAAAAAFABUAAAAAAAAAAAAFABYAAAAAAAAAAAAGABQAAAAAAAAAAAAGABUAAAAAAAAAAAAGABYAAAAAAAAAAAAHABQAAAAAAAAAAAAHABUAAAAAAAAAAAAHABYAAAAAAAAAAAAIABQAAAAAAAAAAAAIABUAAAAAAAAAAAAIABYAAAAAAAAAAAAJABQAAAAAAAAAAAAJABUAAAAAAAAAAAAJABYAAAAAAAAAAAAKABQAAAAAAAAAAAAKABUAAAAAAAAAAAAKABYAAAAAAAAAAAALABQAAAAAAAAAAAALABUAAAAAAAAAAAALABYAAAAAAAAAAAAMABQAAAAAAAAAAAAMABUAAAAAAAAAAAAMABYAAAAAAAAAAAANABQAAAAAAAAAAAANABUAAAAAAAAAAAANABYAAAAAAAAAAAAOABQAAAAAAAAAAAAOABUAAAAAAAAAAAAOABYAAAAAAAAAAAAPABQAAAAAAAAAAAAPABUAAAAAAAAAAAAPABYAAAAAAAAAAAAQABQAAAAAAAAAAAAQABUAAAAAAAAAAAAQABYAAAAAAAAAAAARABQAAAAAAAAAAAARABUAAAAAAAAAAAARABYAAAAAAAAAAAASABQAAAAAAAAAAAASABUAAAAAAAAAAAASABYAAAAAAAAAAAATABQAAAAAAAAAAAATABUAAAAAAAAAAAATABYAAAAAAAAAAAAUABQAAAAAAAAAAAAUABUAAAAAAAAAAAAUABYAAAAAAAAAAAAVABQAAAAAAAAAAAAVABUAAAAAAAAAAAAVABYAAAAAAAAAAAAGAAAAAAAAAAAAAAAGAAEAAAAAAAAAAAAGAAIAAAAAAAAAAAAHAAAAAAAAAAAAAAAHAAEAAAAAAAAAAAAHAAIAAAAAAAAAAAAIAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAIAAIAAAAAAAAAAAAJAAAAAAAAAAAAAAAJAAEAAAAAAAAAAAAJAAIAAAAAAAAAAAAKAAAAAAAAAAAAAAAKAAEAAAAAAAAAAAAKAAIAAAAAAAAAAAALAAAAAAAAAAAAAAALAAEAAAAAAAAAAAALAAIAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAEAAAAAAAAAAAAMAAIAAAAAAAAAAAANAAAAAAAAAAAAAAANAAEAAAAAAAAAAAANAAIAAAAAAAAAAAAOAAAAAAAAAAAAAAAOAAEAAAAAAAAAAAAOAAIAAAAAAAAAAAAcABQAAAAAAAAAAAAcABUAAAAAAAAAAAAcABYAAAAAAAAAAAAdABQAAAAAAAAAAAAdABUAAAAAAAAAAAAdABYAAAAAAAAAAAAeABQAAAAAAAAAAAAeABUAAAAAAAAAAAAeABYAAAAAAAAAAAAfABQAAAAAAAAAAAAfABUAAAAAAAAAAAAfABYAAAAAAAAAAAAgABQAAAAAAAAAAAAgABUAAAAAAAAAAAAgABYAAAAAAAAAAAAhABQAAAAAAAAAAAAhABUAAAAAAAAAAAAhABYAAAAAAAAAAAAiABQAAAAAAAAAAAAiABUAAAAAAAAAAAAiABYAAAAAAAAAAAAjABQAAAAAAAAAAAAjABUAAAAAAAAAAAAjABYAAAAAAAAAAAAkABQAAAAAAAAAAAAkABUAAAAAAAAAAAAkABYAAAAAAAAAAAAlABQAAAAAAAAAAAAlABUAAAAAAAAAAAAlABYAAAAAAAAAAAAmABQAAAAAAAAAAAAmABUAAAAAAAAAAAAmABYAAAAAAAAAAAAnABQAAAAAAAAAAAAnABUAAAAAAAAAAAAnABYAAAAAAAAAAAAoABQAAAAAAAAAAAAoABUAAAAAAAAAAAAoABYAAAAAAAAAAAApABQAAAAAAAAAAAApABUAAAAAAAAAAAApABYAAAAAAAAAAAAWABQAAAAAAAAAAAAWABUAAAAAAAAAAAAWABYAAAAAAAAAAAAbABQAAAAAAAAAAAAbABUAAAAAAAAAAAAbABYAAAAAAAAAAAAXABQAAAAAAAAAAAAXABUAAAAAAAAAAAAXABYAAAAAAAAAAAAYABQAAAAAAAAAAAAYABUAAAAAAAAAAAAYABYAAAAAAAAAAAAZABQAAAAAAAAAAAAZABUAAAAAAAAAAAAZABYAAAAAAAAAAAAaABQAAAAAAAAAAAAaABUAAAAAAAAAAAAaABYAAAAAAAAAAAAPAAAAAAAAAAAAAAAPAAEAAAAAAAAAAAAPAAIAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAEAAAAAAAAAAAAQAAIAAAAAAAAAAAARAAAAAAAAAAAAAAARAAEAAAAAAAAAAAARAAIAAAAAAAAAAAASAAAAAAAAAAAAAAASAAEAAAAAAAAAAAASAAIAAAAAAAAAAAATAAAAAAAAAAAAAAATAAEAAAAAAAAAAAATAAIAAAAAAAAAAAAUAAAAAAAAAAAAAAAUAAEAAAAAAAAAAAAUAAIAAAAAAAAAAAAVAAAAAAAAAAAAAAAVAAEAAAAAAAAAAAAVAAIAAAAAAAAAAAAWAAAAAAAAAAAAAAAWAAEAAAAAAAAAAAAWAAIAAAAAAAAAAAAXAAAAAAAAAAAAAAAXAAEAAAAAAAAAAAAXAAIAAAAAAAAAAAAYAAAAAAAAAAAAAAAYAAEAAAAAAAAAAAAYAAIAAAAAAAAAAAAZAAAAAAAAAAAAAAAZAAEAAAAAAAAAAAAZAAIAAAAAAAAAAAAaAAAAAAAAAAAAAAAaAAEAAAAAAAAAAAAaAAIAAAAAAAAAAAAbAAAAAAAAAAAAAAAbAAEAAAAAAAAAAAAbAAIAAAAAAAAAAAAcAAAAAAAAAAAAAAAcAAEAAAAAAAAAAAAcAAIAAAAAAAAAAAAdAAAAAAAAAAAAAAAdAAEAAAAAAAAAAAAdAAIAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAEAAAAAAAAAAAAeAAIAAAAAAAAAAAAfAAAAAAAAAAAAAAAfAAEAAAAAAAAAAAAfAAIAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAEAAAAAAAAAAAAgAAIAAAAAAAAAAAAhAAAAAAAAAAAAAAAhAAEAAAAAAAAAAAAhAAIAAAAAAAAAAAAiAAAAAAAAAAAAAAAiAAEAAAAAAAAAAAAiAAIAAAAAAAAAAAAjAAAAAAAAAAAAAAAjAAEAAAAAAAAAAAAjAAIAAAAAAAAAAAAkAAAAAAAAAAAAAAAkAAEAAAAAAAAAAAAkAAIAAAAAAAAAAAAlAAAAAAAAAAAAAAAlAAEAAAAAAAAAAAAlAAIAAAAAAAAAAAAmAAAAAAAAAAAAAAAmAAEAAAAAAAAAAAAmAAIAAAAAAAAAAAAnAAAAAAAAAAAAAAAnAAEAAAAAAAAAAAAnAAIAAAAAAAAAAAAoAAAAAAAAAAAAAAAoAAEAAAAAAAAAAAAoAAIAAAAAAAAAAAApAAAAAAAAAAAAAAApAAEAAAAAAAAAAAApAAIAAAAAAAAAAAAoAAMAAAAAAAAAAAAoAAQAAAAAAAAAAAAoAAUAAAAAAAAAAAAoAAYAAAAAAAAAAAAoAAcAAAAAAAAAAAAoAAgAAAAAAAAAAAAoAAkAAAAAAAAAAAAoAAoAAAAAAAAAAAAoAAsAAAAAAAAAAAAoAAwAAAAAAAAAAAApAAMAAAAAAAAAAAApAAQAAAAAAAAAAAApAAUAAAAAAAAAAAApAAYAAAAAAAAAAAApAAcAAAAAAAAAAAApAAgAAAAAAAAAAAApAAkAAAAAAAAAAAApAAoAAAAAAAAAAAApAAsAAAAAAAAAAAApAAwAAAAAAAAAAAA=")
|
||||||
|
|
||||||
|
[node name="Coin" parent="." instance=ExtResource("11_1t0dx")]
|
||||||
|
position = Vector2(596, 291)
|
||||||
|
|
||||||
|
[connection signal="collected" from="Coin" to="SceneManager" method="_on_coin_collected"]
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,24 @@
|
||||||
|
[gd_scene load_steps=6 format=3 uid="uid://jd5d3i4xqj2m"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://5e157vdk6175" path="res://addons/reedscene/scene/ReedScene.gd" id="1_r4clk"]
|
||||||
|
[ext_resource type="Script" uid="uid://bh066o84byplh" path="res://addons/reedscene/scene/ReedSceneID.gd" id="2_oqwc4"]
|
||||||
|
[ext_resource type="Script" uid="uid://dn0ksjoswquf5" path="res://addons/reedscene/scene/SceneManager.gd" id="3_jbgha"]
|
||||||
|
[ext_resource type="Script" uid="uid://dsgl7lbyjsiif" path="res://addons/reedscene/act/ActManager.gd" id="4_w6ro2"]
|
||||||
|
[ext_resource type="Script" uid="uid://pxjf5vst08eo" path="res://addons/reedscene/prop/PropManager.gd" id="5_qmrnk"]
|
||||||
|
|
||||||
|
[node name="l1_s4" type="Node2D"]
|
||||||
|
script = ExtResource("1_r4clk")
|
||||||
|
metadata/_custom_type_script = "uid://5e157vdk6175"
|
||||||
|
|
||||||
|
[node name="[ID_ 9900004]" type="Node" parent="."]
|
||||||
|
script = ExtResource("2_oqwc4")
|
||||||
|
scene_id = 9900004
|
||||||
|
|
||||||
|
[node name="SceneManager" type="Node" parent="."]
|
||||||
|
script = ExtResource("3_jbgha")
|
||||||
|
|
||||||
|
[node name="ActManager" type="Node" parent="."]
|
||||||
|
script = ExtResource("4_w6ro2")
|
||||||
|
|
||||||
|
[node name="Props" type="Node2D" parent="."]
|
||||||
|
script = ExtResource("5_qmrnk")
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
extends SceneManager
|
||||||
|
|
||||||
|
|
||||||
|
func _on_coin_collected(collector: Node2D) -> void:
|
||||||
|
_act_manager.switch_act_with_id(1)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://43ula8nd3yl7
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
extends SceneManager
|
||||||
|
|
||||||
|
|
||||||
|
func _on_coin_collected(collector: Node2D) -> void:
|
||||||
|
_act_manager.switch_act_with_id(1)
|
||||||
|
var l1_s1: ReedScene = ReedSceneRegistry.get_scene(9900001)
|
||||||
|
if l1_s1:
|
||||||
|
l1_s1.switch_act_by_id(2)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://bna42bay8yt1m
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
extends SceneManager
|
||||||
|
|
||||||
|
|
||||||
|
func _on_coin_collected(collector: Node2D) -> void:
|
||||||
|
_act_manager.switch_act_with_id(1)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://c4gk6pcjk8no3
|
||||||
|
|
@ -38,8 +38,11 @@ class_name CelesteLocomotionComponent extends JumpLocomotionComponent
|
||||||
|
|
||||||
#region Custom Move (拉扯移動)
|
#region Custom Move (拉扯移動)
|
||||||
@export_category("Custom Move")
|
@export_category("Custom Move")
|
||||||
|
##進行自定義運動時,移動的拉力
|
||||||
@export var custom_move_force: float = 25.0
|
@export var custom_move_force: float = 25.0
|
||||||
|
##進行自定義運動時,移動的最大速度
|
||||||
@export var custom_move_max_speed: float = 420.0
|
@export var custom_move_max_speed: float = 420.0
|
||||||
|
##進行自定義運動時,如果于目標點小於此距離,則會解除自定義運動
|
||||||
@export var custom_move_stop_distance: float = 4.0
|
@export var custom_move_stop_distance: float = 4.0
|
||||||
|
|
||||||
var _custom_move_target_node: Node = null
|
var _custom_move_target_node: Node = null
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
extends Area2D
|
||||||
|
|
||||||
|
signal collected(collector: Node2D)
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
self.body_entered.connect(_on_collected)
|
||||||
|
self.area_entered.connect(_on_collected)
|
||||||
|
|
||||||
|
func _on_collected(collection: Node2D) -> void:
|
||||||
|
var collector := collection.owner
|
||||||
|
if collector == null:
|
||||||
|
return
|
||||||
|
|
||||||
|
## 如果收集者存在收集接口,那麽就把自己傳過去
|
||||||
|
if collector.has_method("collect_item"):
|
||||||
|
collector.collect_item(self)
|
||||||
|
collected.emit(collector)
|
||||||
|
|
||||||
|
self.queue_free()
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://b7o5456qrwgbf
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://d20u8tfktepxg"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://b7o5456qrwgbf" path="res://_props/_prefabs/collection_prefab.gd" id="1_8ns1b"]
|
||||||
|
|
||||||
|
[node name="CollectionPrefab" type="Area2D"]
|
||||||
|
collision_layer = 16
|
||||||
|
collision_mask = 2
|
||||||
|
script = ExtResource("1_8ns1b")
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
size = Vector2(20, 128)
|
size = Vector2(20, 128)
|
||||||
|
|
||||||
[node name="Door" type="AnimatableBody2D"]
|
[node name="Door" type="AnimatableBody2D"]
|
||||||
|
collision_layer = 4
|
||||||
|
collision_mask = 0
|
||||||
script = ExtResource("1_gt1uq")
|
script = ExtResource("1_gt1uq")
|
||||||
|
|
||||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
[gd_scene load_steps=4 format=3 uid="uid://c3mievyfhx6ni"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://d20u8tfktepxg" path="res://_props/_prefabs/collection_prefab.tscn" id="1_r0qyb"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://c673bap4b12fx" path="res://icon.svg" id="2_igeyo"]
|
||||||
|
|
||||||
|
[sub_resource type="CircleShape2D" id="CircleShape2D_r0qyb"]
|
||||||
|
radius = 23.0
|
||||||
|
|
||||||
|
[node name="Coin" instance=ExtResource("1_r0qyb")]
|
||||||
|
|
||||||
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="." index="0"]
|
||||||
|
shape = SubResource("CircleShape2D_r0qyb")
|
||||||
|
|
||||||
|
[node name="Sprite2D" type="Sprite2D" parent="." index="1"]
|
||||||
|
scale = Vector2(0.33, 0.33)
|
||||||
|
texture = ExtResource("2_igeyo")
|
||||||
|
|
@ -35,8 +35,11 @@ const FALL_SPEED_EXCEED_TOLERANCE_THRESHOLD = 40
|
||||||
|
|
||||||
@export_category("Locomotion Properties")
|
@export_category("Locomotion Properties")
|
||||||
@export_subgroup("Move")
|
@export_subgroup("Move")
|
||||||
|
##存在輸入時,向最大移動輸入運動的加速度
|
||||||
@export var run_accel : float = 1200
|
@export var run_accel : float = 1200
|
||||||
|
##不存在輸入時,向Vector.ZERO運動的加速度
|
||||||
@export var run_reduce : float = 1600
|
@export var run_reduce : float = 1600
|
||||||
|
##移動時的最大速度
|
||||||
@export var move_speed_max : float = 280
|
@export var move_speed_max : float = 280
|
||||||
|
|
||||||
var characterbody: CharacterBody2D
|
var characterbody: CharacterBody2D
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,32 @@
|
||||||
[gd_resource type="Resource" script_class="SceneIDDatabase" load_steps=2 format=3 uid="uid://4c26uejocdos"]
|
[gd_resource type="Resource" script_class="SceneIDDatabase" load_steps=7 format=3 uid="uid://4c26uejocdos"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://delj6tsrxv8s3" path="res://addons/reedscene/scene/SceneIDDatabase.gd" id="1_47k6c"]
|
[ext_resource type="Script" uid="uid://delj6tsrxv8s3" path="res://addons/reedscene/scene/SceneIDDatabase.gd" id="1_47k6c"]
|
||||||
|
[ext_resource type="Script" uid="uid://u5521mvu4rsw" path="res://addons/reedscene/scene/SceneIDEntry.gd" id="1_qlo8y"]
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_qlo8y"]
|
||||||
|
script = ExtResource("1_qlo8y")
|
||||||
|
scene_path = "res://_game/scenes/l_1_s_1.tscn"
|
||||||
|
scene_uid = "uid://bt55vmoc83l6g"
|
||||||
|
scene_id = 9900001
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_nf1f2"]
|
||||||
|
script = ExtResource("1_qlo8y")
|
||||||
|
scene_path = "res://_game/scenes/l_1_s_2.tscn"
|
||||||
|
scene_uid = "uid://c6and5mqr3wv1"
|
||||||
|
scene_id = 9900002
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_ej86d"]
|
||||||
|
script = ExtResource("1_qlo8y")
|
||||||
|
scene_path = "res://_game/scenes/l_1_s_3.tscn"
|
||||||
|
scene_uid = "uid://0sivr6aig7gm"
|
||||||
|
scene_id = 9900003
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_0yfd7"]
|
||||||
|
script = ExtResource("1_qlo8y")
|
||||||
|
scene_path = "res://_game/scenes/l_1_s_4.tscn"
|
||||||
|
scene_uid = "uid://jd5d3i4xqj2m"
|
||||||
|
scene_id = 9900004
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_47k6c")
|
script = ExtResource("1_47k6c")
|
||||||
next_id = 10001
|
entries = Array[ExtResource("1_qlo8y")]([SubResource("Resource_qlo8y"), SubResource("Resource_nf1f2"), SubResource("Resource_ej86d"), SubResource("Resource_0yfd7")])
|
||||||
scene_map = {
|
|
||||||
"res://_game/LevelDemonstration.tscn": 10000
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,137 @@
|
||||||
|
@tool
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
@onready var grid: GridContainer = %GC_Rows
|
||||||
|
@onready var refresh_btn: Button = %BRefresh
|
||||||
|
|
||||||
|
const DB_PATH := "res://addons/reedscene/demo/data_base/GLOBAL_SCENE_ID.tres"
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
refresh_btn.pressed.connect(_reload)
|
||||||
|
#_reload()
|
||||||
|
|
||||||
|
func _notification(what: int) -> void:
|
||||||
|
# 切回该主屏时自动刷新(可选,但很实用)
|
||||||
|
if what == NOTIFICATION_VISIBILITY_CHANGED and visible:
|
||||||
|
pass
|
||||||
|
#_reload()
|
||||||
|
|
||||||
|
func _reload() -> void:
|
||||||
|
_clear_grid()
|
||||||
|
_build_header()
|
||||||
|
|
||||||
|
var db = load(DB_PATH)
|
||||||
|
if db == null:
|
||||||
|
# 没 DB 就只显示表头,避免空白
|
||||||
|
return
|
||||||
|
|
||||||
|
# 假设 db.entries: Array[SceneIDEntry],且 entry.scene_uid / entry.scene_id 存在
|
||||||
|
for entry in db.entries:
|
||||||
|
_add_row(entry)
|
||||||
|
|
||||||
|
func _clear_grid() -> void:
|
||||||
|
for c in grid.get_children():
|
||||||
|
c.queue_free()
|
||||||
|
|
||||||
|
func _build_header() -> void:
|
||||||
|
grid.columns = 5
|
||||||
|
_add_header_cell("ID")
|
||||||
|
_add_header_cell("Name")
|
||||||
|
_add_header_cell("UID")
|
||||||
|
_add_header_cell("Path")
|
||||||
|
_add_header_cell("Function")
|
||||||
|
|
||||||
|
func _add_header_cell(text: String) -> void:
|
||||||
|
var l := Label.new()
|
||||||
|
l.text = text
|
||||||
|
l.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
|
l.clip_text = true
|
||||||
|
grid.add_child(l)
|
||||||
|
|
||||||
|
func _add_row(entry) -> void:
|
||||||
|
var uid_text: String = entry.scene_uid
|
||||||
|
var uid_id := ResourceUID.text_to_id(uid_text)
|
||||||
|
|
||||||
|
var path := ""
|
||||||
|
if uid_id != ResourceUID.INVALID_ID:
|
||||||
|
path = ResourceUID.get_id_path(uid_id)
|
||||||
|
|
||||||
|
var name := path.get_file().get_basename() if path != "" else "(missing)"
|
||||||
|
|
||||||
|
# 1) ID
|
||||||
|
grid.add_child(_cell_label(str(entry.scene_id)))
|
||||||
|
# 2) Name
|
||||||
|
grid.add_child(_cell_label(name))
|
||||||
|
# 3) UID
|
||||||
|
grid.add_child(_cell_label(uid_text))
|
||||||
|
# 4) Path(先显示,后面你想隐藏我们再做)
|
||||||
|
grid.add_child(_cell_label(path))
|
||||||
|
# 5) Function(真按钮)
|
||||||
|
grid.add_child(_function_cell(uid_text))
|
||||||
|
|
||||||
|
func _cell_label(text: String) -> Control:
|
||||||
|
var l := Label.new()
|
||||||
|
l.text = text
|
||||||
|
l.clip_text = true
|
||||||
|
l.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
|
return l
|
||||||
|
|
||||||
|
func _function_cell(uid_text: String) -> Control:
|
||||||
|
var box := HBoxContainer.new()
|
||||||
|
box.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
|
|
||||||
|
## 打開場景所使用的函數
|
||||||
|
var reveal_btn := Button.new()
|
||||||
|
reveal_btn.text = "Show"
|
||||||
|
reveal_btn.tooltip_text = "Reveal in FileSystem"
|
||||||
|
reveal_btn.pressed.connect(func():
|
||||||
|
_reveal_scene_in_filesystem_by_uid(uid_text)
|
||||||
|
)
|
||||||
|
box.add_child(reveal_btn)
|
||||||
|
|
||||||
|
# Delete 先做占位,下一步再落地到 Resource 修改/保存
|
||||||
|
var del_btn := Button.new()
|
||||||
|
del_btn.text = "Delete"
|
||||||
|
del_btn.pressed.connect(func():
|
||||||
|
print("[SceneID] TODO delete: ", uid_text)
|
||||||
|
)
|
||||||
|
box.add_child(del_btn)
|
||||||
|
|
||||||
|
return box
|
||||||
|
|
||||||
|
func _open_scene_by_uid(uid_text: String) -> void:
|
||||||
|
var uid_id := ResourceUID.text_to_id(uid_text)
|
||||||
|
if uid_id == ResourceUID.INVALID_ID:
|
||||||
|
push_warning("[SceneID] Invalid UID: %s" % uid_text)
|
||||||
|
return
|
||||||
|
|
||||||
|
var path := ResourceUID.get_id_path(uid_id)
|
||||||
|
if path == "" or not ResourceLoader.exists(path):
|
||||||
|
push_warning("[SceneID] Scene not found for UID: %s" % uid_text)
|
||||||
|
return
|
||||||
|
|
||||||
|
EditorInterface.open_scene_from_path(path)
|
||||||
|
|
||||||
|
## 打開文件管理系統裏的Scene
|
||||||
|
func _reveal_in_filesystem(path: String) -> void:
|
||||||
|
# FileSystemDock 才有 navigate_to_path
|
||||||
|
var dock := EditorInterface.get_file_system_dock()
|
||||||
|
dock.navigate_to_path(path)
|
||||||
|
|
||||||
|
## 通過UID打開文件管理系統裏的Scene
|
||||||
|
func _reveal_scene_in_filesystem_by_uid(uid_text: String) -> void:
|
||||||
|
var uid_id := ResourceUID.text_to_id(uid_text)
|
||||||
|
if uid_id == ResourceUID.INVALID_ID:
|
||||||
|
push_warning("[SceneID] Invalid UID: %s" % uid_text)
|
||||||
|
return
|
||||||
|
|
||||||
|
var path := ResourceUID.get_id_path(uid_id)
|
||||||
|
if path == "" or not ResourceLoader.exists(path):
|
||||||
|
push_warning("[SceneID] Scene not found for UID: %s" % uid_text)
|
||||||
|
return
|
||||||
|
|
||||||
|
var dock := EditorInterface.get_file_system_dock()
|
||||||
|
dock.navigate_to_path(path)
|
||||||
|
|
||||||
|
func on_activated() -> void:
|
||||||
|
_reload()
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://detpkhtovi6bp"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://bi8dmt4ypmbhq" path="res://addons/reedscene/dock/SceneIDMainPanel.gd" id="1_vunhl"]
|
||||||
|
|
||||||
|
[node name="Control" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
script = ExtResource("1_vunhl")
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_constants/margin_left = 15
|
||||||
|
theme_override_constants/margin_top = 10
|
||||||
|
theme_override_constants/margin_right = 15
|
||||||
|
theme_override_constants/margin_bottom = 10
|
||||||
|
|
||||||
|
[node name="VBC_Main" type="VBoxContainer" parent="MarginContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBC_Main"]
|
||||||
|
custom_minimum_size = Vector2(0, 50)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "ReedScene Manage Panel
|
||||||
|
V0.3"
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBC_Main"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="HBC_Header" type="HBoxContainer" parent="MarginContainer/VBC_Main/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="BRefresh" type="Button" parent="MarginContainer/VBC_Main/VBoxContainer/HBC_Header"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(60, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Refresh"
|
||||||
|
|
||||||
|
[node name="BLoad" type="Button" parent="MarginContainer/VBC_Main/VBoxContainer/HBC_Header"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(60, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Load Database"
|
||||||
|
|
||||||
|
[node name="Spacer" type="Control" parent="MarginContainer/VBC_Main/VBoxContainer/HBC_Header"]
|
||||||
|
custom_minimum_size = Vector2(60, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBC_Main/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="GC_Rows" type="GridContainer" parent="MarginContainer/VBC_Main/VBoxContainer/ScrollContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
columns = 5
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
@tool
|
|
||||||
extends Control
|
|
||||||
|
|
||||||
@onready var tree: Tree = %Tree
|
|
||||||
|
|
||||||
func _ready():
|
|
||||||
_setup_tree()
|
|
||||||
_fill_dummy_data()
|
|
||||||
|
|
||||||
func _setup_tree():
|
|
||||||
tree.clear()
|
|
||||||
tree.columns = 3
|
|
||||||
tree.set_column_title(0, "ID")
|
|
||||||
tree.set_column_title(1, "Scene Path")
|
|
||||||
tree.set_column_title(2, "Action")
|
|
||||||
|
|
||||||
func _fill_dummy_data():
|
|
||||||
var root := tree.create_item()
|
|
||||||
|
|
||||||
_add_row(root, 10001, "res://levels/level_1.tscn")
|
|
||||||
_add_row(root, 10002, "res://levels/level_2.tscn")
|
|
||||||
|
|
||||||
func _add_row(root: TreeItem, id: int, path: String):
|
|
||||||
var item := tree.create_item(root)
|
|
||||||
item.set_text(0, str(id))
|
|
||||||
item.set_text(1, path)
|
|
||||||
item.set_text(2, "Open")
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
[gd_scene load_steps=2 format=3 uid="uid://detpkhtovi6bp"]
|
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://bi8dmt4ypmbhq" path="res://addons/reedscene/dock/scene_id_main_screen.gd" id="1_jm7r3"]
|
|
||||||
|
|
||||||
[node name="SceneIdMainScreen" type="CenterContainer"]
|
|
||||||
anchors_preset = 15
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
grow_horizontal = 2
|
|
||||||
grow_vertical = 2
|
|
||||||
script = ExtResource("1_jm7r3")
|
|
||||||
|
|
||||||
[node name="Tree" type="Tree" parent="."]
|
|
||||||
unique_name_in_owner = true
|
|
||||||
layout_mode = 2
|
|
||||||
columns = 3
|
|
||||||
hide_root = true
|
|
||||||
|
|
@ -3,5 +3,5 @@
|
||||||
name="ReedScene"
|
name="ReedScene"
|
||||||
description="这是一个用于2D游戏场景管理的插件,通过组件化的方式,将一个场景分成了场景中的各个组件和组件所对应的状态,用户可以通过切换状态,来实现一些动画的效果,也可以通过切换状态,来快速的事件存档,不同事件触发不同的结果的任务系统等,总之比较灵活"
|
description="这是一个用于2D游戏场景管理的插件,通过组件化的方式,将一个场景分成了场景中的各个组件和组件所对应的状态,用户可以通过切换状态,来实现一些动画的效果,也可以通过切换状态,来快速的事件存档,不同事件触发不同的结果的任务系统等,总之比较灵活"
|
||||||
author="ReedZhu"
|
author="ReedZhu"
|
||||||
version=".1"
|
version="1.0"
|
||||||
script="reedscene.gd"
|
script="reedscene.gd"
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,10 @@ extends EditorPlugin
|
||||||
|
|
||||||
var inspector_plugins: Array[EditorInspectorPlugin] = []
|
var inspector_plugins: Array[EditorInspectorPlugin] = []
|
||||||
|
|
||||||
const AUTOLOAD_REED_SCENE_NAME: StringName = "ReedSceneSystem"
|
const AUTOLOAD_REED_SCENE_NAME: StringName = "ReedSceneRegistry"
|
||||||
const AUTOLOAD_REED_SCENE_PATH:= "res://addons/reedscene/scene/SceneRegistry.gd"
|
const AUTOLOAD_REED_SCENE_PATH:= "res://addons/reedscene/scene/SceneRegistry.gd"
|
||||||
|
|
||||||
var toolbar_button: Button
|
var toolbar_button: Button
|
||||||
var scene_id_window: Window
|
|
||||||
var main_screen: Control
|
var main_screen: Control
|
||||||
|
|
||||||
func _enter_tree() -> void:
|
func _enter_tree() -> void:
|
||||||
|
|
@ -45,7 +44,7 @@ func _exit_tree() -> void:
|
||||||
|
|
||||||
##加載主界面
|
##加載主界面
|
||||||
func _load_mainscreen() -> void:
|
func _load_mainscreen() -> void:
|
||||||
main_screen = preload("res://addons/reedscene/dock/scene_id_main_screen.tscn").instantiate()
|
main_screen = preload("res://addons/reedscene/dock/SceneIDMainPanel.tscn").instantiate()
|
||||||
EditorInterface.get_editor_main_screen().add_child(main_screen)
|
EditorInterface.get_editor_main_screen().add_child(main_screen)
|
||||||
main_screen.visible = false
|
main_screen.visible = false
|
||||||
|
|
||||||
|
|
@ -59,8 +58,10 @@ func _has_main_screen() -> bool:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
func _make_visible(visible: bool) -> void:
|
func _make_visible(visible: bool) -> void:
|
||||||
if main_screen:
|
if not main_screen: return
|
||||||
main_screen.visible = visible
|
main_screen.visible = visible
|
||||||
|
if visible:
|
||||||
|
main_screen.on_activated()
|
||||||
|
|
||||||
func _get_plugin_name() -> String:
|
func _get_plugin_name() -> String:
|
||||||
return "Reed Scene"
|
return "Reed Scene"
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,8 @@ class_name ReedScene extends Node2D
|
||||||
|
|
||||||
##Act管理器的命名
|
##Act管理器的命名
|
||||||
const ACT_MANAGER_NAME := "ActManager"
|
const ACT_MANAGER_NAME := "ActManager"
|
||||||
|
|
||||||
##Prop的根节点命名
|
##Prop的根节点命名
|
||||||
const PROPS_ROOT_NAME := "Props"
|
const PROPS_ROOT_NAME := "Props"
|
||||||
|
|
||||||
##场景管理器的根节点命名
|
##场景管理器的根节点命名
|
||||||
const SCENE_MANAGER_NAME := "SceneManager"
|
const SCENE_MANAGER_NAME := "SceneManager"
|
||||||
|
|
||||||
|
|
@ -56,20 +54,48 @@ const SCENE_MANAGER_NAME := "SceneManager"
|
||||||
## ==============================
|
## ==============================
|
||||||
## Internal State
|
## Internal State
|
||||||
## ==============================
|
## ==============================
|
||||||
|
var _scene_id_comp: ReedSceneID
|
||||||
var _act_manager: ActManager
|
var _act_manager: ActManager
|
||||||
var _props_root: Node
|
var _props_root: Node
|
||||||
var _prop_map: Dictionary = {} # prop_id -> PropComponent
|
var _prop_map: Dictionary = {} # prop_id -> PropComponent
|
||||||
|
var _scene_manager: SceneManager
|
||||||
|
|
||||||
## ==============================
|
## ==============================
|
||||||
##
|
## Build In
|
||||||
## ==============================
|
## ==============================
|
||||||
func _enter_tree() -> void:
|
func _enter_tree() -> void:
|
||||||
if Engine.is_editor_hint():
|
if Engine.is_editor_hint():
|
||||||
_editor_ensure_scene_nodes() ##进入场景树,自动添加ActManager,PropsRoot,和SceneManager
|
_editor_ensure_scene_nodes() ##进入场景树,自动添加ActManager,PropsRoot,和SceneManager
|
||||||
|
_editor_ensure_scene_id_comp() ##進入場景樹,則自動添加一個IDComp
|
||||||
|
|
||||||
|
func _notification(what):
|
||||||
|
if what == NOTIFICATION_PARENTED:
|
||||||
|
if get_parent() != null and not (get_parent() is ReedScene):
|
||||||
|
push_warning("ReedSceneID must stay under ReedScene.")
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
_resolve_scene_id_comp()
|
||||||
|
_resolve_scene_manager()
|
||||||
|
_resolve_act_manager()
|
||||||
|
_resolve_props_root()
|
||||||
|
_collect_props()
|
||||||
|
_bind_act_events()
|
||||||
|
|
||||||
|
if not Engine.is_editor_hint():
|
||||||
|
ReedSceneRegistry.register_scene(self)
|
||||||
## ==============================
|
## ==============================
|
||||||
## Resolve References
|
## Resolve References
|
||||||
## ==============================
|
## ==============================
|
||||||
|
func _resolve_scene_id_comp() -> void:
|
||||||
|
_scene_id_comp = null
|
||||||
|
for child in get_children():
|
||||||
|
if child is ReedSceneID:
|
||||||
|
_scene_id_comp = child
|
||||||
|
break
|
||||||
|
|
||||||
|
if _scene_id_comp == null:
|
||||||
|
push_error("[ReedScene] ReedSceneID not found.")
|
||||||
|
|
||||||
func _resolve_act_manager() -> void:
|
func _resolve_act_manager() -> void:
|
||||||
_act_manager = get_node_or_null("ActManager")
|
_act_manager = get_node_or_null("ActManager")
|
||||||
if _act_manager == null:
|
if _act_manager == null:
|
||||||
|
|
@ -81,6 +107,10 @@ func _resolve_props_root() -> void:
|
||||||
if _props_root == null:
|
if _props_root == null:
|
||||||
push_error("[ReedScene] Props root not found: %s" % props_root_path)
|
push_error("[ReedScene] Props root not found: %s" % props_root_path)
|
||||||
|
|
||||||
|
func _resolve_scene_manager() -> void:
|
||||||
|
_scene_manager = get_node_or_null(SCENE_MANAGER_NAME)
|
||||||
|
if _scene_manager == null:
|
||||||
|
push_error("[ReedScene] SceneManager not found.")
|
||||||
## ==============================
|
## ==============================
|
||||||
## Prop Collection
|
## Prop Collection
|
||||||
## ==============================
|
## ==============================
|
||||||
|
|
@ -155,8 +185,45 @@ func _editor_ensure_node(name: String, type: Variant) -> Node:
|
||||||
|
|
||||||
return node
|
return node
|
||||||
|
|
||||||
func _ready() -> void:
|
##保證存在ID節點
|
||||||
_resolve_act_manager()
|
func _editor_ensure_scene_id_comp() -> ReedSceneID:
|
||||||
_resolve_props_root()
|
# 1️. 查找已有的 ReedSceneID(只找直接子节点)
|
||||||
_collect_props()
|
var id_comp: ReedSceneID = null
|
||||||
_bind_act_events()
|
for child in get_children():
|
||||||
|
if child is ReedSceneID:
|
||||||
|
id_comp = child
|
||||||
|
break
|
||||||
|
|
||||||
|
# 2️. 不存在就创建
|
||||||
|
if id_comp == null:
|
||||||
|
id_comp = ReedSceneID.new()
|
||||||
|
id_comp.name = "SceneID"
|
||||||
|
add_child(id_comp)
|
||||||
|
|
||||||
|
# 关键:设 owner,才能被保存到场景
|
||||||
|
id_comp.owner = get_tree().edited_scene_root
|
||||||
|
|
||||||
|
if debug_log:
|
||||||
|
print("[ReedScene][Editor] Created ReedSceneID")
|
||||||
|
|
||||||
|
# 3️. 确保在子节点最上层(index = 0)
|
||||||
|
if get_child(0) != id_comp:
|
||||||
|
move_child(id_comp, 0)
|
||||||
|
|
||||||
|
return id_comp
|
||||||
|
|
||||||
|
func switch_act_by_id(act_id: int) -> void:
|
||||||
|
if not _act_manager:
|
||||||
|
push_warning("[ReedScene] ActManager requested before ready.")
|
||||||
|
|
||||||
|
_act_manager.switch_act_with_id(act_id)
|
||||||
|
|
||||||
|
func get_scene_manager() -> SceneManager:
|
||||||
|
if _scene_manager == null:
|
||||||
|
push_warning("[ReedScene] SceneManager requested before ready.")
|
||||||
|
return _scene_manager
|
||||||
|
|
||||||
|
func get_scene_id_comp() -> ReedSceneID:
|
||||||
|
if _scene_id_comp == null:
|
||||||
|
push_warning("[ReedScene] Scene not has a ID Comp.")
|
||||||
|
return _scene_id_comp
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,96 @@
|
||||||
extends Node
|
extends Node
|
||||||
class_name ReedSceneID
|
class_name ReedSceneID
|
||||||
|
|
||||||
@export var scene_id: int = -1
|
##此Scene的描述ID,无法主动修改,你可以向編輯器申請。
|
||||||
|
@export_custom(
|
||||||
|
PROPERTY_HINT_NONE,
|
||||||
|
"",
|
||||||
|
PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY
|
||||||
|
)
|
||||||
|
var scene_id: int = -1:
|
||||||
|
set(value):
|
||||||
|
if _scene_id == value:
|
||||||
|
return
|
||||||
|
_scene_id = value
|
||||||
|
if Engine.is_editor_hint():
|
||||||
|
_sync_node_name()
|
||||||
|
update_configuration_warnings()
|
||||||
|
get():
|
||||||
|
return _scene_id
|
||||||
|
|
||||||
|
var _scene_id: int = -1
|
||||||
|
var _is_syncing_name := false
|
||||||
|
|
||||||
|
const DB_PATH := "res://addons/reedscene/demo/data_base/GLOBAL_SCENE_ID.tres"
|
||||||
|
|
||||||
|
## ==============================
|
||||||
|
## Build In
|
||||||
|
## ==============================
|
||||||
|
|
||||||
|
## 進入Tree
|
||||||
|
func _enter_tree() -> void:
|
||||||
|
if Engine.is_editor_hint():
|
||||||
|
_sync_node_name()
|
||||||
|
|
||||||
|
## 初始化完成后
|
||||||
|
func _ready() -> void:
|
||||||
|
if Engine.is_editor_hint():
|
||||||
|
renamed.connect(func():
|
||||||
|
_sync_node_name()
|
||||||
|
)
|
||||||
|
|
||||||
func has_id() -> bool:
|
func has_id() -> bool:
|
||||||
return scene_id >= 0
|
return scene_id >= 0
|
||||||
|
|
||||||
|
func _get_display_name() -> String:
|
||||||
|
if not has_id():
|
||||||
|
return "[Invalid!]"
|
||||||
|
return "[ID: %d]" % scene_id
|
||||||
|
|
||||||
|
func _sync_node_name() -> void:
|
||||||
|
if _is_syncing_name:
|
||||||
|
return
|
||||||
|
|
||||||
|
_is_syncing_name = true
|
||||||
|
|
||||||
|
var desired := _get_display_name()
|
||||||
|
if name != desired:
|
||||||
|
name = desired
|
||||||
|
|
||||||
|
_is_syncing_name = false
|
||||||
|
|
||||||
|
func _get_configuration_warnings() -> PackedStringArray:
|
||||||
|
var warnings := PackedStringArray()
|
||||||
|
|
||||||
|
# 1️. 结构校验(只跟 Node 结构有关)
|
||||||
|
var parent := get_parent()
|
||||||
|
if parent == null or not (parent is ReedScene):
|
||||||
|
warnings.append("ReedSceneID must be a child of ReedScene.")
|
||||||
|
return warnings
|
||||||
|
|
||||||
|
# 2️. 自身状态
|
||||||
|
if not has_id():
|
||||||
|
warnings.append("Scene ID is not assigned.")
|
||||||
|
return warnings
|
||||||
|
|
||||||
|
# 3️. DB 一致性校验(委托给 DB)
|
||||||
|
var scene_path := parent.scene_file_path
|
||||||
|
if scene_path.is_empty():
|
||||||
|
warnings.append("Parent scene is not saved; cannot validate Scene ID.")
|
||||||
|
return warnings
|
||||||
|
|
||||||
|
var uid := ResourceUID.path_to_uid(scene_path)
|
||||||
|
|
||||||
|
var db := load(DB_PATH) as SceneIDDatabase
|
||||||
|
if not db:
|
||||||
|
warnings.append("SceneIDDatabase not found.")
|
||||||
|
return warnings
|
||||||
|
|
||||||
|
var result := db.validate_scene_id(scene_id, uid, scene_path)
|
||||||
|
if result == null:
|
||||||
|
return warnings
|
||||||
|
|
||||||
|
for msg in result.messages:
|
||||||
|
warnings.append(msg)
|
||||||
|
|
||||||
|
return warnings
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,12 @@ static func request_id_for_scene(scene_path: String) -> int:
|
||||||
push_error("[ReedSceneIDEditorSystem] Database not found: " + DB_PATH)
|
push_error("[ReedSceneIDEditorSystem] Database not found: " + DB_PATH)
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
var db := _clone_db_to_new(db_ro)
|
var db : SceneIDDatabase = _clone_db_to_new(db_ro)
|
||||||
|
|
||||||
if db.scene_map.has(scene_path):
|
if db.scene_map.has(scene_path):
|
||||||
return int(db.scene_map[scene_path])
|
return int(db.scene_map[scene_path])
|
||||||
|
|
||||||
var new_id := db.next_id
|
var new_id :int = db.next_id
|
||||||
db.next_id += 1
|
db.next_id += 1
|
||||||
db.scene_map[scene_path] = new_id
|
db.scene_map[scene_path] = new_id
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,108 @@
|
||||||
@tool
|
@tool
|
||||||
extends EditorInspectorPlugin
|
extends EditorInspectorPlugin
|
||||||
|
|
||||||
|
const DB_PATH := "res://addons/reedscene/demo/data_base/GLOBAL_SCENE_ID.tres"
|
||||||
|
|
||||||
func _can_handle(object) -> bool:
|
func _can_handle(object) -> bool:
|
||||||
return object is ReedSceneID
|
return object is ReedSceneID
|
||||||
|
|
||||||
func _parse_begin(object):
|
func _parse_begin(object) -> void:
|
||||||
var button := Button.new()
|
var comp := object as ReedSceneID
|
||||||
button.text = "Request Scene ID"
|
|
||||||
button.pressed.connect(func():
|
var parent := comp.get_parent()
|
||||||
_request_id(object)
|
var scene := parent if parent is ReedScene else null
|
||||||
|
|
||||||
|
var is_scene_valid := scene != null
|
||||||
|
var is_scene_saved := false
|
||||||
|
|
||||||
|
if scene != null:
|
||||||
|
is_scene_saved = not scene.scene_file_path.is_empty()
|
||||||
|
|
||||||
|
# ==============================
|
||||||
|
# 提示文本(状态说明)
|
||||||
|
# ==============================
|
||||||
|
if not is_scene_valid:
|
||||||
|
var warn := Label.new()
|
||||||
|
warn.text = "SceneID requires parent to be ReedScene."
|
||||||
|
warn.modulate = Color(1, 0.6, 0.4)
|
||||||
|
add_custom_control(warn)
|
||||||
|
|
||||||
|
elif not is_scene_saved:
|
||||||
|
var warn := Label.new()
|
||||||
|
warn.text = "Please save the scene (.tscn) before requesting a Scene ID."
|
||||||
|
warn.modulate = Color(1, 0.6, 0.4)
|
||||||
|
add_custom_control(warn)
|
||||||
|
|
||||||
|
# ==============================
|
||||||
|
# Request 按钮
|
||||||
|
# ==============================
|
||||||
|
var btn := Button.new()
|
||||||
|
btn.text = "Request Scene ID"
|
||||||
|
|
||||||
|
btn.disabled = not (is_scene_valid and is_scene_saved)
|
||||||
|
|
||||||
|
if not btn.disabled:
|
||||||
|
btn.pressed.connect(func():
|
||||||
|
_open_request_dialog(comp)
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_control(btn)
|
||||||
|
|
||||||
|
func _open_request_dialog(comp: ReedSceneID) -> void:
|
||||||
|
var dialog := SceneIDRequestDialog.new()
|
||||||
|
EditorInterface.get_base_control().add_child(dialog)
|
||||||
|
|
||||||
|
dialog.request_confirmed.connect(func(prefix: int):
|
||||||
|
_request_with_prefix(comp, prefix)
|
||||||
|
dialog.queue_free()
|
||||||
)
|
)
|
||||||
add_custom_control(button)
|
|
||||||
|
|
||||||
func _request_id(id_comp: ReedSceneID):
|
dialog.popup_centered(Vector2i(420, 160))
|
||||||
var scene := id_comp.get_owner()
|
|
||||||
if scene == null:
|
func _request_with_prefix(comp: ReedSceneID, prefix: int) -> void:
|
||||||
push_error("[ReedSceneID] Cannot find owning scene")
|
var db := load(DB_PATH) as SceneIDDatabase
|
||||||
|
if not db:
|
||||||
|
push_error("SceneIDDatabase not found: %s" % DB_PATH)
|
||||||
return
|
return
|
||||||
|
|
||||||
var scene_path := scene.scene_file_path
|
# 1) SceneID 节点的父节点才是 Scene
|
||||||
if scene_path == "":
|
var scene_node := comp.get_parent()
|
||||||
push_error("[ReedSceneID] Scene must be saved before requesting ID")
|
if scene_node == null:
|
||||||
|
push_error("Request Scene ID failed: ReedSceneID has no parent.")
|
||||||
return
|
return
|
||||||
|
|
||||||
var id := ReedSceneIDEditorSystem.request_id_for_scene(scene_path)
|
# 2) 父节点必须是 ReedScene 或其子类
|
||||||
if id < 0:
|
if not (scene_node is ReedScene):
|
||||||
|
push_error("Request Scene ID failed: parent must be ReedScene (or subclass). Got: %s" % scene_node.get_class())
|
||||||
return
|
return
|
||||||
|
|
||||||
id_comp.scene_id = id
|
# 3) 父节点必须是一个“保存过的场景”,否则拿不到稳定的 path
|
||||||
id_comp.notify_property_list_changed()
|
var scene_path := scene_node.scene_file_path
|
||||||
|
if scene_path.is_empty():
|
||||||
|
push_error("Request Scene ID failed: parent scene has no scene_file_path (scene not saved?).")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 4) 获取 UID(这里按你的要求,用父节点的 uid)
|
||||||
|
# 注意:instance_id 不是跨会话稳定的,如果你未来需要“真正稳定 UID”,建议换成 ResourceUID / GUID
|
||||||
|
var uid := ResourceUID.path_to_uid(scene_path)
|
||||||
|
|
||||||
|
# 5) 请求一个可用 ID
|
||||||
|
var new_id := db.request_new_id(prefix)
|
||||||
|
if new_id < 0:
|
||||||
|
push_error("Request Scene ID failed: invalid new_id.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 6) 注册到数据库(使用父节点的 path + uid + id)
|
||||||
|
var ok: bool = db.register_scene_id(scene_path, uid, new_id)
|
||||||
|
if not ok:
|
||||||
|
push_error("Request Scene ID failed: register_scene_id returned false.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 7) 写回组件
|
||||||
|
comp.scene_id = new_id
|
||||||
|
comp.notify_property_list_changed()
|
||||||
|
|
||||||
|
# 8) 保存数据库资源
|
||||||
|
var err := ResourceSaver.save(db, DB_PATH)
|
||||||
|
if err != OK:
|
||||||
|
push_error("Failed to save SceneIDDatabase: %s (err=%d)" % [DB_PATH, err])
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,86 @@
|
||||||
|
''' 用來儲存所有的SceneID的數據集
|
||||||
|
'''
|
||||||
|
|
||||||
|
@tool
|
||||||
extends Resource
|
extends Resource
|
||||||
class_name SceneIDDatabase
|
class_name SceneIDDatabase
|
||||||
|
|
||||||
@export var next_id: int = 10000
|
var next_id: int = 10000
|
||||||
|
|
||||||
# scene_path (String) -> scene_id (int)
|
@export var entries: Array[SceneIDEntry] = []
|
||||||
@export var scene_map: Dictionary = {}
|
|
||||||
|
func request_new_id(prefix: int) -> int:
|
||||||
|
##合理性檢測
|
||||||
|
if prefix < 0: return -1
|
||||||
|
|
||||||
|
##獲取到已經使用的所有的ID
|
||||||
|
var used_ids : Array[int] = []
|
||||||
|
var used_set := {}
|
||||||
|
for i in entries:
|
||||||
|
used_ids.append(i.scene_id)
|
||||||
|
|
||||||
|
# 转成 Set(O(1) contains)
|
||||||
|
for id in used_ids:
|
||||||
|
used_set[id] = true
|
||||||
|
|
||||||
|
var candidate := prefix + 1
|
||||||
|
while used_set.has(candidate):
|
||||||
|
candidate += 1
|
||||||
|
|
||||||
|
return candidate
|
||||||
|
|
||||||
|
func register_scene_id(
|
||||||
|
scene_path: String,
|
||||||
|
uid: String,
|
||||||
|
scene_id: int
|
||||||
|
) -> bool:
|
||||||
|
for entry in entries:
|
||||||
|
if entry.scene_id == scene_id:
|
||||||
|
push_error("SceneIDDatabase: duplicated scene_id %d" % scene_id)
|
||||||
|
return false
|
||||||
|
|
||||||
|
var entry := SceneIDEntry.new()
|
||||||
|
entry.scene_id = scene_id
|
||||||
|
entry.scene_path = scene_path
|
||||||
|
entry.scene_uid = uid
|
||||||
|
|
||||||
|
entries.append(entry)
|
||||||
|
|
||||||
|
emit_changed()
|
||||||
|
return true
|
||||||
|
|
||||||
|
|
||||||
|
func validate_scene_id(
|
||||||
|
scene_id: int,
|
||||||
|
scene_uid: String,
|
||||||
|
scene_path: String
|
||||||
|
) -> SceneIDValidationResult:
|
||||||
|
var result := SceneIDValidationResult.new()
|
||||||
|
|
||||||
|
var matched_entry : SceneIDEntry = null
|
||||||
|
for entry in entries:
|
||||||
|
if entry.scene_id == scene_id:
|
||||||
|
matched_entry = entry
|
||||||
|
break
|
||||||
|
|
||||||
|
if matched_entry == null:
|
||||||
|
result.add_warning(
|
||||||
|
"Scene ID %d is not registered in SceneIDDatabase."
|
||||||
|
% scene_id
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
if matched_entry.scene_uid != scene_uid:
|
||||||
|
result.add_warning(
|
||||||
|
"Scene ID %d belongs to a different scene."
|
||||||
|
% scene_id
|
||||||
|
)
|
||||||
|
|
||||||
|
if matched_entry.scene_path != scene_path:
|
||||||
|
result.add_warning(
|
||||||
|
"Scene ID %d path mismatch.\nDB: %s\nCurrent: %s"
|
||||||
|
% [scene_id, matched_entry.scene_path, scene_path]
|
||||||
|
)
|
||||||
|
|
||||||
|
# ✅ 无论有没有 warning,都返回 result
|
||||||
|
return result
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
@tool
|
||||||
|
extends Resource
|
||||||
|
class_name SceneIDEntry
|
||||||
|
|
||||||
|
@export var scene_path: String
|
||||||
|
@export var scene_uid: String
|
||||||
|
@export var scene_id: int
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://u5521mvu4rsw
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
@tool
|
||||||
|
extends ConfirmationDialog
|
||||||
|
class_name SceneIDRequestDialog
|
||||||
|
|
||||||
|
signal request_confirmed(prefix: int)
|
||||||
|
|
||||||
|
var _prefix_edit: SpinBox
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
title = "Request Scene ID"
|
||||||
|
ok_button_text = "Request"
|
||||||
|
cancel_button_text = "Cancel"
|
||||||
|
|
||||||
|
var v := VBoxContainer.new()
|
||||||
|
add_child(v)
|
||||||
|
|
||||||
|
# Prefix
|
||||||
|
var h := HBoxContainer.new()
|
||||||
|
v.add_child(h)
|
||||||
|
|
||||||
|
var l := Label.new()
|
||||||
|
l.text = "Prefix:"
|
||||||
|
h.add_child(l)
|
||||||
|
|
||||||
|
_prefix_edit = SpinBox.new()
|
||||||
|
_prefix_edit.min_value = 0
|
||||||
|
_prefix_edit.max_value = 99999999
|
||||||
|
_prefix_edit.step = 1
|
||||||
|
_prefix_edit.value = 10000 # 默认值,可改成自动推断
|
||||||
|
_prefix_edit.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
|
h.add_child(_prefix_edit)
|
||||||
|
|
||||||
|
confirmed.connect(_on_confirmed)
|
||||||
|
|
||||||
|
func _on_confirmed() -> void:
|
||||||
|
request_confirmed.emit(int(_prefix_edit.value))
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://db5uy3p0j82o6
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
extends RefCounted
|
||||||
|
class_name SceneIDValidationResult
|
||||||
|
|
||||||
|
var is_valid: bool = true
|
||||||
|
var messages: PackedStringArray = []
|
||||||
|
|
||||||
|
func add_warning(msg: String) -> void:
|
||||||
|
is_valid = false
|
||||||
|
messages.append(msg)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://d1c3ov1qwrm3m
|
||||||
|
|
@ -1,74 +1,68 @@
|
||||||
@tool
|
|
||||||
class_name SceneManager
|
class_name SceneManager
|
||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
@export var MainNodes: Array[Node]
|
## ==============================
|
||||||
@export var GameView: Node
|
## References
|
||||||
@export var TransitionNode: Node
|
## ==============================
|
||||||
|
var _scene: ReedScene
|
||||||
func _enter_tree() -> void:
|
var _act_manager: ActManager
|
||||||
check()
|
var _props: Dictionary # prop_id -> PropComponent
|
||||||
|
|
||||||
|
## ==============================
|
||||||
|
## Lifecycle
|
||||||
|
## ==============================
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
if !Engine.is_editor_hint():
|
await get_parent().ready
|
||||||
add_to_group("SceneManager")
|
|
||||||
get_tree().node_removed.connect(check)
|
_resolve_scene()
|
||||||
|
if _scene == null:
|
||||||
# =========================
|
push_error("[SceneManager] Parent is not ReedScene.")
|
||||||
# 对外 API
|
|
||||||
# =========================
|
|
||||||
static func change(scene_path: String) -> void:
|
|
||||||
var mgr := get_instance()
|
|
||||||
if mgr:
|
|
||||||
mgr._change(scene_path)
|
|
||||||
else:
|
|
||||||
push_error("SceneManager not found in scene tree")
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# 内部逻辑
|
|
||||||
# =========================
|
|
||||||
func _change(scene_path: String) -> void:
|
|
||||||
if GameView == null:
|
|
||||||
push_error("SceneManager: GameView is null")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# 清空旧场景
|
|
||||||
for child in GameView.get_children():
|
|
||||||
child.queue_free()
|
|
||||||
|
|
||||||
# 加载新场景
|
|
||||||
var packed: PackedScene = load(scene_path)
|
|
||||||
if packed == null:
|
|
||||||
push_error("Failed to load scene: %s" % scene_path)
|
|
||||||
return
|
|
||||||
|
|
||||||
var instance := packed.instantiate()
|
|
||||||
GameView.add_child(instance)
|
|
||||||
|
|
||||||
print_debug("SceneManager: Changed scene to ", scene_path)
|
|
||||||
|
|
||||||
# =========================
|
_resolve_references()
|
||||||
# 结构检查 / 自修复
|
_bind_signals()
|
||||||
# =========================
|
|
||||||
func check(node: Node = null) -> void:
|
|
||||||
if TransitionNode == node:
|
|
||||||
TransitionNode = null
|
|
||||||
|
|
||||||
var tr := find_child("Transition")
|
## ==============================
|
||||||
if tr != null:
|
## Resolve References
|
||||||
if TransitionNode == null:
|
## ==============================
|
||||||
TransitionNode = tr
|
func _resolve_scene() -> void:
|
||||||
|
var p := get_parent()
|
||||||
|
if p is ReedScene:
|
||||||
|
_scene = p
|
||||||
else:
|
else:
|
||||||
if TransitionNode == null:
|
_scene = null
|
||||||
var transition := Control.new()
|
|
||||||
transition.name = "Transition"
|
|
||||||
add_child.call_deferred(transition)
|
|
||||||
transition.set_owner.call_deferred(self)
|
|
||||||
TransitionNode = transition
|
|
||||||
|
|
||||||
# =========================
|
func _resolve_references() -> void:
|
||||||
# 工具
|
# 从 ReedScene 拿“整理好的结果”
|
||||||
# =========================
|
_act_manager = _scene._act_manager
|
||||||
static func get_instance() -> SceneManager:
|
_props = _scene._prop_map
|
||||||
var tree := Engine.get_main_loop() as SceneTree
|
|
||||||
return tree.get_first_node_in_group("SceneManager") as SceneManager
|
|
||||||
|
## ==============================
|
||||||
|
## Signal Binding
|
||||||
|
## ==============================
|
||||||
|
|
||||||
|
func _bind_signals() -> void:
|
||||||
|
if _act_manager:
|
||||||
|
_act_manager.act_changed.connect(_on_act_changed)
|
||||||
|
|
||||||
|
#for prop_id in _props:
|
||||||
|
#var prop : PropComponent = _props[prop_id]
|
||||||
|
#_bind_prop_signals(prop)
|
||||||
|
#
|
||||||
|
#func _bind_prop_signals(prop: PropComponent) -> void:
|
||||||
|
## 示例:监听 prop 的自定义信号
|
||||||
|
#if prop.has_signal("activated"):
|
||||||
|
#prop.activated.connect(func():
|
||||||
|
#_on_prop_activated(prop)
|
||||||
|
#)
|
||||||
|
|
||||||
|
|
||||||
|
## ==============================
|
||||||
|
## Callbacks
|
||||||
|
## ==============================
|
||||||
|
func _on_act_changed(from_act: int, to_act: int) -> void:
|
||||||
|
print("[SceneManager] Act changed:", from_act, "->", to_act)
|
||||||
|
|
||||||
|
func _on_prop_activated(prop: PropComponent) -> void:
|
||||||
|
print("[SceneManager] Prop activated:", prop.prop_id)
|
||||||
|
|
|
||||||
|
|
@ -1,103 +1,63 @@
|
||||||
# id (int) -> WeakRef(ReedScene)
|
extends Node
|
||||||
var _by_id: Dictionary = {}
|
|
||||||
|
|
||||||
signal registered(id: int, node: ReedScene)
|
## SceneID -> ReedScene
|
||||||
signal unregistered(id: int)
|
var _scene_map: Dictionary = {}
|
||||||
signal conflict(id: int, existing: ReedScene, incoming: ReedScene)
|
## SceneID -> ReedSceneIDComp
|
||||||
|
var _scene_id_comp_map: Dictionary[int, ReedSceneID] = {}
|
||||||
|
|
||||||
# -------------------------
|
signal scene_registered(scene_id: int, scene: ReedScene)
|
||||||
# 注册
|
signal scene_unregistered(scene_id: int)
|
||||||
# -------------------------
|
|
||||||
func register(id: int, node: ReedScene) -> bool:
|
func register_scene(scene: ReedScene) -> bool:
|
||||||
if id < 0:
|
if scene == null:
|
||||||
push_error("[SceneRegistry] register(): invalid id (<0): %d" % id)
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if node == null:
|
var id_comp := scene.get_scene_id_comp()
|
||||||
push_error("[SceneRegistry] register(): node is null for id=%d" % id)
|
if id_comp == null:
|
||||||
|
push_warning("[SceneRegistry] Scene has no ReedSceneID.")
|
||||||
return false
|
return false
|
||||||
|
|
||||||
_cleanup_dead(id)
|
return register_scene_with_id(id_comp.scene_id, scene, id_comp)
|
||||||
|
|
||||||
if _by_id.has(id):
|
func register_scene_with_id(
|
||||||
var existing: ReedScene = _by_id[id].get_ref()
|
scene_id: int,
|
||||||
if existing == node:
|
scene: ReedScene,
|
||||||
return true # 重复注册同一个实例,忽略
|
id_comp: ReedSceneID = null
|
||||||
|
) -> bool:
|
||||||
emit_signal("conflict", id, existing, node)
|
if scene_id < 0:
|
||||||
push_error(
|
push_warning("[SceneRegistry] Reject invalid SceneID: %d" % scene_id)
|
||||||
"[SceneRegistry] Duplicate id=%d existing=%s incoming=%s"
|
|
||||||
% [id, existing, node]
|
|
||||||
)
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
_by_id[id] = weakref(node)
|
if _scene_map.has(scene_id):
|
||||||
emit_signal("registered", id, node)
|
push_warning("[SceneRegistry] SceneID already registered: %d" % scene_id)
|
||||||
|
return false
|
||||||
|
|
||||||
|
_scene_map[scene_id] = scene
|
||||||
|
|
||||||
|
if id_comp != null:
|
||||||
|
_scene_id_comp_map[scene_id] = id_comp
|
||||||
|
|
||||||
|
if scene.debug_log:
|
||||||
|
print("[SceneRegistry] Registered Scene:", scene_id, scene.name)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
# -------------------------
|
|
||||||
# 注销
|
func unregister_scene(scene: ReedScene) -> void:
|
||||||
# -------------------------
|
if scene == null:
|
||||||
func unregister(id: int, node: ReedScene = null) -> void:
|
|
||||||
if not _by_id.has(id):
|
|
||||||
return
|
return
|
||||||
|
|
||||||
var existing: ReedScene = _by_id[id].get_ref()
|
var id_comp := scene.get_node_or_null("SceneID") as ReedSceneID
|
||||||
if node != null and existing != node:
|
if id_comp == null:
|
||||||
# 防止误删
|
|
||||||
return
|
return
|
||||||
|
|
||||||
_by_id.erase(id)
|
var scene_id := id_comp.scene_id
|
||||||
emit_signal("unregistered", id)
|
if not _scene_map.has(scene_id):
|
||||||
|
|
||||||
# -------------------------
|
|
||||||
# 查询
|
|
||||||
# -------------------------
|
|
||||||
func get_scene(id: int) -> ReedScene:
|
|
||||||
_cleanup_dead(id)
|
|
||||||
var ref: WeakRef = _by_id.get(id)
|
|
||||||
return ref.get_ref() if ref else null
|
|
||||||
|
|
||||||
func has(id: int) -> bool:
|
|
||||||
return get_scene(id) != null
|
|
||||||
|
|
||||||
# -------------------------
|
|
||||||
# 调用
|
|
||||||
# -------------------------
|
|
||||||
func call_scene(id: int, method: String, args: Array = []) -> Variant:
|
|
||||||
var n := get_scene(id)
|
|
||||||
if n == null:
|
|
||||||
push_warning("[SceneRegistry] call_scene(): id not found: %d" % id)
|
|
||||||
return null
|
|
||||||
|
|
||||||
if not n.has_method(method):
|
|
||||||
push_warning(
|
|
||||||
"[SceneRegistry] call_scene(): id=%d has no method '%s'"
|
|
||||||
% [id, method]
|
|
||||||
)
|
|
||||||
return null
|
|
||||||
|
|
||||||
return n.callv(method, args)
|
|
||||||
|
|
||||||
# -------------------------
|
|
||||||
# 列表
|
|
||||||
# -------------------------
|
|
||||||
func list_ids() -> PackedInt32Array:
|
|
||||||
for id in _by_id.keys():
|
|
||||||
_cleanup_dead(id)
|
|
||||||
|
|
||||||
var result := PackedInt32Array()
|
|
||||||
for id in _by_id.keys():
|
|
||||||
result.append(id)
|
|
||||||
return result
|
|
||||||
|
|
||||||
# -------------------------
|
|
||||||
# 内部:清理死引用
|
|
||||||
# -------------------------
|
|
||||||
func _cleanup_dead(id: int) -> void:
|
|
||||||
if not _by_id.has(id):
|
|
||||||
return
|
return
|
||||||
|
|
||||||
var ref: WeakRef = _by_id[id]
|
_scene_map.erase(scene_id)
|
||||||
if ref == null or ref.get_ref() == null:
|
_scene_id_comp_map.erase(scene_id)
|
||||||
_by_id.erase(id)
|
|
||||||
|
|
||||||
|
func get_scene(scene_id: int) -> ReedScene:
|
||||||
|
return _scene_map.get(scene_id, null)
|
||||||
|
|
|
||||||
|
|
@ -14,27 +14,6 @@ V0.3
|
||||||
|
|
||||||
- 实现了通过切换ActID来切换Act的功能
|
- 实现了通过切换ActID来切换Act的功能
|
||||||
|
|
||||||
## 更新计划
|
V1.0
|
||||||
|
|
||||||
V0.1
|
- Scene管理器全局ID功能
|
||||||
|
|
||||||
主要的工作是搭建一个插件的基本架构
|
|
||||||
|
|
||||||
V0.2
|
|
||||||
|
|
||||||
完善PropState的功能
|
|
||||||
|
|
||||||
V0.3
|
|
||||||
|
|
||||||
完善Act的功能
|
|
||||||
|
|
||||||
- Act管理器,负责切换Act,广播通知当前Scene下属的Prop进行状态切换。
|
|
||||||
- Act的快捷创建各种不同的Act。
|
|
||||||
|
|
||||||
V0.4
|
|
||||||
|
|
||||||
完善Scene的功能
|
|
||||||
|
|
||||||
- Scene具有全局唯一的ID,
|
|
||||||
- SceneManager可以切换Act,也可以切换PropState,也可以通过ID获取到Prop
|
|
||||||
-
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ CameraSystem="*res://_shared/CameraSystem.tscn"
|
||||||
RoomSystem="*res://_shared/room_system.gd"
|
RoomSystem="*res://_shared/room_system.gd"
|
||||||
GlobalEvent="*res://_shared/global_event.gd"
|
GlobalEvent="*res://_shared/global_event.gd"
|
||||||
ReedVFX="*res://addons/reedfx/vfx/ReedVFXSystem.tscn"
|
ReedVFX="*res://addons/reedfx/vfx/ReedVFXSystem.tscn"
|
||||||
ReedSceneSystem="*res://addons/reedscene/scene/SceneRegistry.gd"
|
ReedSceneRegistry="*res://addons/reedscene/scene/SceneRegistry.gd"
|
||||||
|
|
||||||
[display]
|
[display]
|
||||||
|
|
||||||
|
|
@ -95,3 +95,4 @@ grap_hook={
|
||||||
2d_physics/layer_2="Player"
|
2d_physics/layer_2="Player"
|
||||||
2d_physics/layer_3="Environment"
|
2d_physics/layer_3="Environment"
|
||||||
2d_physics/layer_4="Damage"
|
2d_physics/layer_4="Damage"
|
||||||
|
2d_physics/layer_5="Collectable"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue