diff --git a/addons/flowkit/actions/System/action_press.gd.uid b/addons/flowkit/actions/System/action_press.gd.uid new file mode 100644 index 0000000..a919c09 --- /dev/null +++ b/addons/flowkit/actions/System/action_press.gd.uid @@ -0,0 +1 @@ +uid://c10kcwopyvsey diff --git a/addons/flowkit/actions/System/action_release.gd.uid b/addons/flowkit/actions/System/action_release.gd.uid new file mode 100644 index 0000000..1811887 --- /dev/null +++ b/addons/flowkit/actions/System/action_release.gd.uid @@ -0,0 +1 @@ +uid://cod6y4xdwgl6a diff --git a/addons/flowkit/actions/System/center_window.gd.uid b/addons/flowkit/actions/System/center_window.gd.uid new file mode 100644 index 0000000..f6d43e1 --- /dev/null +++ b/addons/flowkit/actions/System/center_window.gd.uid @@ -0,0 +1 @@ +uid://c670sdy5puuum diff --git a/addons/flowkit/actions/System/change_scene.gd.uid b/addons/flowkit/actions/System/change_scene.gd.uid new file mode 100644 index 0000000..d7d56b0 --- /dev/null +++ b/addons/flowkit/actions/System/change_scene.gd.uid @@ -0,0 +1 @@ +uid://bwhhnrvngidru diff --git a/addons/flowkit/actions/System/open_url.gd.uid b/addons/flowkit/actions/System/open_url.gd.uid new file mode 100644 index 0000000..5475068 --- /dev/null +++ b/addons/flowkit/actions/System/open_url.gd.uid @@ -0,0 +1 @@ +uid://0etbx4ypgwo diff --git a/addons/flowkit/actions/System/reload_scene.gd.uid b/addons/flowkit/actions/System/reload_scene.gd.uid new file mode 100644 index 0000000..d1631b4 --- /dev/null +++ b/addons/flowkit/actions/System/reload_scene.gd.uid @@ -0,0 +1 @@ +uid://bfl8h6axko5ns diff --git a/addons/flowkit/actions/System/set_audio_bus_mute.gd.uid b/addons/flowkit/actions/System/set_audio_bus_mute.gd.uid new file mode 100644 index 0000000..abe5abd --- /dev/null +++ b/addons/flowkit/actions/System/set_audio_bus_mute.gd.uid @@ -0,0 +1 @@ +uid://bmk2xjib5mwff diff --git a/addons/flowkit/actions/System/set_audio_bus_volume.gd.uid b/addons/flowkit/actions/System/set_audio_bus_volume.gd.uid new file mode 100644 index 0000000..c47e3d7 --- /dev/null +++ b/addons/flowkit/actions/System/set_audio_bus_volume.gd.uid @@ -0,0 +1 @@ +uid://wkug7um2ed8p diff --git a/addons/flowkit/actions/System/set_clipboard.gd.uid b/addons/flowkit/actions/System/set_clipboard.gd.uid new file mode 100644 index 0000000..1eac21c --- /dev/null +++ b/addons/flowkit/actions/System/set_clipboard.gd.uid @@ -0,0 +1 @@ +uid://bb3axo5mbbc4l diff --git a/addons/flowkit/actions/System/set_max_fps.gd.uid b/addons/flowkit/actions/System/set_max_fps.gd.uid new file mode 100644 index 0000000..4903508 --- /dev/null +++ b/addons/flowkit/actions/System/set_max_fps.gd.uid @@ -0,0 +1 @@ +uid://cq2fb5tfe1cwd diff --git a/addons/flowkit/actions/System/set_mouse_captured.gd.uid b/addons/flowkit/actions/System/set_mouse_captured.gd.uid new file mode 100644 index 0000000..16e45e1 --- /dev/null +++ b/addons/flowkit/actions/System/set_mouse_captured.gd.uid @@ -0,0 +1 @@ +uid://dgr0swtw6lfvd diff --git a/addons/flowkit/actions/System/set_mouse_cursor.gd.uid b/addons/flowkit/actions/System/set_mouse_cursor.gd.uid new file mode 100644 index 0000000..bd5424f --- /dev/null +++ b/addons/flowkit/actions/System/set_mouse_cursor.gd.uid @@ -0,0 +1 @@ +uid://bkhl0fi2n20to diff --git a/addons/flowkit/actions/System/set_mouse_visible.gd.uid b/addons/flowkit/actions/System/set_mouse_visible.gd.uid new file mode 100644 index 0000000..d7fdeab --- /dev/null +++ b/addons/flowkit/actions/System/set_mouse_visible.gd.uid @@ -0,0 +1 @@ +uid://dxshj285wbvps diff --git a/addons/flowkit/actions/System/set_time_scale.gd.uid b/addons/flowkit/actions/System/set_time_scale.gd.uid new file mode 100644 index 0000000..7bdbe97 --- /dev/null +++ b/addons/flowkit/actions/System/set_time_scale.gd.uid @@ -0,0 +1 @@ +uid://c2ca1mdxnw5h4 diff --git a/addons/flowkit/actions/System/set_vsync.gd.uid b/addons/flowkit/actions/System/set_vsync.gd.uid new file mode 100644 index 0000000..1fb5b97 --- /dev/null +++ b/addons/flowkit/actions/System/set_vsync.gd.uid @@ -0,0 +1 @@ +uid://khybqre6qkvg diff --git a/addons/flowkit/actions/System/set_window_mode.gd.uid b/addons/flowkit/actions/System/set_window_mode.gd.uid new file mode 100644 index 0000000..6d591b4 --- /dev/null +++ b/addons/flowkit/actions/System/set_window_mode.gd.uid @@ -0,0 +1 @@ +uid://b14mkunkodo0y diff --git a/addons/flowkit/actions/System/set_window_position.gd.uid b/addons/flowkit/actions/System/set_window_position.gd.uid new file mode 100644 index 0000000..e092288 --- /dev/null +++ b/addons/flowkit/actions/System/set_window_position.gd.uid @@ -0,0 +1 @@ +uid://dyyhovrjafl40 diff --git a/addons/flowkit/actions/System/set_window_size.gd.uid b/addons/flowkit/actions/System/set_window_size.gd.uid new file mode 100644 index 0000000..ee52685 --- /dev/null +++ b/addons/flowkit/actions/System/set_window_size.gd.uid @@ -0,0 +1 @@ +uid://dr8b3106qfpn6 diff --git a/addons/flowkit/actions/System/set_window_title.gd.uid b/addons/flowkit/actions/System/set_window_title.gd.uid new file mode 100644 index 0000000..3f271f9 --- /dev/null +++ b/addons/flowkit/actions/System/set_window_title.gd.uid @@ -0,0 +1 @@ +uid://bsm0om0ifky8g diff --git a/addons/flowkit/actions/System/vibrate.gd.uid b/addons/flowkit/actions/System/vibrate.gd.uid new file mode 100644 index 0000000..6311e96 --- /dev/null +++ b/addons/flowkit/actions/System/vibrate.gd.uid @@ -0,0 +1 @@ +uid://0w1qnbvrfk4f diff --git a/addons/flowkit/actions/System/warp_mouse.gd.uid b/addons/flowkit/actions/System/warp_mouse.gd.uid new file mode 100644 index 0000000..e9c00c4 --- /dev/null +++ b/addons/flowkit/actions/System/warp_mouse.gd.uid @@ -0,0 +1 @@ +uid://b3it25w1hryos diff --git a/addons/flowkit/conditions/System/is_action_released.gd.uid b/addons/flowkit/conditions/System/is_action_released.gd.uid new file mode 100644 index 0000000..fc90c5c --- /dev/null +++ b/addons/flowkit/conditions/System/is_action_released.gd.uid @@ -0,0 +1 @@ +uid://biicbuow4a5a6 diff --git a/addons/flowkit/conditions/System/is_audio_bus_muted.gd.uid b/addons/flowkit/conditions/System/is_audio_bus_muted.gd.uid new file mode 100644 index 0000000..52fdf3f --- /dev/null +++ b/addons/flowkit/conditions/System/is_audio_bus_muted.gd.uid @@ -0,0 +1 @@ +uid://b1dfpy7xxsg2e diff --git a/addons/flowkit/conditions/System/is_debug_build.gd.uid b/addons/flowkit/conditions/System/is_debug_build.gd.uid new file mode 100644 index 0000000..81ed973 --- /dev/null +++ b/addons/flowkit/conditions/System/is_debug_build.gd.uid @@ -0,0 +1 @@ +uid://cxy876kvp5k8d diff --git a/addons/flowkit/conditions/System/is_elapsed_time_greater.gd.uid b/addons/flowkit/conditions/System/is_elapsed_time_greater.gd.uid new file mode 100644 index 0000000..d4a34f8 --- /dev/null +++ b/addons/flowkit/conditions/System/is_elapsed_time_greater.gd.uid @@ -0,0 +1 @@ +uid://dy3xcpnasb2lj diff --git a/addons/flowkit/conditions/System/is_fast_forward.gd.uid b/addons/flowkit/conditions/System/is_fast_forward.gd.uid new file mode 100644 index 0000000..d327536 --- /dev/null +++ b/addons/flowkit/conditions/System/is_fast_forward.gd.uid @@ -0,0 +1 @@ +uid://cxkfxb0h6ympk diff --git a/addons/flowkit/conditions/System/is_fps_above.gd.uid b/addons/flowkit/conditions/System/is_fps_above.gd.uid new file mode 100644 index 0000000..a76e752 --- /dev/null +++ b/addons/flowkit/conditions/System/is_fps_above.gd.uid @@ -0,0 +1 @@ +uid://vfmm3dr06lm7 diff --git a/addons/flowkit/conditions/System/is_fps_below.gd.uid b/addons/flowkit/conditions/System/is_fps_below.gd.uid new file mode 100644 index 0000000..f5aca09 --- /dev/null +++ b/addons/flowkit/conditions/System/is_fps_below.gd.uid @@ -0,0 +1 @@ +uid://brvhh5wd4s71h diff --git a/addons/flowkit/conditions/System/is_key_pressed.gd.uid b/addons/flowkit/conditions/System/is_key_pressed.gd.uid new file mode 100644 index 0000000..c5f32b5 --- /dev/null +++ b/addons/flowkit/conditions/System/is_key_pressed.gd.uid @@ -0,0 +1 @@ +uid://b2xrb5fws0xna diff --git a/addons/flowkit/conditions/System/is_mobile.gd.uid b/addons/flowkit/conditions/System/is_mobile.gd.uid new file mode 100644 index 0000000..fc2ac59 --- /dev/null +++ b/addons/flowkit/conditions/System/is_mobile.gd.uid @@ -0,0 +1 @@ +uid://cw3n6py2ii23j diff --git a/addons/flowkit/conditions/System/is_mouse_button_pressed.gd.uid b/addons/flowkit/conditions/System/is_mouse_button_pressed.gd.uid new file mode 100644 index 0000000..93cc19c --- /dev/null +++ b/addons/flowkit/conditions/System/is_mouse_button_pressed.gd.uid @@ -0,0 +1 @@ +uid://b86gmquj27did diff --git a/addons/flowkit/conditions/System/is_mouse_captured.gd.uid b/addons/flowkit/conditions/System/is_mouse_captured.gd.uid new file mode 100644 index 0000000..d1ba25d --- /dev/null +++ b/addons/flowkit/conditions/System/is_mouse_captured.gd.uid @@ -0,0 +1 @@ +uid://tjst2gdqpj22 diff --git a/addons/flowkit/conditions/System/is_mouse_visible.gd.uid b/addons/flowkit/conditions/System/is_mouse_visible.gd.uid new file mode 100644 index 0000000..fe9b22b --- /dev/null +++ b/addons/flowkit/conditions/System/is_mouse_visible.gd.uid @@ -0,0 +1 @@ +uid://cfc4ov8mg1t0w diff --git a/addons/flowkit/conditions/System/is_platform.gd.uid b/addons/flowkit/conditions/System/is_platform.gd.uid new file mode 100644 index 0000000..50a57ae --- /dev/null +++ b/addons/flowkit/conditions/System/is_platform.gd.uid @@ -0,0 +1 @@ +uid://m3y1mg1m7387 diff --git a/addons/flowkit/conditions/System/is_slow_motion.gd.uid b/addons/flowkit/conditions/System/is_slow_motion.gd.uid new file mode 100644 index 0000000..0f33a0b --- /dev/null +++ b/addons/flowkit/conditions/System/is_slow_motion.gd.uid @@ -0,0 +1 @@ +uid://igwkos73jilo diff --git a/addons/flowkit/conditions/System/is_window_focused.gd.uid b/addons/flowkit/conditions/System/is_window_focused.gd.uid new file mode 100644 index 0000000..166aa1b --- /dev/null +++ b/addons/flowkit/conditions/System/is_window_focused.gd.uid @@ -0,0 +1 @@ +uid://bfmn34wus56yx diff --git a/addons/flowkit/conditions/System/is_window_fullscreen.gd.uid b/addons/flowkit/conditions/System/is_window_fullscreen.gd.uid new file mode 100644 index 0000000..fba9521 --- /dev/null +++ b/addons/flowkit/conditions/System/is_window_fullscreen.gd.uid @@ -0,0 +1 @@ +uid://6xmyqa1naxxy diff --git a/addons/flowkit/events/System/on_action_released.gd.uid b/addons/flowkit/events/System/on_action_released.gd.uid new file mode 100644 index 0000000..4d33f55 --- /dev/null +++ b/addons/flowkit/events/System/on_action_released.gd.uid @@ -0,0 +1 @@ +uid://bho10i1x72nog diff --git a/addons/flowkit/events/System/on_key_pressed.gd.uid b/addons/flowkit/events/System/on_key_pressed.gd.uid new file mode 100644 index 0000000..4cd48f4 --- /dev/null +++ b/addons/flowkit/events/System/on_key_pressed.gd.uid @@ -0,0 +1 @@ +uid://c6qcnovg7h8hv diff --git a/addons/flowkit/events/System/on_key_released.gd.uid b/addons/flowkit/events/System/on_key_released.gd.uid new file mode 100644 index 0000000..d918b13 --- /dev/null +++ b/addons/flowkit/events/System/on_key_released.gd.uid @@ -0,0 +1 @@ +uid://c1lhw2l7jhhf2 diff --git a/addons/flowkit/events/System/on_mouse_button_pressed.gd.uid b/addons/flowkit/events/System/on_mouse_button_pressed.gd.uid new file mode 100644 index 0000000..cca052e --- /dev/null +++ b/addons/flowkit/events/System/on_mouse_button_pressed.gd.uid @@ -0,0 +1 @@ +uid://bub7x14ra70wf diff --git a/addons/flowkit/events/System/on_mouse_button_released.gd.uid b/addons/flowkit/events/System/on_mouse_button_released.gd.uid new file mode 100644 index 0000000..e88dfb5 --- /dev/null +++ b/addons/flowkit/events/System/on_mouse_button_released.gd.uid @@ -0,0 +1 @@ +uid://dffgkvy33vxgm diff --git a/addons/flowkit/events/System/on_physics_process.gd.uid b/addons/flowkit/events/System/on_physics_process.gd.uid new file mode 100644 index 0000000..55df7af --- /dev/null +++ b/addons/flowkit/events/System/on_physics_process.gd.uid @@ -0,0 +1 @@ +uid://dvbmve2twc5jv diff --git a/addons/flowkit/events/System/on_process.gd.uid b/addons/flowkit/events/System/on_process.gd.uid new file mode 100644 index 0000000..8d1604c --- /dev/null +++ b/addons/flowkit/events/System/on_process.gd.uid @@ -0,0 +1 @@ +uid://damyb216suue2 diff --git a/addons/flowkit/events/System/on_scene_ready.gd.uid b/addons/flowkit/events/System/on_scene_ready.gd.uid new file mode 100644 index 0000000..ad38b70 --- /dev/null +++ b/addons/flowkit/events/System/on_scene_ready.gd.uid @@ -0,0 +1 @@ +uid://cli02w1sre8fj diff --git a/addons/flowkit/events/System/on_time_scale_changed.gd.uid b/addons/flowkit/events/System/on_time_scale_changed.gd.uid new file mode 100644 index 0000000..da2e41f --- /dev/null +++ b/addons/flowkit/events/System/on_time_scale_changed.gd.uid @@ -0,0 +1 @@ +uid://733tc0ya730s diff --git a/addons/flowkit/events/System/on_window_focus_changed.gd.uid b/addons/flowkit/events/System/on_window_focus_changed.gd.uid new file mode 100644 index 0000000..3f64f37 --- /dev/null +++ b/addons/flowkit/events/System/on_window_focus_changed.gd.uid @@ -0,0 +1 @@ +uid://cso6d8nig7o0f diff --git a/addons/flowkit/events/System/on_window_focus_gained.gd.uid b/addons/flowkit/events/System/on_window_focus_gained.gd.uid new file mode 100644 index 0000000..2c98bba --- /dev/null +++ b/addons/flowkit/events/System/on_window_focus_gained.gd.uid @@ -0,0 +1 @@ +uid://byu322vxcv7bt diff --git a/addons/flowkit/events/System/on_window_focus_lost.gd.uid b/addons/flowkit/events/System/on_window_focus_lost.gd.uid new file mode 100644 index 0000000..62626f7 --- /dev/null +++ b/addons/flowkit/events/System/on_window_focus_lost.gd.uid @@ -0,0 +1 @@ +uid://bdr2xea731a1i diff --git a/addons/flowkit/ui/editor.gd b/addons/flowkit/ui/editor.gd index 8c73474..47ad082 100644 --- a/addons/flowkit/ui/editor.gd +++ b/addons/flowkit/ui/editor.gd @@ -1137,6 +1137,10 @@ func _connect_comment_signals(comment) -> void: comment.selected.connect(_on_comment_selected) comment.delete_requested.connect(_on_comment_delete.bind(comment)) comment.data_changed.connect(_save_sheet) + comment.insert_comment_above_requested.connect(_on_comment_insert_above.bind(comment)) + comment.insert_comment_below_requested.connect(_on_comment_insert_below.bind(comment)) + comment.insert_event_above_requested.connect(_on_comment_insert_event_above.bind(comment)) + comment.insert_event_below_requested.connect(_on_comment_insert_event_below.bind(comment)) func _create_group_block(data: FKGroupBlock) -> Control: """Create group block node from data.""" @@ -1178,10 +1182,15 @@ func _connect_group_signals(group) -> void: group.condition_edit_requested.connect(_on_condition_edit_requested) group.action_edit_requested.connect(_on_action_edit_requested) group.insert_event_below_requested.connect(func(row): _on_row_insert_below(row, row)) + group.insert_event_above_requested.connect(func(target): _on_comment_insert_event_above(target, target)) + group.insert_comment_below_requested.connect(func(row): _on_row_insert_comment_below(row, row)) + group.insert_comment_above_requested.connect(func(target): _on_comment_insert_above(target, target)) group.replace_event_requested.connect(func(row): _on_row_replace(row, row)) group.edit_event_requested.connect(func(row): _on_row_edit(row, row)) group.add_condition_requested.connect(func(row): _on_row_add_condition(row, row)) group.add_action_requested.connect(func(row): _on_row_add_action(row, row)) + group.condition_dropped.connect(_on_condition_dropped) + group.action_dropped.connect(_on_action_dropped) func _on_group_add_event_requested(group_node) -> void: """Handle request to add an event inside a group.""" @@ -1256,6 +1265,7 @@ func _on_add_group_button_pressed() -> void: func _connect_event_row_signals(row) -> void: row.insert_event_below_requested.connect(_on_row_insert_below.bind(row)) + row.insert_comment_below_requested.connect(_on_row_insert_comment_below.bind(row)) row.replace_event_requested.connect(_on_row_replace.bind(row)) row.delete_event_requested.connect(_on_row_delete.bind(row)) row.edit_event_requested.connect(_on_row_edit.bind(row)) @@ -1416,6 +1426,45 @@ func _on_comment_delete(comment) -> void: comment.queue_free() _save_sheet() +func _on_comment_insert_above(signal_node, bound_comment) -> void: + """Insert a new comment above the specified comment.""" + _insert_comment_relative_to(bound_comment, 0) + +func _on_comment_insert_below(signal_node, bound_comment) -> void: + """Insert a new comment below the specified comment.""" + _insert_comment_relative_to(bound_comment, 1) + +func _on_comment_insert_event_above(signal_node, bound_comment) -> void: + """Insert a new event above the specified comment.""" + pending_target_row = bound_comment + _start_add_workflow("event_above_target", bound_comment) + +func _on_comment_insert_event_below(signal_node, bound_comment) -> void: + """Insert a new event below the specified comment.""" + pending_target_row = bound_comment + _start_add_workflow("event", bound_comment) + +func _on_row_insert_comment_below(signal_row, bound_row) -> void: + """Insert a new comment below the specified event row.""" + _insert_comment_relative_to(bound_row, 1) + +func _insert_comment_relative_to(target_block, offset: int) -> void: + """Insert a new comment relative to a target block (0 = above, 1 = below).""" + _push_undo_state() + + var data = FKCommentBlock.new() + data.text = "" + + var comment = _create_comment_block(data) + blocks_container.add_child(comment) + + # Calculate insert position + var insert_idx = target_block.get_index() + offset + blocks_container.move_child(comment, insert_idx) + + _show_content_state() + _save_sheet() + func _on_condition_selected_in_row(condition_node) -> void: """Handle condition item selection.""" # Deselect previous row @@ -1503,6 +1552,8 @@ func _on_event_selected(node_path: String, event_id: String, inputs: Array) -> v _replace_event({}) elif pending_block_type == "event_in_group": _finalize_event_in_group({}) + elif pending_block_type == "event_above_target": + _finalize_event_above_target({}) else: _finalize_event_creation({}) @@ -1543,6 +1594,8 @@ func _on_expressions_confirmed(_node_path: String, _id: String, expressions: Dic _finalize_event_creation(expressions) "event_in_group": _finalize_event_in_group(expressions) + "event_above_target": + _finalize_event_above_target(expressions) "condition": _finalize_condition_creation(expressions) "action": @@ -1585,6 +1638,31 @@ func _finalize_event_creation(inputs: Dictionary) -> void: _save_sheet() +func _finalize_event_above_target(inputs: Dictionary) -> void: + """Create and add event row above the target (GDevelop-style).""" + # Push undo state before adding event + _push_undo_state() + + # Generate new block_id for new events (pass empty string to auto-generate) + var data = FKEventBlock.new("", pending_id, pending_node_path) + data.inputs = inputs + data.conditions = [] as Array[FKEventCondition] + data.actions = [] as Array[FKEventAction] + + var row = _create_event_row(data) + + if pending_target_row: + var insert_idx = pending_target_row.get_index() # Insert at same position (above) + blocks_container.add_child(row) + blocks_container.move_child(row, insert_idx) + else: + blocks_container.add_child(row) + + _show_content_state() + _reset_workflow() + _save_sheet() + + func _finalize_event_in_group(inputs: Dictionary) -> void: """Create and add event inside a group.""" if not pending_target_group: diff --git a/addons/flowkit/ui/workspace/comment.gd b/addons/flowkit/ui/workspace/comment.gd index 7325019..6f6ab14 100644 --- a/addons/flowkit/ui/workspace/comment.gd +++ b/addons/flowkit/ui/workspace/comment.gd @@ -4,6 +4,10 @@ extends MarginContainer signal selected(comment_node) signal delete_requested signal data_changed +signal insert_comment_above_requested(comment_node) +signal insert_comment_below_requested(comment_node) +signal insert_event_above_requested(comment_node) +signal insert_event_below_requested(comment_node) var comment_data: FKCommentBlock var is_selected: bool = false @@ -170,15 +174,31 @@ func _gui_input(event: InputEvent) -> void: func _show_context_menu(pos: Vector2) -> void: var menu = PopupMenu.new() + menu.add_item("Insert Event Above", 10) + menu.add_item("Insert Event Below", 11) + menu.add_separator() + menu.add_item("Insert Comment Above", 12) + menu.add_item("Insert Comment Below", 13) + menu.add_separator() menu.add_item("Edit Comment", 1) + menu.add_separator() menu.add_item("Delete Comment", 0) add_child(menu) menu.position = Vector2i(pos) menu.popup() menu.id_pressed.connect(func(id): - if id == 0: - delete_requested.emit() - elif id == 1: - _set_edit_mode() + match id: + 0: + delete_requested.emit() + 1: + _set_edit_mode() + 10: + insert_event_above_requested.emit(self) + 11: + insert_event_below_requested.emit(self) + 12: + insert_comment_above_requested.emit(self) + 13: + insert_comment_below_requested.emit(self) menu.queue_free() ) diff --git a/addons/flowkit/ui/workspace/event_row.gd b/addons/flowkit/ui/workspace/event_row.gd index 6e35d2d..e4212e2 100644 --- a/addons/flowkit/ui/workspace/event_row.gd +++ b/addons/flowkit/ui/workspace/event_row.gd @@ -2,6 +2,7 @@ extends MarginContainer signal insert_event_below_requested(event_row) +signal insert_comment_below_requested(event_row) signal replace_event_requested(event_row) signal delete_event_requested(event_row) signal edit_event_requested(event_row) @@ -100,6 +101,8 @@ func _on_gui_input(event: InputEvent) -> void: if context_menu: context_menu.clear() context_menu.add_item("Add Event Below", 0) + context_menu.add_item("Add Comment Below", 4) + context_menu.add_separator() context_menu.add_item("Replace Event", 1) context_menu.add_item("Edit Event", 2) context_menu.add_separator() @@ -156,6 +159,8 @@ func _on_context_menu_id_pressed(id: int) -> void: edit_event_requested.emit(self) 3: # Delete Event delete_event_requested.emit(self) + 4: # Add Comment Below + insert_comment_below_requested.emit(self) func set_event_data(data: FKEventBlock) -> void: event_data = data diff --git a/addons/flowkit/ui/workspace/group.gd b/addons/flowkit/ui/workspace/group.gd index 5c27915..0e13afb 100644 --- a/addons/flowkit/ui/workspace/group.gd +++ b/addons/flowkit/ui/workspace/group.gd @@ -16,10 +16,15 @@ signal add_comment_requested(group_node) ## Emitted when user wants to add comm signal condition_edit_requested(condition_item, row) ## Emitted when condition needs editing signal action_edit_requested(action_item, row) ## Emitted when action needs editing signal insert_event_below_requested(row) ## Emitted when inserting event below +signal insert_event_above_requested(target) ## Emitted when inserting event above +signal insert_comment_below_requested(row) ## Emitted when inserting comment below event +signal insert_comment_above_requested(target) ## Emitted when inserting comment above signal replace_event_requested(row) ## Emitted when replacing event signal edit_event_requested(row) ## Emitted when editing event signal add_condition_requested(row) ## Emitted when adding condition to event signal add_action_requested(row) ## Emitted when adding action to event +signal condition_dropped(source_row, condition_data, target_row) ## Emitted when condition is dropped on an event +signal action_dropped(source_row, action_data, target_row) ## Emitted when action is dropped on an event # === Constants === const EVENT_ROW_SCENE = preload("res://addons/flowkit/ui/workspace/event_row.tscn") @@ -233,10 +238,13 @@ func _instantiate_event_row(data: FKEventBlock) -> Control: row.condition_edit_requested.connect(func(item): condition_edit_requested.emit(item, row)) row.action_edit_requested.connect(func(item): action_edit_requested.emit(item, row)) row.insert_event_below_requested.connect(func(r): insert_event_below_requested.emit(r)) + row.insert_comment_below_requested.connect(func(r): insert_comment_below_requested.emit(r)) row.replace_event_requested.connect(func(r): replace_event_requested.emit(r)) row.edit_event_requested.connect(func(r): edit_event_requested.emit(r)) row.add_condition_requested.connect(func(r): add_condition_requested.emit(r)) row.add_action_requested.connect(func(r): add_action_requested.emit(r)) + row.condition_dropped.connect(func(src, cond, tgt): condition_dropped.emit(src, cond, tgt)) + row.action_dropped.connect(func(src, act, tgt): action_dropped.emit(src, act, tgt)) row.data_changed.connect(_on_child_modified) row.before_data_changed.connect(func(): before_data_changed.emit()) @@ -252,6 +260,10 @@ func _instantiate_comment(data: FKCommentBlock) -> Control: comment.delete_requested.connect(_on_child_comment_delete_requested.bind(data)) comment.selected.connect(func(n): _on_child_selected(data); selected.emit(n)) comment.data_changed.connect(_on_child_modified) + comment.insert_comment_above_requested.connect(func(c): insert_comment_above_requested.emit(c)) + comment.insert_comment_below_requested.connect(func(c): insert_comment_below_requested.emit(c)) + comment.insert_event_above_requested.connect(func(c): insert_event_above_requested.emit(c)) + comment.insert_event_below_requested.connect(func(c): insert_event_below_requested.emit(c)) return comment @@ -273,10 +285,15 @@ func _instantiate_group(data: FKGroupBlock) -> Control: nested.condition_edit_requested.connect(func(item, row): condition_edit_requested.emit(item, row)) nested.action_edit_requested.connect(func(item, row): action_edit_requested.emit(item, row)) nested.insert_event_below_requested.connect(func(r): insert_event_below_requested.emit(r)) + nested.insert_event_above_requested.connect(func(r): insert_event_above_requested.emit(r)) + nested.insert_comment_below_requested.connect(func(r): insert_comment_below_requested.emit(r)) + nested.insert_comment_above_requested.connect(func(r): insert_comment_above_requested.emit(r)) nested.replace_event_requested.connect(func(r): replace_event_requested.emit(r)) nested.edit_event_requested.connect(func(r): edit_event_requested.emit(r)) nested.add_condition_requested.connect(func(r): add_condition_requested.emit(r)) nested.add_action_requested.connect(func(r): add_action_requested.emit(r)) + nested.condition_dropped.connect(func(src, cond, tgt): condition_dropped.emit(src, cond, tgt)) + nested.action_dropped.connect(func(src, act, tgt): action_dropped.emit(src, act, tgt)) return nested @@ -692,11 +709,47 @@ func _handle_drop(drag_node: Node, drag_type: String) -> void: func _handle_internal_reorder(drag_node: Node) -> void: """Handle reordering within this group.""" - before_data_changed.emit() + # Get visible children (excluding drop_hint, indicator) + var visible_children = [] + for child in children_container.get_children(): + if child == drop_hint or DropIndicatorManager.is_indicator(child): + continue + if child.visible: + visible_children.append(child) - # Just move the visual node - data will be synced from UI - var drop_idx = _calculate_drop_index(drag_node) - children_container.move_child(drag_node, drop_idx) + # Calculate visual drop index using same logic as blocks_container + var local_y = children_container.get_local_mouse_position().y + var target_visual_idx = visible_children.size() # Default to end + + for i in range(visible_children.size()): + var child = visible_children[i] + var rect = child.get_rect() + var mid_y = rect.position.y + rect.size.y * 0.5 + if local_y < mid_y: + target_visual_idx = i + break + + var current_visual_idx = visible_children.find(drag_node) + + # No-op if same position + if target_visual_idx == current_visual_idx or target_visual_idx == current_visual_idx + 1: + return + + # Calculate actual child index from visual index + var target_child_idx: int + if target_visual_idx >= visible_children.size(): + target_child_idx = children_container.get_child_count() + else: + target_child_idx = visible_children[target_visual_idx].get_index() + + var current_child_idx = drag_node.get_index() + + # Adjust for moving down (same as blocks_container) + if target_child_idx > current_child_idx: + target_child_idx -= 1 + + before_data_changed.emit() + children_container.move_child(drag_node, target_child_idx) # Sync data from new visual order _sync_children_to_data() @@ -786,17 +839,11 @@ func _calculate_drop_index(dragged_node: Node) -> int: var mid_y = rect.position.y + rect.size.y * 0.5 if local_y < mid_y: - # Insert before this child - find its position in group_data - # Iterate through data to find the matching visual child - for data_idx in range(group_data.children.size()): - var child_obj = _get_child_node_at_data_index(data_idx) - if child_obj == child: - return data_idx - # Fallback if not found + # Insert at this position (i is the visual index which maps to data index) return i # Insert at end (after all visible children) - return group_data.children.size() + return visible_children.size() func _get_child_node_at_data_index(data_idx: int) -> Node: diff --git a/addons/flowkit/ui/workspace/group_children_container.gd b/addons/flowkit/ui/workspace/group_children_container.gd index 0bbb5f0..ec18a92 100644 --- a/addons/flowkit/ui/workspace/group_children_container.gd +++ b/addons/flowkit/ui/workspace/group_children_container.gd @@ -1,9 +1,10 @@ @tool extends VBoxContainer -## Container for group children that handles internal drag-drop reordering. +## Container for group children that handles drag-drop reordering. +## Handles both internal reordering and external drops from outside the group. func _can_drop_data(at_position: Vector2, data) -> bool: - """Check if we can accept drops for internal reordering.""" + """Check if we can accept drops.""" if not data is Dictionary: return false @@ -13,30 +14,55 @@ func _can_drop_data(at_position: Vector2, data) -> bool: if not drag_node or not is_instance_valid(drag_node): return false - # Only handle internal reordering (same parent) - if drag_node.get_parent() == self: - var parent_group = get_meta("_parent_group", null) - if parent_group and parent_group.has_method("_show_drop_indicator"): - parent_group._show_drop_indicator(at_position, drag_node) - return true + # Only accept block types (event_row, comment, group) + if drag_type not in ["event_row", "comment", "group"]: + return false + + var parent_group = get_meta("_parent_group", null) + + # Prevent dropping a group into itself or its descendants + # Check if this group (parent_group) is a descendant of the dragged group + if drag_type == "group" and parent_group: + var current = parent_group + while current: + if current == drag_node: + DropIndicatorManager.hide_indicator() + return false + current = current.get_parent() + + # Show drop indicator via parent group + if parent_group and parent_group.has_method("_show_drop_indicator"): + parent_group._show_drop_indicator(at_position, drag_node) - return false + return true func _drop_data(at_position: Vector2, data) -> void: - """Handle drops for internal reordering.""" + """Handle drops.""" DropIndicatorManager.hide_indicator() if not data is Dictionary: return var drag_node = data.get("node") + var drag_type = data.get("type", "") if not drag_node or not is_instance_valid(drag_node): return - # Only handle internal reorders + # Only accept block types + if drag_type not in ["event_row", "comment", "group"]: + return + + var parent_group = get_meta("_parent_group", null) + if not parent_group: + return + + # Internal reorder (same parent) if drag_node.get_parent() == self: - var parent_group = get_meta("_parent_group", null) - if parent_group and parent_group.has_method("_handle_internal_reorder"): + if parent_group.has_method("_handle_internal_reorder"): parent_group._handle_internal_reorder(drag_node) + else: + # External drop - delegate to parent group + if parent_group.has_method("_handle_drop"): + parent_group._handle_drop(drag_node, drag_type)