Skip to content

Commit 62c0cc1

Browse files
CopilotLexian-droid
andcommitted
Add object-based event sheet support to FlowKit
- Modified flowkit_inspector_section.gd to add Event Sheet section in the inspector - Added New, Assign, Edit, and Clear buttons for event sheet management - Updated flowkit_engine.gd to scan nodes for attached event sheets (flowkit_event_sheet metadata) - Updated editor.gd to support editing both scene-based and object-based event sheets - Event sheets can now be assigned to individual nodes like regular Godot scripts Co-authored-by: Lexian-droid <83799577+Lexian-droid@users.noreply.github.com>
1 parent cfb33ae commit 62c0cc1

3 files changed

Lines changed: 345 additions & 9 deletions

File tree

addons/flowkit/runtime/flowkit_engine.gd

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ func _on_scene_changed(scene_root: Node) -> void:
7070
# Scan and activate behaviors for all nodes in the scene
7171
_scan_and_activate_behaviors(scene_root)
7272

73-
# Load event sheets for the scene root and any instanced child scenes
73+
# Load event sheets for nodes with attached event sheets (object-based)
74+
# and also load scene-based sheets for backward compatibility
7475
_load_sheets_for_scene(scene_root)
7576

7677

@@ -79,6 +80,44 @@ func _load_sheets_for_scene(scene_root: Node) -> void:
7980
# Clear previous sheets
8081
active_sheets.clear()
8182

83+
# First, scan for object-based event sheets (nodes with flowkit_event_sheet metadata)
84+
_scan_and_load_object_sheets(scene_root)
85+
86+
# Then, load scene-based sheets for backward compatibility
87+
_load_scene_based_sheets(scene_root)
88+
89+
90+
func _scan_and_load_object_sheets(node: Node) -> void:
91+
"""Recursively scan nodes for attached event sheets (object-based)."""
92+
# Check if this node has an event sheet assigned
93+
if node.has_meta("flowkit_event_sheet"):
94+
var sheet_path: String = node.get_meta("flowkit_event_sheet", "")
95+
if not sheet_path.is_empty() and ResourceLoader.exists(sheet_path):
96+
var sheet: FKEventSheet = load(sheet_path)
97+
if sheet:
98+
# Ensure all blocks have unique IDs
99+
for block in sheet.events:
100+
if block:
101+
block.ensure_block_id()
102+
_ensure_block_ids_in_groups(sheet.groups)
103+
104+
# Add entry with this node as the root context
105+
active_sheets.append({
106+
"sheet": sheet,
107+
"root": node,
108+
"scene_name": sheet_path.get_file().get_basename(),
109+
"uid": -1, # Object-based sheets use -1 to indicate not scene-based
110+
"object_based": true
111+
})
112+
print("[FlowKit] Loaded object-based event sheet for node: ", node.name, " (", sheet_path.get_file(), ") with ", sheet.events.size(), " events")
113+
114+
# Recursively scan children
115+
for child in node.get_children():
116+
_scan_and_load_object_sheets(child)
117+
118+
119+
func _load_scene_based_sheets(scene_root: Node) -> void:
120+
"""Load scene-based event sheets (legacy/backward compatibility)."""
82121
# Collect unique scene_file_path UIDs and map to their root node instances
83122
var uid_to_node: Dictionary = {}
84123

addons/flowkit/ui/editor.gd

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ var registry: Node
66
var generator
77
var current_scene_uid: int = 0
88

9+
# Object-based event sheet editing
10+
var editing_object_sheet: bool = false # True when editing an object-based sheet (not scene-based)
11+
var current_sheet_path: String = "" # Path to the currently edited event sheet
12+
var current_object_node: Node = null # The node that has this sheet attached (for object-based editing)
13+
914
# Scene preloads - GDevelop-style event rows
1015
const EVENT_ROW_SCENE = preload("res://addons/flowkit/ui/workspace/event_row.tscn")
1116
const COMMENT_SCENE = preload("res://addons/flowkit/ui/workspace/comment.tscn")
@@ -885,6 +890,10 @@ func _process(delta: float) -> void:
885890
if not editor_interface:
886891
return
887892

893+
# If editing an object-based sheet, don't auto-switch to scene-based
894+
if editing_object_sheet:
895+
return
896+
888897
var scene_root = editor_interface.get_edited_scene_root()
889898
if not scene_root:
890899
if current_scene_uid != 0:
@@ -944,13 +953,55 @@ func _show_content_state() -> void:
944953
# === File Operations ===
945954

