diff --git a/GameEntry.tscn b/GameEntry.tscn new file mode 100644 index 0000000..a026a7a --- /dev/null +++ b/GameEntry.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=2 format=3 uid="uid://bgxnvmxg2jsx2"] + +[ext_resource type="PackedScene" uid="uid://b4ojkr2fq8xjm" path="res://_ui/main_menu/main_menu.tscn" id="1_fcou6"] + +[node name="GameEntry" type="Node"] + +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="MainMenu" parent="CanvasLayer" instance=ExtResource("1_fcou6")] diff --git a/_ui/main_menu/main_menu.tscn b/_ui/main_menu/main_menu.tscn new file mode 100644 index 0000000..fd1483e --- /dev/null +++ b/_ui/main_menu/main_menu.tscn @@ -0,0 +1,60 @@ +[gd_scene load_steps=2 format=3 uid="uid://b4ojkr2fq8xjm"] + +[ext_resource type="Texture2D" uid="uid://c673bap4b12fx" path="res://icon.svg" id="1_j8fyu"] + +[node name="MainMenu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="TextureRect" type="TextureRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("1_j8fyu") + +[node name="MC_Title" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="L_Title" type="Label" parent="MC_Title"] +layout_mode = 2 +text = "游戏名称" + +[node name="MC_Options" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="MC_Options"] +layout_mode = 2 + +[node name="B_Start" type="Button" parent="MC_Options/VBoxContainer"] +layout_mode = 2 +text = "Start" + +[node name="B_Continue" type="Button" parent="MC_Options/VBoxContainer"] +layout_mode = 2 +text = "Continue +" + +[node name="B_Option" type="Button" parent="MC_Options/VBoxContainer"] +layout_mode = 2 +text = "Option" + +[node name="B_Exit" type="Button" parent="MC_Options/VBoxContainer"] +layout_mode = 2 +text = "Exit" diff --git a/addons/reedfx/vfx/VFXSignalBinding.gd b/addons/reedfx/vfx/VFXSignalBinding.gd index 0264171..b0170ce 100644 --- a/addons/reedfx/vfx/VFXSignalBinding.gd +++ b/addons/reedfx/vfx/VFXSignalBinding.gd @@ -13,7 +13,14 @@ enum SpawnSpace { TARGET_NODE, ##如果是直接Spawn在World,需要提供一个额外的全局坐标 - WORLD_POSITION + WORLD_POSITION, +} + +## VFX 播放的层级 +enum SpawnLayer +{ + LOCAL, + GLOBAL } @export var spawn_space := SpawnSpace.TARGET_NODE diff --git a/addons/reedscene/act/StateDrapSlot.tscn b/addons/reedscene/act/StateDrapSlot.tscn index e01be3d..6b1d4d7 100644 --- a/addons/reedscene/act/StateDrapSlot.tscn +++ b/addons/reedscene/act/StateDrapSlot.tscn @@ -96,6 +96,7 @@ layout_mode = 2 text = "Choose" [node name="ClearButton" type="Button" parent="MarginContainer/HBC_Main/VBoxContainer/HBC_Drop/HBC_Option"] +unique_name_in_owner = true layout_mode = 2 text = "Clear" diff --git a/addons/reedscene/act/StateDropArea.gd b/addons/reedscene/act/StateDropArea.gd index d2e8786..e093186 100644 --- a/addons/reedscene/act/StateDropArea.gd +++ b/addons/reedscene/act/StateDropArea.gd @@ -11,11 +11,18 @@ const COLOR_CAN_DROP: Color = Color(0.4, 0.7, 1.0, 1.0) const COLOR_CANNOT_DROP: Color = Color(1.0, 0.35, 0.35, 1.0) const COLOR_CHECKED: Color = Color.GREEN +## 設置Locker的時候自更新一次State +var vaild: bool = false: + set(value): + _set_state(3) + vaild = value + var _icon: TextureRect var _state := 0 # 0 idle, 1 can, 2 cannot var _current_drag_data: Variant = null signal node_path_dropped(node_path: NodePath) +signal state_change(state: int) # ===================================================== # Life cycle @@ -81,6 +88,9 @@ func _set_state(s: int) -> void: match _state: 0: + if vaild: + _set_state(3) + return _icon.modulate = COLOR_IDLE 1: _icon.modulate = COLOR_CAN_DROP @@ -88,3 +98,5 @@ func _set_state(s: int) -> void: _icon.modulate = COLOR_CANNOT_DROP 3: _icon.modulate = COLOR_CHECKED + + state_change.emit(_state) diff --git a/addons/reedscene/act/StateDropSlot.gd b/addons/reedscene/act/StateDropSlot.gd index 2279fc8..af10fe6 100644 --- a/addons/reedscene/act/StateDropSlot.gd +++ b/addons/reedscene/act/StateDropSlot.gd @@ -8,6 +8,7 @@ extends Control @onready var context: RichTextLabel = %Context @onready var cb_use_trans: CheckBox = %CB_UseTrans +@onready var clear_button: Button = %ClearButton @onready var index: Label = %Index @@ -15,25 +16,57 @@ var _cached_single_act: SingleAct = null var _cached_prop_id: int = -1 var _cached_info: Dictionary +var _state: int = 0 + const NORMAL_STATE_LABLE: String = "Drag state node to icon." const NORMAL_CONTEXT: String = "Information will be show here." +#const ICON_COLOR: Dictionary = { + #"Idle": Color.GRAY, + #"" +#} const COLOR_IDLE: Color = Color.GRAY const COLOR_CHECKED_1: Color = Color.GREEN const COLOR_CHECKED_2: Color = Color.YELLOW const COLOR_CHECKED_3: Color = Color.ORANGE_RED + func _ready() -> void: _reset_to_default() _reset_cb_use_trans() if drop_area: drop_area.node_path_dropped.connect(_on_node_path_dropped) + drop_area.state_change.connect(_on_drap_area_state_change) + +## 核心函數,通過狀態機來控制UI組件的狀態。 +func _set_state(new_state: int) -> void: + if _state == new_state: + return + + _state = new_state + + match _state: + 0: ## 初始狀態,什麽都沒有 + pass + 1: ## vaild 狀態,可以插入了 + pass + +func _btn_init() -> void: + clear_button.pressed.connect(_on_clear_pressed) + +func _on_clear_pressed() -> void: + _clear_cached_act() func init(index: int) -> void: self.index.text = str(index) func _on_node_path_dropped(path: NodePath) -> void: + + ## 如果已經可以插入但是重新被插入了一個State,先clear再插入。 + if get_ready_to_insert(): + _clear_cached_act() + var state := StateResolveUtils.get_state_node_from_path(path) if state == null: _clear_cached_act() @@ -57,12 +90,12 @@ func _on_node_path_dropped(path: NodePath) -> void: _cached_prop_id = int(info.prop_id) - ## 启用 CheckBox - #cb_use_trans.disabled = false - #cb_use_trans.button_pressed = _cached_single_act.use_trans - - # 直接用 info + cached 刷 UI _update_context(info) + + drop_area.vaild = true + +func _on_drap_area_state_change(state:int) -> void: + pass func _on_use_trans_toggled(pressed: bool) -> void: # 如果存在就改,不存在無事發生 @@ -71,7 +104,6 @@ func _on_use_trans_toggled(pressed: bool) -> void: _update_context() - func _resolve_state_from_path(path: NodePath) -> ReedPropState: var root := EditorInterface.get_edited_scene_root() if root == null: @@ -116,6 +148,10 @@ func _build_cached_act(state: ReedPropState, info: Dictionary) -> void: func _clear_cached_act() -> void: _cached_single_act = null _cached_prop_id = -1 + _cached_info = {} + + drop_area.vaild = false + _update_context() ## 设置文本 func _update_context(info:Dictionary = {}) ->void: @@ -174,3 +210,13 @@ func _update_context(info:Dictionary = {}) ->void: bbcode += "[/cell][/table]" context.text = bbcode + + +## 外部調用,可以返回當前的Slot是否有效,懶檢查 +func get_ready_to_insert() -> bool: + return ( + _cached_single_act != null + and _cached_prop_id >= 0 + and _cached_info != null + and _cached_info != {} + ) diff --git a/addons/reedscene/act/StateQuickConfigPanel.gd b/addons/reedscene/act/StateQuickConfigPanel.gd index 18bb440..8c066c0 100644 --- a/addons/reedscene/act/StateQuickConfigPanel.gd +++ b/addons/reedscene/act/StateQuickConfigPanel.gd @@ -1,9 +1,20 @@ @tool extends PanelContainer -@onready var spawn_slot_root: VBoxContainer = %SpawnSlotRoot -@onready var add_button: Button = %AddButton -@onready var remove_button: Button = %RemoveButton +@onready var vbc_spawn_slot_root: VBoxContainer = %VBC_SpawnSlotRoot + +@onready var b_insert: Button = %B_Insert +@onready var b_remove: Button = %B_Remove +@onready var b_add: Button = %B_Add + +@onready var rtl_context: RichTextLabel = %RTL_Context + +const DEFAULT_CONTEXT: Dictionary = { + "default": "Press insert to generate a act.", + "removerr": "Act need at least on single act.", + "adderr": "Single act count cannot over the count of props.", + "inserterr": "Insert act with empty slot." +} var _inited: bool = false var _max_length: int = -1 @@ -16,14 +27,15 @@ func _ready() -> void: return # 连接按钮 - add_button.pressed.connect(_on_add_pressed) - remove_button.pressed.connect(_on_remove_pressed) + b_add.pressed.connect(_on_add_pressed) + b_remove.pressed.connect(_on_remove_pressed) + b_insert.pressed.connect(_on_insert_pressed) # 初始保证至少有一个 Slot - if spawn_slot_root.get_child_count() == 0: + if vbc_spawn_slot_root.get_child_count() == 0: _add_slot() - _update_remove_button_state() + _update_b_remove_state() func init(info:Dictionary) -> void: _inited = true @@ -36,26 +48,42 @@ func _on_add_pressed() -> void: func _on_remove_pressed() -> void: _remove_slot() +func _on_insert_pressed() -> void: + _insert_act() + +## 插入一個根據當前的條目生成的Act +func _insert_act()-> void: + var slots = vbc_spawn_slot_root.get_children() + for s in slots: + var vs = s as StateDrapSlot + if not vs: + continue ##後續要有報錯Message + + + +## 添加一個Slot,不能超過當前Scene的最大prop數量 func _add_slot() -> void: - if spawn_slot_root.get_child_count() >= _max_length: + if vbc_spawn_slot_root.get_child_count() >= _max_length: return var slot := SLOT.instantiate() - spawn_slot_root.add_child(slot) + vbc_spawn_slot_root.add_child(slot) slot.owner = get_tree().edited_scene_root # 编辑器可保存 - slot.init(spawn_slot_root.get_children().size()) + slot.init(vbc_spawn_slot_root.get_children().size()) - _update_remove_button_state() + _update_b_remove_state() +## 移除一個Slot,最少不能為0 func _remove_slot() -> void: - var count := spawn_slot_root.get_child_count() + var count := vbc_spawn_slot_root.get_child_count() if count <= 1: return - var last := spawn_slot_root.get_child(count - 1) + var last := vbc_spawn_slot_root.get_child(count - 1) last.queue_free() - _update_remove_button_state() + _update_b_remove_state() -func _update_remove_button_state() -> void: - remove_button.disabled = spawn_slot_root.get_child_count() <= 1 + +func _update_b_remove_state() -> void: + b_remove.disabled = vbc_spawn_slot_root.get_child_count() <= 1 diff --git a/addons/reedscene/act/StateQuickConfigPanel.tscn b/addons/reedscene/act/StateQuickConfigPanel.tscn index 0b516c2..6361bae 100644 --- a/addons/reedscene/act/StateQuickConfigPanel.tscn +++ b/addons/reedscene/act/StateQuickConfigPanel.tscn @@ -25,16 +25,17 @@ layout_mode = 2 text = "State Quick Config Panel" [node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer"] -custom_minimum_size = Vector2(0, 300) +custom_minimum_size = Vector2(0, 240) layout_mode = 2 size_flags_vertical = 3 -[node name="SpawnSlotRoot" type="VBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer"] +[node name="VBC_SpawnSlotRoot" type="VBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 -[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBoxContainer"] +[node name="RTL_Context" type="RichTextLabel" parent="MarginContainer/VBoxContainer"] +unique_name_in_owner = true custom_minimum_size = Vector2(0, 32) layout_mode = 2 bbcode_enabled = true @@ -44,21 +45,22 @@ fit_content = true [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"] layout_mode = 2 -[node name="AddButton" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"] +[node name="B_Add" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"] unique_name_in_owner = true custom_minimum_size = Vector2(0, 24) layout_mode = 2 size_flags_horizontal = 3 text = "Add" -[node name="RemoveButton" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"] +[node name="B_Remove" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"] unique_name_in_owner = true custom_minimum_size = Vector2(24, 24) layout_mode = 2 size_flags_horizontal = 3 +disabled = true text = "Remove" -[node name="InsertButton" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"] +[node name="B_Insert" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"] unique_name_in_owner = true custom_minimum_size = Vector2(24, 24) layout_mode = 2