小更新

This commit is contained in:
Reed 2026-01-01 16:33:32 +08:00
parent 93aa31c38e
commit bc848b8526
17 changed files with 320 additions and 10 deletions

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=39 format=4 uid="uid://bj2318o3y68x2"] [gd_scene load_steps=40 format=4 uid="uid://bj2318o3y68x2"]
[ext_resource type="Script" uid="uid://ds6jy3s0hhmwt" path="res://_game/DemoScript.gd" id="1_2tycc"] [ext_resource type="Script" uid="uid://ds6jy3s0hhmwt" path="res://_game/DemoScript.gd" id="1_2tycc"]
[ext_resource type="PackedScene" uid="uid://1l06de041i40" path="res://_levels/l_level_1.tscn" id="1_p0ota"] [ext_resource type="PackedScene" uid="uid://1l06de041i40" path="res://_levels/l_level_1.tscn" id="1_p0ota"]
@ -7,6 +7,7 @@
[ext_resource type="PackedScene" uid="uid://b5nx4dntm0gyn" path="res://_props/door_manager/event_trigger_door.tscn" id="4_p0ota"] [ext_resource type="PackedScene" uid="uid://b5nx4dntm0gyn" path="res://_props/door_manager/event_trigger_door.tscn" id="4_p0ota"]
[ext_resource type="Script" uid="uid://b4menkyub4ce7" path="res://addons/reedscene/prop/PropComponent.gd" id="5_gslp7"] [ext_resource type="Script" uid="uid://b4menkyub4ce7" path="res://addons/reedscene/prop/PropComponent.gd" id="5_gslp7"]
[ext_resource type="Script" uid="uid://7lml6d1t5xtq" path="res://addons/reedscene/prop/PropState.gd" id="6_6jw57"] [ext_resource type="Script" uid="uid://7lml6d1t5xtq" path="res://addons/reedscene/prop/PropState.gd" id="6_6jw57"]
[ext_resource type="Script" uid="uid://bh066o84byplh" path="res://addons/reedscene/scene/ReedSceneID.gd" id="6_hc6q0"]
[ext_resource type="Script" uid="uid://cdvgq0xqdbagk" path="res://addons/reedscene/prop/ReedPropEffect.gd" id="7_2t6pm"] [ext_resource type="Script" uid="uid://cdvgq0xqdbagk" path="res://addons/reedscene/prop/ReedPropEffect.gd" id="7_2t6pm"]
[ext_resource type="Script" uid="uid://fxpk2ot6otfh" path="res://addons/reedscene/act/Act.gd" id="7_xotud"] [ext_resource type="Script" uid="uid://fxpk2ot6otfh" path="res://addons/reedscene/act/Act.gd" id="7_xotud"]
[ext_resource type="Script" uid="uid://baqgorvlumyju" path="res://addons/reedscene/act/SingleAct.gd" id="8_2tycc"] [ext_resource type="Script" uid="uid://baqgorvlumyju" path="res://addons/reedscene/act/SingleAct.gd" id="8_2tycc"]
@ -50,12 +51,12 @@ script = ExtResource("8_2tycc")
state_id = 1 state_id = 1
metadata/_custom_type_script = "uid://baqgorvlumyju" metadata/_custom_type_script = "uid://baqgorvlumyju"
[sub_resource type="Resource" id="Resource_xiw5v"] [sub_resource type="Resource" id="Resource_cqglw"]
script = ExtResource("8_2tycc") script = ExtResource("8_2tycc")
state_id = 1 state_id = 1
metadata/_custom_type_script = "uid://baqgorvlumyju" metadata/_custom_type_script = "uid://baqgorvlumyju"
[sub_resource type="Resource" id="Resource_cqglw"] [sub_resource type="Resource" id="Resource_xiw5v"]
script = ExtResource("8_2tycc") script = ExtResource("8_2tycc")
state_id = 1 state_id = 1
metadata/_custom_type_script = "uid://baqgorvlumyju" metadata/_custom_type_script = "uid://baqgorvlumyju"
@ -164,6 +165,11 @@ collision_mask = 4
script = ExtResource("13_2tycc") script = ExtResource("13_2tycc")
metadata/_custom_type_script = "uid://5e157vdk6175" metadata/_custom_type_script = "uid://5e157vdk6175"
[node name="ReedSceneID" type="Node" parent="ReedScene"]
script = ExtResource("6_hc6q0")
scene_id = 10000
metadata/_custom_type_script = "uid://bh066o84byplh"
[node name="SceneManager" type="Node" parent="ReedScene" node_paths=PackedStringArray("TransitionNode")] [node name="SceneManager" type="Node" parent="ReedScene" node_paths=PackedStringArray("TransitionNode")]
script = ExtResource("15_hc6q0") script = ExtResource("15_hc6q0")
TransitionNode = NodePath("Transition") TransitionNode = NodePath("Transition")