946955
func _get_sheet_path() -> String:
947-
"""Get the file path for current scene's event sheet."""
956+
"""Get the file path for current event sheet (object-based or scene-based)."""
957+
# Object-based sheet path takes precedence
958+
if editing_object_sheet and not current_sheet_path.is_empty():
959+
return current_sheet_path
960+
961+
# Scene-based path
948962
if current_scene_uid == 0:
949963
return ""
950964
return "res://addons/flowkit/saved/event_sheet/%d.tres" % current_scene_uid
951965

966+
func edit_event_sheet(sheet_path: String) -> void:
967+
"""Edit a specific event sheet file (called from inspector for object-based sheets)."""
968+
editing_object_sheet = true
969+
current_sheet_path = sheet_path
970+
current_scene_uid = 0 # Clear scene-based tracking
971+
972+
_clear_undo_history()
973+
_clear_all_blocks()
974+
975+
if not FileAccess.file_exists(sheet_path):
976+
# Create a new empty sheet at this path
977+
var new_sheet = FKEventSheet.new()
978+
var dir_path = sheet_path.get_base_dir()
979+
DirAccess.make_dir_recursive_absolute(dir_path)
980+
var error = ResourceSaver.save(new_sheet, sheet_path)
981+
if error != OK:
982+
push_error("[FlowKit] Failed to create event sheet: ", sheet_path)
983+
_show_empty_state()
984+
return
985+
print("[FlowKit] Created new event sheet: ", sheet_path)
986+
_show_empty_blocks_state()
987+
return
988+
989+
var sheet = ResourceLoader.load(sheet_path)
990+
if not (sheet is FKEventSheet):
991+
push_error("[FlowKit] Invalid event sheet resource: ", sheet_path)
992+
_show_empty_blocks_state()
993+
return
994+
995+
_populate_from_sheet(sheet)
996+
_show_content_state()
997+
print("[FlowKit] Editing object-based event sheet: ", sheet_path)
998+
952999
func _load_scene_sheet() -> void:
953-
"""Load event sheet for current scene."""
1000+
"""Load event sheet for current scene (scene-based mode)."""
1001+
# Reset object-based mode when loading scene sheet
1002+
editing_object_sheet = false
1003+
current_sheet_path = ""
1004+
9541005
_clear_all_blocks()
9551006

9561007
var sheet_path = _get_sheet_path()
@@ -991,16 +1042,19 @@ func _populate_from_sheet(sheet: FKEventSheet) -> void:
9911042

9921043
func _save_sheet() -> void:
9931044
"""Generate and save event sheet from current blocks."""
994-
if current_scene_uid == 0:
995-
push_warning("No scene open to save event sheet.")
1045+
var sheet_path = _get_sheet_path()
1046+
1047+
# Check if we have a valid path (either object-based or scene-based)
1048+
if sheet_path.is_empty():
1049+
if not editing_object_sheet and current_scene_uid == 0:
1050+
push_warning("No scene open to save event sheet.")
9961051
return
9971052

9981053
var sheet = _generate_sheet_from_blocks()
9991054

1000-
var dir_path = "res://addons/flowkit/saved/event_sheet"
1055+
var dir_path = sheet_path.get_base_dir()
10011056
DirAccess.make_dir_recursive_absolute(dir_path)
10021057

1003-
var sheet_path = _get_sheet_path()
10041058
var error = ResourceSaver.save(sheet, sheet_path)
10051059

10061060
if error == OK:
@@ -1011,7 +1065,10 @@ func _save_sheet() -> void:
10111065
func _save_and_reload_sheet() -> void:
10121066
"""Save sheet and reload UI to ensure visual/data sync (for drag-drop operations)."""
10131067
_save_sheet()
1014-
_load_scene_sheet()
1068+
if editing_object_sheet and not current_sheet_path.is_empty():
1069+
edit_event_sheet(current_sheet_path)
1070+
else:
1071+
_load_scene_sheet()
10151072

10161073
func _generate_sheet_from_blocks() -> FKEventSheet:
10171074
"""Build event sheet from event rows, comments, and groups (GDevelop-style)."""
@@ -1102,6 +1159,14 @@ func _copy_group_block(data: FKGroupBlock) -> FKGroupBlock:
11021159

11031160
func _new_sheet() -> void:
11041161
"""Create new empty sheet."""
1162+
# In object-based mode, clear the current sheet
1163+
if editing_object_sheet and not current_sheet_path.is_empty():
1164+
_clear_all_blocks()
1165+
_save_sheet() # Save the empty sheet
1166+
_show_content_state()
1167+
return
1168+
1169+
# In scene-based mode, require a scene
11051170
if current_scene_uid == 0:
11061171
push_warning("No scene open to create event sheet.")
11071172
return

0 commit comments

Comments
 (0)