View File

@ -0,0 +1,10 @@
[gd_resource type="Resource" script_class="SceneIDDatabase" load_steps=2 format=3 uid="uid://4c26uejocdos"]
[ext_resource type="Script" uid="uid://delj6tsrxv8s3" path="res://addons/reedscene/scene/SceneIDDatabase.gd" id="1_47k6c"]
[resource]
script = ExtResource("1_47k6c")
next_id = 10001
scene_map = {
"res://_game/LevelDemonstration.tscn": 10000
}

View File

@ -0,0 +1,27 @@
@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")

View File

@ -0,0 +1 @@
uid://bi8dmt4ypmbhq

View File

@ -0,0 +1,17 @@
[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

View File

@ -1,14 +1,69 @@
@tool @tool
extends EditorPlugin extends EditorPlugin
var inspector_plugin var inspector_plugins: Array[EditorInspectorPlugin] = []
const AUTOLOAD_REED_SCENE_NAME: StringName = "ReedSceneSystem"
const AUTOLOAD_REED_SCENE_PATH:= "res://addons/reedscene/scene/SceneRegistry.gd"
var toolbar_button: Button
var scene_id_window: Window
var main_screen: Control
func _enter_tree() -> void: func _enter_tree() -> void:
inspector_plugin = preload("res://addons/reedscene/act/ActManagerInspector.gd").new() _load_mainscreen()
# ✅ 注入 EditorInterface
inspector_plugin.editor_interface = get_editor_interface() if not ProjectSettings.has_setting("autoload/%s" % AUTOLOAD_REED_SCENE_NAME):
add_inspector_plugin(inspector_plugin) add_autoload_singleton(AUTOLOAD_REED_SCENE_NAME, AUTOLOAD_REED_SCENE_PATH)
# Inspector 1你已有的
var act_inspector := preload(
"res://addons/reedscene/act/ActManagerInspector.gd"
).new()
act_inspector.editor_interface = get_editor_interface()
add_inspector_plugin(act_inspector)
inspector_plugins.append(act_inspector)
# Inspector 2新的比如 ReedSceneID
var scene_id_inspector := preload(
"res://addons/reedscene/scene/ReedSceneIDInspector.gd"
).new()
add_inspector_plugin(scene_id_inspector)
inspector_plugins.append(scene_id_inspector)
func _exit_tree() -> void: func _exit_tree() -> void:
if inspector_plugin: _unload_mainscreen()
remove_inspector_plugin(inspector_plugin)
##自动删除单例
if ProjectSettings.has_setting("autoload/%s" % AUTOLOAD_REED_SCENE_NAME):
remove_autoload_singleton(AUTOLOAD_REED_SCENE_NAME)
# 移除 InspectorPlugin
for plugin in inspector_plugins:
remove_inspector_plugin(plugin)
inspector_plugins.clear()
##加載主界面
func _load_mainscreen() -> void:
main_screen = preload("res://addons/reedscene/dock/scene_id_main_screen.tscn").instantiate()
EditorInterface.get_editor_main_screen().add_child(main_screen)
main_screen.visible = false
##卸載主界面
func _unload_mainscreen() -> void:
if main_screen:
main_screen.queue_free()
main_screen = null
func _has_main_screen() -> bool:
return true
func _make_visible(visible: bool) -> void:
if main_screen:
main_screen.visible = visible
func _get_plugin_name() -> String:
return "Reed Scene"
func _get_plugin_icon() -> Texture2D:
return EditorInterface.get_editor_theme().get_icon("Node", "EditorIcons")

View File

@ -0,0 +1,8 @@
@tool
extends Node
class_name ReedSceneID
@export var scene_id: int = -1
func has_id() -> bool:
return scene_id >= 0

View File

@ -0,0 +1 @@
uid://bh066o84byplh

View File

@ -0,0 +1,39 @@
@tool
extends RefCounted
class_name ReedSceneIDEditorSystem
const DB_PATH := "res://addons/reedscene/demo/data_base/GLOBAL_SCENE_ID.tres"
static func _load_db_readonly() -> SceneIDDatabase:
# 忽略缓存,避免拿到同一个共享实例(更稳)
return ResourceLoader.load(DB_PATH, "", ResourceLoader.CACHE_MODE_IGNORE)
static func _clone_db_to_new(db_ro: SceneIDDatabase) -> SceneIDDatabase:
var db := SceneIDDatabase.new()
if db_ro:
db.next_id = db_ro.next_id
# 深拷贝 Dictionary彻底断开只读引用链
db.scene_map = db_ro.scene_map.duplicate(true)
return db
static func request_id_for_scene(scene_path: String) -> int:
var db_ro := _load_db_readonly()
if db_ro == null:
push_error("[ReedSceneIDEditorSystem] Database not found: " + DB_PATH)
return -1
var db := _clone_db_to_new(db_ro)
if db.scene_map.has(scene_path):
return int(db.scene_map[scene_path])
var new_id := db.next_id
db.next_id += 1
db.scene_map[scene_path] = new_id
var err := ResourceSaver.save(db, DB_PATH)
if err != OK:
push_error("[ReedSceneIDEditorSystem] Failed to save DB (%s), err=%d" % [DB_PATH, err])
return -1
return new_id

View File

@ -0,0 +1 @@
uid://b86r8tai4kygo

View File

@ -0,0 +1,31 @@
@tool
extends EditorInspectorPlugin
func _can_handle(object) -> bool:
return object is ReedSceneID
func _parse_begin(object):
var button := Button.new()
button.text = "Request Scene ID"
button.pressed.connect(func():
_request_id(object)
)
add_custom_control(button)
func _request_id(id_comp: ReedSceneID):
var scene := id_comp.get_owner()
if scene == null:
push_error("[ReedSceneID] Cannot find owning scene")
return
var scene_path := scene.scene_file_path
if scene_path == "":
push_error("[ReedSceneID] Scene must be saved before requesting ID")
return
var id := ReedSceneIDEditorSystem.request_id_for_scene(scene_path)
if id < 0:
return
id_comp.scene_id = id
id_comp.notify_property_list_changed()

View File

@ -0,0 +1 @@
uid://h6liq147is5g

View File

@ -0,0 +1,7 @@
extends Resource
class_name SceneIDDatabase
@export var next_id: int = 10000
# scene_path (String) -> scene_id (int)
@export var scene_map: Dictionary = {}

View File

@ -0,0 +1 @@
uid://delj6tsrxv8s3

View File

@ -0,0 +1,103 @@
# id (int) -> WeakRef(ReedScene)
var _by_id: Dictionary = {}
signal registered(id: int, node: ReedScene)
signal unregistered(id: int)
signal conflict(id: int, existing: ReedScene, incoming: ReedScene)
# -------------------------
# 注册
# -------------------------
func register(id: int, node: ReedScene) -> bool:
if id < 0:
push_error("[SceneRegistry] register(): invalid id (<0): %d" % id)
return false
if node == null:
push_error("[SceneRegistry] register(): node is null for id=%d" % id)
return false
_cleanup_dead(id)
if _by_id.has(id):
var existing: ReedScene = _by_id[id].get_ref()
if existing == node:
return true # 重复注册同一个实例,忽略
emit_signal("conflict", id, existing, node)
push_error(
"[SceneRegistry] Duplicate id=%d existing=%s incoming=%s"
% [id, existing, node]
)
return false
_by_id[id] = weakref(node)
emit_signal("registered", id, node)
return true
# -------------------------
# 注销
# -------------------------
func unregister(id: int, node: ReedScene = null) -> void:
if not _by_id.has(id):
return
var existing: ReedScene = _by_id[id].get_ref()
if node != null and existing != node:
# 防止误删
return
_by_id.erase(id)
emit_signal("unregistered", 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
var ref: WeakRef = _by_id[id]
if ref == null or ref.get_ref() == null:
_by_id.erase(id)

View File

@ -0,0 +1 @@
uid://iau86ajv4jv

View File

@ -22,6 +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"
[display] [display]