From b262af0b88dcf435a9527894b352e04971d37863 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Tue, 2 Jul 2024 11:51:03 +0100 Subject: [PATCH 001/423] plugin.cfg: Use lightweight tags to determine version By default, `git describe` (which is what backs this `$Format:%(describe)$` placeholder) only uses annotated tags to construct a version number. However I have just discovered that if you use the GitHub web interface to create a tag as part of making a release, the resulting tag is lightweight, not annotated. As a result the 0.4.0 release describes its version as `v0.3.1-27-ga9a2ee9`. Update the placeholder to (the equivalent of) `git describe --tags`, which considers lightweight tags as well as annotated tags. --- addons/block_code/plugin.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/block_code/plugin.cfg b/addons/block_code/plugin.cfg index 2c50b5de..95f1c348 100644 --- a/addons/block_code/plugin.cfg +++ b/addons/block_code/plugin.cfg @@ -3,5 +3,5 @@ name="BlockCode" description="Create games using a high-level, block-based visual programming language." author="Endless" -version="$Format:%(describe)$" +version="$Format:%(describe:tags)$" script="block_code_plugin.gd" From f291395a47650af4fc2c10f6b33c672064bd37b0 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Tue, 2 Jul 2024 14:45:30 -0600 Subject: [PATCH 002/423] ui: Use EditorInterface method to display Block Code editor Rather than locating the Block Code tab in the editor tab bar and simulating a button press on it, just use the EditorInterface.set_main_screen_editor method to display the Block Code editor. With that, the EditorInterfaceAccess class (and utilities) vendored from GDTour can be dropped. https://phabricator.endlessm.com/T35494 --- addons/block_code/block_code_plugin.gd | 1 - .../block_code/lib/editor_interface_access.gd | 497 ------------------ addons/block_code/lib/utils.gd | 113 ---- addons/block_code/ui/main_panel.gd | 8 +- 4 files changed, 1 insertion(+), 618 deletions(-) delete mode 100644 addons/block_code/lib/editor_interface_access.gd delete mode 100644 addons/block_code/lib/utils.gd diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 204d69fb..950ae75c 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -13,7 +13,6 @@ const DISABLED_CLASSES := [ "BlockScriptData", "DragManager", "InstructionTree", - "EditorInterfaceAccess", "Types", "BasicBlock", "Block", diff --git a/addons/block_code/lib/editor_interface_access.gd b/addons/block_code/lib/editor_interface_access.gd deleted file mode 100644 index f8cc40da..00000000 --- a/addons/block_code/lib/editor_interface_access.gd +++ /dev/null @@ -1,497 +0,0 @@ -class_name EditorInterfaceAccess -extends Object - -## Finds and gives easy access to many key Control nodes of the Godot editor. -## Extend this script to add support for more areas of the Godot editor or Godot plugins. -const Utils := preload("utils.gd") - -## This is the base control of the Godot editor, the parent to all UI nodes in the entire -## application. -var base_control: Control = null - -# Title Bar -var menu_bar: MenuBar = null -## The "main screen" buttons centered at the top of the editor (2D, 3D, Script, and AssetLib). -var context_switcher: HBoxContainer = null -var context_switcher_2d_button: Button = null -var context_switcher_3d_button: Button = null -var context_switcher_script_button: Button = null -var context_switcher_asset_lib_button: Button = null -var run_bar: MarginContainer = null -var run_bar_play_button: Button = null -var run_bar_pause_button: Button = null -var run_bar_stop_button: Button = null -var run_bar_debug_button: MenuButton = null -var run_bar_play_current_button: Button = null -var run_bar_play_custom_button: Button = null -var run_bar_movie_mode_button: Button = null -var rendering_options: OptionButton = null - -# Main Screen -var main_screen: VBoxContainer = null -var main_screen_tabs: TabBar = null -var distraction_free_button: Button = null - -var canvas_item_editor: VBoxContainer = null -## The 2D viewport in the 2D editor. Its bounds stop right before the toolbar. -var canvas_item_editor_viewport: Control = null -var canvas_item_editor_toolbar: Control = null -var canvas_item_editor_toolbar_select_button: Button = null -var canvas_item_editor_toolbar_move_button: Button = null -var canvas_item_editor_toolbar_rotate_button: Button = null -var canvas_item_editor_toolbar_scale_button: Button = null -var canvas_item_editor_toolbar_selectable_button: Button = null -var canvas_item_editor_toolbar_pivot_button: Button = null -var canvas_item_editor_toolbar_pan_button: Button = null -var canvas_item_editor_toolbar_ruler_button: Button = null -var canvas_item_editor_toolbar_smart_snap_button: Button = null -var canvas_item_editor_toolbar_grid_button: Button = null -var canvas_item_editor_toolbar_snap_options_button: MenuButton = null -var canvas_item_editor_toolbar_lock_button: Button = null -var canvas_item_editor_toolbar_unlock_button: Button = null -var canvas_item_editor_toolbar_group_button: Button = null -var canvas_item_editor_toolbar_ungroup_button: Button = null -var canvas_item_editor_toolbar_skeleton_options_button: Button = null -## Parent container of the zoom buttons in the top-left of the 2D editor. -var canvas_item_editor_zoom_widget: Control = null -## Lower zoom button in the top-left of the 2D viewport. -var canvas_item_editor_zoom_button_lower: Button = null -## Button showing the current zoom percentage in the top-left of the 2D viewport. Pressing it resets -## the zoom to 100%. -var canvas_item_editor_zoom_button_reset: Button = null -## Increase zoom button in the top-left of the 2D viewport. -var canvas_item_editor_zoom_button_increase: Button = null - -var spatial_editor: Control = null -var spatial_editor_surfaces: Array[Control] = [] -var spatial_editor_surfaces_menu_buttons: Array[MenuButton] = [] -var spatial_editor_viewports: Array[Control] = [] -var spatial_editor_preview_check_boxes: Array[CheckBox] = [] -var spatial_editor_cameras: Array[Camera3D] = [] -var spatial_editor_toolbar: Control = null -var spatial_editor_toolbar_select_button: Button = null -var spatial_editor_toolbar_move_button: Button = null -var spatial_editor_toolbar_rotate_button: Button = null -var spatial_editor_toolbar_scale_button: Button = null -var spatial_editor_toolbar_selectable_button: Button = null -var spatial_editor_toolbar_lock_button: Button = null -var spatial_editor_toolbar_unlock_button: Button = null -var spatial_editor_toolbar_group_button: Button = null -var spatial_editor_toolbar_ungroup_button: Button = null -var spatial_editor_toolbar_local_button: Button = null -var spatial_editor_toolbar_snap_button: Button = null -var spatial_editor_toolbar_camera_button: Button = null -var spatial_editor_toolbar_sun_button: Button = null -var spatial_editor_toolbar_environment_button: Button = null -var spatial_editor_toolbar_sun_environment_button: Button = null -var spatial_editor_toolbar_transform_menu_button: MenuButton = null -var spatial_editor_toolbar_view_menu_button: MenuButton = null - -var script_editor: ScriptEditor = null -## Parent node of the script editor, used to pop out the editor and controls the script editor's -## visibility. Used to check if students are in the scripting context. -var script_editor_window_wrapper: Node = null -var script_editor_top_bar: HBoxContainer = null -var script_editor_items: ItemList = null -var script_editor_items_panel: VBoxContainer = null -var script_editor_functions_panel: VBoxContainer = null -var script_editor_code_panel: VBoxContainer = null -var asset_lib: PanelContainer = null - -# Snap Dialog, AKA Configure Snap window -var snap_options_window: ConfirmationDialog = null -var snap_options_cancel_button: Button = null -var snap_options_ok_button: Button = null -var snap_options: VBoxContainer = null -var snap_options_grid_offset_controls: Array[Control] = [] -var snap_options_grid_step_controls: Array[Control] = [] -var snap_options_primary_line_controls: Array[Control] = [] -var snap_options_rotation_offset_controls: Array[Control] = [] -var snap_options_rotation_step_controls: Array[Control] = [] -var snap_options_scale_step_controls: Array[Control] = [] - -# Left Upper -var scene_tabs: TabBar = null -var scene_dock: VBoxContainer = null -var scene_dock_button_add: Button = null -var scene_tree: Tree = null -var import_dock: VBoxContainer = null -var select_node_window: ConfirmationDialog = null - -var node_create_window: ConfirmationDialog = null -var script_create_window: ConfirmationDialog = null -var node_create_panel: HSplitContainer = null -var node_create_dialog_node_tree: Tree = null -var node_create_dialog_search_bar: LineEdit = null -var node_create_dialog_button_create: Button = null -var node_create_dialog_button_cancel: Button = null - -# Left Bttom -var filesystem_tabs: TabBar = null -var filesystem_dock: VBoxContainer = null -var filesystem_tree: Tree = null - -# Right -var inspector_tabs: TabBar = null -var inspector_dock: VBoxContainer = null -var inspector_editor: EditorInspector = null - -var node_dock: VBoxContainer = null -var node_dock_buttons_box: HBoxContainer = null -var node_dock_signals_button: Button = null -var node_dock_groups_button: Button = null -var node_dock_signals_editor: VBoxContainer = null -var node_dock_signals_tree: Tree = null - -var signals_dialog_window: ConfirmationDialog = null -var signals_dialog: HBoxContainer = null -var signals_dialog_tree: Tree = null -var signals_dialog_signal_line_edit: LineEdit = null -var signals_dialog_method_line_edit: LineEdit = null -var signals_dialog_cancel_button: Button = null -var signals_dialog_ok_button: Button = null -var node_dock_groups_editor: VBoxContainer = null -var history_dock: VBoxContainer = null - -# Bottom -var bottom_panels_container: Control = null - -var tilemap: Control = null -var tilemap_tabs: TabBar = null -var tilemap_tiles_panel: VBoxContainer = null -var tilemap_tiles: ItemList = null -var tilemap_tiles_atlas_view: Control = null -var tilemap_tiles_toolbar: HBoxContainer = null -var tilemap_patterns_panel: VBoxContainer = null -var tilemap_terrains_panel: VBoxContainer = null -## The tree on the left to select terrains in the TileMap -> Terrains tab. -var tilemap_terrains_tree: Tree = null -## The list of terrain drawing mode and individual tiles on the right in the TileMap -> Terrains tab. -var tilemap_terrains_tiles: ItemList = null -var tilemap_terrains_toolbar: HBoxContainer = null -var tilemap_terrains_tool_draw: Button = null -var tilemap_panels: Array[Control] = [] - -var tileset: Control = null -var tileset_tabs: TabBar = null -var tileset_tiles_panel: HSplitContainer = null -var tileset_patterns_panel: ItemList = null -var tileset_panels: Array[Control] = [] - -var logger: HBoxContainer = null -var logger_rich_text_label: RichTextLabel = null -var debugger: MarginContainer = null -var find_in_files: Control = null -var audio_buses: VBoxContainer = null -var animation_player: VBoxContainer = null -var shader: MarginContainer = null - -var bottom_buttons_container: HBoxContainer = null -var bottom_button_output: Button = null -var bottom_button_debugger: Button = null -var bottom_button_tilemap: Button = null -var bottom_button_tileset: Button = null -var bottom_buttons: Array[Button] = [] - -var scene_import_settings_window: ConfirmationDialog = null -var scene_import_settings: VBoxContainer = null -var scene_import_settings_ok_button: Button = null -var scene_import_settings_cancel_button: Button = null - -var windows: Array[ConfirmationDialog] = [] - - -func _init() -> void: - base_control = EditorInterface.get_base_control() - - # Top - var editor_title_bar := Utils.find_child_by_type(base_control, "EditorTitleBar") - menu_bar = Utils.find_child_by_type(editor_title_bar, "MenuBar") - - context_switcher = Utils.find_child_by_type( - editor_title_bar, - "HBoxContainer", - true, - func(c: HBoxContainer) -> bool: return c.get_child_count() > 1 - ) - var context_switcher_buttons := context_switcher.get_children() - context_switcher_2d_button = context_switcher_buttons[0] - context_switcher_3d_button = context_switcher_buttons[1] - context_switcher_script_button = context_switcher_buttons[2] - context_switcher_asset_lib_button = context_switcher_buttons[3] - - run_bar = Utils.find_child_by_type(editor_title_bar, "EditorRunBar") - var run_bar_buttons = run_bar.find_children("", "Button", true, false) - run_bar_play_button = run_bar_buttons[0] - run_bar_pause_button = run_bar_buttons[1] - run_bar_stop_button = run_bar_buttons[2] - run_bar_debug_button = run_bar_buttons[3] - run_bar_play_current_button = run_bar_buttons[5] - run_bar_play_custom_button = run_bar_buttons[6] - run_bar_movie_mode_button = run_bar_buttons[7] - rendering_options = Utils.find_child_by_type(editor_title_bar, "OptionButton") - - # Main Screen - main_screen = EditorInterface.get_editor_main_screen() - main_screen_tabs = Utils.find_child_by_type(main_screen.get_parent().get_parent(), "TabBar") - distraction_free_button = ( - main_screen_tabs.get_parent().find_children("", "Button", true, false).back() - ) - canvas_item_editor = Utils.find_child_by_type(main_screen, "CanvasItemEditor") - canvas_item_editor_viewport = Utils.find_child_by_type( - canvas_item_editor, "CanvasItemEditorViewport" - ) - canvas_item_editor_toolbar = canvas_item_editor.get_child(0).get_child(0).get_child(0) - var canvas_item_editor_toolbar_buttons := canvas_item_editor_toolbar.find_children( - "", "Button", false, false - ) - canvas_item_editor_toolbar_select_button = canvas_item_editor_toolbar_buttons[0] - canvas_item_editor_toolbar_move_button = canvas_item_editor_toolbar_buttons[1] - canvas_item_editor_toolbar_rotate_button = canvas_item_editor_toolbar_buttons[2] - canvas_item_editor_toolbar_scale_button = canvas_item_editor_toolbar_buttons[3] - canvas_item_editor_toolbar_selectable_button = canvas_item_editor_toolbar_buttons[4] - canvas_item_editor_toolbar_pivot_button = canvas_item_editor_toolbar_buttons[5] - canvas_item_editor_toolbar_pan_button = canvas_item_editor_toolbar_buttons[6] - canvas_item_editor_toolbar_ruler_button = canvas_item_editor_toolbar_buttons[7] - canvas_item_editor_toolbar_smart_snap_button = canvas_item_editor_toolbar_buttons[8] - canvas_item_editor_toolbar_grid_button = canvas_item_editor_toolbar_buttons[9] - canvas_item_editor_toolbar_snap_options_button = canvas_item_editor_toolbar_buttons[10] - canvas_item_editor_toolbar_lock_button = canvas_item_editor_toolbar_buttons[11] - canvas_item_editor_toolbar_unlock_button = canvas_item_editor_toolbar_buttons[12] - canvas_item_editor_toolbar_group_button = canvas_item_editor_toolbar_buttons[13] - canvas_item_editor_toolbar_ungroup_button = canvas_item_editor_toolbar_buttons[14] - canvas_item_editor_toolbar_skeleton_options_button = canvas_item_editor_toolbar_buttons[15] - - canvas_item_editor_zoom_widget = Utils.find_child_by_type( - canvas_item_editor, "EditorZoomWidget" - ) - canvas_item_editor_zoom_button_lower = canvas_item_editor_zoom_widget.get_child(0) - canvas_item_editor_zoom_button_reset = canvas_item_editor_zoom_widget.get_child(1) - canvas_item_editor_zoom_button_increase = canvas_item_editor_zoom_widget.get_child(2) - - snap_options_window = Utils.find_child_by_type(base_control, "SnapDialog") - snap_options = snap_options_window.get_child(0) - snap_options_cancel_button = snap_options_window.get_cancel_button() - snap_options_ok_button = snap_options_window.get_ok_button() - var snap_options_controls: Array[Node] = snap_options.get_child(0).get_children() - snap_options_grid_offset_controls.assign(snap_options_controls.slice(0, 3)) - snap_options_grid_step_controls.assign(snap_options_controls.slice(3, 6)) - snap_options_primary_line_controls.assign(snap_options_controls.slice(6, 9)) - snap_options_controls = snap_options.get_child(2).get_children() - snap_options_rotation_offset_controls.assign(snap_options_controls.slice(0, 2)) - snap_options_rotation_step_controls.assign(snap_options_controls.slice(2, 4)) - snap_options_scale_step_controls.assign(snap_options.get_child(4).get_children()) - - spatial_editor = Utils.find_child_by_type(main_screen, "Node3DEditor") - spatial_editor_viewports.assign( - spatial_editor.find_children("", "Node3DEditorViewport", true, false) - ) - spatial_editor_preview_check_boxes.assign( - spatial_editor.find_children("", "CheckBox", true, false) - ) - spatial_editor_cameras.assign(spatial_editor.find_children("", "Camera3D", true, false)) - var surfaces := {} - for surface in spatial_editor.find_children("", "ViewportNavigationControl", true, false).map( - func(c: Control) -> Control: return c.get_parent() - ): - surfaces[surface] = null - spatial_editor_surfaces.assign(surfaces.keys()) - for surface in spatial_editor_surfaces: - spatial_editor_surfaces_menu_buttons.append_array( - surface.find_children("", "MenuButton", true, false) - ) - spatial_editor_toolbar = spatial_editor.get_child(0).get_child(0).get_child(0) - var spatial_editor_toolbar_buttons := spatial_editor_toolbar.find_children( - "", "Button", false, false - ) - spatial_editor_toolbar_select_button = spatial_editor_toolbar_buttons[0] - spatial_editor_toolbar_move_button = spatial_editor_toolbar_buttons[1] - spatial_editor_toolbar_rotate_button = spatial_editor_toolbar_buttons[2] - spatial_editor_toolbar_scale_button = spatial_editor_toolbar_buttons[3] - spatial_editor_toolbar_selectable_button = spatial_editor_toolbar_buttons[4] - spatial_editor_toolbar_lock_button = spatial_editor_toolbar_buttons[5] - spatial_editor_toolbar_unlock_button = spatial_editor_toolbar_buttons[6] - spatial_editor_toolbar_group_button = spatial_editor_toolbar_buttons[7] - spatial_editor_toolbar_ungroup_button = spatial_editor_toolbar_buttons[8] - spatial_editor_toolbar_local_button = spatial_editor_toolbar_buttons[9] - spatial_editor_toolbar_snap_button = spatial_editor_toolbar_buttons[10] - spatial_editor_toolbar_camera_button = spatial_editor_toolbar_buttons[11] - spatial_editor_toolbar_sun_button = spatial_editor_toolbar_buttons[12] - spatial_editor_toolbar_environment_button = spatial_editor_toolbar_buttons[13] - spatial_editor_toolbar_sun_environment_button = spatial_editor_toolbar_buttons[14] - spatial_editor_toolbar_transform_menu_button = spatial_editor_toolbar_buttons[15] - spatial_editor_toolbar_view_menu_button = spatial_editor_toolbar_buttons[16] - - script_editor = EditorInterface.get_script_editor() - script_editor_window_wrapper = script_editor.get_parent() - script_editor_code_panel = script_editor.get_child(0).get_child(1).get_child(1) - script_editor_top_bar = script_editor.get_child(0).get_child(0) - script_editor_items = Utils.find_child_by_type(script_editor, "ItemList") - script_editor_items_panel = script_editor_items.get_parent() - script_editor_functions_panel = script_editor_items_panel.get_parent().get_child(1) - asset_lib = Utils.find_child_by_type(main_screen, "EditorAssetLibrary") - - # Left Upper - scene_dock = Utils.find_child_by_type(base_control, "SceneTreeDock") - scene_dock_button_add = scene_dock.get_child(0).get_child(0) - node_create_window = Utils.find_child_by_type(scene_dock, "CreateDialog") - script_create_window = Utils.find_child_by_type(scene_dock, "ScriptCreateDialog") - node_create_panel = Utils.find_child_by_type(node_create_window, "HSplitContainer") - var node_create_dialog_vboxcontainer: VBoxContainer = Utils.find_child_by_type( - node_create_panel, "VBoxContainer", false - ) - node_create_dialog_node_tree = Utils.find_child_by_type( - node_create_dialog_vboxcontainer, "Tree" - ) - node_create_dialog_search_bar = Utils.find_child_by_type( - node_create_dialog_vboxcontainer, "LineEdit" - ) - node_create_dialog_button_create = node_create_window.get_ok_button() - node_create_dialog_button_cancel = node_create_window.get_cancel_button() - scene_tabs = Utils.find_child_by_type(scene_dock.get_parent(), "TabBar") - var scene_tree_editor := Utils.find_child_by_type(scene_dock, "SceneTreeEditor") - scene_tree = Utils.find_child_by_type(scene_tree_editor, "Tree") - select_node_window = Utils.find_child_by_type(base_control, "SceneTreeDialog") - import_dock = Utils.find_child_by_type(base_control, "ImportDock") - - # Left Bottom - filesystem_dock = Utils.find_child_by_type(base_control, "FileSystemDock") - filesystem_tabs = Utils.find_child_by_type(filesystem_dock.get_parent(), "TabBar") - filesystem_tree = Utils.find_child_by_type( - Utils.find_child_by_type(filesystem_dock, "SplitContainer"), "Tree" - ) - - # Right - inspector_dock = Utils.find_child_by_type(base_control, "InspectorDock") - inspector_tabs = Utils.find_child_by_type(inspector_dock.get_parent(), "TabBar") - inspector_editor = EditorInterface.get_inspector() - node_dock = Utils.find_child_by_type(base_control, "NodeDock") - node_dock_buttons_box = node_dock.get_child(0) - var node_dock_buttons := node_dock_buttons_box.get_children() - node_dock_signals_button = node_dock_buttons[0] - node_dock_groups_button = node_dock_buttons[1] - node_dock_signals_editor = Utils.find_child_by_type(node_dock, "ConnectionsDock") - node_dock_signals_tree = Utils.find_child_by_type(node_dock_signals_editor, "Tree") - - signals_dialog_window = Utils.find_child_by_type(node_dock_signals_editor, "ConnectDialog") - signals_dialog = signals_dialog_window.get_child(0) - signals_dialog_tree = Utils.find_child_by_type(signals_dialog, "Tree") - var signals_dialog_line_edits := signals_dialog.get_child(0).find_children( - "", "LineEdit", true, false - ) - signals_dialog_signal_line_edit = signals_dialog_line_edits[0] - signals_dialog_method_line_edit = signals_dialog_line_edits[-1] - signals_dialog_cancel_button = signals_dialog_window.get_cancel_button() - signals_dialog_ok_button = signals_dialog_window.get_ok_button() - node_dock_groups_editor = Utils.find_child_by_type(node_dock, "GroupsEditor") - history_dock = Utils.find_child_by_type(base_control, "HistoryDock") - - # Bottom - logger = Utils.find_child_by_type(base_control, "EditorLog") - logger_rich_text_label = Utils.find_child_by_type(logger, "RichTextLabel") - - bottom_panels_container = logger.get_parent().get_parent() - var bottom_panels_vboxcontainer: VBoxContainer = logger.get_parent() - - debugger = Utils.find_child_by_type(bottom_panels_vboxcontainer, "EditorDebuggerNode", false) - find_in_files = Utils.find_child_by_type(bottom_panels_vboxcontainer, "FindInFilesPanel", false) - audio_buses = Utils.find_child_by_type(bottom_panels_vboxcontainer, "EditorAudioBuses", false) - animation_player = Utils.find_child_by_type( - bottom_panels_vboxcontainer, "AnimationPlayerEditor", false - ) - shader = Utils.find_child_by_type(bottom_panels_vboxcontainer, "WindowWrapper", false) - var editor_toaster := Utils.find_child_by_type(bottom_panels_vboxcontainer, "EditorToaster") - bottom_buttons_container = Utils.find_child_by_type( - editor_toaster.get_parent(), "HBoxContainer", false - ) - - var bottom_button_children := bottom_buttons_container.get_children() - bottom_button_output = bottom_button_children[0] - bottom_button_debugger = bottom_button_children[1] - bottom_button_tileset = bottom_button_children[-3] - bottom_button_tilemap = bottom_button_children[-2] - bottom_buttons = [ - bottom_button_output, bottom_button_debugger, bottom_button_tileset, bottom_button_tilemap - ] - - tilemap = Utils.find_child_by_type(bottom_panels_vboxcontainer, "TileMapEditor", false) - var tilemap_flow_container: HFlowContainer = Utils.find_child_by_type( - tilemap, "HFlowContainer", false - ) - tilemap_tabs = tilemap_flow_container.get_child(0) - - tilemap_tiles_panel = tilemap.get_child(2) - var tilemap_tiles_hsplitcontainer: HSplitContainer = Utils.find_child_by_type( - tilemap_tiles_panel, "HSplitContainer", false - ) - tilemap_tiles = Utils.find_child_by_type(tilemap_tiles_hsplitcontainer, "ItemList") - tilemap_tiles_atlas_view = Utils.find_child_by_type( - tilemap_tiles_hsplitcontainer, "TileAtlasView", false - ) - tilemap_tiles_toolbar = tilemap_flow_container.get_child(1) - - tilemap_patterns_panel = tilemap.get_child(3) - tilemap_terrains_panel = tilemap.get_child(4) - var tilemap_terrains_hsplitcontainer: HSplitContainer = tilemap_terrains_panel.get_child(0) - tilemap_terrains_tree = Utils.find_child_by_type(tilemap_terrains_hsplitcontainer, "Tree") - tilemap_terrains_tiles = Utils.find_child_by_type(tilemap_terrains_hsplitcontainer, "ItemList") - tilemap_terrains_toolbar = tilemap_flow_container.get_child(2) - tilemap_terrains_tool_draw = tilemap_terrains_toolbar.get_child(0).get_child(0) - - tilemap_panels = [tilemap_tiles_panel, tilemap_patterns_panel, tilemap_terrains_panel] - - tileset = Utils.find_child_by_type(bottom_panels_vboxcontainer, "TileSetEditor", false) - tileset_tabs = Utils.find_child_by_type(tileset, "TabBar") - tileset_tiles_panel = tileset.get_child(0).get_child(1) - tileset_patterns_panel = tileset.get_child(0).get_child(2) - tileset_panels = [tileset_tiles_panel, tileset_patterns_panel] - - scene_import_settings_window = Utils.find_child_by_type(base_control, "SceneImportSettings") - scene_import_settings = scene_import_settings_window.get_child(0) - scene_import_settings_cancel_button = scene_import_settings_window.get_cancel_button() - scene_import_settings_ok_button = scene_import_settings_window.get_ok_button() - - windows.assign([signals_dialog_window, node_create_window, scene_import_settings_window]) - for window in windows: - window_toggle_tour_mode(window, true) - - -func clean_up() -> void: - for window in windows: - window_toggle_tour_mode(window, false) - - -func window_toggle_tour_mode(window: ConfirmationDialog, is_in_tour: bool) -> void: - window.dialog_close_on_escape = not is_in_tour - window.transient = is_in_tour - window.exclusive = not is_in_tour - window.physics_object_picking = is_in_tour - window.physics_object_picking_sort = is_in_tour - - -## Applies the Default layout to the editor. -## This is the equivalent of going to Editor -> Editor Layout -> Default. -## -## We call this at the start of a tour, so that every tour starts from the same base layout. -## This can't be done in the _init() function because upon opening Godot, loading previously opened -## scenes and restoring the user's editor layout can take several seconds. -func restore_default_layout() -> void: - var editor_popup_menu := menu_bar.get_menu_popup(3) - for layouts_popup_menu: PopupMenu in editor_popup_menu.get_children(): - var id: int = layouts_popup_menu.get_item_id(3) - layouts_popup_menu.id_pressed.emit(id) - - -func unfold_tree_item(item: TreeItem) -> void: - var parent := item.get_parent() - if parent != null: - item = parent - - var tree := item.get_tree() - while item != tree.get_root(): - item.collapsed = false - item = item.get_parent() - - -func is_in_scripting_context() -> bool: - return script_editor_window_wrapper.visible diff --git a/addons/block_code/lib/utils.gd b/addons/block_code/lib/utils.gd deleted file mode 100644 index 3d4015b1..00000000 --- a/addons/block_code/lib/utils.gd +++ /dev/null @@ -1,113 +0,0 @@ -class Helper: - static func noop() -> void: - pass - -const SEP := "/" - -## Finds files matching the String.match [code]pattern[/code] in the given directory [code]path[/code], recursively. -static func fs_find(pattern: String = "*", path: String = "res://") -> Array[String]: - var result: Array[String] = [] - var is_file := not pattern.ends_with(SEP) - - var dir := DirAccess.open(path) - if DirAccess.get_open_error() != OK: - printerr("ERROR: could not open [%s]" % path) - return result - - if dir.list_dir_begin() != OK: - printerr("ERROR: could not list contents of [%s]" % path) - return result - - path = dir.get_next() - while path.is_valid_filename(): - var new_path: String = dir.get_current_dir().path_join(path) - if dir.current_is_dir(): - if path.match(pattern.rstrip(SEP)) and not is_file: - result.push_back(new_path) - result += fs_find(pattern, new_path) - elif path.match(pattern): - result.push_back(new_path) - path = dir.get_next() - return result - - -static func find_children_by_path(from: Node, paths: Array[String]) -> Array[Node]: - var result: Array[Node] = [] - if from == null: - return result - - if from.name in paths: - result.push_back(from) - - for child in from.find_children("*"): - if child.owner == from and from.name.path_join(from.get_path_to(child)) in paths: - result.push_back(child) - return result - - -## Returns the first child of parent_node with the given type. -static func find_child_by_type(from: Node, type: String, is_recursive := true, predicate := Helper.noop) -> Node: - if from == null: - return null - var result := from.find_children("", type, is_recursive, false) - if not result.is_empty() and predicate != Helper.noop: - result = result.filter(predicate) - return null if result.is_empty() else result[0] - - -static func find_children_by_type(from: Node, type: String, is_recursive := true, predicate := Helper.noop): - if from == null: - return null - var result := from.find_children("", type, is_recursive, false) - if not result.is_empty() and predicate != Helper.noop: - result = result.filter(predicate) - return null if result.is_empty() else result - - -static func find_child_by_name(from: Node, name: String, is_recursive := true, predicate := Helper.noop) -> Node: - if from == null: - return null - var result := from.find_children(name, "", is_recursive, false) - if not result.is_empty() and predicate != Helper.noop: - result = result.filter(predicate) - return null if result.is_empty() else result[0] - - -static func get_tree_item_path(item: TreeItem, column: int = 0) -> String: - var partial_result: Array[String] = [item.get_text(column)] - var parent: TreeItem = item.get_parent() - while parent != null: - partial_result.push_front(parent.get_text(0)) - parent = parent.get_parent() - return partial_result.reduce(func(accum: String, p: String) -> String: return accum.path_join(p)) - - -static func filter_tree_items(item: TreeItem, predicate: Callable) -> Array[TreeItem]: - var go := func(go: Callable, root: TreeItem) -> Array[TreeItem]: - var result: Array[TreeItem] = [] - if predicate.call(root): - result.push_back(root) - for child in root.get_children(): - result.append_array(go.call(go, child)) - return result - return go.call(go, item) - - -## Searches children of the root TreeItem recursively and returns the first one with the given name. -## Stops at the first match found. -static func find_tree_item_by_name(tree: Tree, name: String) -> TreeItem: - var root: TreeItem = tree.get_root() - if root.get_text(0) == name: - return root - - var result: TreeItem = null - var stack: Array[TreeItem] = [root] - while not stack.is_empty(): - var item: TreeItem = stack.pop_back() - if item.get_text(0) == name: - result = item - break - - if item.get_child_count() > 0: - stack += item.get_children() - return result diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index e102404a..fe4ee0f9 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -2,8 +2,6 @@ class_name MainPanel extends Control -var eia: EditorInterfaceAccess - @onready var _picker: Picker = %Picker @onready var _block_canvas: BlockCanvas = %NodeBlockCanvas @onready var _drag_manager: DragManager = %DragManager @@ -15,7 +13,6 @@ var eia: EditorInterfaceAccess @onready var _icon_collapse := EditorInterface.get_editor_theme().get_icon("Back", "EditorIcons") @onready var _icon_expand := EditorInterface.get_editor_theme().get_icon("Forward", "EditorIcons") -var block_code_tab: Button var _current_block_code_node: BlockCode var _scene_root: Node var _block_code_nodes: Array @@ -30,10 +27,7 @@ func _ready(): _drag_manager.block_dropped.connect(save_script) _drag_manager.block_modified.connect(save_script) - eia = EditorInterfaceAccess.new() - # Setup block scripting environment - block_code_tab = eia.Utils.find_child_by_name(eia.context_switcher, "Block Code") undo_redo.version_changed.connect(_on_undo_redo_version_changed) _collapse_button.icon = _icon_collapse @@ -64,7 +58,7 @@ func switch_script(block_code_node: BlockCode): _title_bar.bsd_selected(block_script) _block_canvas.bsd_selected(block_script) if block_code_node: - block_code_tab.pressed.emit() + EditorInterface.set_main_screen_editor("Block Code") func save_script(): From 445a1d874d6134ef82c5cbd7ac7a6213a656325c Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 2 Jul 2024 17:52:48 -0700 Subject: [PATCH 003/423] Fix errors from duplicate output parameter blocks https://phabricator.endlessm.com/T35531 --- addons/block_code/drag_manager/drag_manager.gd | 6 ++++-- .../blocks/utilities/parameter_output/parameter_output.gd | 4 ++-- .../block_code/ui/blocks/utilities/snap_point/snap_point.gd | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index 620d80bf..bf553e32 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -245,8 +245,10 @@ func drag_ended(): func connect_block_canvas_signals(block: Block): - block.drag_started.connect(drag_block) - block.modified.connect(func(): block_modified.emit()) + if block.drag_started.get_connections().size() == 0: + block.drag_started.connect(drag_block) + if block.modified.get_connections().size() == 0: + block.modified.connect(func(): block_modified.emit()) ## Returns the scope of the first non-empty scope child block diff --git a/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd b/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd index daa77eb4..093014f0 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd +++ b/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd @@ -13,7 +13,7 @@ var output_block: Block func _ready(): _snap_point.block_type = Types.BlockType.NONE - _update_parameter_block() + _update_parameter_block.call_deferred() func _update_parameter_block(): @@ -38,4 +38,4 @@ func _on_snap_point_snapped_block_changed(snap_block: Block): func _on_snap_point_snapped_block_removed(snap_block: Block): snap_block.drag_started.disconnect(_on_parameter_block_drag_started) - _update_parameter_block() + _update_parameter_block.call_deferred() diff --git a/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd b/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd index 59f6e794..a1780074 100644 --- a/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd +++ b/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd @@ -88,7 +88,7 @@ func _on_child_entered_tree(node): if snapped_block: # We only allow a single snapped block at a time push_warning("Attempted to add more than one Block node ({block}) to the same SnapPoint ({snap_point})".format({"block": new_block, "snap_point": self})) - call_deferred("remove_child", snapped_block) + remove_child.call_deferred(snapped_block) snapped_block = new_block From 754aa9d9c5d9a9eb4dfbaef1fb949936d058aa08 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 2 Jul 2024 17:53:49 -0700 Subject: [PATCH 004/423] Remove a parameter block if it is dragged back to its source https://phabricator.endlessm.com/T35531 --- .../block_code/drag_manager/drag_manager.gd | 76 +++++++++++-------- .../blocks/parameter_block/parameter_block.gd | 1 + .../parameter_output/parameter_output.gd | 4 + 3 files changed, 51 insertions(+), 30 deletions(-) diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index bf553e32..5b4d1d87 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -19,6 +19,8 @@ class Drag: var _block_scope: String var _block_canvas: BlockCanvas var _preview_block: Control + var _snap_points: Array[Node] + var _delete_areas: Array[Rect2] var action: DragAction: get: return action @@ -49,7 +51,28 @@ class Drag: _block_scope = block_scope _block_canvas = block_canvas + func set_snap_points(snap_points: Array[Node]): + _snap_points = snap_points.filter(_snaps_to) + + func add_delete_area(delete_area: Rect2): + _delete_areas.append(delete_area) + + func update_drag_position(): + global_position = get_global_mouse_position() + + for rect in _delete_areas: + if rect.has_point(get_global_mouse_position()): + action = DragAction.REMOVE + target_snap_point = null + return + + action = DragAction.PLACE + + target_snap_point = _find_closest_snap_point() + func apply_drag() -> Block: + update_drag_position() + if action == DragAction.PLACE: _place_block() return _block @@ -82,7 +105,7 @@ class Drag: target_snap_point = null - func snaps_to(node: Node) -> bool: + func _snaps_to(node: Node) -> bool: var _snap_point: SnapPoint = node as SnapPoint if not _snap_point: @@ -101,9 +124,6 @@ class Drag: # We only snap Value blocks to snaps that can cast to same variant: return false - if _get_distance_to_snap_point(_snap_point) > Constants.MINIMUM_SNAP_DISTANCE: - return false - # Check if any parent node is this node if _snap_point.is_ancestor_of(_block): return false @@ -122,15 +142,24 @@ class Drag: return true + func _find_closest_snap_point() -> Node: + var closest_snap_point: SnapPoint = null + var closest_distance: int + for snap_point in _snap_points: + var distance = _get_distance_to_snap_point(snap_point) + if distance > Constants.MINIMUM_SNAP_DISTANCE: + continue + elif closest_snap_point == null or distance < closest_distance: + closest_snap_point = snap_point + closest_distance = distance + return closest_snap_point + func _get_top_block_for_node(node: Node) -> Block: for top_block in _block_canvas.get_blocks(): if top_block.is_ancestor_of(node): return top_block return null - func sort_snap_points_by_distance(a: SnapPoint, b: SnapPoint): - return _get_distance_to_snap_point(a) < _get_distance_to_snap_point(b) - func _get_distance_to_snap_point(snap_point: SnapPoint) -> float: var from_global: Vector2 = _block.global_position return from_global.distance_to(snap_point.global_position) @@ -172,34 +201,19 @@ func _ready(): func _process(_delta): - _update_drag_position() - - -func _update_drag_position(): - if not drag: - return - - drag.position = get_local_mouse_position() - - if _picker.get_global_rect().has_point(get_global_mouse_position()): - drag.action = DragAction.REMOVE - else: - drag.action = DragAction.PLACE - - # Find closest snap point not child of current node - var snap_points: Array[Node] = get_tree().get_nodes_in_group("snap_point").filter(drag.snaps_to) - snap_points.sort_custom(drag.sort_snap_points_by_distance) - - drag.target_snap_point = snap_points[0] if snap_points.size() > 0 else null + if drag: + drag.update_drag_position() func drag_block(block: Block, copied_from: Block = null): var offset: Vector2 - if copied_from: + if copied_from and copied_from.is_inside_tree(): offset = get_global_mouse_position() - copied_from.global_position - else: + elif block.is_inside_tree(): offset = get_global_mouse_position() - block.global_position + else: + offset = Vector2.ZERO var parent = block.get_parent() @@ -213,6 +227,10 @@ func drag_block(block: Block, copied_from: Block = null): _block_canvas.set_scope(block_scope) drag = Drag.new(block, block_scope, offset, _block_canvas) + drag.set_snap_points(get_tree().get_nodes_in_group("snap_point")) + drag.add_delete_area(_picker.get_global_rect()) + if block is ParameterBlock and block.spawned_by: + drag.add_delete_area(block.spawned_by.get_global_rect()) add_child(drag) @@ -229,8 +247,6 @@ func drag_ended(): if not drag: return - _update_drag_position() - var block = drag.apply_drag() if block: diff --git a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd index bb2ce232..2ee9b51f 100644 --- a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd +++ b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd @@ -12,6 +12,7 @@ extends Block var param_name_input_pairs: Array var param_input_strings: Dictionary # Only loaded from serialized +var spawned_by: ParameterOutput func _ready(): diff --git a/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd b/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd index 093014f0..a8edf4df 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd +++ b/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd @@ -23,6 +23,7 @@ func _update_parameter_block(): var parameter_block = preload("res://addons/block_code/ui/blocks/parameter_block/parameter_block.tscn").instantiate() for key in block_params: parameter_block[key] = block_params[key] + parameter_block.spawned_by = self _snap_point.add_child.call_deferred(parameter_block) @@ -33,6 +34,9 @@ func _on_parameter_block_drag_started(drag_block: Block): func _on_snap_point_snapped_block_changed(snap_block: Block): if snap_block == null: return + # FIXME: The spawned_by property isn't serialized, so we'll set it here to + # be sure. In the future, we should try to get rid of this property. + snap_block.spawned_by = self snap_block.drag_started.connect(_on_parameter_block_drag_started) From 0359e24de5218247ee15d9678984dfda40ea44d9 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Tue, 2 Jul 2024 22:45:07 +0100 Subject: [PATCH 005/423] background: Simplify shift_top/_bottom handling There is no need for a conditional here. The previous code boiled down to: stroke_polygon += [[0.0 if shift_top == 0.0 else shift_top, 0.0]] which makes the redundant condition clearer. --- .../blocks/utilities/background/background.gd | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/addons/block_code/ui/blocks/utilities/background/background.gd b/addons/block_code/ui/blocks/utilities/background/background.gd index 541edb2e..666c1f1a 100644 --- a/addons/block_code/ui/blocks/utilities/background/background.gd +++ b/addons/block_code/ui/blocks/utilities/background/background.gd @@ -77,14 +77,9 @@ func _draw(): ] var stroke_polygon = [] - if shift_top == 0: - stroke_polygon += [ - [0.0, 0.0], - ] - else: - stroke_polygon += [ - [shift_top, 0.0], - ] + stroke_polygon += [ + [shift_top, 0.0], + ] if show_top: stroke_polygon += [ [Constants.KNOB_X + shift_top, 0.0], @@ -100,14 +95,10 @@ func _draw(): [Constants.KNOB_X + Constants.KNOB_Z + shift_bottom, size.y + Constants.KNOB_H], [Constants.KNOB_X + shift_bottom, size.y], ] - if shift_bottom == 0: - stroke_polygon += [ - [0.0, size.y], - ] - else: - stroke_polygon += [ - [shift_bottom, size.y], - ] + + stroke_polygon += [ + [shift_bottom, size.y], + ] if shift_top + shift_bottom == 0: stroke_polygon += [ [0.0, 0.0], From d19c2fa44a122d61fc0ef59652a6f0edf98185f6 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Wed, 3 Jul 2024 11:31:37 +0100 Subject: [PATCH 006/423] main_panel: Correct tooltip for block picker toggle button The tooltip previously claimed that the shortcut was Ctrl + Space, but in fact it is Ctrl + Backslash. Fix this error; and adjust the tooltip style to match the tooltip on the equivalent button in the script editor view. I personally don't like the camel-casing of BackSlash but that's what Godot calls that key. --- addons/block_code/ui/main_panel.tscn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/block_code/ui/main_panel.tscn b/addons/block_code/ui/main_panel.tscn index 70801637..e8716335 100644 --- a/addons/block_code/ui/main_panel.tscn +++ b/addons/block_code/ui/main_panel.tscn @@ -73,7 +73,7 @@ layout_mode = 2 unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 8 -tooltip_text = "Collapse the picker toolbar. Shortcut (Ctrl-Space)" +tooltip_text = "Toggle Block Picker (Ctrl+BackSlash)" flat = true [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/BottomBar"] From f642d43c3a85f06cfc86b6604cc1d4520bd4bd50 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Wed, 3 Jul 2024 09:17:19 +0100 Subject: [PATCH 007/423] background: Build PackedVector2Array directly --- .../blocks/utilities/background/background.gd | 99 +++++++++---------- 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/addons/block_code/ui/blocks/utilities/background/background.gd b/addons/block_code/ui/blocks/utilities/background/background.gd index 666c1f1a..f8e3dae9 100644 --- a/addons/block_code/ui/blocks/utilities/background/background.gd +++ b/addons/block_code/ui/blocks/utilities/background/background.gd @@ -46,65 +46,58 @@ func _set_shift_bottom(new_shift_bottom): queue_redraw() -func float_array_to_Vector2Array(coords: Array) -> PackedVector2Array: - # Convert the array of floats into a PackedVector2Array. - var array: PackedVector2Array = [] - for coord in coords: - array.append(Vector2(coord[0], coord[1])) - return array - - func _draw(): outline_color = color.darkened(0.2) - var fill_polygon = [[0.0, 0.0]] + var fill_polygon: PackedVector2Array + fill_polygon.append(Vector2(0.0, 0.0)) if show_top: - fill_polygon += [ - [Constants.KNOB_X + shift_top, 0.0], - [Constants.KNOB_X + Constants.KNOB_Z + shift_top, Constants.KNOB_H], - [Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_top, Constants.KNOB_H], - [Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_top, 0.0], + fill_polygon.append_array(PackedVector2Array( + [ + Vector2(Constants.KNOB_X + shift_top, 0.0), + Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_top, Constants.KNOB_H), + Vector2(Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_top, Constants.KNOB_H), + Vector2(Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_top, 0.0), + ] + )) + fill_polygon.append_array(PackedVector2Array( + [ + Vector2(size.x, 0.0), + Vector2(size.x, size.y), + Vector2(Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_bottom, size.y), + Vector2(Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_bottom, size.y + Constants.KNOB_H), + Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_bottom, size.y + Constants.KNOB_H), + Vector2(Constants.KNOB_X + shift_bottom, size.y), + Vector2(0.0, size.y), + Vector2(0.0, 0.0), ] - fill_polygon += [ - [size.x, 0.0], - [size.x, size.y], - [Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_bottom, size.y], - [Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_bottom, size.y + Constants.KNOB_H], - [Constants.KNOB_X + Constants.KNOB_Z + shift_bottom, size.y + Constants.KNOB_H], - [Constants.KNOB_X + shift_bottom, size.y], - [0.0, size.y], - [0.0, 0.0], - ] - - var stroke_polygon = [] - stroke_polygon += [ - [shift_top, 0.0], - ] + )) + + var stroke_polygon: PackedVector2Array + stroke_polygon.append(Vector2(shift_top, 0.0)) if show_top: - stroke_polygon += [ - [Constants.KNOB_X + shift_top, 0.0], - [Constants.KNOB_X + Constants.KNOB_Z + shift_top, Constants.KNOB_H], - [Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_top, Constants.KNOB_H], - [Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_top, 0.0], + stroke_polygon.append_array(PackedVector2Array( + [ + Vector2(Constants.KNOB_X + shift_top, 0.0), + Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_top, Constants.KNOB_H), + Vector2(Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_top, Constants.KNOB_H), + Vector2(Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_top, 0.0), + ] + )) + stroke_polygon.append_array(PackedVector2Array( + [ + Vector2(size.x, 0.0), + Vector2(size.x, size.y), + Vector2(Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_bottom, size.y), + Vector2(Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_bottom, size.y + Constants.KNOB_H), + Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_bottom, size.y + Constants.KNOB_H), + Vector2(Constants.KNOB_X + shift_bottom, size.y), ] - stroke_polygon += [ - [size.x, 0.0], - [size.x, size.y], - [Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_bottom, size.y], - [Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_bottom, size.y + Constants.KNOB_H], - [Constants.KNOB_X + Constants.KNOB_Z + shift_bottom, size.y + Constants.KNOB_H], - [Constants.KNOB_X + shift_bottom, size.y], - ] - - stroke_polygon += [ - [shift_bottom, size.y], - ] + )) + + stroke_polygon.append(Vector2(shift_bottom, size.y)) if shift_top + shift_bottom == 0: - stroke_polygon += [ - [0.0, 0.0], - ] + stroke_polygon.append(Vector2(0.0, 0.0)) - var packed_fill_polygon = float_array_to_Vector2Array(fill_polygon) - var packed_stroke_polygon = float_array_to_Vector2Array(stroke_polygon) - draw_colored_polygon(packed_fill_polygon, color) - draw_polyline(packed_stroke_polygon, outline_color, Constants.OUTLINE_WIDTH) + draw_colored_polygon(fill_polygon, color) + draw_polyline(stroke_polygon, outline_color, Constants.OUTLINE_WIDTH) From ae2a0a109c64eff7a84218816146560a6d7793b9 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Wed, 3 Jul 2024 13:57:10 +0100 Subject: [PATCH 008/423] background: Placate gdformat --- .../blocks/utilities/background/background.gd | 62 +++++++------------ 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/addons/block_code/ui/blocks/utilities/background/background.gd b/addons/block_code/ui/blocks/utilities/background/background.gd index f8e3dae9..9a330d73 100644 --- a/addons/block_code/ui/blocks/utilities/background/background.gd +++ b/addons/block_code/ui/blocks/utilities/background/background.gd @@ -52,48 +52,34 @@ func _draw(): var fill_polygon: PackedVector2Array fill_polygon.append(Vector2(0.0, 0.0)) if show_top: - fill_polygon.append_array(PackedVector2Array( - [ - Vector2(Constants.KNOB_X + shift_top, 0.0), - Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_top, Constants.KNOB_H), - Vector2(Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_top, Constants.KNOB_H), - Vector2(Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_top, 0.0), - ] - )) - fill_polygon.append_array(PackedVector2Array( - [ - Vector2(size.x, 0.0), - Vector2(size.x, size.y), - Vector2(Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_bottom, size.y), - Vector2(Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_bottom, size.y + Constants.KNOB_H), - Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_bottom, size.y + Constants.KNOB_H), - Vector2(Constants.KNOB_X + shift_bottom, size.y), - Vector2(0.0, size.y), - Vector2(0.0, 0.0), - ] - )) + fill_polygon.append(Vector2(Constants.KNOB_X + shift_top, 0.0)) + fill_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_top, Constants.KNOB_H)) + fill_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_top, Constants.KNOB_H)) + fill_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_top, 0.0)) + + fill_polygon.append(Vector2(size.x, 0.0)) + fill_polygon.append(Vector2(size.x, size.y)) + fill_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_bottom, size.y)) + fill_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_bottom, size.y + Constants.KNOB_H)) + fill_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_bottom, size.y + Constants.KNOB_H)) + fill_polygon.append(Vector2(Constants.KNOB_X + shift_bottom, size.y)) + fill_polygon.append(Vector2(0.0, size.y)) + fill_polygon.append(Vector2(0.0, 0.0)) var stroke_polygon: PackedVector2Array stroke_polygon.append(Vector2(shift_top, 0.0)) if show_top: - stroke_polygon.append_array(PackedVector2Array( - [ - Vector2(Constants.KNOB_X + shift_top, 0.0), - Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_top, Constants.KNOB_H), - Vector2(Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_top, Constants.KNOB_H), - Vector2(Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_top, 0.0), - ] - )) - stroke_polygon.append_array(PackedVector2Array( - [ - Vector2(size.x, 0.0), - Vector2(size.x, size.y), - Vector2(Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_bottom, size.y), - Vector2(Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_bottom, size.y + Constants.KNOB_H), - Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_bottom, size.y + Constants.KNOB_H), - Vector2(Constants.KNOB_X + shift_bottom, size.y), - ] - )) + stroke_polygon.append(Vector2(Constants.KNOB_X + shift_top, 0.0)) + stroke_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_top, Constants.KNOB_H)) + stroke_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_top, Constants.KNOB_H)) + stroke_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_top, 0.0)) + + stroke_polygon.append(Vector2(size.x, 0.0)) + stroke_polygon.append(Vector2(size.x, size.y)) + stroke_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z * 2 + Constants.KNOB_W + shift_bottom, size.y)) + stroke_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z + Constants.KNOB_W + shift_bottom, size.y + Constants.KNOB_H)) + stroke_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_bottom, size.y + Constants.KNOB_H)) + stroke_polygon.append(Vector2(Constants.KNOB_X + shift_bottom, size.y)) stroke_polygon.append(Vector2(shift_bottom, size.y)) if shift_top + shift_bottom == 0: From e5029470882f1e39864620eeb690ea1fe4d1b9fd Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Wed, 3 Jul 2024 13:29:58 +0100 Subject: [PATCH 009/423] picker: Animate when scrolling to category --- addons/block_code/ui/picker/picker.gd | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/addons/block_code/ui/picker/picker.gd b/addons/block_code/ui/picker/picker.gd index 831a7261..64d9a1b7 100644 --- a/addons/block_code/ui/picker/picker.gd +++ b/addons/block_code/ui/picker/picker.gd @@ -9,6 +9,8 @@ signal block_picked(block: Block) @onready var _category_list := %CategoryList @onready var _widget_container := %WidgetContainer +var scroll_tween: Tween + func bsd_selected(bsd: BlockScriptData): if not bsd: @@ -74,10 +76,17 @@ func _block_picked(block: Block): block_picked.emit(block) +func scroll_to(y: float): + if scroll_tween: + scroll_tween.kill() + scroll_tween = create_tween() + scroll_tween.tween_property(_block_scroll, "scroll_vertical", y, 0.2) + + func _category_selected(category: BlockCategory): for block_category_display in _block_list.get_children(): if block_category_display.category.name == category.name: - _block_scroll.scroll_vertical = block_category_display.position.y + scroll_to(block_category_display.position.y) break From f2a24e58f6b8091e82d2581905c89bf490e67c40 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Wed, 3 Jul 2024 15:35:32 +0100 Subject: [PATCH 010/423] Remove unused BasicBlock scene & code This has been unused for some time; I believe since commit 06f89c75cea70cc4352b1ef160fa425a73110fa1. --- addons/block_code/block_code_plugin.gd | 1 - .../ui/blocks/basic_block/basic_block.gd | 25 -------- .../ui/blocks/basic_block/basic_block.tscn | 64 ------------------- .../ui/picker/categories/category_factory.gd | 1 - 4 files changed, 91 deletions(-) delete mode 100644 addons/block_code/ui/blocks/basic_block/basic_block.gd delete mode 100644 addons/block_code/ui/blocks/basic_block/basic_block.tscn diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 950ae75c..7173e096 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -14,7 +14,6 @@ const DISABLED_CLASSES := [ "DragManager", "InstructionTree", "Types", - "BasicBlock", "Block", "ControlBlock", "ParameterBlock", diff --git a/addons/block_code/ui/blocks/basic_block/basic_block.gd b/addons/block_code/ui/blocks/basic_block/basic_block.gd deleted file mode 100644 index 8b7f2bf1..00000000 --- a/addons/block_code/ui/blocks/basic_block/basic_block.gd +++ /dev/null @@ -1,25 +0,0 @@ -@tool -class_name BasicBlock -extends Block - -@onready var _top_bar := %TopBar -@onready var _label := %Label - - -func _ready(): - super() - - _top_bar.color = color - _label.text = label - - -func _on_drag_drop_area_mouse_down(): - _drag_started() - - -static func get_block_class(): - return "BasicBlock" - - -static func get_scene_path(): - return "res://addons/block_code/ui/blocks/basic_block/basic_block.tscn" diff --git a/addons/block_code/ui/blocks/basic_block/basic_block.tscn b/addons/block_code/ui/blocks/basic_block/basic_block.tscn deleted file mode 100644 index a99b7af8..00000000 --- a/addons/block_code/ui/blocks/basic_block/basic_block.tscn +++ /dev/null @@ -1,64 +0,0 @@ -[gd_scene load_steps=5 format=3 uid="uid://c4cjt0oi4me43"] - -[ext_resource type="Script" path="res://addons/block_code/ui/blocks/basic_block/basic_block.gd" id="1_ph7wu"] -[ext_resource type="Script" path="res://addons/block_code/ui/blocks/utilities/background/background.gd" id="2_iwx12"] -[ext_resource type="PackedScene" uid="uid://c7puyxpqcq6xo" path="res://addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.tscn" id="2_r14pb"] -[ext_resource type="PackedScene" uid="uid://b1oge52xhjqnu" path="res://addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn" id="3_15ikp"] - -[node name="BasicBlock" type="MarginContainer"] -size_flags_horizontal = 0 -script = ExtResource("1_ph7wu") -block_name = "basic_block" -label = "Basic Block" -color = Color(0.530082, 0.933559, 0.726557, 1) -bottom_snap_path = NodePath("VBoxContainer/SnapPoint") - -[node name="VBoxContainer" type="VBoxContainer" parent="."] -layout_mode = 2 -theme_override_constants/separation = 0 - -[node name="TopMarginContainer" type="MarginContainer" parent="VBoxContainer"] -custom_minimum_size = Vector2(0, 30) -layout_mode = 2 -size_flags_horizontal = 0 -theme_override_constants/margin_left = 0 -theme_override_constants/margin_top = 0 -theme_override_constants/margin_right = 0 -theme_override_constants/margin_bottom = 0 - -[node name="TopBar" type="Control" parent="VBoxContainer/TopMarginContainer"] -unique_name_in_owner = true -layout_mode = 2 -mouse_filter = 1 -script = ExtResource("2_iwx12") -color = Color(0.530082, 0.933559, 0.726557, 1) -outline_color = Color(0.424066, 0.746847, 0.581246, 1) -show_top = false - -[node name="DragDropArea" parent="VBoxContainer/TopMarginContainer" instance=ExtResource("2_r14pb")] -layout_mode = 2 - -[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/TopMarginContainer"] -layout_mode = 2 -mouse_filter = 2 -theme_override_constants/margin_left = 10 -theme_override_constants/margin_top = 6 -theme_override_constants/margin_right = 12 -theme_override_constants/margin_bottom = 6 - -[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/TopMarginContainer/MarginContainer"] -custom_minimum_size = Vector2(200, 0) -layout_mode = 2 -mouse_filter = 2 - -[node name="Label" type="Label" parent="VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer"] -unique_name_in_owner = true -layout_mode = 2 -theme_override_colors/font_color = Color(1, 1, 1, 1) -text = "Basic Block" - -[node name="SnapPoint" parent="VBoxContainer" instance=ExtResource("3_15ikp")] -layout_mode = 2 -block_path = NodePath("../..") - -[connection signal="mouse_down" from="VBoxContainer/TopMarginContainer/DragDropArea" to="." method="_on_drag_drop_area_mouse_down"] diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 56f81c18..fb001816 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -2,7 +2,6 @@ class_name CategoryFactory extends Object const BLOCKS: Dictionary = { - "basic_block": preload("res://addons/block_code/ui/blocks/basic_block/basic_block.tscn"), "control_block": preload("res://addons/block_code/ui/blocks/control_block/control_block.tscn"), "parameter_block": preload("res://addons/block_code/ui/blocks/parameter_block/parameter_block.tscn"), "statement_block": preload("res://addons/block_code/ui/blocks/statement_block/statement_block.tscn"), From 16ab468742f47901174e43ab19608380ba6d8c52 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Wed, 3 Jul 2024 16:21:04 +0100 Subject: [PATCH 011/423] Use is_physical_key_pressed for game input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documentation of `Input.is_physical_key_pressed` says: > `is_physical_key_pressed()` is recommended over `is_key_pressed()` for > in-game actions, as it will make `W`/`A`/`S`/`D` layouts work regardless of > the user's keyboard layout. `is_physical_key_pressed()` will also ensure that > the top row number keys work on any keyboard layout. If in doubt, use > `is_physical_key_pressed()`. The physical keys labelled `W` `A` `S` `D` on a US keyboard enter different characters on some non-US keyboard layouts: - AZERTY (standard in France): `Z` `Q` `S` `D` - Dvorak (standard on my desk): `,` `A` `O` `E` (The other widely-used layout for Latin text is QWERTZ, used primarily in German-speaking regions; though I have learned while trying to justify this change that the Serbian Cyrillic layout is a rare example of a non-Latin layout that is based on QWERTZ, presumably for geographic reasons. But WASD are the same in QWERTZ and QWERTY.) Adjust the “Move with player 1/2 buttons” blocks accordingly. I have not adjusted the “Move with keys {up: STRING} {down: STRING} {left: STRING} {right: STRING} with speed {speed: VECTOR2}” block because when the user enters strings into that block, they will be entering the logical character corresponding to the physical key on their keyboard that they want to use. It would be very confusing if a French user configured that block to use keys Z S Q D and then those keys were mapped to their physical locations on a US keyboard. The distinction between physical keys and logical keys is confusing and not something we want to try to explain here (IMO). --- .../examples/pong_game/pong_game.tscn | 32 +++++++++---------- .../simple_character/simple_character.gd | 16 +++++----- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index cbeb2378..149f5429 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -16,10 +16,10 @@ script = ExtResource("5_wr38c") block_class = &"StatementBlock" serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.835294, 0.262745, 0.133333, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Move with player 1 buttons, speed {speed: VECTOR2}"], ["statement", "var dir = Vector2() -dir.x += float(Input.is_key_pressed(KEY_D)) -dir.x -= float(Input.is_key_pressed(KEY_A)) -dir.y += float(Input.is_key_pressed(KEY_S)) -dir.y -= float(Input.is_key_pressed(KEY_W)) +dir.x += float(Input.is_physical_key_pressed(KEY_D)) +dir.x -= float(Input.is_physical_key_pressed(KEY_A)) +dir.y += float(Input.is_physical_key_pressed(KEY_S)) +dir.y -= float(Input.is_physical_key_pressed(KEY_W)) dir = dir.normalized() velocity = dir*{speed} move_and_slide()"], ["defaults", {}], ["param_input_strings", { @@ -55,10 +55,10 @@ var VAR_DICT := {} func _process(delta): var dir = Vector2() - dir.x += float(Input.is_key_pressed(KEY_D)) - dir.x -= float(Input.is_key_pressed(KEY_A)) - dir.y += float(Input.is_key_pressed(KEY_S)) - dir.y -= float(Input.is_key_pressed(KEY_W)) + dir.x += float(Input.is_physical_key_pressed(KEY_D)) + dir.x -= float(Input.is_physical_key_pressed(KEY_A)) + dir.y += float(Input.is_physical_key_pressed(KEY_S)) + dir.y -= float(Input.is_physical_key_pressed(KEY_W)) dir = dir.normalized() velocity = dir*Vector2(0,1000) move_and_slide() @@ -69,10 +69,10 @@ func _process(delta): script = ExtResource("5_wr38c") block_class = &"StatementBlock" serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.835294, 0.262745, 0.133333, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Move with player 2 buttons, speed {speed: VECTOR2}"], ["statement", "var dir = Vector2() -dir.x += float(Input.is_key_pressed(KEY_RIGHT)) -dir.x -= float(Input.is_key_pressed(KEY_LEFT)) -dir.y += float(Input.is_key_pressed(KEY_DOWN)) -dir.y -= float(Input.is_key_pressed(KEY_UP)) +dir.x += float(Input.is_physical_key_pressed(KEY_RIGHT)) +dir.x -= float(Input.is_physical_key_pressed(KEY_LEFT)) +dir.y += float(Input.is_physical_key_pressed(KEY_DOWN)) +dir.y -= float(Input.is_physical_key_pressed(KEY_UP)) dir = dir.normalized() velocity = dir*{speed} move_and_slide()"], ["defaults", {}], ["param_input_strings", { @@ -108,10 +108,10 @@ var VAR_DICT := {} func _process(delta): var dir = Vector2() - dir.x += float(Input.is_key_pressed(KEY_RIGHT)) - dir.x -= float(Input.is_key_pressed(KEY_LEFT)) - dir.y += float(Input.is_key_pressed(KEY_DOWN)) - dir.y -= float(Input.is_key_pressed(KEY_UP)) + dir.x += float(Input.is_physical_key_pressed(KEY_RIGHT)) + dir.x -= float(Input.is_physical_key_pressed(KEY_LEFT)) + dir.y += float(Input.is_physical_key_pressed(KEY_DOWN)) + dir.y -= float(Input.is_physical_key_pressed(KEY_UP)) dir = dir.normalized() velocity = dir*Vector2(0,1000) move_and_slide() diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index 1b488fd2..4b20b690 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -40,10 +40,10 @@ static func get_custom_blocks() -> Array[Block]: b.block_format = "Move with player 1 buttons, speed {speed: VECTOR2}" b.statement = ( "var dir = Vector2()\n" - + "dir.x += float(Input.is_key_pressed(KEY_D))\n" - + "dir.x -= float(Input.is_key_pressed(KEY_A))\n" - + "dir.y += float(Input.is_key_pressed(KEY_S))\n" - + "dir.y -= float(Input.is_key_pressed(KEY_W))\n" + + "dir.x += float(Input.is_physical_key_pressed(KEY_D))\n" + + "dir.x -= float(Input.is_physical_key_pressed(KEY_A))\n" + + "dir.y += float(Input.is_physical_key_pressed(KEY_S))\n" + + "dir.y -= float(Input.is_physical_key_pressed(KEY_W))\n" + "dir = dir.normalized()\n" + "velocity = dir*{speed}\n" + "move_and_slide()" @@ -56,10 +56,10 @@ static func get_custom_blocks() -> Array[Block]: b.block_format = "Move with player 2 buttons, speed {speed: VECTOR2}" b.statement = ( "var dir = Vector2()\n" - + "dir.x += float(Input.is_key_pressed(KEY_RIGHT))\n" - + "dir.x -= float(Input.is_key_pressed(KEY_LEFT))\n" - + "dir.y += float(Input.is_key_pressed(KEY_DOWN))\n" - + "dir.y -= float(Input.is_key_pressed(KEY_UP))\n" + + "dir.x += float(Input.is_physical_key_pressed(KEY_RIGHT))\n" + + "dir.x -= float(Input.is_physical_key_pressed(KEY_LEFT))\n" + + "dir.y += float(Input.is_physical_key_pressed(KEY_DOWN))\n" + + "dir.y -= float(Input.is_physical_key_pressed(KEY_UP))\n" + "dir = dir.normalized()\n" + "velocity = dir*{speed}\n" + "move_and_slide()" From cc307af93c21f39bf695f205f8731385e703708a Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Wed, 3 Jul 2024 09:45:43 -0600 Subject: [PATCH 012/423] background: Avoid infinite draw cycle Setting outline_color queues a redraw, so setting it in the draw handler implies that it will queue infinite redraws. In Godot 4.2 this doesn't happen, but in Godot 4.3 it does and causes the editor to lock up until it finally crashes. I don't know if it's a bug in one version or the other, but either way we don't need to do that. If outline_color is already set based on the color, then set it at the time color is set and stop exporting it since any user provided value would be ignored. https://phabricator.endlessm.com/T35494 --- .../ui/blocks/utilities/background/background.gd | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/addons/block_code/ui/blocks/utilities/background/background.gd b/addons/block_code/ui/blocks/utilities/background/background.gd index 9a330d73..0c61f669 100644 --- a/addons/block_code/ui/blocks/utilities/background/background.gd +++ b/addons/block_code/ui/blocks/utilities/background/background.gd @@ -3,12 +3,11 @@ extends Control const Constants = preload("res://addons/block_code/ui/constants.gd") +var outline_color: Color + @export var color: Color: set = _set_color -@export var outline_color: Color: - set = _set_outline_color - @export var show_top: bool = true: set = _set_show_top @@ -23,11 +22,7 @@ const Constants = preload("res://addons/block_code/ui/constants.gd") func _set_color(new_color): color = new_color - queue_redraw() - - -func _set_outline_color(new_outline_color): - outline_color = new_outline_color + outline_color = color.darkened(0.2) queue_redraw() @@ -47,8 +42,6 @@ func _set_shift_bottom(new_shift_bottom): func _draw(): - outline_color = color.darkened(0.2) - var fill_polygon: PackedVector2Array fill_polygon.append(Vector2(0.0, 0.0)) if show_top: From 29bef8c753d0cc5b8c6adbb934f4d1540f1f8e20 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Wed, 3 Jul 2024 14:35:23 -0600 Subject: [PATCH 013/423] category_factory: Fix static Callable use in Godot 4.2.1 In Godot 4.2.1, a static function used as a Callable from a static function fails to be resolved. This causes the following error in our case: ``` res://addons/block_code/ui/picker/categories/category_factory.gd:109 - Invalid get index '_category_cmp' (on base: 'Nil') ``` See https://github.com/godotengine/godot/issues/86032 for details. This can be worked around by using the fully qualified class method name. Fixes: #94 --- addons/block_code/ui/picker/categories/category_factory.gd | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index fb001816..b1c57009 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -150,7 +150,10 @@ static func get_categories(blocks: Array[Block], extra_categories: Array[BlockCa # convert an array type besides Array.assign(). var cats: Array[BlockCategory] = [] cats.assign(cat_map.values()) - cats.sort_custom(_category_cmp) + # Accessing a static Callable from a static function fails in 4.2.1. + # Use the fully qualified name. + # https://github.com/godotengine/godot/issues/86032 + cats.sort_custom(CategoryFactory._category_cmp) return cats From 1fdfe85f577a35d1710db5ba96c289895577181f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 5 Jul 2024 15:49:21 -0300 Subject: [PATCH 014/423] SimpleCharacter: Use methods for player movement Add 2 methods and call them, instead of having the implementation in the code template ("statement" property). This improves a bit when serializing the implementation. But most importantly, allows the 2 blocks to be added to the same node without a collision on the var dir being declared twice. --- .../simple_character/simple_character.gd | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index 4b20b690..da51a012 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -5,6 +5,23 @@ extends CharacterBody2D @export var texture: Texture2D: set = _set_texture +const PLAYER_KEYS = { + "player_1": + { + "up": KEY_W, + "down": KEY_S, + "left": KEY_A, + "right": KEY_D, + }, + "player_2": + { + "up": KEY_UP, + "down": KEY_DOWN, + "left": KEY_LEFT, + "right": KEY_RIGHT, + } +} + func _set_texture(new_texture): texture = new_texture @@ -30,6 +47,16 @@ func get_custom_class(): return "SimpleCharacter" +func move_with_player_buttons(player: String, speed: Vector2): + var dir = Vector2() + dir.x += float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["right"])) + dir.x -= float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["left"])) + dir.y += float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["down"])) + dir.y -= float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["up"])) + velocity = dir.normalized() * speed + move_and_slide() + + static func get_custom_blocks() -> Array[Block]: var b: Block var block_list: Array[Block] = [] @@ -38,32 +65,14 @@ static func get_custom_blocks() -> Array[Block]: b = CategoryFactory.BLOCKS["statement_block"].instantiate() b.block_type = Types.BlockType.EXECUTE b.block_format = "Move with player 1 buttons, speed {speed: VECTOR2}" - b.statement = ( - "var dir = Vector2()\n" - + "dir.x += float(Input.is_physical_key_pressed(KEY_D))\n" - + "dir.x -= float(Input.is_physical_key_pressed(KEY_A))\n" - + "dir.y += float(Input.is_physical_key_pressed(KEY_S))\n" - + "dir.y -= float(Input.is_physical_key_pressed(KEY_W))\n" - + "dir = dir.normalized()\n" - + "velocity = dir*{speed}\n" - + "move_and_slide()" - ) + b.statement = "move_with_player_buttons('player_1', {speed})" b.category = "Input" block_list.append(b) b = CategoryFactory.BLOCKS["statement_block"].instantiate() b.block_type = Types.BlockType.EXECUTE b.block_format = "Move with player 2 buttons, speed {speed: VECTOR2}" - b.statement = ( - "var dir = Vector2()\n" - + "dir.x += float(Input.is_physical_key_pressed(KEY_RIGHT))\n" - + "dir.x -= float(Input.is_physical_key_pressed(KEY_LEFT))\n" - + "dir.y += float(Input.is_physical_key_pressed(KEY_DOWN))\n" - + "dir.y -= float(Input.is_physical_key_pressed(KEY_UP))\n" - + "dir = dir.normalized()\n" - + "velocity = dir*{speed}\n" - + "move_and_slide()" - ) + b.statement = "move_with_player_buttons('player_2', {speed})" b.category = "Input" block_list.append(b) From 52d0c5f4fb751203c2d0f3a0c0bd231917ecbf0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 5 Jul 2024 16:03:44 -0300 Subject: [PATCH 015/423] SimpleCharacter: Single movement block Make player 1, player 2 options, defaulting to player 1. And add default to speed too. A speed of Vector2(300,300) is very opinionated but seems fine for the default project viewport. --- .../simple_character/simple_character.gd | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index da51a012..536509d5 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -64,15 +64,12 @@ static func get_custom_blocks() -> Array[Block]: # Movement b = CategoryFactory.BLOCKS["statement_block"].instantiate() b.block_type = Types.BlockType.EXECUTE - b.block_format = "Move with player 1 buttons, speed {speed: VECTOR2}" - b.statement = "move_with_player_buttons('player_1', {speed})" - b.category = "Input" - block_list.append(b) - - b = CategoryFactory.BLOCKS["statement_block"].instantiate() - b.block_type = Types.BlockType.EXECUTE - b.block_format = "Move with player 2 buttons, speed {speed: VECTOR2}" - b.statement = "move_with_player_buttons('player_2', {speed})" + b.block_format = "Move with {player: OPTION} buttons, speed {speed: VECTOR2}" + b.statement = 'move_with_player_buttons("{player}", {speed})' + b.defaults = { + "player": OptionData.new(["player_1", "player_2"]), + "speed": "300,300", + } b.category = "Input" block_list.append(b) From 1bb2fd45b8ab09e3ca714bf693d01ae57aae034e Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Fri, 5 Jul 2024 12:24:22 -0700 Subject: [PATCH 016/423] Add a warning when a BlockCode node is inside a BlockCode node --- addons/block_code/block_code_node/block_code.gd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/block_code/block_code_node/block_code.gd b/addons/block_code/block_code_node/block_code.gd index 8c2b867f..9a14a43c 100644 --- a/addons/block_code/block_code_node/block_code.gd +++ b/addons/block_code/block_code_node/block_code.gd @@ -67,6 +67,8 @@ func _update_parent_script(): func _get_configuration_warnings(): var warnings = [] + if get_parent() is BlockCode: + warnings.append("The parent must not be a BlockCode.") if block_script and _get_custom_or_native_class(get_parent()) != block_script.script_inherits: var warning = "The parent is not a %s. Create a new BlockCode node and reattach." % block_script.script_inherits warnings.append(warning) From b68fea58708b108a53f357e542ee1639b49c2dbc Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Fri, 5 Jul 2024 12:24:55 -0700 Subject: [PATCH 017/423] Add a warning when a BlockCode node has multiple BlockCode siblings --- addons/block_code/block_code_node/block_code.gd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/block_code/block_code_node/block_code.gd b/addons/block_code/block_code_node/block_code.gd index 9a14a43c..d3bcd783 100644 --- a/addons/block_code/block_code_node/block_code.gd +++ b/addons/block_code/block_code_node/block_code.gd @@ -69,6 +69,8 @@ func _get_configuration_warnings(): var warnings = [] if get_parent() is BlockCode: warnings.append("The parent must not be a BlockCode.") + if get_parent().find_children("*", "BlockCode", false).size() > 1: + warnings.append("The parent should only contain one BlockCode.") if block_script and _get_custom_or_native_class(get_parent()) != block_script.script_inherits: var warning = "The parent is not a %s. Create a new BlockCode node and reattach." % block_script.script_inherits warnings.append(warning) From 7a9ee1138b6fc1f0fc5ea5fc4b44e23e6a219b86 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Fri, 5 Jul 2024 13:25:55 -0700 Subject: [PATCH 018/423] Add a warning when a BlockCode node is placed as a root node --- addons/block_code/block_code_node/block_code.gd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/block_code/block_code_node/block_code.gd b/addons/block_code/block_code_node/block_code.gd index d3bcd783..fc03f04f 100644 --- a/addons/block_code/block_code_node/block_code.gd +++ b/addons/block_code/block_code_node/block_code.gd @@ -67,6 +67,8 @@ func _update_parent_script(): func _get_configuration_warnings(): var warnings = [] + if self.owner == null: + warnings.append("A BlockCode must not be a root node.") if get_parent() is BlockCode: warnings.append("The parent must not be a BlockCode.") if get_parent().find_children("*", "BlockCode", false).size() > 1: From 3fd3d06bf8287c184dc1da6087dbf4bd63a3d4d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 8 Jul 2024 10:06:58 -0300 Subject: [PATCH 019/423] Make SimpleCharacter more flexible To allow different movement kinds for different game possibilities. The previous is now the default and named "as top-down". In addition, now "as platformer" and "as spaceship" are available. The speed is now exposed as a property to prevent the block getting too long with 3 parameters. The speed vector is used differently in each situation: - for platformer, Y is the jump speed - for spaceship, X is the rotation speed For platformer, the gravity is read from project settings, but also there is a method to update it. Remove the gravity custom setting from the project setting, that was added back at some point by mistake. https://phabricator.endlessm.com/T35549 --- .../simple_character/simple_character.gd | 75 ++++++++++++++++--- project.godot | 4 - 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index 536509d5..8d19179b 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -5,6 +5,9 @@ extends CharacterBody2D @export var texture: Texture2D: set = _set_texture +@export var speed: Vector2 = Vector2(300, 300): + set = _set_speed + const PLAYER_KEYS = { "player_1": { @@ -22,6 +25,11 @@ const PLAYER_KEYS = { } } +# Get the gravity from the project settings to be synced with RigidBody nodes. +var gravity = ProjectSettings.get_setting("physics/2d/default_gravity") + +var _jumping = false + func _set_texture(new_texture): texture = new_texture @@ -35,25 +43,58 @@ func _set_texture(new_texture): $CollisionShape2D.shape = shape +func _set_speed(new_speed): + speed = new_speed + + +## Nodes in the "affected_by_gravity" group will receive gravity changes: +func on_gravity_changed(new_gravity): + gravity = new_gravity + + func _ready(): + add_to_group("affected_by_gravity") simple_setup() func simple_setup(): _set_texture(texture) + _set_speed(speed) func get_custom_class(): return "SimpleCharacter" -func move_with_player_buttons(player: String, speed: Vector2): - var dir = Vector2() - dir.x += float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["right"])) - dir.x -= float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["left"])) - dir.y += float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["down"])) - dir.y -= float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["up"])) - velocity = dir.normalized() * speed +func _player_input_to_direction(player: String): + var direction = Vector2() + direction.x += float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["right"])) + direction.x -= float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["left"])) + direction.y += float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["down"])) + direction.y -= float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["up"])) + return direction + + +func move_with_player_buttons(player: String, kind: String, delta: float): + var direction = _player_input_to_direction(player) + + if kind == "top-down": + velocity = direction * speed + + elif kind == "platformer": + velocity.x = direction.x * speed.x + if not is_on_floor(): + velocity.y += gravity * delta + else: + if not _jumping and Input.is_physical_key_pressed(PLAYER_KEYS[player]["up"]): + _jumping = true + velocity.y -= speed.y + else: + _jumping = false + + elif kind == "spaceship": + rotation_degrees += direction.x * speed.x / 100.0 + velocity = Vector2.DOWN.rotated(rotation) * speed.y * direction.y move_and_slide() @@ -64,13 +105,27 @@ static func get_custom_blocks() -> Array[Block]: # Movement b = CategoryFactory.BLOCKS["statement_block"].instantiate() b.block_type = Types.BlockType.EXECUTE - b.block_format = "Move with {player: OPTION} buttons, speed {speed: VECTOR2}" - b.statement = 'move_with_player_buttons("{player}", {speed})' + b.block_format = "Move with {player: OPTION} buttons as {kind: OPTION}" + # TODO: delta here is assumed to be the parameter name of + # the _process or _physics_process method: + b.statement = 'move_with_player_buttons("{player}", "{kind}", delta)' b.defaults = { "player": OptionData.new(["player_1", "player_2"]), - "speed": "300,300", + "kind": OptionData.new(["top-down", "platformer", "spaceship"]), } b.category = "Input" block_list.append(b) + var property_blocks = ( + CategoryFactory + . property_to_blocklist( + { + "name": "speed", + "type": TYPE_VECTOR2, + "category": "Physics | Velocity", + } + ) + ) + block_list.append_array(property_blocks) + return block_list diff --git a/project.godot b/project.godot index 80eaedcd..4be7b9c3 100644 --- a/project.godot +++ b/project.godot @@ -19,10 +19,6 @@ config/icon="res://icon.svg" enabled=PackedStringArray("res://addons/block_code/plugin.cfg", "res://addons/gut/plugin.cfg", "res://addons/plugin_refresher/plugin.cfg") -[physics] - -2d/default_gravity=0.0 - [rendering] renderer/rendering_method="gl_compatibility" From 63d405a084402985b6202e8b4122b72eb998c554 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 3 Jul 2024 15:51:04 -0700 Subject: [PATCH 020/423] Move Block Code editor to the bottom panel This new bottom panel control will appear whenever a BlockCode node is present in the scene. https://phabricator.endlessm.com/T35541 --- addons/block_code/block_code_plugin.gd | 31 +++++++++++++------------- addons/block_code/ui/main_panel.gd | 2 -- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 7173e096..2ee704f2 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -3,7 +3,8 @@ class_name BlockCodePlugin extends EditorPlugin const MainPanel := preload("res://addons/block_code/ui/main_panel.tscn") -static var main_panel +static var main_panel: MainPanel +static var block_code_button: Button var editor_inspector: EditorInspector @@ -52,11 +53,6 @@ func _enter_tree(): main_panel = MainPanel.instantiate() main_panel.undo_redo = get_undo_redo() - # Add the main panel to the editor's main viewport. - EditorInterface.get_editor_main_screen().add_child(main_panel) - # Hide the main panel. Very much required. - _make_visible(false) - # Remove unwanted class nodes from create node old_feature_profile = EditorInterface.get_current_feature_profile() @@ -75,8 +71,13 @@ func _enter_tree(): func _exit_tree(): + if block_code_button: + remove_control_from_bottom_panel(main_panel) + block_code_button = null + if main_panel: main_panel.queue_free() + main_panel = null var editor_paths: EditorPaths = EditorInterface.get_editor_paths() if editor_paths: @@ -96,21 +97,21 @@ func _ready(): func _on_scene_changed(scene_root: Node): + var scene_has_block_code_nodes = scene_root.find_children("*", "BlockCode").size() > 0 if scene_root else false + if scene_has_block_code_nodes and block_code_button == null: + block_code_button = add_control_to_bottom_panel(main_panel, _get_plugin_name()) + elif not scene_has_block_code_nodes and block_code_button: + remove_control_from_bottom_panel(main_panel) + block_code_button = null BlockCodePlugin.main_panel.switch_scene(scene_root) + _on_editor_inspector_edited_object_changed() func _on_editor_inspector_edited_object_changed(): var block_code: BlockCode = editor_inspector.get_edited_object() as BlockCode BlockCodePlugin.main_panel.switch_script(block_code) - - -func _has_main_screen(): - return true - - -func _make_visible(visible): - if main_panel: - main_panel.visible = visible + if block_code: + make_bottom_panel_item_visible(main_panel) func _get_plugin_name(): diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index fe4ee0f9..f285fbbf 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -57,8 +57,6 @@ func switch_script(block_code_node: BlockCode): _picker.bsd_selected(block_script) _title_bar.bsd_selected(block_script) _block_canvas.bsd_selected(block_script) - if block_code_node: - EditorInterface.set_main_screen_editor("Block Code") func save_script(): From 4e2af87f199812da514d82ecd65c47c94f9bafe3 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 3 Jul 2024 16:37:42 -0700 Subject: [PATCH 021/423] Add a button to create a block code node https://phabricator.endlessm.com/T35541 --- addons/block_code/block_code_plugin.gd | 7 +--- .../examples/pong_game/pong_game.tscn | 22 +++++------ .../ui/block_canvas/block_canvas.gd | 37 +++++++++++++++---- .../ui/block_canvas/block_canvas.tscn | 30 ++++++++++++--- 4 files changed, 66 insertions(+), 30 deletions(-) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 2ee704f2..4b42fb97 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -52,6 +52,7 @@ func _enter_tree(): main_panel = MainPanel.instantiate() main_panel.undo_redo = get_undo_redo() + block_code_button = add_control_to_bottom_panel(main_panel, _get_plugin_name()) # Remove unwanted class nodes from create node old_feature_profile = EditorInterface.get_current_feature_profile() @@ -97,12 +98,6 @@ func _ready(): func _on_scene_changed(scene_root: Node): - var scene_has_block_code_nodes = scene_root.find_children("*", "BlockCode").size() > 0 if scene_root else false - if scene_has_block_code_nodes and block_code_button == null: - block_code_button = add_control_to_bottom_panel(main_panel, _get_plugin_name()) - elif not scene_has_block_code_nodes and block_code_button: - remove_control_from_bottom_panel(main_panel) - block_code_button = null BlockCodePlugin.main_panel.switch_scene(scene_root) _on_editor_inspector_edited_object_changed() diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index 149f5429..41c45314 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -12,7 +12,7 @@ [ext_resource type="PackedScene" uid="uid://c7l70grmkauij" path="res://addons/block_code/examples/pong_game/ball.tscn" id="9_xrqll"] [ext_resource type="PackedScene" uid="uid://fhoapg3anjsu" path="res://addons/block_code/examples/pong_game/goal_area.tscn" id="12_nqmxu"] -[sub_resource type="Resource" id="Resource_k50df"] +[sub_resource type="Resource" id="Resource_k6jw1"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.835294, 0.262745, 0.133333, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Move with player 1 buttons, speed {speed: VECTOR2}"], ["statement", "var dir = Vector2() @@ -26,29 +26,29 @@ move_and_slide()"], ["defaults", {}], ["param_input_strings", { "speed": "0,1000" }]] -[sub_resource type="Resource" id="Resource_bjhgb"] +[sub_resource type="Resource" id="Resource_e61h1"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_k50df") +serialized_block = SubResource("Resource_k6jw1") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_fwk6m"] +[sub_resource type="Resource" id="Resource_pm7ay"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "process_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(167, 112)], ["scope", ""], ["block_format", "On Process"], ["statement", "func _process(delta):"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] +serialized_props = [["block_name", "process_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(174, 102)], ["scope", ""], ["block_format", "On Process"], ["statement", "func _process(delta):"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_8ar27"] +[sub_resource type="Resource" id="Resource_uln40"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_fwk6m") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_bjhgb")]] +serialized_block = SubResource("Resource_pm7ay") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_e61h1")]] -[sub_resource type="Resource" id="Resource_ue2t3"] +[sub_resource type="Resource" id="Resource_4j61k"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_8ar27")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_uln40")]) [sub_resource type="Resource" id="Resource_qmak3"] script = ExtResource("7_uuuue") script_inherits = "SimpleCharacter" -block_trees = SubResource("Resource_ue2t3") +block_trees = SubResource("Resource_4j61k") generated_script = "extends SimpleCharacter var VAR_DICT := {} diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index ce6f5693..955cbcf8 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -7,8 +7,9 @@ const BLOCK_AUTO_PLACE_MARGIN: Vector2 = Vector2(16, 8) @onready var _window: Control = %Window @onready var _window_scroll: ScrollContainer = %WindowScroll -@onready var _choose_block_code_label: Label = %ChooseBlockCodeLabel -@onready var _create_block_code_label: Label = %CreateBlockCodeLabel +@onready var _select_node_box: BoxContainer = %SelectNodeBox +@onready var _create_block_code_box: BoxContainer = %CreateBlockCodeBox +@onready var _add_block_code_button: Button = %AddBlockCodeButton var _block_scenes_by_class = {} @@ -59,14 +60,16 @@ func set_child(n: Node): func bsd_selected(bsd: BlockScriptData): clear_canvas() - _choose_block_code_label.visible = false - _create_block_code_label.visible = false + _select_node_box.visible = false + _create_block_code_box.visible = false + _add_block_code_button.disabled = true - if not bsd and scene_has_bsd_nodes(): - _choose_block_code_label.visible = true + if not bsd and EditorInterface.get_inspector().get_edited_object() is Node: + _create_block_code_box.visible = true + _add_block_code_button.disabled = false return - elif not bsd and not scene_has_bsd_nodes(): - _create_block_code_label.visible = true + elif not bsd: + _select_node_box.visible = true return for tree in bsd.block_trees.array: @@ -151,3 +154,21 @@ func set_scope(scope: String): func release_scope(): for block in _window.get_children(): block.modulate = Color.WHITE + + +func _on_add_block_code_button_pressed(): + _add_block_code_button.disabled = true + + var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node + var scene_root: Node = EditorInterface.get_edited_scene_root() + + if edited_node == null or scene_root == null: + return + + var block_code = BlockCode.new() + block_code.name = "BlockCode" + edited_node.add_child(block_code, true) + block_code.owner = scene_root + + EditorInterface.get_selection().clear() + EditorInterface.get_selection().add_node(block_code) diff --git a/addons/block_code/ui/block_canvas/block_canvas.tscn b/addons/block_code/ui/block_canvas/block_canvas.tscn index 29a9a9d7..804e7981 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.tscn +++ b/addons/block_code/ui/block_canvas/block_canvas.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=2 format=3 uid="uid://c6vumewgnfquy"] +[gd_scene load_steps=3 format=3 uid="uid://c6vumewgnfquy"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/block_canvas.gd" id="1_tk8h2"] +[ext_resource type="Texture2D" uid="uid://cmusxj1ppspnp" path="res://addons/block_code/block_code_node/block_code_node.svg" id="2_710vn"] [node name="BlockCanvas" type="MarginContainer"] anchors_preset = 15 @@ -25,16 +26,35 @@ layout_mode = 2 size_flags_horizontal = 3 mouse_filter = 1 -[node name="ChooseBlockCodeLabel" type="Label" parent="."] +[node name="SelectNodeBox" type="VBoxContainer" parent="."] unique_name_in_owner = true visible = false layout_mode = 2 -text = "Choose a BlockCode node in the inspector." +size_flags_vertical = 4 + +[node name="Label" type="Label" parent="SelectNodeBox"] +layout_mode = 2 +text = "First, select a node in the current scene." horizontal_alignment = 1 -[node name="CreateBlockCodeLabel" type="Label" parent="."] +[node name="CreateBlockCodeBox" type="VBoxContainer" parent="."] unique_name_in_owner = true visible = false layout_mode = 2 -text = "First, add a BlockCode node to the scene." +size_flags_vertical = 4 + +[node name="Label" type="Label" parent="CreateBlockCodeBox"] +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 +text = "Use block coding to create custom behavior and game mechanics for this node." horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="AddBlockCodeButton" type="Button" parent="CreateBlockCodeBox"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 4 +text = "Add Block Code" +icon = ExtResource("2_710vn") + +[connection signal="pressed" from="CreateBlockCodeBox/AddBlockCodeButton" to="." method="_on_add_block_code_button_pressed"] From 2c2db15e50831fe6cff4f8902b74ed755d13fc7a Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 3 Jul 2024 16:39:56 -0700 Subject: [PATCH 022/423] Clear editor selection when switching nodes via option button This now works as expected. https://phabricator.endlessm.com/T35541 --- addons/block_code/ui/title_bar/title_bar.gd | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/addons/block_code/ui/title_bar/title_bar.gd b/addons/block_code/ui/title_bar/title_bar.gd index 3d9053ad..f9370822 100644 --- a/addons/block_code/ui/title_bar/title_bar.gd +++ b/addons/block_code/ui/title_bar/title_bar.gd @@ -60,9 +60,5 @@ func _get_index_for_bsd(bsd: BlockScriptData) -> int: func _on_node_option_button_item_selected(index): var block_code_node = _node_option_button.get_item_metadata(index) as BlockCode - # FIXME: We should clear the existing selection, but at the moment this - # causes the new node to be deselected due to signal handlers being - # called in the wrong order. - #_editor_selection.clear() - if block_code_node: - EditorInterface.edit_node(block_code_node) + _editor_selection.clear() + _editor_selection.add_node(block_code_node) From 4593d1fca88c39cc08c0807c8f719007a6abbc7b Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 3 Jul 2024 16:40:48 -0700 Subject: [PATCH 023/423] Show block code for a node with a BlockCode node as a child To improve the experience when using block coding side by side with the 2D or 3D canvas, the Block Code panel will display block code associated with the selected node. https://phabricator.endlessm.com/T35541 --- addons/block_code/block_code_plugin.gd | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 4b42fb97..b6cdbe38 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -103,7 +103,14 @@ func _on_scene_changed(scene_root: Node): func _on_editor_inspector_edited_object_changed(): - var block_code: BlockCode = editor_inspector.get_edited_object() as BlockCode + var edited_node: Node = editor_inspector.get_edited_object() as Node + var block_code: BlockCode = edited_node as BlockCode + if block_code == null and edited_node: + # As a fallback, check if the edited node has a BlockCode node as a + # child and use that. We will only check one level deep to avoid + # confusing scenarios where a node could have multiple children, each + # with their own BlockCode nodes. + block_code = edited_node.find_children("*", "BlockCode", false).pop_front() BlockCodePlugin.main_panel.switch_script(block_code) if block_code: make_bottom_panel_item_visible(main_panel) From ea31273d173a8b950a2c5e215ae2a7e3a2994442 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Thu, 4 Jul 2024 10:25:36 -0700 Subject: [PATCH 024/423] Mention the selected node in "Add Block Code" text https://phabricator.endlessm.com/T35541 --- addons/block_code/ui/block_canvas/block_canvas.gd | 11 +++++++---- addons/block_code/ui/block_canvas/block_canvas.tscn | 7 +++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 955cbcf8..a608d7c3 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -9,7 +9,9 @@ const BLOCK_AUTO_PLACE_MARGIN: Vector2 = Vector2(16, 8) @onready var _window_scroll: ScrollContainer = %WindowScroll @onready var _select_node_box: BoxContainer = %SelectNodeBox @onready var _create_block_code_box: BoxContainer = %CreateBlockCodeBox -@onready var _add_block_code_button: Button = %AddBlockCodeButton +@onready var _create_block_code_label: Label = %CreateBlockCodeBox/Label +@onready var _create_block_code_button: Button = %CreateBlockCodeBox/Button +@onready var _create_block_code_label_format: String = _create_block_code_label.text var _block_scenes_by_class = {} @@ -62,11 +64,12 @@ func bsd_selected(bsd: BlockScriptData): _select_node_box.visible = false _create_block_code_box.visible = false - _add_block_code_button.disabled = true + _create_block_code_button.disabled = true if not bsd and EditorInterface.get_inspector().get_edited_object() is Node: _create_block_code_box.visible = true - _add_block_code_button.disabled = false + _create_block_code_label.text = _create_block_code_label_format.format({"node": EditorInterface.get_inspector().get_edited_object().name}) + _create_block_code_button.disabled = false return elif not bsd: _select_node_box.visible = true @@ -157,7 +160,7 @@ func release_scope(): func _on_add_block_code_button_pressed(): - _add_block_code_button.disabled = true + _create_block_code_button.disabled = true var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node var scene_root: Node = EditorInterface.get_edited_scene_root() diff --git a/addons/block_code/ui/block_canvas/block_canvas.tscn b/addons/block_code/ui/block_canvas/block_canvas.tscn index 804e7981..6a836e0d 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.tscn +++ b/addons/block_code/ui/block_canvas/block_canvas.tscn @@ -46,15 +46,14 @@ size_flags_vertical = 4 [node name="Label" type="Label" parent="CreateBlockCodeBox"] custom_minimum_size = Vector2(200, 0) layout_mode = 2 -text = "Use block coding to create custom behavior and game mechanics for this node." +text = "Use block coding to create custom behavior and game mechanics for \"{node}\"." horizontal_alignment = 1 autowrap_mode = 2 -[node name="AddBlockCodeButton" type="Button" parent="CreateBlockCodeBox"] -unique_name_in_owner = true +[node name="Button" type="Button" parent="CreateBlockCodeBox"] layout_mode = 2 size_flags_horizontal = 4 text = "Add Block Code" icon = ExtResource("2_710vn") -[connection signal="pressed" from="CreateBlockCodeBox/AddBlockCodeButton" to="." method="_on_add_block_code_button_pressed"] +[connection signal="pressed" from="CreateBlockCodeBox/Button" to="." method="_on_add_block_code_button_pressed"] From e0a420820edd2a5eef1642f53f3b237f3eda184e Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Thu, 4 Jul 2024 17:05:26 -0700 Subject: [PATCH 025/423] Duplicate instead of modifying block code resources from other scenes When editing a block code resource in the context of a scene, make sure we are saving the result in the same scene by creating a new copy. This improves the workflow when editing BlockCode nodes from instantiated child scenes: a user is unlikely to expect a change with the Block Code editor in one scene to modify a different scene file. https://phabricator.endlessm.com/T35541 --- addons/block_code/ui/main_panel.gd | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index f285fbbf..84a9f3ee 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -14,7 +14,6 @@ extends Control @onready var _icon_expand := EditorInterface.get_editor_theme().get_icon("Forward", "EditorIcons") var _current_block_code_node: BlockCode -var _scene_root: Node var _block_code_nodes: Array var _collapsed: bool = false @@ -51,7 +50,7 @@ func switch_scene(scene_root: Node): _title_bar.scene_selected(scene_root) -func switch_script(block_code_node: BlockCode): +func switch_block_code_node(block_code_node: BlockCode): var block_script: BlockScriptData = block_code_node.block_script if block_code_node else null _current_block_code_node = block_code_node _picker.bsd_selected(block_script) @@ -64,9 +63,24 @@ func save_script(): print("No script loaded to save.") return + var scene_node = EditorInterface.get_edited_scene_root() + var block_script: BlockScriptData = _current_block_code_node.block_script + var resource_path_split = block_script.resource_path.split("::", true, 1) + var resource_scene = resource_path_split[0] + undo_redo.create_action("Modify %s's block code script" % _current_block_code_node.get_parent().name) + + if resource_scene and resource_scene != scene_node.scene_file_path: + # This resource is from another scene. Since the user is changing it + # here, we'll make a copy for this scene rather than changing it in the + # other scene file. + undo_redo.add_undo_property(_current_block_code_node, "block_script", _current_block_code_node.block_script) + block_script = block_script.duplicate(true) + _current_block_code_node.block_script = block_script + undo_redo.add_do_property(_current_block_code_node, "block_script", _current_block_code_node.block_script) + undo_redo.add_undo_property(_current_block_code_node.block_script, "block_trees", _current_block_code_node.block_script.block_trees) undo_redo.add_undo_property(_current_block_code_node.block_script, "generated_script", _current_block_code_node.block_script.generated_script) From a3b6898d6cbcac6e6ffc26922b6f9447106ce0fc Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Thu, 4 Jul 2024 17:11:07 -0700 Subject: [PATCH 026/423] Add a feature to override BlockCode from a child scene This reorganizes the empty state widgets in BlockCanvas, adding a new set of actions when the user selects a node which contains block code, but the block code can't be edited. This commit also includes changes to better handle when a BlockCode node is inside a node from a different scene but with editable children. https://phabricator.endlessm.com/T35541 --- addons/block_code/block_code_plugin.gd | 55 +++++++++--- .../ui/block_canvas/block_canvas.gd | 83 +++++++++++++++---- .../ui/block_canvas/block_canvas.tscn | 66 +++++++++++++-- addons/block_code/ui/main_panel.gd | 4 + addons/block_code/ui/title_bar/title_bar.gd | 11 ++- 5 files changed, 180 insertions(+), 39 deletions(-) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index b6cdbe38..94fa24d6 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -8,6 +8,8 @@ static var block_code_button: Button var editor_inspector: EditorInspector +var selected_block_code_node: BlockCode + var old_feature_profile: String = "" const DISABLED_CLASSES := [ @@ -93,6 +95,7 @@ func _exit_tree(): func _ready(): connect("scene_changed", _on_scene_changed) editor_inspector.connect("edited_object_changed", _on_editor_inspector_edited_object_changed) + editor_inspector.connect("property_edited", _on_editor_inspector_property_edited) _on_scene_changed(EditorInterface.get_edited_scene_root()) _on_editor_inspector_edited_object_changed() @@ -103,19 +106,51 @@ func _on_scene_changed(scene_root: Node): func _on_editor_inspector_edited_object_changed(): - var edited_node: Node = editor_inspector.get_edited_object() as Node - var block_code: BlockCode = edited_node as BlockCode - if block_code == null and edited_node: - # As a fallback, check if the edited node has a BlockCode node as a - # child and use that. We will only check one level deep to avoid - # confusing scenarios where a node could have multiple children, each - # with their own BlockCode nodes. - block_code = edited_node.find_children("*", "BlockCode", false).pop_front() - BlockCodePlugin.main_panel.switch_script(block_code) - if block_code: + var edited_node = editor_inspector.get_edited_object() as Node + + # We will edit either the selected node (if it is a BlockCode node) or + # the first BlockCode child of that node. + selected_block_code_node = list_block_code_for_node(edited_node).pop_front() + if not is_block_code_editable(selected_block_code_node): + selected_block_code_node = null + + BlockCodePlugin.main_panel.switch_block_code_node(selected_block_code_node) + if selected_block_code_node: make_bottom_panel_item_visible(main_panel) +static func is_block_code_editable(block_code: BlockCode) -> bool: + if not block_code: + return false + + # A BlockCode node can be edited if it belongs to the edited scene, or it + # is an editable instance. + + var scene_node = EditorInterface.get_edited_scene_root() + + return block_code == scene_node or block_code.owner == scene_node or scene_node.is_editable_instance(block_code.owner) + + +static func node_has_block_code(node: Node, recursive: bool = false) -> bool: + return list_block_code_for_node(node, recursive).size() > 0 + + +static func list_block_code_for_node(node: Node, recursive: bool = false) -> Array[BlockCode]: + var result: Array[BlockCode] = [] + + if node is BlockCode: + result.append(node) + elif node: + result.append_array(node.find_children("*", "BlockCode", recursive)) + + return result + + +func _on_editor_inspector_property_edited(property: String): + if selected_block_code_node: + _on_editor_inspector_edited_object_changed() + + func _get_plugin_name(): return "Block Code" diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index a608d7c3..4cebbd3a 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -7,11 +7,19 @@ const BLOCK_AUTO_PLACE_MARGIN: Vector2 = Vector2(16, 8) @onready var _window: Control = %Window @onready var _window_scroll: ScrollContainer = %WindowScroll -@onready var _select_node_box: BoxContainer = %SelectNodeBox -@onready var _create_block_code_box: BoxContainer = %CreateBlockCodeBox -@onready var _create_block_code_label: Label = %CreateBlockCodeBox/Label -@onready var _create_block_code_button: Button = %CreateBlockCodeBox/Button -@onready var _create_block_code_label_format: String = _create_block_code_label.text +@onready var _empty_box: BoxContainer = %EmptyBox + +@onready var _selected_node_box: BoxContainer = %SelectedNodeBox +@onready var _selected_node_label: Label = %SelectedNodeBox/Label +@onready var _selected_node_label_format: String = _selected_node_label.text + +@onready var _selected_node_with_block_code_box: BoxContainer = %SelectedNodeWithBlockCodeBox +@onready var _selected_node_with_block_code_label: Label = %SelectedNodeWithBlockCodeBox/Label +@onready var _selected_node_with_block_code_label_format: String = _selected_node_with_block_code_label.text + +@onready var _add_block_code_button: Button = %AddBlockCodeButton +@onready var _open_scene_button: Button = %OpenSceneButton +@onready var _replace_block_code_button: Button = %ReplaceBlockCodeButton var _block_scenes_by_class = {} @@ -19,6 +27,7 @@ signal reconnect_block(block: Block) func _ready(): + _open_scene_button.icon = _open_scene_button.get_theme_icon("Load", "EditorIcons") _populate_block_scenes_by_class() @@ -62,19 +71,36 @@ func set_child(n: Node): func bsd_selected(bsd: BlockScriptData): clear_canvas() - _select_node_box.visible = false - _create_block_code_box.visible = false - _create_block_code_button.disabled = true + var edited_node = EditorInterface.get_inspector().get_edited_object() as Node + + _empty_box.visible = false + _selected_node_box.visible = false + _selected_node_with_block_code_box.visible = false + _add_block_code_button.disabled = true + _open_scene_button.disabled = true + _replace_block_code_button.disabled = true + + if bsd != null: + _load_bsd(bsd) + elif edited_node == null: + _empty_box.visible = true + elif BlockCodePlugin.node_has_block_code(edited_node): + # If the selected node has a block code node, but BlockCodePlugin didn't + # provide it to bsd_selected, we assume the block code itself is not + # editable. In that case, provide options to either edit the node's + # scene file, or override the BlockCode node. This is mostly to avoid + # creating a situation where a node has multiple BlockCode nodes. + _selected_node_with_block_code_box.visible = true + _selected_node_with_block_code_label.text = _selected_node_with_block_code_label_format.format({"node": edited_node.name}) + _open_scene_button.disabled = false if edited_node.scene_file_path else true + _replace_block_code_button.disabled = false + else: + _selected_node_box.visible = true + _selected_node_label.text = _selected_node_label_format.format({"node": edited_node.name}) + _add_block_code_button.disabled = false - if not bsd and EditorInterface.get_inspector().get_edited_object() is Node: - _create_block_code_box.visible = true - _create_block_code_label.text = _create_block_code_label_format.format({"node": EditorInterface.get_inspector().get_edited_object().name}) - _create_block_code_button.disabled = false - return - elif not bsd: - _select_node_box.visible = true - return +func _load_bsd(bsd: BlockScriptData): for tree in bsd.block_trees.array: load_tree(_window, tree) @@ -160,7 +186,7 @@ func release_scope(): func _on_add_block_code_button_pressed(): - _create_block_code_button.disabled = true + _add_block_code_button.disabled = true var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node var scene_root: Node = EditorInterface.get_edited_scene_root() @@ -175,3 +201,26 @@ func _on_add_block_code_button_pressed(): EditorInterface.get_selection().clear() EditorInterface.get_selection().add_node(block_code) + + +func _on_open_scene_button_pressed(): + _open_scene_button.disabled = true + + var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node + + if edited_node == null or edited_node.owner == null: + return + + EditorInterface.open_scene_from_path(edited_node.scene_file_path) + + +func _on_replace_block_code_button_pressed(): + var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node + var scene_root: Node = EditorInterface.get_edited_scene_root() + + scene_root.set_editable_instance(edited_node, true) + + var block_code_nodes = BlockCodePlugin.list_block_code_for_node(edited_node) +# + EditorInterface.get_selection().clear() + EditorInterface.get_selection().add_node(block_code_nodes.pop_front() if block_code_nodes.size() > 0 else edited_node) diff --git a/addons/block_code/ui/block_canvas/block_canvas.tscn b/addons/block_code/ui/block_canvas/block_canvas.tscn index 6a836e0d..d4422476 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.tscn +++ b/addons/block_code/ui/block_canvas/block_canvas.tscn @@ -1,8 +1,20 @@ -[gd_scene load_steps=3 format=3 uid="uid://c6vumewgnfquy"] +[gd_scene load_steps=5 format=3 uid="uid://c6vumewgnfquy"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/block_canvas.gd" id="1_tk8h2"] [ext_resource type="Texture2D" uid="uid://cmusxj1ppspnp" path="res://addons/block_code/block_code_node/block_code_node.svg" id="2_710vn"] +[sub_resource type="Image" id="Image_p0ogw"] +data = { +"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), +"format": "RGBA8", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id="ImageTexture_vt8ew"] +image = SubResource("Image_p0ogw") + [node name="BlockCanvas" type="MarginContainer"] anchors_preset = 15 anchor_right = 1.0 @@ -26,34 +38,72 @@ layout_mode = 2 size_flags_horizontal = 3 mouse_filter = 1 -[node name="SelectNodeBox" type="VBoxContainer" parent="."] +[node name="EmptyBox" type="VBoxContainer" parent="."] unique_name_in_owner = true visible = false layout_mode = 2 size_flags_vertical = 4 -[node name="Label" type="Label" parent="SelectNodeBox"] +[node name="Label" type="Label" parent="EmptyBox"] layout_mode = 2 -text = "First, select a node in the current scene." +text = "Select a node to create and edit block code." horizontal_alignment = 1 -[node name="CreateBlockCodeBox" type="VBoxContainer" parent="."] +[node name="SelectedNodeBox" type="VBoxContainer" parent="."] unique_name_in_owner = true visible = false layout_mode = 2 size_flags_vertical = 4 -[node name="Label" type="Label" parent="CreateBlockCodeBox"] +[node name="Label" type="Label" parent="SelectedNodeBox"] custom_minimum_size = Vector2(200, 0) layout_mode = 2 text = "Use block coding to create custom behavior and game mechanics for \"{node}\"." horizontal_alignment = 1 autowrap_mode = 2 -[node name="Button" type="Button" parent="CreateBlockCodeBox"] +[node name="ButtonsBox" type="HBoxContainer" parent="SelectedNodeBox"] +layout_mode = 2 +size_flags_horizontal = 4 + +[node name="AddBlockCodeButton" type="Button" parent="SelectedNodeBox/ButtonsBox"] +unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 4 text = "Add Block Code" icon = ExtResource("2_710vn") -[connection signal="pressed" from="CreateBlockCodeBox/Button" to="." method="_on_add_block_code_button_pressed"] +[node name="SelectedNodeWithBlockCodeBox" type="VBoxContainer" parent="."] +unique_name_in_owner = true +visible = false +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Label" type="Label" parent="SelectedNodeWithBlockCodeBox"] +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 +text = "\"{node}\" uses block coding." +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="ButtonsBox" type="HBoxContainer" parent="SelectedNodeWithBlockCodeBox"] +layout_mode = 2 +size_flags_horizontal = 4 + +[node name="OpenSceneButton" type="Button" parent="SelectedNodeWithBlockCodeBox/ButtonsBox"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 4 +text = "Open in Editor" +icon = SubResource("ImageTexture_vt8ew") + +[node name="ReplaceBlockCodeButton" type="Button" parent="SelectedNodeWithBlockCodeBox/ButtonsBox"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 4 +text = "Override Block Code" +icon = ExtResource("2_710vn") + +[connection signal="pressed" from="SelectedNodeBox/ButtonsBox/AddBlockCodeButton" to="." method="_on_add_block_code_button_pressed"] +[connection signal="pressed" from="SelectedNodeWithBlockCodeBox/ButtonsBox/OpenSceneButton" to="." method="_on_open_scene_button_pressed"] +[connection signal="pressed" from="SelectedNodeWithBlockCodeBox/ButtonsBox/ReplaceBlockCodeButton" to="." method="_on_replace_block_code_button_pressed"] diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index 84a9f3ee..7382d127 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -65,6 +65,10 @@ func save_script(): var scene_node = EditorInterface.get_edited_scene_root() + if not BlockCodePlugin.is_block_code_editable(_current_block_code_node): + print("Block code for {node} is not editable.".format({"node": _current_block_code_node})) + return + var block_script: BlockScriptData = _current_block_code_node.block_script var resource_path_split = block_script.resource_path.split("::", true, 1) diff --git a/addons/block_code/ui/title_bar/title_bar.gd b/addons/block_code/ui/title_bar/title_bar.gd index f9370822..699412d8 100644 --- a/addons/block_code/ui/title_bar/title_bar.gd +++ b/addons/block_code/ui/title_bar/title_bar.gd @@ -15,7 +15,7 @@ func _ready(): func scene_selected(scene_root: Node): - _update_node_option_button_options() + _update_node_option_button_items() var current_block_code = _editor_inspector.get_edited_object() as BlockCode if not current_block_code: bsd_selected(null) @@ -27,14 +27,14 @@ func bsd_selected(bsd: BlockScriptData): # we'll crudely update the list of BlockCode nodes whenever the # selection changes. - _update_node_option_button_options() + _update_node_option_button_items() var select_index = _get_index_for_bsd(bsd) if _node_option_button.selected != select_index: _node_option_button.select(select_index) -func _update_node_option_button_options(): +func _update_node_option_button_items(): _node_option_button.clear() var scene_root = EditorInterface.get_edited_scene_root() @@ -42,7 +42,10 @@ func _update_node_option_button_options(): if not scene_root: return - for block_code_node in scene_root.find_children("*", "BlockCode"): + for block_code_node in BlockCodePlugin.list_block_code_for_node(scene_root, true): + if not BlockCodePlugin.is_block_code_editable(block_code_node): + continue + var node_item_index = _node_option_button.item_count var node_label = "{name} ({type})".format({"name": scene_root.get_path_to(block_code_node).get_concatenated_names(), "type": block_code_node.block_script.script_inherits}) _node_option_button.add_item(node_label) From de848959678bdb6140fb2d87d3c97fd74b2ae96f Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Fri, 5 Jul 2024 12:26:06 -0700 Subject: [PATCH 027/423] Only show the Block Code panel if a BlockCode node is selected https://phabricator.endlessm.com/T35541 --- addons/block_code/block_code_plugin.gd | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 94fa24d6..1b1fee70 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -115,7 +115,10 @@ func _on_editor_inspector_edited_object_changed(): selected_block_code_node = null BlockCodePlugin.main_panel.switch_block_code_node(selected_block_code_node) - if selected_block_code_node: + if edited_node is BlockCode: + # If the user explicitly chose a BlockCode node, show the Block Code + # editor. We only do this for the BlockCode node itself, rather than + # nodes containing BlockCode, to avoid conflicts with other panels. make_bottom_panel_item_visible(main_panel) From 875a7c8c1a0fb64ef4f6a4820562af14a5da7818 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Mon, 8 Jul 2024 11:03:47 -0700 Subject: [PATCH 028/423] Add InspectorActionButton type variation for block canvas buttons We want the buttons in the block canvas empty state to have a visible outline against the default background. We can achieve this by using the "InspectorActionButton" type variation, which is used for a similar situation in the Godot editor's built in Inspector panel. https://phabricator.endlessm.com/T35541 --- addons/block_code/ui/block_canvas/block_canvas.gd | 3 ++- addons/block_code/ui/block_canvas/block_canvas.tscn | 11 +++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 4cebbd3a..c49f92ed 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -27,7 +27,8 @@ signal reconnect_block(block: Block) func _ready(): - _open_scene_button.icon = _open_scene_button.get_theme_icon("Load", "EditorIcons") + if not _open_scene_button.icon: + _open_scene_button.icon = _open_scene_button.get_theme_icon("Load", "EditorIcons") _populate_block_scenes_by_class() diff --git a/addons/block_code/ui/block_canvas/block_canvas.tscn b/addons/block_code/ui/block_canvas/block_canvas.tscn index d4422476..1d7bdeba 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.tscn +++ b/addons/block_code/ui/block_canvas/block_canvas.tscn @@ -3,7 +3,7 @@ [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/block_canvas.gd" id="1_tk8h2"] [ext_resource type="Texture2D" uid="uid://cmusxj1ppspnp" path="res://addons/block_code/block_code_node/block_code_node.svg" id="2_710vn"] -[sub_resource type="Image" id="Image_p0ogw"] +[sub_resource type="Image" id="Image_2jxnn"] data = { "data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), "format": "RGBA8", @@ -12,8 +12,8 @@ data = { "width": 16 } -[sub_resource type="ImageTexture" id="ImageTexture_vt8ew"] -image = SubResource("Image_p0ogw") +[sub_resource type="ImageTexture" id="ImageTexture_jgo72"] +image = SubResource("Image_2jxnn") [node name="BlockCanvas" type="MarginContainer"] anchors_preset = 15 @@ -70,6 +70,7 @@ size_flags_horizontal = 4 unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 4 +theme_type_variation = &"InspectorActionButton" text = "Add Block Code" icon = ExtResource("2_710vn") @@ -94,13 +95,15 @@ size_flags_horizontal = 4 unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 4 +theme_type_variation = &"InspectorActionButton" text = "Open in Editor" -icon = SubResource("ImageTexture_vt8ew") +icon = SubResource("ImageTexture_jgo72") [node name="ReplaceBlockCodeButton" type="Button" parent="SelectedNodeWithBlockCodeBox/ButtonsBox"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 4 +theme_type_variation = &"InspectorActionButton" text = "Override Block Code" icon = ExtResource("2_710vn") From 296d13236fe7e8d76ccf9c8ddc0073229755ad0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 8 Jul 2024 15:41:56 -0300 Subject: [PATCH 029/423] Add blocks for AnimationPlayer - Play (ahead/backwards) - Pause - Stop - is playing? https://phabricator.endlessm.com/T35543 --- .../ui/picker/categories/category_factory.gd | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index b1c57009..ba85a11e 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -47,6 +47,11 @@ const BUILTIN_PROPS: Dictionary = { "color": Color("03aa74"), "order": 61, }, + "Graphics | Animation": + { + "color": Color("03aa74"), + "order": 62, + }, "Sounds": { "color": Color("e30fc0"), @@ -630,6 +635,47 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: "angular_velocity": "Physics | Velocity", } + "AnimationPlayer": + var b = BLOCKS["statement_block"].instantiate() + b.block_format = "Play {animation: STRING} {direction: OPTION}" + b.statement = ( + """ + if "{direction}" == "ahead": + play({animation}) + else: + play_backwards({animation}) + """ + . dedent() + ) + b.defaults = { + "direction": OptionData.new(["ahead", "backwards"]), + } + b.tooltip_text = "Play the animation." + b.category = "Graphics | Animation" + block_list.append(b) + + b = BLOCKS["statement_block"].instantiate() + b.block_format = "Pause" + b.statement = "pause()" + b.tooltip_text = "Pause the currently playing animation." + b.category = "Graphics | Animation" + block_list.append(b) + + b = BLOCKS["statement_block"].instantiate() + b.block_format = "Stop" + b.statement = "stop()" + b.tooltip_text = "Stop the currently playing animation." + b.category = "Graphics | Animation" + block_list.append(b) + + b = BLOCKS["parameter_block"].instantiate() + b.variant_type = TYPE_BOOL + b.block_format = "Is playing" + b.statement = "is_playing()" + b.tooltip_text = "Check if an animation is currently playing." + b.category = "Graphics | Animation" + block_list.append(b) + "Area2D": for verb in ["entered", "exited"]: var b = BLOCKS["entry_block"].instantiate() From 86bbdeb8502517bbdeb0cc4831b7e3a84ae9162b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 20:19:27 +0000 Subject: [PATCH 030/423] Bump chickensoft-games/setup-godot from 2.0.1 to 2.1.1 Bumps [chickensoft-games/setup-godot](https://github.com/chickensoft-games/setup-godot) from 2.0.1 to 2.1.1. - [Release notes](https://github.com/chickensoft-games/setup-godot/releases) - [Commits](https://github.com/chickensoft-games/setup-godot/compare/v2.0.1...v2.1.1) --- updated-dependencies: - dependency-name: chickensoft-games/setup-godot dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/checks.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index a88a41a4..4cfebd86 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -28,7 +28,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Setup Godot - uses: chickensoft-games/setup-godot@v2.0.1 + uses: chickensoft-games/setup-godot@v2.1.1 with: version: 4.2.2 use-dotnet: false From a808f671d22af4725fdbf71a9a04e41a9c5526b8 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Mon, 8 Jul 2024 15:58:10 -0700 Subject: [PATCH 031/423] Select parent node when a BlockCode is selected In order for a node to be selected on the 2D canvas while its associated BlockCode is being edited, automatically select the current BlockCode node's parent. This requires some changes in BlockCodePlugin to deal with cases when multiple nodes are selected in the Scene panel and in the Inspector panel. https://phabricator.endlessm.com/T35541 --- addons/block_code/block_code_plugin.gd | 39 +++++++++++++++------ addons/block_code/ui/title_bar/title_bar.gd | 3 ++ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 1b1fee70..99273f21 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -7,6 +7,7 @@ static var main_panel: MainPanel static var block_code_button: Button var editor_inspector: EditorInspector +var editor_selection: EditorSelection var selected_block_code_node: BlockCode @@ -51,6 +52,7 @@ func _enter_tree(): Types.init_cast_graph() editor_inspector = EditorInterface.get_inspector() + editor_selection = EditorInterface.get_selection() main_panel = MainPanel.instantiate() main_panel.undo_redo = get_undo_redo() @@ -101,25 +103,42 @@ func _ready(): func _on_scene_changed(scene_root: Node): - BlockCodePlugin.main_panel.switch_scene(scene_root) + main_panel.switch_scene(scene_root) _on_editor_inspector_edited_object_changed() func _on_editor_inspector_edited_object_changed(): - var edited_node = editor_inspector.get_edited_object() as Node + var edited_object = editor_inspector.get_edited_object() + #var edited_node = edited_object as Node + var selected_nodes = editor_selection.get_selected_nodes() + + if edited_object is BlockCode and selected_nodes.has(edited_object): + # If a BlockCode node is being edited, and it was explicitly selected + # (as opposed to edited in the Inspector alone), select its parent node + # as well. This provides a clearer indication of what is being edited. + # Changing the selection will cause edited_object_changed to fire again, + # so we will return early to avoid duplicate work. + var parent_node = edited_object.get_parent() + if parent_node: + EditorInterface.get_selection().add_node.call_deferred(parent_node) + make_bottom_panel_item_visible(main_panel) + return + + if edited_object and edited_object.get_class() == "MultiNodeEdit": + # If multiple nodes are shown in the inspector, we will find the first + # BlockCode node in the list of selected nodes and use that. This + # occurs when the user selects multiple items in the Scene panel, or + # when we select the parent of a BlockCode node. + edited_object = selected_nodes.filter(func(node): return node is BlockCode).pop_front() # We will edit either the selected node (if it is a BlockCode node) or - # the first BlockCode child of that node. - selected_block_code_node = list_block_code_for_node(edited_node).pop_front() + # the first BlockCode child of that node. Keep track of the block code node + # being edited so we know to monitor for changes from EditorInspector. + selected_block_code_node = list_block_code_for_node(edited_object as Node).pop_front() if not is_block_code_editable(selected_block_code_node): selected_block_code_node = null - BlockCodePlugin.main_panel.switch_block_code_node(selected_block_code_node) - if edited_node is BlockCode: - # If the user explicitly chose a BlockCode node, show the Block Code - # editor. We only do this for the BlockCode node itself, rather than - # nodes containing BlockCode, to avoid conflicts with other panels. - make_bottom_panel_item_visible(main_panel) + main_panel.switch_block_code_node(selected_block_code_node) static func is_block_code_editable(block_code: BlockCode) -> bool: diff --git a/addons/block_code/ui/title_bar/title_bar.gd b/addons/block_code/ui/title_bar/title_bar.gd index 699412d8..c5809fa9 100644 --- a/addons/block_code/ui/title_bar/title_bar.gd +++ b/addons/block_code/ui/title_bar/title_bar.gd @@ -63,5 +63,8 @@ func _get_index_for_bsd(bsd: BlockScriptData) -> int: func _on_node_option_button_item_selected(index): var block_code_node = _node_option_button.get_item_metadata(index) as BlockCode + var parent_node = block_code_node.get_parent() as Node _editor_selection.clear() _editor_selection.add_node(block_code_node) + if parent_node: + _editor_selection.add_node(parent_node) From 8874010835bbf2f48623420bdc59f04e8cf62000 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Mon, 8 Jul 2024 16:01:30 -0700 Subject: [PATCH 032/423] Add a button to delete the current BlockCode node With the change to always select a BlockCode node's parent along with the BlockCode node itself, it is difficult to select just a BlockCode node to delete it. To work around this, add a button to delete the current block code node. https://phabricator.endlessm.com/T35541 --- addons/block_code/ui/main_panel.gd | 41 ++++++++++++++++++++++++++-- addons/block_code/ui/main_panel.tscn | 10 +++++-- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index 7382d127..adfda485 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -6,10 +6,12 @@ extends Control @onready var _block_canvas: BlockCanvas = %NodeBlockCanvas @onready var _drag_manager: DragManager = %DragManager @onready var _title_bar: TitleBar = %TitleBar +@onready var _delete_node_button: Button = %DeleteNodeButton @onready var _editor_inspector: EditorInspector = EditorInterface.get_inspector() @onready var _picker_split: HSplitContainer = %PickerSplit @onready var _collapse_button: Button = %CollapseButton +@onready var _icon_delete := EditorInterface.get_editor_theme().get_icon("Remove", "EditorIcons") @onready var _icon_collapse := EditorInterface.get_editor_theme().get_icon("Back", "EditorIcons") @onready var _icon_expand := EditorInterface.get_editor_theme().get_icon("Forward", "EditorIcons") @@ -28,7 +30,9 @@ func _ready(): # Setup block scripting environment undo_redo.version_changed.connect(_on_undo_redo_version_changed) - + + if not _delete_node_button.icon: + _delete_node_button.icon = _icon_delete _collapse_button.icon = _icon_collapse @@ -42,10 +46,42 @@ func _on_undo_redo_version_changed(): _block_canvas.bsd_selected(block_script) -func _on_button_pressed(): +func _on_print_script_button_pressed(): _print_generated_script() +func _on_delete_node_button_pressed(): + var scene_root = EditorInterface.get_edited_scene_root() + + if not scene_root: + return + + if not _current_block_code_node: + return + + var dialog = ConfirmationDialog.new() + var text_format: String = 'Delete block code ("{node}") for "{parent}"?' + dialog.dialog_text = text_format.format({"node": _current_block_code_node.name, "parent": _current_block_code_node.get_parent().name}) + EditorInterface.popup_dialog_centered(dialog) + dialog.connect("confirmed", _on_delete_dialog_confirmed.bind(_current_block_code_node)) + pass # Replace with function body. + + +func _on_delete_dialog_confirmed(block_code_node: BlockCode): + var parent_node = block_code_node.get_parent() + + if not parent_node: + return + + undo_redo.create_action("Delete %s's block code script" % _current_block_code_node.get_parent().name, UndoRedo.MERGE_DISABLE, parent_node) + undo_redo.add_do_property(block_code_node, "owner", null) + undo_redo.add_do_method(parent_node, "remove_child", block_code_node) + undo_redo.add_undo_method(parent_node, "add_child", block_code_node) + undo_redo.add_undo_property(block_code_node, "owner", block_code_node.owner) + undo_redo.add_undo_reference(block_code_node) + undo_redo.commit_action() + + func switch_scene(scene_root: Node): _title_bar.scene_selected(scene_root) @@ -53,6 +89,7 @@ func switch_scene(scene_root: Node): func switch_block_code_node(block_code_node: BlockCode): var block_script: BlockScriptData = block_code_node.block_script if block_code_node else null _current_block_code_node = block_code_node + _delete_node_button.disabled = _current_block_code_node == null _picker.bsd_selected(block_script) _title_bar.bsd_selected(block_script) _block_canvas.bsd_selected(block_script) diff --git a/addons/block_code/ui/main_panel.tscn b/addons/block_code/ui/main_panel.tscn index e8716335..45d9813a 100644 --- a/addons/block_code/ui/main_panel.tscn +++ b/addons/block_code/ui/main_panel.tscn @@ -36,11 +36,16 @@ unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 -[node name="Button" type="Button" parent="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer"] +[node name="PrintScriptButton" type="Button" parent="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer"] layout_mode = 2 size_flags_horizontal = 0 text = "Print Generated Script" +[node name="DeleteNodeButton" type="Button" parent="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Delete Block Code" + [node name="MarginContainer" type="MarginContainer" parent="MarginContainer/HBoxContainer/ScriptVBox"] layout_mode = 2 size_flags_vertical = 3 @@ -86,5 +91,6 @@ mouse_filter = 2 picker_path = NodePath("../PickerSplit/Picker") block_canvas_path = NodePath("../PickerSplit/MarginContainer/VBoxContainer/NodeBlockCanvas") -[connection signal="pressed" from="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer/Button" to="." method="_on_button_pressed"] +[connection signal="pressed" from="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer/PrintScriptButton" to="." method="_on_print_script_button_pressed"] +[connection signal="pressed" from="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer/DeleteNodeButton" to="." method="_on_delete_node_button_pressed"] [connection signal="pressed" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/BottomBar/CollapseButton" to="." method="_on_collapse_button_pressed"] From ed99a8488af57a5b9c66ffcf8b35b5b48bbb81fd Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Mon, 8 Jul 2024 16:07:02 -0700 Subject: [PATCH 033/423] Add undo / redo history for the Add Block Code action https://phabricator.endlessm.com/T35541 --- .../ui/block_canvas/block_canvas.gd | 38 ++++---------- addons/block_code/ui/main_panel.gd | 52 ++++++++++++++++++- addons/block_code/ui/main_panel.tscn | 3 ++ 3 files changed, 64 insertions(+), 29 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index c49f92ed..bea7acd7 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -21,14 +21,19 @@ const BLOCK_AUTO_PLACE_MARGIN: Vector2 = Vector2(16, 8) @onready var _open_scene_button: Button = %OpenSceneButton @onready var _replace_block_code_button: Button = %ReplaceBlockCodeButton +@onready var _open_scene_icon = _open_scene_button.get_theme_icon("Load", "EditorIcons") + var _block_scenes_by_class = {} signal reconnect_block(block: Block) +signal add_block_code +signal open_scene +signal replace_block_code func _ready(): if not _open_scene_button.icon: - _open_scene_button.icon = _open_scene_button.get_theme_icon("Load", "EditorIcons") + _open_scene_button.icon = _open_scene_icon _populate_block_scenes_by_class() @@ -189,39 +194,16 @@ func release_scope(): func _on_add_block_code_button_pressed(): _add_block_code_button.disabled = true - var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node - var scene_root: Node = EditorInterface.get_edited_scene_root() - - if edited_node == null or scene_root == null: - return - - var block_code = BlockCode.new() - block_code.name = "BlockCode" - edited_node.add_child(block_code, true) - block_code.owner = scene_root - - EditorInterface.get_selection().clear() - EditorInterface.get_selection().add_node(block_code) + add_block_code.emit() func _on_open_scene_button_pressed(): _open_scene_button.disabled = true - var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node - - if edited_node == null or edited_node.owner == null: - return - - EditorInterface.open_scene_from_path(edited_node.scene_file_path) + open_scene.emit() func _on_replace_block_code_button_pressed(): - var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node - var scene_root: Node = EditorInterface.get_edited_scene_root() - - scene_root.set_editable_instance(edited_node, true) + _replace_block_code_button.disabled = true - var block_code_nodes = BlockCodePlugin.list_block_code_for_node(edited_node) -# - EditorInterface.get_selection().clear() - EditorInterface.get_selection().add_node(block_code_nodes.pop_front() if block_code_nodes.size() > 0 else edited_node) + replace_block_code.emit() diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index adfda485..d00f3db9 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -30,7 +30,7 @@ func _ready(): # Setup block scripting environment undo_redo.version_changed.connect(_on_undo_redo_version_changed) - + if not _delete_node_button.icon: _delete_node_button.icon = _icon_delete _collapse_button.icon = _icon_collapse @@ -172,3 +172,53 @@ func toggle_collapse(): func _on_collapse_button_pressed(): toggle_collapse() + + +func _on_node_block_canvas_add_block_code(): + var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node + var scene_root: Node = EditorInterface.get_edited_scene_root() + + if edited_node == null or scene_root == null: + return + + var block_code = BlockCode.new() + block_code.name = "BlockCode" + + undo_redo.create_action("Add block code for %s" % edited_node.name, UndoRedo.MERGE_DISABLE, edited_node) + + undo_redo.add_do_method(edited_node, "add_child", block_code, true) + undo_redo.add_do_property(block_code, "owner", scene_root) + undo_redo.add_do_reference(block_code) + undo_redo.add_undo_method(edited_node, "remove_child", block_code) + undo_redo.add_undo_property(block_code, "owner", null) + + undo_redo.commit_action() + + EditorInterface.get_selection().clear() + EditorInterface.get_selection().add_node(block_code) + + +func _on_node_block_canvas_open_scene(): + var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node + + if edited_node == null or edited_node.owner == null: + return + + EditorInterface.open_scene_from_path(edited_node.scene_file_path) + + +func _on_node_block_canvas_replace_block_code(): + var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node + var scene_root: Node = EditorInterface.get_edited_scene_root() + + undo_redo.create_action("Replace block code %s" % edited_node.name, UndoRedo.MERGE_DISABLE, scene_root) + + undo_redo.add_do_method(scene_root, "set_editable_instance", edited_node, true) + undo_redo.add_undo_method(scene_root, "set_editable_instance", edited_node, false) + + undo_redo.commit_action() + + var block_code_nodes = BlockCodePlugin.list_block_code_for_node(edited_node) +# + EditorInterface.get_selection().clear() + EditorInterface.get_selection().add_node(block_code_nodes.pop_front() if block_code_nodes.size() > 0 else edited_node) diff --git a/addons/block_code/ui/main_panel.tscn b/addons/block_code/ui/main_panel.tscn index 45d9813a..41bad753 100644 --- a/addons/block_code/ui/main_panel.tscn +++ b/addons/block_code/ui/main_panel.tscn @@ -93,4 +93,7 @@ block_canvas_path = NodePath("../PickerSplit/MarginContainer/VBoxContainer/NodeB [connection signal="pressed" from="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer/PrintScriptButton" to="." method="_on_print_script_button_pressed"] [connection signal="pressed" from="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer/DeleteNodeButton" to="." method="_on_delete_node_button_pressed"] +[connection signal="add_block_code" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/NodeBlockCanvas" to="." method="_on_node_block_canvas_add_block_code"] +[connection signal="open_scene" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/NodeBlockCanvas" to="." method="_on_node_block_canvas_open_scene"] +[connection signal="replace_block_code" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/NodeBlockCanvas" to="." method="_on_node_block_canvas_replace_block_code"] [connection signal="pressed" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/BottomBar/CollapseButton" to="." method="_on_collapse_button_pressed"] From 7e79f302ac2278948e20f3dfa367c22687cfbf5d Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Fri, 5 Jul 2024 18:21:10 -0400 Subject: [PATCH 034/423] Add zoom and pan to block canvas --- .../ui/block_canvas/block_canvas.gd | 64 +++++++++++++++++-- .../ui/block_canvas/block_canvas.tscn | 44 +++++++++++-- 2 files changed, 98 insertions(+), 10 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index bea7acd7..2875ee49 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -4,9 +4,9 @@ extends MarginContainer const EXTEND_MARGIN: float = 800 const BLOCK_AUTO_PLACE_MARGIN: Vector2 = Vector2(16, 8) +const ZOOM_FACTOR: float = 1.1 @onready var _window: Control = %Window -@onready var _window_scroll: ScrollContainer = %WindowScroll @onready var _empty_box: BoxContainer = %EmptyBox @onready var _selected_node_box: BoxContainer = %SelectedNodeBox @@ -23,7 +23,11 @@ const BLOCK_AUTO_PLACE_MARGIN: Vector2 = Vector2(16, 8) @onready var _open_scene_icon = _open_scene_button.get_theme_icon("Load", "EditorIcons") +@onready var _mouse_override: Control = %MouseOverride +@onready var _zoom_label: Label = %ZoomLabel + var _block_scenes_by_class = {} +var _panning := false signal reconnect_block(block: Block) signal add_block_code @@ -48,10 +52,8 @@ func _populate_block_scenes_by_class(): func add_block(block: Block, position: Vector2 = Vector2.ZERO) -> void: - block.position = position - block.position.y += _window_scroll.scroll_vertical + block.position = canvas_to_window(position) _window.add_child(block) - _window.custom_minimum_size.y = max(block.position.y + EXTEND_MARGIN, _window.custom_minimum_size.y) func get_blocks() -> Array[Block]: @@ -79,6 +81,10 @@ func bsd_selected(bsd: BlockScriptData): var edited_node = EditorInterface.get_inspector().get_edited_object() as Node + _window.position = Vector2(0, 0) + _window.scale = Vector2(1, 1) + _zoom_label.visible = false + _empty_box.visible = false _selected_node_box.visible = false _selected_node_with_block_code_box.visible = false @@ -88,6 +94,7 @@ func bsd_selected(bsd: BlockScriptData): if bsd != null: _load_bsd(bsd) + _zoom_label.visible = true elif edited_node == null: _empty_box.visible = true elif BlockCodePlugin.node_has_block_code(edited_node): @@ -105,7 +112,6 @@ func bsd_selected(bsd: BlockScriptData): _selected_node_label.text = _selected_node_label_format.format({"node": edited_node.name}) _add_block_code_button.disabled = false - func _load_bsd(bsd: BlockScriptData): for tree in bsd.block_trees.array: load_tree(_window, tree) @@ -207,3 +213,51 @@ func _on_replace_block_code_button_pressed(): _replace_block_code_button.disabled = true replace_block_code.emit() + + +func _input(event): + if event is InputEventKey: + if event.keycode == KEY_SHIFT: + if event.pressed: + _mouse_override.mouse_filter = Control.MOUSE_FILTER_PASS + _mouse_override.mouse_default_cursor_shape = Control.CURSOR_MOVE + else: + _mouse_override.mouse_filter = Control.MOUSE_FILTER_IGNORE + _mouse_override.mouse_default_cursor_shape = Control.CURSOR_ARROW + + if event is InputEventMouseButton: + if event.button_index == MOUSE_BUTTON_LEFT: + if event.pressed and is_mouse_over(): + _panning = true + else: + _panning = false + + var relative_mouse_pos := get_global_mouse_position() - get_global_rect().position + + if is_mouse_over(): + var old_mouse_window_pos := canvas_to_window(relative_mouse_pos) + + if event.button_index == MOUSE_BUTTON_WHEEL_UP and _window.scale.x < 2: + _window.scale *= ZOOM_FACTOR + if event.button_index == MOUSE_BUTTON_WHEEL_DOWN and _window.scale.x > 0.2: + _window.scale /= ZOOM_FACTOR + + _zoom_label.text = "%.1fx" % _window.scale.x + + _window.position -= (old_mouse_window_pos - canvas_to_window(relative_mouse_pos)) * _window.scale.x + + if event is InputEventMouseMotion: + if Input.is_key_pressed(KEY_SHIFT) and _panning: + _window.position += event.relative + + +func canvas_to_window(v: Vector2) -> Vector2: + return _window.get_transform().affine_inverse() * v + + +func window_to_canvas(v: Vector2) -> Vector2: + return _window.get_transform() * v + + +func is_mouse_over() -> bool: + return get_global_rect().has_point(get_global_mouse_position()) diff --git a/addons/block_code/ui/block_canvas/block_canvas.tscn b/addons/block_code/ui/block_canvas/block_canvas.tscn index 1d7bdeba..d181c04f 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.tscn +++ b/addons/block_code/ui/block_canvas/block_canvas.tscn @@ -3,7 +3,7 @@ [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/block_canvas.gd" id="1_tk8h2"] [ext_resource type="Texture2D" uid="uid://cmusxj1ppspnp" path="res://addons/block_code/block_code_node/block_code_node.svg" id="2_710vn"] -[sub_resource type="Image" id="Image_2jxnn"] +[sub_resource type="Image" id="Image_0g48l"] data = { "data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), "format": "RGBA8", @@ -13,7 +13,7 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_jgo72"] -image = SubResource("Image_2jxnn") +image = SubResource("Image_0g48l") [node name="BlockCanvas" type="MarginContainer"] anchors_preset = 15 @@ -28,16 +28,50 @@ script = ExtResource("1_tk8h2") [node name="Panel" type="Panel" parent="."] layout_mode = 2 -[node name="WindowScroll" type="ScrollContainer" parent="."] -unique_name_in_owner = true +[node name="WindowContainer" type="MarginContainer" parent="."] +clip_contents = true layout_mode = 2 -[node name="Window" type="Control" parent="WindowScroll"] +[node name="Window" type="Control" parent="WindowContainer"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 mouse_filter = 1 +[node name="Overlay" type="Control" parent="WindowContainer"] +layout_mode = 2 +mouse_filter = 2 + +[node name="MarginContainer" type="MarginContainer" parent="WindowContainer/Overlay"] +layout_mode = 1 +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -40.0 +offset_top = -40.0 +grow_horizontal = 0 +grow_vertical = 0 +mouse_filter = 2 +theme_override_constants/margin_left = 4 +theme_override_constants/margin_top = 4 +theme_override_constants/margin_right = 4 +theme_override_constants/margin_bottom = 4 + +[node name="ZoomLabel" type="Label" parent="WindowContainer/Overlay/MarginContainer"] +unique_name_in_owner = true +layout_mode = 2 +theme_override_colors/font_color = Color(1, 1, 1, 0.196078) +theme_override_font_sizes/font_size = 24 +text = "1x" +horizontal_alignment = 2 + +[node name="MouseOverride" type="MarginContainer" parent="."] +unique_name_in_owner = true +layout_mode = 2 +mouse_filter = 2 + [node name="EmptyBox" type="VBoxContainer" parent="."] unique_name_in_owner = true visible = false From 0af8b52425e96b6c8c42b7cb805c9203e692d010 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Mon, 8 Jul 2024 16:31:22 -0400 Subject: [PATCH 035/423] Middle mouse pan --- .../ui/block_canvas/block_canvas.gd | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 2875ee49..e1a9bcad 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -218,20 +218,18 @@ func _on_replace_block_code_button_pressed(): func _input(event): if event is InputEventKey: if event.keycode == KEY_SHIFT: - if event.pressed: - _mouse_override.mouse_filter = Control.MOUSE_FILTER_PASS - _mouse_override.mouse_default_cursor_shape = Control.CURSOR_MOVE - else: - _mouse_override.mouse_filter = Control.MOUSE_FILTER_IGNORE - _mouse_override.mouse_default_cursor_shape = Control.CURSOR_ARROW + set_mouse_override(event.pressed) if event is InputEventMouseButton: - if event.button_index == MOUSE_BUTTON_LEFT: + if event.button_index == MOUSE_BUTTON_LEFT or event.button_index == MOUSE_BUTTON_MIDDLE: if event.pressed and is_mouse_over(): _panning = true else: _panning = false + if event.button_index == MOUSE_BUTTON_MIDDLE: + set_mouse_override(event.pressed) + var relative_mouse_pos := get_global_mouse_position() - get_global_rect().position if is_mouse_over(): @@ -247,7 +245,7 @@ func _input(event): _window.position -= (old_mouse_window_pos - canvas_to_window(relative_mouse_pos)) * _window.scale.x if event is InputEventMouseMotion: - if Input.is_key_pressed(KEY_SHIFT) and _panning: + if (Input.is_key_pressed(KEY_SHIFT) and _panning) or (Input.is_mouse_button_pressed(MOUSE_BUTTON_MIDDLE) and _panning): _window.position += event.relative @@ -261,3 +259,12 @@ func window_to_canvas(v: Vector2) -> Vector2: func is_mouse_over() -> bool: return get_global_rect().has_point(get_global_mouse_position()) + + +func set_mouse_override(override: bool): + if override: + _mouse_override.mouse_filter = Control.MOUSE_FILTER_PASS + _mouse_override.mouse_default_cursor_shape = Control.CURSOR_MOVE + else: + _mouse_override.mouse_filter = Control.MOUSE_FILTER_IGNORE + _mouse_override.mouse_default_cursor_shape = Control.CURSOR_ARROW From 9929a181b3d357479de0fd2383f58615a9fe88cc Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Mon, 8 Jul 2024 16:44:59 -0400 Subject: [PATCH 036/423] Scale blocks when dragged over canvas --- .../block_code/drag_manager/drag_manager.gd | 16 +++++++++++---- .../ui/block_canvas/block_canvas.gd | 20 ++++++++++++------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index 5b4d1d87..8875b44b 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -57,9 +57,14 @@ class Drag: func add_delete_area(delete_area: Rect2): _delete_areas.append(delete_area) - func update_drag_position(): + func update_drag_state(): global_position = get_global_mouse_position() + if _block_canvas.is_mouse_over(): + scale = Vector2(_block_canvas.zoom, _block_canvas.zoom) + else: + scale = Vector2(1, 1) + for rect in _delete_areas: if rect.has_point(get_global_mouse_position()): action = DragAction.REMOVE @@ -71,7 +76,7 @@ class Drag: target_snap_point = _find_closest_snap_point() func apply_drag() -> Block: - update_drag_position() + update_drag_state() if action == DragAction.PLACE: _place_block() @@ -147,7 +152,7 @@ class Drag: var closest_distance: int for snap_point in _snap_points: var distance = _get_distance_to_snap_point(snap_point) - if distance > Constants.MINIMUM_SNAP_DISTANCE: + if distance > Constants.MINIMUM_SNAP_DISTANCE * _block_canvas.zoom: continue elif closest_snap_point == null or distance < closest_distance: closest_snap_point = snap_point @@ -202,7 +207,7 @@ func _ready(): func _process(_delta): if drag: - drag.update_drag_position() + drag.update_drag_state() func drag_block(block: Block, copied_from: Block = null): @@ -215,6 +220,9 @@ func drag_block(block: Block, copied_from: Block = null): else: offset = Vector2.ZERO + if _block_canvas.is_ancestor_of(block): + offset /= _block_canvas.zoom + var parent = block.get_parent() if parent: diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index e1a9bcad..1f4e7696 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -28,6 +28,11 @@ const ZOOM_FACTOR: float = 1.1 var _block_scenes_by_class = {} var _panning := false +var zoom: float: + set(value): + _window.scale = Vector2(value, value) + get: + return _window.scale.x signal reconnect_block(block: Block) signal add_block_code @@ -82,7 +87,7 @@ func bsd_selected(bsd: BlockScriptData): var edited_node = EditorInterface.get_inspector().get_edited_object() as Node _window.position = Vector2(0, 0) - _window.scale = Vector2(1, 1) + zoom = 1 _zoom_label.visible = false _empty_box.visible = false @@ -112,6 +117,7 @@ func bsd_selected(bsd: BlockScriptData): _selected_node_label.text = _selected_node_label_format.format({"node": edited_node.name}) _add_block_code_button.disabled = false + func _load_bsd(bsd: BlockScriptData): for tree in bsd.block_trees.array: load_tree(_window, tree) @@ -235,14 +241,14 @@ func _input(event): if is_mouse_over(): var old_mouse_window_pos := canvas_to_window(relative_mouse_pos) - if event.button_index == MOUSE_BUTTON_WHEEL_UP and _window.scale.x < 2: - _window.scale *= ZOOM_FACTOR - if event.button_index == MOUSE_BUTTON_WHEEL_DOWN and _window.scale.x > 0.2: - _window.scale /= ZOOM_FACTOR + if event.button_index == MOUSE_BUTTON_WHEEL_UP and zoom < 2: + zoom *= ZOOM_FACTOR + if event.button_index == MOUSE_BUTTON_WHEEL_DOWN and zoom > 0.2: + zoom /= ZOOM_FACTOR - _zoom_label.text = "%.1fx" % _window.scale.x + _zoom_label.text = "%.1fx" % zoom - _window.position -= (old_mouse_window_pos - canvas_to_window(relative_mouse_pos)) * _window.scale.x + _window.position -= (old_mouse_window_pos - canvas_to_window(relative_mouse_pos)) * zoom if event is InputEventMouseMotion: if (Input.is_key_pressed(KEY_SHIFT) and _panning) or (Input.is_mouse_button_pressed(MOUSE_BUTTON_MIDDLE) and _panning): From 43dd08b5d2abf8d33eba83177c6447684c05407e Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 9 Jul 2024 13:54:37 -0700 Subject: [PATCH 037/423] Update selection in undo actions When adding a BlockCode node, select the new node as part of the undo / redo action. This is consistent with the behaviour of other actions in Godot. https://phabricator.endlessm.com/T35541 --- addons/block_code/ui/main_panel.gd | 37 ++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index d00f3db9..e05a1a8d 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -19,7 +19,13 @@ var _current_block_code_node: BlockCode var _block_code_nodes: Array var _collapsed: bool = false -var undo_redo: EditorUndoRedoManager +var undo_redo: EditorUndoRedoManager: + set(value): + if undo_redo: + undo_redo.version_changed.disconnect(_on_undo_redo_version_changed) + undo_redo = value + if undo_redo: + undo_redo.version_changed.connect(_on_undo_redo_version_changed) func _ready(): @@ -28,12 +34,10 @@ func _ready(): _drag_manager.block_dropped.connect(save_script) _drag_manager.block_modified.connect(save_script) - # Setup block scripting environment - undo_redo.version_changed.connect(_on_undo_redo_version_changed) - if not _delete_node_button.icon: _delete_node_button.icon = _icon_delete - _collapse_button.icon = _icon_collapse + if not _collapse_button.icon: + _collapse_button.icon = _icon_collapse func _on_undo_redo_version_changed(): @@ -188,15 +192,13 @@ func _on_node_block_canvas_add_block_code(): undo_redo.add_do_method(edited_node, "add_child", block_code, true) undo_redo.add_do_property(block_code, "owner", scene_root) + undo_redo.add_do_method(self, "_select_block_code_node", edited_node) undo_redo.add_do_reference(block_code) undo_redo.add_undo_method(edited_node, "remove_child", block_code) undo_redo.add_undo_property(block_code, "owner", null) undo_redo.commit_action() - EditorInterface.get_selection().clear() - EditorInterface.get_selection().add_node(block_code) - func _on_node_block_canvas_open_scene(): var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node @@ -213,12 +215,27 @@ func _on_node_block_canvas_replace_block_code(): undo_redo.create_action("Replace block code %s" % edited_node.name, UndoRedo.MERGE_DISABLE, scene_root) + # FIXME: When this is undone, the new state is not correctly shown in the + # editor due to an issue in Godot: + # + # Ideally this should fix itself in a future version of Godot. + undo_redo.add_do_method(scene_root, "set_editable_instance", edited_node, true) + undo_redo.add_do_method(self, "_select_block_code_node", edited_node) undo_redo.add_undo_method(scene_root, "set_editable_instance", edited_node, false) undo_redo.commit_action() + +func _select_block_code_node(edited_node: Node): var block_code_nodes = BlockCodePlugin.list_block_code_for_node(edited_node) -# + if block_code_nodes.size() > 0: + _set_selection([block_code_nodes.pop_front()]) + else: + _set_selection([edited_node]) + + +func _set_selection(nodes: Array[Node]): EditorInterface.get_selection().clear() - EditorInterface.get_selection().add_node(block_code_nodes.pop_front() if block_code_nodes.size() > 0 else edited_node) + for node in nodes: + EditorInterface.get_selection().add_node(node) From 88100d544c403b9364d5dbef96b7d78e8d527f28 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 9 Jul 2024 14:20:48 -0700 Subject: [PATCH 038/423] Watch for changes to the selected BlockCode node https://phabricator.endlessm.com/T35541 --- addons/block_code/block_code_plugin.gd | 44 +++++++++++++++------ addons/block_code/ui/main_panel.gd | 2 +- addons/block_code/ui/title_bar/title_bar.gd | 8 ++-- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 99273f21..2194db78 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -9,7 +9,7 @@ static var block_code_button: Button var editor_inspector: EditorInspector var editor_selection: EditorSelection -var selected_block_code_node: BlockCode +var _selected_block_code: BlockCode var old_feature_profile: String = "" @@ -97,14 +97,12 @@ func _exit_tree(): func _ready(): connect("scene_changed", _on_scene_changed) editor_inspector.connect("edited_object_changed", _on_editor_inspector_edited_object_changed) - editor_inspector.connect("property_edited", _on_editor_inspector_property_edited) _on_scene_changed(EditorInterface.get_edited_scene_root()) _on_editor_inspector_edited_object_changed() func _on_scene_changed(scene_root: Node): main_panel.switch_scene(scene_root) - _on_editor_inspector_edited_object_changed() func _on_editor_inspector_edited_object_changed(): @@ -131,14 +129,29 @@ func _on_editor_inspector_edited_object_changed(): # when we select the parent of a BlockCode node. edited_object = selected_nodes.filter(func(node): return node is BlockCode).pop_front() - # We will edit either the selected node (if it is a BlockCode node) or - # the first BlockCode child of that node. Keep track of the block code node - # being edited so we know to monitor for changes from EditorInspector. - selected_block_code_node = list_block_code_for_node(edited_object as Node).pop_front() - if not is_block_code_editable(selected_block_code_node): - selected_block_code_node = null + var block_code_node = list_block_code_nodes_for_node(edited_object as Node).pop_front() + select_block_code_node(block_code_node) + + +func select_block_code_node(block_code: BlockCode): + if not is_block_code_editable(block_code): + block_code = null + + if _selected_block_code: + _selected_block_code.tree_entered.disconnect(_on_selected_block_code_changed) + _selected_block_code.tree_exited.disconnect(_on_selected_block_code_changed) + _selected_block_code.property_list_changed.disconnect(_on_selected_block_code_changed) + editor_inspector.property_edited.disconnect(_on_editor_inspector_property_edited) + + _selected_block_code = block_code - main_panel.switch_block_code_node(selected_block_code_node) + if _selected_block_code: + _selected_block_code.tree_entered.connect(_on_selected_block_code_changed) + _selected_block_code.tree_exited.connect(_on_selected_block_code_changed) + _selected_block_code.property_list_changed.connect(_on_selected_block_code_changed) + editor_inspector.property_edited.connect(_on_editor_inspector_property_edited) + + main_panel.switch_block_code_node(_selected_block_code) static func is_block_code_editable(block_code: BlockCode) -> bool: @@ -154,10 +167,10 @@ static func is_block_code_editable(block_code: BlockCode) -> bool: static func node_has_block_code(node: Node, recursive: bool = false) -> bool: - return list_block_code_for_node(node, recursive).size() > 0 + return list_block_code_nodes_for_node(node, recursive).size() > 0 -static func list_block_code_for_node(node: Node, recursive: bool = false) -> Array[BlockCode]: +static func list_block_code_nodes_for_node(node: Node, recursive: bool = false) -> Array[BlockCode]: var result: Array[BlockCode] = [] if node is BlockCode: @@ -168,8 +181,13 @@ static func list_block_code_for_node(node: Node, recursive: bool = false) -> Arr return result +func _on_selected_block_code_changed(): + if _selected_block_code: + _on_editor_inspector_edited_object_changed() + + func _on_editor_inspector_property_edited(property: String): - if selected_block_code_node: + if _selected_block_code: _on_editor_inspector_edited_object_changed() diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index e05a1a8d..b57ab2c7 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -228,7 +228,7 @@ func _on_node_block_canvas_replace_block_code(): func _select_block_code_node(edited_node: Node): - var block_code_nodes = BlockCodePlugin.list_block_code_for_node(edited_node) + var block_code_nodes = BlockCodePlugin.list_block_code_nodes_for_node(edited_node) if block_code_nodes.size() > 0: _set_selection([block_code_nodes.pop_front()]) else: diff --git a/addons/block_code/ui/title_bar/title_bar.gd b/addons/block_code/ui/title_bar/title_bar.gd index c5809fa9..79531122 100644 --- a/addons/block_code/ui/title_bar/title_bar.gd +++ b/addons/block_code/ui/title_bar/title_bar.gd @@ -42,15 +42,15 @@ func _update_node_option_button_items(): if not scene_root: return - for block_code_node in BlockCodePlugin.list_block_code_for_node(scene_root, true): - if not BlockCodePlugin.is_block_code_editable(block_code_node): + for block_code in BlockCodePlugin.list_block_code_nodes_for_node(scene_root, true): + if not BlockCodePlugin.is_block_code_editable(block_code): continue var node_item_index = _node_option_button.item_count - var node_label = "{name} ({type})".format({"name": scene_root.get_path_to(block_code_node).get_concatenated_names(), "type": block_code_node.block_script.script_inherits}) + var node_label = "{name} ({type})".format({"name": scene_root.get_path_to(block_code).get_concatenated_names(), "type": block_code.block_script.script_inherits}) _node_option_button.add_item(node_label) _node_option_button.set_item_icon(node_item_index, _block_code_icon) - _node_option_button.set_item_metadata(node_item_index, block_code_node) + _node_option_button.set_item_metadata(node_item_index, block_code) func _get_index_for_bsd(bsd: BlockScriptData) -> int: From d4103f1037868146c03f7f3c5cf6b1622971d7da Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 9 Jul 2024 14:22:27 -0700 Subject: [PATCH 039/423] Do not expand selection if BlockCode is selected a second time https://phabricator.endlessm.com/T35541 --- addons/block_code/block_code_plugin.gd | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 2194db78..3a0b8ffa 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -110,7 +110,10 @@ func _on_editor_inspector_edited_object_changed(): #var edited_node = edited_object as Node var selected_nodes = editor_selection.get_selected_nodes() - if edited_object is BlockCode and selected_nodes.has(edited_object): + if edited_object is BlockCode: + make_bottom_panel_item_visible(main_panel) + + if edited_object is BlockCode and selected_nodes.size() == 1 and edited_object.owner and edited_object != _selected_block_code: # If a BlockCode node is being edited, and it was explicitly selected # (as opposed to edited in the Inspector alone), select its parent node # as well. This provides a clearer indication of what is being edited. @@ -118,8 +121,7 @@ func _on_editor_inspector_edited_object_changed(): # so we will return early to avoid duplicate work. var parent_node = edited_object.get_parent() if parent_node: - EditorInterface.get_selection().add_node.call_deferred(parent_node) - make_bottom_panel_item_visible(main_panel) + editor_selection.add_node.call_deferred(parent_node) return if edited_object and edited_object.get_class() == "MultiNodeEdit": From dbd764376d205a66ae339ba2c2d87e7dba39dfad Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 9 Jul 2024 15:02:29 -0700 Subject: [PATCH 040/423] Avoid duplicate work when BlockCode changes https://phabricator.endlessm.com/T35541 --- addons/block_code/block_code_plugin.gd | 27 ++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 3a0b8ffa..80991aa0 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -136,6 +136,9 @@ func _on_editor_inspector_edited_object_changed(): func select_block_code_node(block_code: BlockCode): + if block_code == _selected_block_code: + return + if not is_block_code_editable(block_code): block_code = null @@ -153,9 +156,23 @@ func select_block_code_node(block_code: BlockCode): _selected_block_code.property_list_changed.connect(_on_selected_block_code_changed) editor_inspector.property_edited.connect(_on_editor_inspector_property_edited) + _refresh_block_code_node() + + +func _refresh_block_code_node(): main_panel.switch_block_code_node(_selected_block_code) +func _on_selected_block_code_changed(): + if _selected_block_code: + _refresh_block_code_node() + + +func _on_editor_inspector_property_edited(property: String): + if _selected_block_code: + _refresh_block_code_node() + + static func is_block_code_editable(block_code: BlockCode) -> bool: if not block_code: return false @@ -183,16 +200,6 @@ static func list_block_code_nodes_for_node(node: Node, recursive: bool = false) return result -func _on_selected_block_code_changed(): - if _selected_block_code: - _on_editor_inspector_edited_object_changed() - - -func _on_editor_inspector_property_edited(property: String): - if _selected_block_code: - _on_editor_inspector_edited_object_changed() - - func _get_plugin_name(): return "Block Code" From 20f5f54c5c1004855a98b3f12c0b4105ccf260a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 10 Jul 2024 09:51:48 -0300 Subject: [PATCH 041/423] Add version to block script data In the plugin, add a new constant for the current data version. This will start in 0 and be bumped each time the data format changes. In the BlockScriptData resource, add an integer version field which defaults to zero. The version will be set to the current version when the resource is saved. The actual migration is TBD. Only a warning is printed for now. https://phabricator.endlessm.com/T35547 --- .../block_script_data/block_script_data.gd | 4 +++- addons/block_code/ui/constants.gd | 2 ++ addons/block_code/ui/main_panel.gd | 13 +++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/addons/block_code/block_script_data/block_script_data.gd b/addons/block_code/block_script_data/block_script_data.gd index 6696c8a0..4e933c41 100644 --- a/addons/block_code/block_script_data/block_script_data.gd +++ b/addons/block_code/block_script_data/block_script_data.gd @@ -4,9 +4,11 @@ extends Resource @export var script_inherits: String @export var block_trees: SerializedBlockTreeNodeArray @export var generated_script: String +@export var version: int -func _init(p_script_inherits: String = "", p_block_trees: SerializedBlockTreeNodeArray = null, p_generated_script: String = ""): +func _init(p_script_inherits: String = "", p_block_trees: SerializedBlockTreeNodeArray = null, p_generated_script: String = "", p_version = 0): script_inherits = p_script_inherits block_trees = p_block_trees generated_script = p_generated_script + version = p_version diff --git a/addons/block_code/ui/constants.gd b/addons/block_code/ui/constants.gd index d36d45aa..88d6d9ab 100644 --- a/addons/block_code/ui/constants.gd +++ b/addons/block_code/ui/constants.gd @@ -1,5 +1,7 @@ extends Object +const CURRENT_DATA_VERSION = 0 + const KNOB_X = 10.0 const KNOB_W = 20.0 const KNOB_H = 5.0 diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index d00f3db9..3193e6c1 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -15,6 +15,8 @@ extends Control @onready var _icon_collapse := EditorInterface.get_editor_theme().get_icon("Back", "EditorIcons") @onready var _icon_expand := EditorInterface.get_editor_theme().get_icon("Forward", "EditorIcons") +const Constants = preload("res://addons/block_code/ui/constants.gd") + var _current_block_code_node: BlockCode var _block_code_nodes: Array var _collapsed: bool = false @@ -82,6 +84,14 @@ func _on_delete_dialog_confirmed(block_code_node: BlockCode): undo_redo.commit_action() +func _try_migration(): + var version: int = _current_block_code_node.block_script.version + if version == Constants.CURRENT_DATA_VERSION: + # No migration needed. + return + push_warning("Migration not implemented from %d to %d" % [version, Constants.CURRENT_DATA_VERSION]) + + func switch_scene(scene_root: Node): _title_bar.scene_selected(scene_root) @@ -90,6 +100,8 @@ func switch_block_code_node(block_code_node: BlockCode): var block_script: BlockScriptData = block_code_node.block_script if block_code_node else null _current_block_code_node = block_code_node _delete_node_button.disabled = _current_block_code_node == null + if _current_block_code_node != null: + _try_migration() _picker.bsd_selected(block_script) _title_bar.bsd_selected(block_script) _block_canvas.bsd_selected(block_script) @@ -129,6 +141,7 @@ func save_script(): var generated_script = _block_canvas.generate_script_from_current_window(block_script.script_inherits) block_script.block_trees = block_trees block_script.generated_script = generated_script + block_script.version = Constants.CURRENT_DATA_VERSION undo_redo.add_do_property(_current_block_code_node.block_script, "block_trees", block_trees) undo_redo.add_do_property(_current_block_code_node.block_script, "generated_script", generated_script) From 96691a9af7883cd749383d7f9a98f2aafa6ca8aa Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 10 Jul 2024 15:03:21 -0700 Subject: [PATCH 042/423] Always scroll block canvas to the top-left block on open For this to work correctly, we need to change WindowContainer to be a Control, instead of a MarginContainer. The MarginContainer node was occasionally changing the Window node's position on its own. --- .../ui/block_canvas/block_canvas.gd | 26 ++++++++++++++++--- .../ui/block_canvas/block_canvas.tscn | 21 +++++++++++---- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 1f4e7696..d3b53a2e 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -4,6 +4,7 @@ extends MarginContainer const EXTEND_MARGIN: float = 800 const BLOCK_AUTO_PLACE_MARGIN: Vector2 = Vector2(16, 8) +const DEFAULT_WINDOW_MARGIN: Vector2 = Vector2(24, 24) const ZOOM_FACTOR: float = 1.1 @onready var _window: Control = %Window @@ -31,6 +32,7 @@ var _panning := false var zoom: float: set(value): _window.scale = Vector2(value, value) + _zoom_label.text = "%.1fx" % value get: return _window.scale.x @@ -88,6 +90,8 @@ func bsd_selected(bsd: BlockScriptData): _window.position = Vector2(0, 0) zoom = 1 + + _window.visible = false _zoom_label.visible = false _empty_box.visible = false @@ -99,7 +103,9 @@ func bsd_selected(bsd: BlockScriptData): if bsd != null: _load_bsd(bsd) + _window.visible = true _zoom_label.visible = true + reset_window_position() elif edited_node == null: _empty_box.visible = true elif BlockCodePlugin.node_has_block_code(edited_node): @@ -132,6 +138,7 @@ func scene_has_bsd_nodes() -> bool: func clear_canvas(): for child in _window.get_children(): + _window.remove_child(child) child.queue_free() @@ -140,7 +147,6 @@ func load_tree(parent: Node, node: SerializedBlockTreeNode): var scene: Block = load(_block_scene_path).instantiate() for prop_pair in node.serialized_block.serialized_props: scene.set(prop_pair[0], prop_pair[1]) - parent.add_child(scene) var scene_block: Block = scene as Block @@ -246,8 +252,6 @@ func _input(event): if event.button_index == MOUSE_BUTTON_WHEEL_DOWN and zoom > 0.2: zoom /= ZOOM_FACTOR - _zoom_label.text = "%.1fx" % zoom - _window.position -= (old_mouse_window_pos - canvas_to_window(relative_mouse_pos)) * zoom if event is InputEventMouseMotion: @@ -255,6 +259,22 @@ func _input(event): _window.position += event.relative +func reset_window_position(): + var blocks = get_blocks() + var top_left: Vector2 = Vector2.INF + + for block in blocks: + if block.position.x < top_left.x: + top_left.x = block.position.x + if block.position.y < top_left.y: + top_left.y = block.position.y + + if top_left == Vector2.INF: + top_left = Vector2.ZERO + + _window.position = (-top_left + DEFAULT_WINDOW_MARGIN) * zoom + + func canvas_to_window(v: Vector2) -> Vector2: return _window.get_transform().affine_inverse() * v diff --git a/addons/block_code/ui/block_canvas/block_canvas.tscn b/addons/block_code/ui/block_canvas/block_canvas.tscn index d181c04f..0513ee99 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.tscn +++ b/addons/block_code/ui/block_canvas/block_canvas.tscn @@ -3,7 +3,7 @@ [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/block_canvas.gd" id="1_tk8h2"] [ext_resource type="Texture2D" uid="uid://cmusxj1ppspnp" path="res://addons/block_code/block_code_node/block_code_node.svg" id="2_710vn"] -[sub_resource type="Image" id="Image_0g48l"] +[sub_resource type="Image" id="Image_0aray"] data = { "data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), "format": "RGBA8", @@ -13,7 +13,7 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_jgo72"] -image = SubResource("Image_0g48l") +image = SubResource("Image_0aray") [node name="BlockCanvas" type="MarginContainer"] anchors_preset = 15 @@ -28,18 +28,29 @@ script = ExtResource("1_tk8h2") [node name="Panel" type="Panel" parent="."] layout_mode = 2 -[node name="WindowContainer" type="MarginContainer" parent="."] +[node name="WindowContainer" type="Control" parent="."] clip_contents = true layout_mode = 2 [node name="Window" type="Control" parent="WindowContainer"] unique_name_in_owner = true layout_mode = 2 -size_flags_horizontal = 3 +anchors_preset = 0 +offset_right = 1152.0 +offset_bottom = 648.0 mouse_filter = 1 [node name="Overlay" type="Control" parent="WindowContainer"] -layout_mode = 2 +layout_mode = 1 +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -1152.0 +offset_top = -648.0 +grow_horizontal = 0 +grow_vertical = 0 mouse_filter = 2 [node name="MarginContainer" type="MarginContainer" parent="WindowContainer/Overlay"] From fb3a4c94caba7a6b8957f9fcfba28ad8c8d21c7f Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Thu, 11 Jul 2024 20:06:56 -0700 Subject: [PATCH 043/423] In block_canvas, snap EntryBlock blocks to a grid --- .../ui/block_canvas/block_canvas.gd | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index d3b53a2e..7e5737e8 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -3,8 +3,9 @@ class_name BlockCanvas extends MarginContainer const EXTEND_MARGIN: float = 800 -const BLOCK_AUTO_PLACE_MARGIN: Vector2 = Vector2(16, 8) -const DEFAULT_WINDOW_MARGIN: Vector2 = Vector2(24, 24) +const BLOCK_AUTO_PLACE_MARGIN: Vector2 = Vector2(25, 8) +const DEFAULT_WINDOW_MARGIN: Vector2 = Vector2(25, 25) +const SNAP_GRID: Vector2 = Vector2(25, 25) const ZOOM_FACTOR: float = 1.1 @onready var _window: Control = %Window @@ -27,6 +28,7 @@ const ZOOM_FACTOR: float = 1.1 @onready var _mouse_override: Control = %MouseOverride @onready var _zoom_label: Label = %ZoomLabel +var _current_bsd: BlockScriptData var _block_scenes_by_class = {} var _panning := false var zoom: float: @@ -59,7 +61,11 @@ func _populate_block_scenes_by_class(): func add_block(block: Block, position: Vector2 = Vector2.ZERO) -> void: - block.position = canvas_to_window(position) + if block is EntryBlock: + block.position = canvas_to_window(position).snapped(SNAP_GRID) + else: + block.position = canvas_to_window(position) + _window.add_child(block) @@ -74,7 +80,9 @@ func get_blocks() -> Array[Block]: func arrange_block(block: Block, nearby_block: Block) -> void: add_block(block) - block.global_position = (nearby_block.global_position + (nearby_block.get_size() * Vector2.RIGHT) + BLOCK_AUTO_PLACE_MARGIN) + var rect = nearby_block.get_global_rect() + rect.position += (rect.size * Vector2.RIGHT) + BLOCK_AUTO_PLACE_MARGIN + block.global_position = rect.position func set_child(n: Node): @@ -105,7 +113,9 @@ func bsd_selected(bsd: BlockScriptData): _load_bsd(bsd) _window.visible = true _zoom_label.visible = true - reset_window_position() + + if bsd != _current_bsd: + reset_window_position() elif edited_node == null: _empty_box.visible = true elif BlockCodePlugin.node_has_block_code(edited_node): @@ -123,6 +133,8 @@ func bsd_selected(bsd: BlockScriptData): _selected_node_label.text = _selected_node_label_format.format({"node": edited_node.name}) _add_block_code_button.disabled = false + _current_bsd = bsd + func _load_bsd(bsd: BlockScriptData): for tree in bsd.block_trees.array: From e178d97bac141f1dc3cc30d6648b3c4224487ee8 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Thu, 11 Jul 2024 19:06:41 -0700 Subject: [PATCH 044/423] Set MOUSE_FILTER_IGNORE for blocks where necessary Certain components inside our Block scenes were consuming input events, making it difficult to interact with other blocks positioned around them. --- addons/block_code/ui/blocks/block/block.gd | 1 + addons/block_code/ui/blocks/control_block/control_block.gd | 3 +++ .../block_code/ui/blocks/control_block/control_block.tscn | 6 +++++- .../ui/blocks/statement_block/statement_block.tscn | 6 +++--- .../ui/blocks/utilities/snap_point/snap_point.tscn | 1 + 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 9966fe8f..dd7d4526 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -31,6 +31,7 @@ var bottom_snap: SnapPoint func _ready(): bottom_snap = get_node_or_null(bottom_snap_path) + mouse_filter = Control.MOUSE_FILTER_IGNORE static func get_block_class(): diff --git a/addons/block_code/ui/blocks/control_block/control_block.gd b/addons/block_code/ui/blocks/control_block/control_block.gd index 1b58522e..24938ab9 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.gd +++ b/addons/block_code/ui/blocks/control_block/control_block.gd @@ -141,7 +141,10 @@ func format(): var snap_container := MarginContainer.new() snap_container.name = "SnapContainer%d" % i + snap_container.mouse_filter = Control.MOUSE_FILTER_IGNORE + snap_container.custom_minimum_size.x = 30 snap_container.custom_minimum_size.y = 30 + snap_container.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN snap_container.add_theme_constant_override("margin_left", Constants.CONTROL_MARGIN) var snap_point: SnapPoint = preload("res://addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn").instantiate() diff --git a/addons/block_code/ui/blocks/control_block/control_block.tscn b/addons/block_code/ui/blocks/control_block/control_block.tscn index 92cb6a03..81790457 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.tscn +++ b/addons/block_code/ui/blocks/control_block/control_block.tscn @@ -5,6 +5,7 @@ [node name="ControlBlock" type="MarginContainer"] size_flags_horizontal = 0 +mouse_filter = 2 script = ExtResource("1_2hbir") block_name = "control_block" label = "Control Block" @@ -13,13 +14,16 @@ bottom_snap_path = NodePath("VBoxContainer/SnapPoint") [node name="VBoxContainer" type="VBoxContainer" parent="."] layout_mode = 2 +mouse_filter = 2 theme_override_constants/separation = 0 [node name="MarginContainer" type="MarginContainer" parent="VBoxContainer"] layout_mode = 2 +mouse_filter = 2 [node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/MarginContainer"] layout_mode = 2 +mouse_filter = 2 theme_override_constants/margin_top = 30 theme_override_constants/margin_bottom = 30 @@ -34,8 +38,8 @@ color = Color(0.59979, 0.536348, 0.876215, 1) unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 0 +mouse_filter = 2 theme_override_constants/separation = 0 [node name="SnapPoint" parent="VBoxContainer" instance=ExtResource("3_nhryi")] layout_mode = 2 -block_path = NodePath("../..") diff --git a/addons/block_code/ui/blocks/statement_block/statement_block.tscn b/addons/block_code/ui/blocks/statement_block/statement_block.tscn index 70f0adfd..96ed6e48 100644 --- a/addons/block_code/ui/blocks/statement_block/statement_block.tscn +++ b/addons/block_code/ui/blocks/statement_block/statement_block.tscn @@ -7,20 +7,22 @@ [node name="StatementBlock" type="MarginContainer"] size_flags_horizontal = 0 +mouse_filter = 2 script = ExtResource("1_6wvlf") -defaults = null block_name = "statement_block" label = "StatementBlock" bottom_snap_path = NodePath("VBoxContainer/SnapPoint") [node name="VBoxContainer" type="VBoxContainer" parent="."] layout_mode = 2 +mouse_filter = 2 theme_override_constants/separation = 0 [node name="TopMarginContainer" type="MarginContainer" parent="VBoxContainer"] custom_minimum_size = Vector2(0, 30) layout_mode = 2 size_flags_horizontal = 0 +mouse_filter = 2 theme_override_constants/margin_left = 0 theme_override_constants/margin_top = 0 theme_override_constants/margin_right = 0 @@ -32,7 +34,6 @@ layout_mode = 2 mouse_filter = 1 script = ExtResource("2_lctqt") color = Color(1, 1, 1, 1) -outline_color = Color(0.8, 0.8, 0.8, 1) [node name="DragDropArea" parent="VBoxContainer/TopMarginContainer" instance=ExtResource("2_owgdx")] layout_mode = 2 @@ -54,6 +55,5 @@ theme_override_constants/separation = 0 [node name="SnapPoint" parent="VBoxContainer" instance=ExtResource("3_5vaov")] layout_mode = 2 -block_path = NodePath("../..") [connection signal="mouse_down" from="VBoxContainer/TopMarginContainer/DragDropArea" to="." method="_on_drag_drop_area_mouse_down"] diff --git a/addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn b/addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn index 97ec5f2c..35b82a61 100644 --- a/addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn +++ b/addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn @@ -10,6 +10,7 @@ offset_right = -1152.0 offset_bottom = -648.0 grow_horizontal = 2 grow_vertical = 2 +mouse_filter = 2 script = ExtResource("1_kseym") [connection signal="child_entered_tree" from="." to="." method="_on_child_entered_tree"] From 16537da2cbaa810b3c0ef87c32d60bee658ec54a Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Tue, 2 Jul 2024 16:25:03 -0400 Subject: [PATCH 045/423] Revamp variable system Instead of accessing variables by VAR_DICT, use GDScript properties. Add a new "variables" property to block script data resource. Add a menu for creating variable of specific type. Validate new variable name and check for conflicts with existing variables. --- addons/block_code/block_code_plugin.gd | 4 +- .../block_script_data/block_script_data.gd | 4 +- addons/block_code/types/types.gd | 1 + .../node_block_canvas/node_block_canvas.gd | 9 +- .../ui/block_canvas/variable_resource.gd | 10 ++ addons/block_code/ui/main_panel.gd | 24 ++++- .../ui/picker/categories/category_factory.gd | 64 +++++------ .../create_variable_button.gd | 15 +++ .../create_variable_button.tscn | 20 ++++ .../create_variable_dialog.gd | 100 ++++++++++++++++++ .../create_variable_dialog.tscn | 68 ++++++++++++ .../variable_category_display.gd | 15 +++ .../variable_category_display.tscn | 22 ++++ addons/block_code/ui/picker/picker.gd | 28 ++++- 14 files changed, 340 insertions(+), 44 deletions(-) create mode 100644 addons/block_code/ui/block_canvas/variable_resource.gd create mode 100644 addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd create mode 100644 addons/block_code/ui/picker/categories/variable_category/create_variable_button.tscn create mode 100644 addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd create mode 100644 addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.tscn create mode 100644 addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd create mode 100644 addons/block_code/ui/picker/categories/variable_category/variable_category_display.tscn diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 80991aa0..2140879b 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -44,7 +44,9 @@ const DISABLED_CLASSES := [ "TitleBar", "MainPanel", "BlockCodePlugin", - "BlockCategoryButton" + "BlockCategoryButton", + "CreateVariableButton", + "VariableCategoryDisplay" ] diff --git a/addons/block_code/block_script_data/block_script_data.gd b/addons/block_code/block_script_data/block_script_data.gd index 4e933c41..3502ca73 100644 --- a/addons/block_code/block_script_data/block_script_data.gd +++ b/addons/block_code/block_script_data/block_script_data.gd @@ -3,12 +3,14 @@ extends Resource @export var script_inherits: String @export var block_trees: SerializedBlockTreeNodeArray +@export var variables: Array[VariableResource] @export var generated_script: String @export var version: int -func _init(p_script_inherits: String = "", p_block_trees: SerializedBlockTreeNodeArray = null, p_generated_script: String = "", p_version = 0): +func _init(p_script_inherits: String = "", p_block_trees: SerializedBlockTreeNodeArray = null, p_variables: Array[VariableResource] = [], p_generated_script: String = "", p_version = 0): script_inherits = p_script_inherits block_trees = p_block_trees generated_script = p_generated_script + variables = p_variables version = p_version diff --git a/addons/block_code/types/types.gd b/addons/block_code/types/types.gd index e4f6ed64..afe4c13e 100644 --- a/addons/block_code/types/types.gd +++ b/addons/block_code/types/types.gd @@ -36,6 +36,7 @@ const cast_relationships = [ [TYPE_INT, TYPE_STRING, "str(%s)"], [TYPE_FLOAT, TYPE_STRING, "str(%s)"], [TYPE_COLOR, TYPE_STRING, "str(%s)"], + [TYPE_VECTOR2, TYPE_STRING, "str(%s)"], ] # Directed graph, edges are CastGraphEdge diff --git a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd b/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd index 27ede777..25cf6cd8 100644 --- a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd +++ b/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd @@ -3,7 +3,7 @@ class_name NodeBlockCanvas extends BlockCanvas -func generate_script_from_current_window(script_inherits: String = ""): +func generate_script_from_current_window(bsd: BlockScriptData): # TODO: implement multiple windows var current_window := _window @@ -21,9 +21,12 @@ func generate_script_from_current_window(script_inherits: String = ""): var script: String = "" - script += "extends %s\n\n" % script_inherits + script += "extends %s\n\n" % bsd.script_inherits - script += "var VAR_DICT := {}\n\n" + for variable in bsd.variables: + script += "var %s\n\n" % variable.var_name + + script += "\n" var init_func = InstructionTree.TreeNode.new("func _init():") diff --git a/addons/block_code/ui/block_canvas/variable_resource.gd b/addons/block_code/ui/block_canvas/variable_resource.gd new file mode 100644 index 00000000..119d4371 --- /dev/null +++ b/addons/block_code/ui/block_canvas/variable_resource.gd @@ -0,0 +1,10 @@ +class_name VariableResource +extends Resource + +@export var var_name: String +@export var var_type: Variant.Type + + +func _init(p_var_name: String = "", p_var_type: Variant.Type = TYPE_NIL): + var_name = p_var_name + var_type = p_var_type diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index 45f0f59e..afc9ce61 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -32,6 +32,7 @@ var undo_redo: EditorUndoRedoManager: func _ready(): _picker.block_picked.connect(_drag_manager.copy_picked_block_and_drag) + _picker.variable_created.connect(_create_variable) _block_canvas.reconnect_block.connect(_drag_manager.connect_block_canvas_signals) _drag_manager.block_dropped.connect(save_script) _drag_manager.block_modified.connect(save_script) @@ -142,7 +143,7 @@ func save_script(): undo_redo.add_undo_property(_current_block_code_node.block_script, "generated_script", _current_block_code_node.block_script.generated_script) var block_trees := _block_canvas.get_canvas_block_trees() - var generated_script = _block_canvas.generate_script_from_current_window(block_script.script_inherits) + var generated_script = _block_canvas.generate_script_from_current_window(block_script) block_script.block_trees = block_trees block_script.generated_script = generated_script block_script.version = Constants.CURRENT_DATA_VERSION @@ -174,7 +175,7 @@ func _print_generated_script(): if _current_block_code_node == null: return var block_script: BlockScriptData = _current_block_code_node.block_script - var script: String = _block_canvas.generate_script_from_current_window(block_script.script_inherits) + var script: String = _block_canvas.generate_script_from_current_window(block_script) print(script) print("Debug script! (not saved)") @@ -252,3 +253,22 @@ func _set_selection(nodes: Array[Node]): EditorInterface.get_selection().clear() for node in nodes: EditorInterface.get_selection().add_node(node) + + +func _create_variable(variable: VariableResource): + if _current_block_code_node == null: + print("No script loaded to add variable to.") + return + + var block_script: BlockScriptData = _current_block_code_node.block_script + + undo_redo.create_action("Create variable %s in %s's block code script" % [variable.var_name, _current_block_code_node.get_parent().name]) + undo_redo.add_undo_property(_current_block_code_node.block_script, "variables", _current_block_code_node.block_script.variables) + + var new_variables = block_script.variables.duplicate() + new_variables.append(variable) + + undo_redo.add_do_property(_current_block_code_node.block_script, "variables", new_variables) + undo_redo.commit_action() + + _picker.reload_variables(new_variables) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index ba85a11e..c987ddcb 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -328,38 +328,6 @@ static func get_general_blocks() -> Array[Block]: #endregion #region Variables - - b = BLOCKS["statement_block"].instantiate() - b.block_format = "Set String {var: STRING} {value: STRING}" - b.statement = "VAR_DICT[{var}] = {value}" - b.category = "Variables" - block_list.append(b) - - b = BLOCKS["parameter_block"].instantiate() - b.block_format = "Get String {var: STRING}" - b.statement = "VAR_DICT[{var}]" - b.category = "Variables" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_format = "Set Int {var: STRING} {value: INT}" - b.statement = "VAR_DICT[{var}] = {value}" - b.category = "Variables" - block_list.append(b) - - b = BLOCKS["parameter_block"].instantiate() - b.variant_type = TYPE_INT - b.block_format = "Get Int {var: STRING}" - b.statement = "VAR_DICT[{var}]" - b.category = "Variables" - block_list.append(b) - - b = BLOCKS["parameter_block"].instantiate() - b.block_format = "To String {int: INT}" - b.statement = "str({int})" - b.category = "Variables" - block_list.append(b) - b = BLOCKS["parameter_block"].instantiate() b.variant_type = TYPE_VECTOR2 b.block_format = "Vector2 x: {x: FLOAT} y: {y: FLOAT}" @@ -513,10 +481,10 @@ static func get_general_blocks() -> Array[Block]: static func property_to_blocklist(property: Dictionary) -> Array[Block]: var block_list: Array[Block] = [] - var block_type = property.type + var variant_type = property.type - if block_type: - var type_string: String = Types.VARIANT_TYPE_TO_STRING[block_type] + if variant_type: + var type_string: String = Types.VARIANT_TYPE_TO_STRING[variant_type] var b = BLOCKS["statement_block"].instantiate() b.block_format = "Set %s to {value: %s}" % [property.name.capitalize(), type_string] @@ -531,7 +499,7 @@ static func property_to_blocklist(property: Dictionary) -> Array[Block]: block_list.append(b) b = BLOCKS["parameter_block"].instantiate() - b.block_type = block_type + b.variant_type = variant_type b.block_format = "%s" % property.name.capitalize() b.statement = "%s" % property.name b.category = property.category @@ -766,3 +734,27 @@ static func _get_input_blocks() -> Array[Block]: InputMap.action_add_event(action, event) return block_list + + +static func get_variable_blocks(variables: Array[VariableResource]): + var block_list: Array[Block] + + for variable in variables: + var type_string: String = Types.VARIANT_TYPE_TO_STRING[variable.var_type] + + var b = BLOCKS["parameter_block"].instantiate() + b.variant_type = variable.var_type + b.block_format = variable.var_name + b.statement = variable.var_name + # HACK: Color the blocks since they are outside of the normal picker system + b.color = BUILTIN_PROPS["Variables"].color + block_list.append(b) + + b = BLOCKS["statement_block"].instantiate() + b.block_type = Types.BlockType.EXECUTE + b.block_format = "Set %s to {value: %s}" % [variable.var_name, type_string] + b.statement = "%s = {value}" % [variable.var_name] + b.color = BUILTIN_PROPS["Variables"].color + block_list.append(b) + + return block_list diff --git a/addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd b/addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd new file mode 100644 index 00000000..85959cc9 --- /dev/null +++ b/addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd @@ -0,0 +1,15 @@ +@tool +class_name CreateVariableButton +extends MarginContainer + +signal create_variable(var_name: String, var_type: String) + +@onready var _create_variable_dialog := %CreateVariableDialog + + +func _on_create_button_pressed(): + _create_variable_dialog.visible = true + + +func _on_create_variable_dialog_create_variable(var_name, var_type): + create_variable.emit(var_name, var_type) diff --git a/addons/block_code/ui/picker/categories/variable_category/create_variable_button.tscn b/addons/block_code/ui/picker/categories/variable_category/create_variable_button.tscn new file mode 100644 index 00000000..74770a6c --- /dev/null +++ b/addons/block_code/ui/picker/categories/variable_category/create_variable_button.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=3 format=3 uid="uid://t0eoc4ekvjr1"] + +[ext_resource type="Script" path="res://addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd" id="1_cw6c3"] +[ext_resource type="PackedScene" uid="uid://dbrm7wwkao0c0" path="res://addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.tscn" id="2_udpg5"] + +[node name="CreateVariableButton" type="MarginContainer"] +size_flags_horizontal = 0 +theme_override_constants/margin_bottom = 12 +script = ExtResource("1_cw6c3") + +[node name="CreateButton" type="Button" parent="."] +layout_mode = 2 +text = "Create New Variable" + +[node name="CreateVariableDialog" parent="." instance=ExtResource("2_udpg5")] +unique_name_in_owner = true +visible = false + +[connection signal="pressed" from="CreateButton" to="." method="_on_create_button_pressed"] +[connection signal="create_variable" from="CreateVariableDialog" to="." method="_on_create_variable_dialog_create_variable"] diff --git a/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd new file mode 100644 index 00000000..af1db397 --- /dev/null +++ b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd @@ -0,0 +1,100 @@ +@tool +extends ConfirmationDialog + +signal create_variable(var_name: String, var_type: String) + +@onready var _variable_input := %VariableInput +@onready var _type_option := %TypeOption +@onready var _messages := %Messages + +const available_types = ["STRING", "BOOL", "INT", "FLOAT", "VECTOR2", "COLOR"] + + +func _ready(): + _type_option.clear() + + for type in available_types: + _type_option.add_item(type) + + check_errors(_variable_input.text) + + +func _clear(): + _variable_input.text = "" + check_errors(_variable_input.text) + _type_option.select(0) + + +func _on_variable_input_text_changed(new_text): + get_ok_button().disabled = check_errors(new_text) + + +func check_errors(new_var_name: String) -> bool: + if new_var_name.contains(" "): + var caret_column = _variable_input.caret_column + new_var_name = new_var_name.replace(" ", "_") + _variable_input.text = new_var_name + _variable_input.caret_column = caret_column + + _messages.clear() + + var errors: Array = [] + + if new_var_name == "": + errors.append("Variable requires a name") + elif new_var_name == "_": + errors.append("Variable name cannot be a single underscore") + elif RegEx.create_from_string("^[0-9]").search(new_var_name) != null: + errors.append("Variable name cannot start with numbers") + + if new_var_name.begins_with("__"): + errors.append("Variable name cannot start with two underscores") + + if RegEx.create_from_string("[^_a-zA-Z0-9-]+").search(new_var_name) != null: + errors.append("Variable name cannot contain special characters") + + var duplicate_variable_name := false + var current_block_code = BlockCodePlugin.main_panel._current_block_code_node + if current_block_code: + var current_bsd = current_block_code.block_script + if current_bsd: + for variable in current_bsd.variables: + if variable.var_name == new_var_name: + duplicate_variable_name = true + break + + if duplicate_variable_name: + errors.append("Variable already exists") + + if errors.is_empty(): + _messages.push_context() + _messages.push_color(Color("73F27F")) + _messages.push_list(0, RichTextLabel.LIST_DOTS, false) + + _messages.add_text("Will create new variable") + + _messages.pop_context() + + return false + else: + _messages.push_context() + _messages.push_color(Color("FF786B")) + _messages.push_list(0, RichTextLabel.LIST_DOTS, false) + + for error in errors: + _messages.add_text(error) + _messages.newline() + + _messages.pop_context() + + return true + + +func _on_confirmed(): + if not check_errors(_variable_input.text): + create_variable.emit(_variable_input.text, _type_option.get_item_text(_type_option.selected)) + _clear() + + +func _on_canceled(): + _clear() diff --git a/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.tscn b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.tscn new file mode 100644 index 00000000..f8678a2f --- /dev/null +++ b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.tscn @@ -0,0 +1,68 @@ +[gd_scene load_steps=2 format=3 uid="uid://dbrm7wwkao0c0"] + +[ext_resource type="Script" path="res://addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd" id="1_b52me"] + +[node name="CreateVariableDialog" type="ConfirmationDialog"] +title = "Create New Variable" +initial_position = 1 +size = Vector2i(300, 183) +visible = true +ok_button_text = "Create" +script = ExtResource("1_b52me") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +offset_left = 8.0 +offset_top = 8.0 +offset_right = 292.0 +offset_bottom = 134.0 + +[node name="GridContainer" type="GridContainer" parent="VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Name " + +[node name="VariableInput" type="LineEdit" parent="VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="Label2" type="Label" parent="VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Type " + +[node name="TypeOption" type="OptionButton" parent="VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +item_count = 6 +selected = 0 +popup/item_0/text = "STRING" +popup/item_0/id = 0 +popup/item_1/text = "BOOL" +popup/item_1/id = 1 +popup/item_2/text = "INT" +popup/item_2/id = 2 +popup/item_3/text = "FLOAT" +popup/item_3/id = 3 +popup/item_4/text = "VECTOR2" +popup/item_4/id = 4 +popup/item_5/text = "COLOR" +popup/item_5/id = 5 + +[node name="ErrorsContainer" type="MarginContainer" parent="VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +theme_override_constants/margin_top = 8 + +[node name="Messages" type="RichTextLabel" parent="VBoxContainer/ErrorsContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(0, 48) +layout_mode = 2 +theme_override_constants/line_separation = 4 +fit_content = true + +[connection signal="canceled" from="." to="." method="_on_canceled"] +[connection signal="confirmed" from="." to="." method="_on_confirmed"] +[connection signal="text_changed" from="VBoxContainer/GridContainer/VariableInput" to="." method="_on_variable_input_text_changed"] diff --git a/addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd b/addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd new file mode 100644 index 00000000..03de2a0b --- /dev/null +++ b/addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd @@ -0,0 +1,15 @@ +@tool +class_name VariableCategoryDisplay +extends BlockCategoryDisplay + +signal variable_created(variable: VariableResource) + +@onready var variable_blocks := %VariableBlocks + + +func _ready(): + super() + + +func _on_create_variable(var_name, var_type): + variable_created.emit(VariableResource.new(var_name, Types.STRING_TO_VARIANT_TYPE[var_type])) diff --git a/addons/block_code/ui/picker/categories/variable_category/variable_category_display.tscn b/addons/block_code/ui/picker/categories/variable_category/variable_category_display.tscn new file mode 100644 index 00000000..dd681c30 --- /dev/null +++ b/addons/block_code/ui/picker/categories/variable_category/variable_category_display.tscn @@ -0,0 +1,22 @@ +[gd_scene load_steps=4 format=3 uid="uid://byne4g2yvdf3"] + +[ext_resource type="PackedScene" uid="uid://duhpwtfo3k0sk" path="res://addons/block_code/ui/picker/categories/block_category_display.tscn" id="1_vermd"] +[ext_resource type="Script" path="res://addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd" id="2_ggvi7"] +[ext_resource type="PackedScene" uid="uid://t0eoc4ekvjr1" path="res://addons/block_code/ui/picker/categories/variable_category/create_variable_button.tscn" id="3_gjvnq"] + +[node name="VariableCategoryDisplay" instance=ExtResource("1_vermd")] +script = ExtResource("2_ggvi7") + +[node name="CreateVariableButton" parent="VBoxContainer" index="1" instance=ExtResource("3_gjvnq")] +layout_mode = 2 + +[node name="VariableBlocks" type="VBoxContainer" parent="VBoxContainer" index="2"] +unique_name_in_owner = true +layout_mode = 2 +theme_override_constants/separation = 14 + +[node name="Spacer" type="Control" parent="VBoxContainer" index="3"] +custom_minimum_size = Vector2(0, 30) +layout_mode = 2 + +[connection signal="create_variable" from="VBoxContainer/CreateVariableButton" to="." method="_on_create_variable"] diff --git a/addons/block_code/ui/picker/picker.gd b/addons/block_code/ui/picker/picker.gd index 64d9a1b7..a18e5d4b 100644 --- a/addons/block_code/ui/picker/picker.gd +++ b/addons/block_code/ui/picker/picker.gd @@ -3,6 +3,7 @@ class_name Picker extends MarginContainer signal block_picked(block: Block) +signal variable_created(variable: VariableResource) @onready var _block_list := %BlockList @onready var _block_scroll := %BlockScroll @@ -10,6 +11,7 @@ signal block_picked(block: Block) @onready var _widget_container := %WidgetContainer var scroll_tween: Tween +var _variable_category_display: VariableCategoryDisplay = null func bsd_selected(bsd: BlockScriptData): @@ -35,6 +37,7 @@ func bsd_selected(bsd: BlockScriptData): blocks_to_add.append_array(CategoryFactory.get_inherited_blocks(parent_class)) init_picker(blocks_to_add, categories_to_add) + reload_variables(bsd.variables) func reset_picker(): @@ -60,7 +63,14 @@ func init_picker(extra_blocks: Array[Block] = [], extra_categories: Array[BlockC _category_list.add_child(block_category_button) - var block_category_display := preload("res://addons/block_code/ui/picker/categories/block_category_display.tscn").instantiate() + var block_category_display: BlockCategoryDisplay + if category.name != "Variables": + block_category_display = preload("res://addons/block_code/ui/picker/categories/block_category_display.tscn").instantiate() + else: + block_category_display = preload("res://addons/block_code/ui/picker/categories/variable_category/variable_category_display.tscn").instantiate() + block_category_display.variable_created.connect(func(variable): variable_created.emit(variable)) + _variable_category_display = block_category_display + block_category_display.category = category _block_list.add_child(block_category_display) @@ -92,3 +102,19 @@ func _category_selected(category: BlockCategory): func set_collapsed(collapsed: bool): _widget_container.visible = not collapsed + + +func reload_variables(variables: Array[VariableResource]): + if _variable_category_display: + for c in _variable_category_display.variable_blocks.get_children(): + c.queue_free() + + var i := 1 + for block in CategoryFactory.get_variable_blocks(variables): + _variable_category_display.variable_blocks.add_child(block) + block.drag_started.connect(_block_picked) + if i % 2 == 0: + var spacer := Control.new() + spacer.custom_minimum_size.y = 12 + _variable_category_display.variable_blocks.add_child(spacer) + i += 1 From 725e94529ebd17b6bf2c4d8408d5973ca5cd33f2 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Fri, 5 Jul 2024 12:45:06 -0400 Subject: [PATCH 046/423] Add type string to generated code --- .../ui/block_canvas/node_block_canvas/node_block_canvas.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd b/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd index 25cf6cd8..7ec76f3a 100644 --- a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd +++ b/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd @@ -24,7 +24,7 @@ func generate_script_from_current_window(bsd: BlockScriptData): script += "extends %s\n\n" % bsd.script_inherits for variable in bsd.variables: - script += "var %s\n\n" % variable.var_name + script += "var %s: %s\n\n" % [variable.var_name, type_string(variable.var_type)] script += "\n" From e4f1e35b2983084e1b342f081968df1742899383 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Wed, 10 Jul 2024 22:06:48 -0400 Subject: [PATCH 047/423] Unique local variables Allows us to declare local variables in block scripts with unique names. Uses new static functions in InstructionTree to handle this. For example, "var __temp = 0" in a block statement will become "var temp_1 = 0" in the generated code. --- .../instruction_tree/instruction_tree.gd | 29 +++++++++++++++++++ .../node_block_canvas/node_block_canvas.gd | 2 ++ .../ui/blocks/control_block/control_block.gd | 2 ++ .../blocks/parameter_block/parameter_block.gd | 2 ++ .../blocks/statement_block/statement_block.gd | 2 ++ 5 files changed, 37 insertions(+) diff --git a/addons/block_code/instruction_tree/instruction_tree.gd b/addons/block_code/instruction_tree/instruction_tree.gd index 5122074e..3ee7b9a3 100644 --- a/addons/block_code/instruction_tree/instruction_tree.gd +++ b/addons/block_code/instruction_tree/instruction_tree.gd @@ -14,6 +14,35 @@ class TreeNode: children.append(node) +class IDHandler: + static var counts: Dictionary = {} + + static func reset(): + counts = {} + + static func get_unique_id(str: String) -> int: + if not counts.has(str): + counts[str] = 0 + + counts[str] += 1 + + return counts[str] + + static func make_unique(formatted_string: String) -> String: + var unique_string = formatted_string + var regex = RegEx.new() + regex.compile("[^\\s]+__\\b") + var ids: Dictionary = {} + for result in regex.search_all(formatted_string): + var result_string = result.get_string() + var base_string = result_string.trim_suffix("__") + if not ids.has(base_string): + ids[base_string] = get_unique_id(base_string) + unique_string = unique_string.replace(result_string, base_string + "_%d" % ids[base_string]) + + return unique_string + + func generate_text(root_node: TreeNode, start_depth: int = 0) -> String: var out = PackedStringArray() generate_text_recursive(root_node, start_depth, out) diff --git a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd b/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd index 7ec76f3a..aab18d5e 100644 --- a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd +++ b/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd @@ -46,6 +46,8 @@ func _generate_script_from_entry_blocks(entry_statement: String, entry_blocks: A var signal_node: InstructionTree.TreeNode var is_empty = true + InstructionTree.IDHandler.reset() + for entry_block in entry_blocks: var next_block := entry_block.bottom_snap.get_snapped_block() diff --git a/addons/block_code/ui/blocks/control_block/control_block.gd b/addons/block_code/ui/blocks/control_block/control_block.gd index 1b58522e..0eba1449 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.gd +++ b/addons/block_code/ui/blocks/control_block/control_block.gd @@ -45,6 +45,8 @@ func get_instruction_node() -> InstructionTree.TreeNode: for pair in param_name_input_pairs_array[i]: formatted_statement = formatted_statement.replace("{%s}" % pair[0], pair[1].get_string()) + formatted_statement = InstructionTree.IDHandler.make_unique(formatted_statement) + var new_node := InstructionTree.TreeNode.new(formatted_statement) if i == 0: node = new_node diff --git a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd index 2ee9b51f..95a2b7b4 100644 --- a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd +++ b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd @@ -55,6 +55,8 @@ func get_parameter_string() -> String: for pair in param_name_input_pairs: formatted_statement = formatted_statement.replace("{%s}" % pair[0], pair[1].get_string()) + formatted_statement = InstructionTree.IDHandler.make_unique(formatted_statement) + return formatted_statement diff --git a/addons/block_code/ui/blocks/statement_block/statement_block.gd b/addons/block_code/ui/blocks/statement_block/statement_block.gd index 15015795..20aa2e58 100644 --- a/addons/block_code/ui/blocks/statement_block/statement_block.gd +++ b/addons/block_code/ui/blocks/statement_block/statement_block.gd @@ -58,6 +58,8 @@ func get_instruction_node() -> InstructionTree.TreeNode: for pair in param_name_input_pairs: formatted_statement = formatted_statement.replace("{%s}" % pair[0], pair[1].get_string()) + formatted_statement = InstructionTree.IDHandler.make_unique(formatted_statement) + var statement_lines := formatted_statement.split("\n") var root: InstructionTree.TreeNode = InstructionTree.TreeNode.new(statement_lines[0]) From aaf9f2dd2025e869c28310c18755e9a2781ed73f Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Wed, 10 Jul 2024 22:07:22 -0400 Subject: [PATCH 048/423] Fix old sound blocks. Use local variables instead of VAR_DICT --- .../examples/pong_game/pong_game.tscn | 249 ++++++++++-------- .../instruction_tree/instruction_tree.gd | 9 +- .../ui/picker/categories/category_factory.gd | 17 +- 3 files changed, 152 insertions(+), 123 deletions(-) diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index 41c45314..02c6f96e 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -49,6 +49,7 @@ array = Array[ExtResource("4_qtggh")]([SubResource("Resource_uln40")]) script = ExtResource("7_uuuue") script_inherits = "SimpleCharacter" block_trees = SubResource("Resource_4j61k") +variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends SimpleCharacter var VAR_DICT := {} @@ -64,6 +65,7 @@ func _process(delta): move_and_slide() " +version = 0 [sub_resource type="Resource" id="Resource_d4hry"] script = ExtResource("5_wr38c") @@ -102,6 +104,7 @@ array = Array[ExtResource("4_qtggh")]([SubResource("Resource_75h61")]) script = ExtResource("7_uuuue") script_inherits = "SimpleCharacter" block_trees = SubResource("Resource_r5rk4") +variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends SimpleCharacter var VAR_DICT := {} @@ -117,66 +120,73 @@ func _process(delta): move_and_slide() " +version = 0 -[sub_resource type="Resource" id="Resource_lbd5h"] +[sub_resource type="Resource" id="Resource_80onm"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", "VAR_DICT[{name}] = AudioStreamPlayer.new() -VAR_DICT[{name}].name = {name} -VAR_DICT[{name}].set_stream(load({file_path})) -add_child(VAR_DICT[{name}])"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " +var __sound = AudioStreamPlayer.new() +__sound.name = {name} +__sound.set_stream(load({file_path})) +add_child(__sound) +"], ["defaults", {}], ["param_input_strings", { "file_path": "res://addons/block_code/examples/pong_game/assets/score.ogg", "name": "score_sound" }]] -[sub_resource type="Resource" id="Resource_6fxi6"] +[sub_resource type="Resource" id="Resource_jfgyp"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_lbd5h") +serialized_block = SubResource("Resource_80onm") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_4ns0q"] +[sub_resource type="Resource" id="Resource_0qgyx"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", "VAR_DICT[{name}] = AudioStreamPlayer.new() -VAR_DICT[{name}].name = {name} -VAR_DICT[{name}].set_stream(load({file_path})) -add_child(VAR_DICT[{name}])"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " +var __sound = AudioStreamPlayer.new() +__sound.name = {name} +__sound.set_stream(load({file_path})) +add_child(__sound) +"], ["defaults", {}], ["param_input_strings", { "file_path": "res://addons/block_code/examples/pong_game/assets/wall_hit.ogg", "name": "wall_hit" }]] -[sub_resource type="Resource" id="Resource_bp15q"] +[sub_resource type="Resource" id="Resource_515lv"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_4ns0q") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_6fxi6")]] +serialized_block = SubResource("Resource_0qgyx") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_jfgyp")]] -[sub_resource type="Resource" id="Resource_qlhw3"] +[sub_resource type="Resource" id="Resource_na8wd"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", "VAR_DICT[{name}] = AudioStreamPlayer.new() -VAR_DICT[{name}].name = {name} -VAR_DICT[{name}].set_stream(load({file_path})) -add_child(VAR_DICT[{name}])"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " +var __sound = AudioStreamPlayer.new() +__sound.name = {name} +__sound.set_stream(load({file_path})) +add_child(__sound) +"], ["defaults", {}], ["param_input_strings", { "file_path": "res://addons/block_code/examples/pong_game/assets/paddle_hit.ogg", "name": "paddle_hit" }]] -[sub_resource type="Resource" id="Resource_4o4ck"] +[sub_resource type="Resource" id="Resource_bku44"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_qlhw3") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_bp15q")]] +serialized_block = SubResource("Resource_na8wd") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_515lv")]] -[sub_resource type="Resource" id="Resource_sltlk"] +[sub_resource type="Resource" id="Resource_2m4ct"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" serialized_props = [["block_name", "ready_block"], ["label", "EntryBlock"], ["color", Color(0.980392, 0.34902, 0.337255, 1)], ["block_type", 1], ["position", Vector2(49, 42)], ["scope", ""], ["block_format", "On Ready"], ["statement", "func _ready():"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_wlbg2"] +[sub_resource type="Resource" id="Resource_lfbxc"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_sltlk") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_4o4ck")]] +serialized_block = SubResource("Resource_2m4ct") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_bku44")]] -[sub_resource type="Resource" id="Resource_5ftwo"] +[sub_resource type="Resource" id="Resource_0sepo"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -184,12 +194,12 @@ func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_2kdpe"] +[sub_resource type="Resource" id="Resource_k5cwt"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_5ftwo") +serialized_block = SubResource("Resource_0sepo") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_282k5"] +[sub_resource type="Resource" id="Resource_uucid"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -197,12 +207,12 @@ func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_rofb0"] +[sub_resource type="Resource" id="Resource_64xkq"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_282k5") +serialized_block = SubResource("Resource_uucid") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_7ldo3"] +[sub_resource type="Resource" id="Resource_76m34"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { @@ -210,17 +220,20 @@ serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["col "node": "" }]] -[sub_resource type="Resource" id="Resource_nqdjc"] +[sub_resource type="Resource" id="Resource_fmoex"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_7ldo3") -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_rofb0")]] +serialized_block = SubResource("Resource_76m34") +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_64xkq")]] -[sub_resource type="Resource" id="Resource_j6m6b"] +[sub_resource type="Resource" id="Resource_d7dfr"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", "VAR_DICT[{name}].volume_db = {db} -VAR_DICT[{name}].pitch_scale = {pitch} -VAR_DICT[{name}].play()"], ["defaults", { +serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " +var __sound_node = get_node({name}) +__sound_node.volume_db = {db} +__sound_node.pitch_scale = {pitch} +__sound_node.play() +"], ["defaults", { "db": "0.0", "pitch": "1.0" }], ["param_input_strings", { @@ -229,12 +242,12 @@ VAR_DICT[{name}].play()"], ["defaults", { "pitch": "1.0" }]] -[sub_resource type="Resource" id="Resource_scf28"] +[sub_resource type="Resource" id="Resource_oqnor"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_j6m6b") +serialized_block = SubResource("Resource_d7dfr") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_2mpvd"] +[sub_resource type="Resource" id="Resource_uibbi"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -242,12 +255,12 @@ func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_1lxsg"] +[sub_resource type="Resource" id="Resource_7jqxw"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_2mpvd") +serialized_block = SubResource("Resource_uibbi") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_jiood"] +[sub_resource type="Resource" id="Resource_nchna"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { @@ -255,17 +268,20 @@ serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["col "node": "" }]] -[sub_resource type="Resource" id="Resource_cxr6m"] +[sub_resource type="Resource" id="Resource_35nkf"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_jiood") -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_1lxsg")]] +serialized_block = SubResource("Resource_nchna") +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_7jqxw")]] -[sub_resource type="Resource" id="Resource_4luxm"] +[sub_resource type="Resource" id="Resource_fywef"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", "VAR_DICT[{name}].volume_db = {db} -VAR_DICT[{name}].pitch_scale = {pitch} -VAR_DICT[{name}].play()"], ["defaults", { +serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " +var __sound_node = get_node({name}) +__sound_node.volume_db = {db} +__sound_node.pitch_scale = {pitch} +__sound_node.play() +"], ["defaults", { "db": "0.0", "pitch": "1.0" }], ["param_input_strings", { @@ -274,36 +290,36 @@ VAR_DICT[{name}].play()"], ["defaults", { "pitch": "1.0" }]] -[sub_resource type="Resource" id="Resource_e1yr3"] +[sub_resource type="Resource" id="Resource_pucal"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_4luxm") +serialized_block = SubResource("Resource_fywef") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_v4fm4"] +[sub_resource type="Resource" id="Resource_8nvnv"] script = ExtResource("5_wr38c") block_class = &"ControlBlock" serialized_props = [["block_name", "control_block"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ "condition": false }]]] -[sub_resource type="Resource" id="Resource_2s53u"] +[sub_resource type="Resource" id="Resource_r8172"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_v4fm4") -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_cxr6m")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_e1yr3")]] +serialized_block = SubResource("Resource_8nvnv") +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_35nkf")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_pucal")]] -[sub_resource type="Resource" id="Resource_1st46"] +[sub_resource type="Resource" id="Resource_fl4h4"] script = ExtResource("5_wr38c") block_class = &"ControlBlock" serialized_props = [["block_name", "control_block"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ "condition": false }]]] -[sub_resource type="Resource" id="Resource_ci12p"] +[sub_resource type="Resource" id="Resource_3xq0k"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_1st46") -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_nqdjc")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_scf28")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_2s53u")]] +serialized_block = SubResource("Resource_fl4h4") +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_fmoex")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_oqnor")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_r8172")]] -[sub_resource type="Resource" id="Resource_gpji8"] +[sub_resource type="Resource" id="Resource_eiexb"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" serialized_props = [["block_name", "entry_block"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(50, 226)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " @@ -311,27 +327,30 @@ func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() "], ["defaults", {}], ["param_input_strings", {}], ["signal_name", "body_entered"]] -[sub_resource type="Resource" id="Resource_kidbc"] +[sub_resource type="Resource" id="Resource_gg652"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_gpji8") -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_2kdpe")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ci12p")]] +serialized_block = SubResource("Resource_eiexb") +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_k5cwt")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_3xq0k")]] -[sub_resource type="Resource" id="Resource_s53m4"] +[sub_resource type="Resource" id="Resource_py8f3"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.0117647, 0.666667, 0.454902, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Viewport Center"], ["statement", "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()"], ["defaults", {}], ["variant_type", 5], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_l3fka"] +[sub_resource type="Resource" id="Resource_kck4x"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_s53m4") +serialized_block = SubResource("Resource_py8f3") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_5id23"] +[sub_resource type="Resource" id="Resource_fyaul"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", "VAR_DICT[{name}].volume_db = {db} -VAR_DICT[{name}].pitch_scale = {pitch} -VAR_DICT[{name}].play()"], ["defaults", { +serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " +var __sound_node = get_node({name}) +__sound_node.volume_db = {db} +__sound_node.pitch_scale = {pitch} +__sound_node.play() +"], ["defaults", { "db": "0.0", "pitch": "1.0" }], ["param_input_strings", { @@ -340,83 +359,87 @@ VAR_DICT[{name}].play()"], ["defaults", { "pitch": "1.0" }]] -[sub_resource type="Resource" id="Resource_2xngh"] +[sub_resource type="Resource" id="Resource_1o8v3"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_5id23") +serialized_block = SubResource("Resource_fyaul") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_4nxq2"] +[sub_resource type="Resource" id="Resource_5fsso"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.439216, 0.501961, 0.564706, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Physics Position {position: VECTOR2}"], ["statement", "PhysicsServer2D.body_set_state(get_rid(),PhysicsServer2D.BODY_STATE_TRANSFORM,Transform2D.IDENTITY.translated({position}))"], ["defaults", {}], ["param_input_strings", { "position": "960,544" }]] -[sub_resource type="Resource" id="Resource_jy6wp"] +[sub_resource type="Resource" id="Resource_uyy35"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_4nxq2") -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_l3fka")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_2xngh")]] +serialized_block = SubResource("Resource_5fsso") +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_kck4x")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_1o8v3")]] -[sub_resource type="Resource" id="Resource_ysjrw"] +[sub_resource type="Resource" id="Resource_f3xvu"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" serialized_props = [["block_name", "entry_block"], ["label", "EntryBlock"], ["color", Color(0.941176, 0.764706, 0, 1)], ["block_type", 1], ["position", Vector2(51, 616)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { "method_name": "reset" }], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_y82yh"] +[sub_resource type="Resource" id="Resource_n4cap"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_ysjrw") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_jy6wp")]] +serialized_block = SubResource("Resource_f3xvu") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_uyy35")]] -[sub_resource type="Resource" id="Resource_vlu5s"] +[sub_resource type="Resource" id="Resource_gn6n3"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_wlbg2"), SubResource("Resource_kidbc"), SubResource("Resource_y82yh")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_lfbxc"), SubResource("Resource_gg652"), SubResource("Resource_n4cap")]) [sub_resource type="Resource" id="Resource_hnwk2"] script = ExtResource("7_uuuue") script_inherits = "RigidBody2D" -block_trees = SubResource("Resource_vlu5s") +block_trees = SubResource("Resource_gn6n3") +variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends RigidBody2D -var VAR_DICT := {} func _ready(): - VAR_DICT['paddle_hit'] = AudioStreamPlayer.new() - VAR_DICT['paddle_hit'].name = 'paddle_hit' - VAR_DICT['paddle_hit'].set_stream(load('res://addons/block_code/examples/pong_game/assets/paddle_hit.ogg')) - add_child(VAR_DICT['paddle_hit']) - VAR_DICT['wall_hit'] = AudioStreamPlayer.new() - VAR_DICT['wall_hit'].name = 'wall_hit' - VAR_DICT['wall_hit'].set_stream(load('res://addons/block_code/examples/pong_game/assets/wall_hit.ogg')) - add_child(VAR_DICT['wall_hit']) - VAR_DICT['score_sound'] = AudioStreamPlayer.new() - VAR_DICT['score_sound'].name = 'score_sound' - VAR_DICT['score_sound'].set_stream(load('res://addons/block_code/examples/pong_game/assets/score.ogg')) - add_child(VAR_DICT['score_sound']) + var __sound_1 = AudioStreamPlayer.new() + __sound_1.name = 'paddle_hit' + __sound_1.set_stream(load('res://addons/block_code/examples/pong_game/assets/paddle_hit.ogg')) + add_child(__sound_1) + var __sound_2 = AudioStreamPlayer.new() + __sound_2.name = 'wall_hit' + __sound_2.set_stream(load('res://addons/block_code/examples/pong_game/assets/wall_hit.ogg')) + add_child(__sound_2) + var __sound_3 = AudioStreamPlayer.new() + __sound_3.name = 'score_sound' + __sound_3.set_stream(load('res://addons/block_code/examples/pong_game/assets/score.ogg')) + add_child(__sound_3) func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() if get_node(body).is_in_group('paddles'): - VAR_DICT['paddle_hit'].volume_db = 0.0 - VAR_DICT['paddle_hit'].pitch_scale = 1.0 - VAR_DICT['paddle_hit'].play() + var __sound_node_1 = get_node('paddle_hit') + __sound_node_1.volume_db = 0.0 + __sound_node_1.pitch_scale = 1.0 + __sound_node_1.play() if get_node(body).is_in_group('walls'): - VAR_DICT['wall_hit'].volume_db = 0.0 - VAR_DICT['wall_hit'].pitch_scale = 1.0 - VAR_DICT['wall_hit'].play() + var __sound_node_2 = get_node('wall_hit') + __sound_node_2.volume_db = 0.0 + __sound_node_2.pitch_scale = 1.0 + __sound_node_2.play() func reset(): PhysicsServer2D.body_set_state(get_rid(),PhysicsServer2D.BODY_STATE_TRANSFORM,Transform2D.IDENTITY.translated((func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call())) - VAR_DICT['score_sound'].volume_db = 0.0 - VAR_DICT['score_sound'].pitch_scale = 1.0 - VAR_DICT['score_sound'].play() + var __sound_node_1 = get_node('score_sound') + __sound_node_1.volume_db = 0.0 + __sound_node_1.pitch_scale = 1.0 + __sound_node_1.play() func _init(): body_entered.connect(_on_body_entered) " +version = 0 [sub_resource type="Resource" id="Resource_tasas"] script = ExtResource("5_wr38c") @@ -516,6 +539,7 @@ array = Array[ExtResource("4_qtggh")]([SubResource("Resource_jwpt1")]) script = ExtResource("7_uuuue") script_inherits = "Area2D" block_trees = SubResource("Resource_7qerp") +variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends Area2D var VAR_DICT := {} @@ -531,6 +555,7 @@ func _on_body_entered(_body: Node2D): func _init(): body_entered.connect(_on_body_entered) " +version = 0 [sub_resource type="Resource" id="Resource_doveu"] script = ExtResource("5_wr38c") @@ -630,6 +655,7 @@ array = Array[ExtResource("4_qtggh")]([SubResource("Resource_uj1xx")]) script = ExtResource("7_uuuue") script_inherits = "Area2D" block_trees = SubResource("Resource_xphhp") +variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends Area2D var VAR_DICT := {} @@ -645,6 +671,7 @@ func _on_body_entered(_body: Node2D): func _init(): body_entered.connect(_on_body_entered) " +version = 0 [sub_resource type="Resource" id="Resource_nh5qb"] script = ExtResource("5_wr38c") @@ -748,6 +775,7 @@ array = Array[ExtResource("4_qtggh")]([SubResource("Resource_kt2b1"), SubResourc script = ExtResource("7_uuuue") script_inherits = "SimpleScoring" block_trees = SubResource("Resource_c8btv") +variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends SimpleScoring var VAR_DICT := {} @@ -764,6 +792,7 @@ func goal_left(): score_right += 1 " +version = 0 [node name="Pong" type="Node2D"] diff --git a/addons/block_code/instruction_tree/instruction_tree.gd b/addons/block_code/instruction_tree/instruction_tree.gd index 3ee7b9a3..f8781100 100644 --- a/addons/block_code/instruction_tree/instruction_tree.gd +++ b/addons/block_code/instruction_tree/instruction_tree.gd @@ -31,14 +31,13 @@ class IDHandler: static func make_unique(formatted_string: String) -> String: var unique_string = formatted_string var regex = RegEx.new() - regex.compile("[^\\s]+__\\b") + regex.compile("\\b__[^\\s]+") var ids: Dictionary = {} for result in regex.search_all(formatted_string): var result_string = result.get_string() - var base_string = result_string.trim_suffix("__") - if not ids.has(base_string): - ids[base_string] = get_unique_id(base_string) - unique_string = unique_string.replace(result_string, base_string + "_%d" % ids[base_string]) + if not ids.has(result_string): + ids[result_string] = get_unique_id(result_string) + unique_string = unique_string.replace(result_string, result_string + "_%d" % ids[result_string]) return unique_string diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index c987ddcb..ac4ae36f 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -204,7 +204,7 @@ static func get_general_blocks() -> Array[Block]: b = BLOCKS["control_block"].instantiate() b.block_formats = ["repeat {number: INT}"] - b.statements = ["for i in {number}:"] + b.statements = ["for __i in {number}:"] b.category = "Loops" block_list.append(b) @@ -423,10 +423,10 @@ static func get_general_blocks() -> Array[Block]: b.block_format = "Load file {file_path: STRING} as sound {name: STRING}" b.statement = ( """ - VAR_DICT[{name}] = AudioStreamPlayer.new() - VAR_DICT[{name}].name = {name} - VAR_DICT[{name}].set_stream(load({file_path})) - add_child(VAR_DICT[{name}]) + var __sound = AudioStreamPlayer.new() + __sound.name = {name} + __sound.set_stream(load({file_path})) + add_child(__sound) """ . dedent() ) @@ -439,9 +439,10 @@ static func get_general_blocks() -> Array[Block]: b.block_format = "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}" b.statement = ( """ - VAR_DICT[{name}].volume_db = {db} - VAR_DICT[{name}].pitch_scale = {pitch} - VAR_DICT[{name}].play() + var __sound_node = get_node({name}) + __sound_node.volume_db = {db} + __sound_node.pitch_scale = {pitch} + __sound_node.play() """ . dedent() ) From 446ee74fb9ea120a34449899a85b4d5524978f5e Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Mon, 15 Jul 2024 18:11:34 -0700 Subject: [PATCH 049/423] Add _to_string for Block The to_string implementation for Block follows the same pattern as the default for Godot objects, but it uses get_block_class and includes the block_name property for each block. This will make it easier to differentiate between different blocks while debugging the block code editor. --- addons/block_code/ui/blocks/block/block.gd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index dd7d4526..2e5b54cb 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -69,6 +69,10 @@ func get_serialized_props() -> Array: return serialize_props(["block_name", "label", "color", "block_type", "position", "scope"]) +func _to_string(): + return "<{block_class}:{block_name}#{rid}>".format({"block_name": block_name, "block_class": get_block_class(), "rid": get_instance_id()}) + + func serialize_props(prop_names: Array) -> Array: var pairs := [] for p in prop_names: From a9fb571f67bac8aa62d39d708f065d68301a66c4 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Tue, 16 Jul 2024 11:49:14 +0100 Subject: [PATCH 050/423] ci: Set Python version for setup-python This fixes the following warning that was previously seen on every run of the checks workflow: > Warning: Neither 'python-version' nor 'python-version-file' inputs were supplied. Attempting to find '.python-version' file. > Warning: .python-version doesn't exist. > Warning: The `python-version` input is not set. The version of Python currently in `PATH` will be used. Python 3.11 happens to be what is in Endless OS 6. --- .github/workflows/checks.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 4cfebd86..5ed986b8 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -13,6 +13,8 @@ jobs: steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 + with: + python-version: '3.11' - name: set PY run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV - uses: actions/cache@v4 From 80ea0baf5d005d06d296ed8d88d12a0e583a0d5b Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Mon, 15 Jul 2024 14:14:03 +0100 Subject: [PATCH 051/423] block: Use RichTextLabel for tooltip By default, a plain-text label is used which does not support rich text formatting. Define a `Tooltip` scene; and override `Control._make_custom_tooltip()` in `Block` to return an instance of this scene. `Tooltip` is initially just a `RichTextLabel` with BBCode enabled and a custom minimum size set as suggested by the `_make_custom_tooltip()` documentation: > Note: The tooltip is shrunk to minimal size. If you want to ensure it's fully > visible, you might want to set its `custom_minimum_size` to some non-zero > value. We override the theme styles on the `RichTextLabel` to match the styles used in the built-in inspector's help tooltips. In particular, bold, italic and bold-italic text doesn't work without overriding these styles. The [BBCode in RichTextLabel][0] documentation claims: > If no custom bold or italic fonts are defined, faux bold and italic fonts > will be generated by Godot. but empirically this is not true. The Editor Theme Explorer plugin was useful, as was reading the editor source code, specifically `editor_fonts.cpp` and `editor_help.cpp`. None of the existing `tooltip_text` properties in the codebase use the `[` character that is used by BBCode tags, so there is no need to adjust the existing tooltips to keep displaying as they previously did. https://phabricator.endlessm.com/T35540 [0]: https://docs.godotengine.org/en/stable/tutorials/ui/bbcode_in_richtextlabel.html#reference --- addons/block_code/ui/blocks/block/block.gd | 6 ++++++ addons/block_code/ui/tooltip/tooltip.gd | 24 ++++++++++++++++++++++ addons/block_code/ui/tooltip/tooltip.tscn | 14 +++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 addons/block_code/ui/tooltip/tooltip.gd create mode 100644 addons/block_code/ui/tooltip/tooltip.tscn diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index dd7d4526..127e4bfa 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -74,3 +74,9 @@ func serialize_props(prop_names: Array) -> Array: for p in prop_names: pairs.append([p, self.get(p)]) return pairs + + +func _make_custom_tooltip(for_text) -> Control: + var tooltip = preload("res://addons/block_code/ui/tooltip/tooltip.tscn").instantiate() + tooltip.text = for_text + return tooltip diff --git a/addons/block_code/ui/tooltip/tooltip.gd b/addons/block_code/ui/tooltip/tooltip.gd new file mode 100644 index 00000000..a0e44f26 --- /dev/null +++ b/addons/block_code/ui/tooltip/tooltip.gd @@ -0,0 +1,24 @@ +@tool +class_name Tooltip +extends RichTextLabel +## Rich-text control for block tooltips that matches the built-in inspector's tooltips' font styles + + +func override_font(font_name: StringName, editor_font_name: StringName) -> Font: + var font = get_theme_font(editor_font_name, &"EditorFonts") + add_theme_font_override(font_name, font) + return font + + +func _ready(): + # Set fonts to match documentation tooltips in inspector + override_font(&"normal_font", &"doc") + override_font(&"mono_font", &"doc_source") + override_font(&"bold_font", &"doc_bold") + var italics = override_font(&"italics_font", &"doc_italic") + + # No doc_ style for bold italic; fake it by emboldening the italic style + var bold_italics = FontVariation.new() + bold_italics.set_base_font(italics) + bold_italics.set_variation_embolden(1.2) + add_theme_font_override(&"bold_italics_font", bold_italics) diff --git a/addons/block_code/ui/tooltip/tooltip.tscn b/addons/block_code/ui/tooltip/tooltip.tscn new file mode 100644 index 00000000..4caa4514 --- /dev/null +++ b/addons/block_code/ui/tooltip/tooltip.tscn @@ -0,0 +1,14 @@ +[gd_scene load_steps=2 format=3 uid="uid://bmxco03vqyq2t"] + +[ext_resource type="Script" path="res://addons/block_code/ui/tooltip/tooltip.gd" id="1_4ko6a"] + +[node name="Tooltip" type="RichTextLabel"] +custom_minimum_size = Vector2(360, 48) +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +bbcode_enabled = true +fit_content = true +script = ExtResource("1_4ko6a") From db819ee14c690e68e7b078df94de207ed9c6fb8b Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Mon, 15 Jul 2024 14:23:24 +0100 Subject: [PATCH 052/423] Add a couple of rich-text tooltips --- .../block_code/ui/picker/categories/category_factory.gd | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index ba85a11e..90fa8f65 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -206,12 +206,21 @@ static func get_general_blocks() -> Array[Block]: b.block_formats = ["repeat {number: INT}"] b.statements = ["for i in {number}:"] b.category = "Loops" + b.tooltip_text = "Run the connected blocks [i]number[/i] times" block_list.append(b) b = BLOCKS["control_block"].instantiate() b.block_formats = ["while {condition: BOOL}"] b.statements = ["while {condition}:"] b.category = "Loops" + b.tooltip_text = ( + """ + Run the connected blocks as long as [i]condition[/i] is true. + + Hint: snap a [b]Comparison[/b] block into the condition. + """ + . dedent() + ) block_list.append(b) b = BLOCKS["statement_block"].instantiate() From edd1f65601826df11f3eee391a6cfd891f83737a Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Fri, 12 Jul 2024 06:39:01 -0600 Subject: [PATCH 053/423] InstructionTree: Make generation methods static These methods don't use any state, so there's no reason to allocate an InstructionTree object. This likely cleans some memory leaks as the allocated objects weren't being freed in NodeBlockCanvas. --- .../instruction_tree/instruction_tree.gd | 4 ++-- .../node_block_canvas/node_block_canvas.gd | 5 ++--- tests/test_instruction_tree.gd | 22 +++++-------------- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/addons/block_code/instruction_tree/instruction_tree.gd b/addons/block_code/instruction_tree/instruction_tree.gd index f8781100..1361eddc 100644 --- a/addons/block_code/instruction_tree/instruction_tree.gd +++ b/addons/block_code/instruction_tree/instruction_tree.gd @@ -42,13 +42,13 @@ class IDHandler: return unique_string -func generate_text(root_node: TreeNode, start_depth: int = 0) -> String: +static func generate_text(root_node: TreeNode, start_depth: int = 0) -> String: var out = PackedStringArray() generate_text_recursive(root_node, start_depth, out) return "".join(out) -func generate_text_recursive(node: TreeNode, depth: int, out: PackedStringArray): +static func generate_text_recursive(node: TreeNode, depth: int, out: PackedStringArray): if node.data != "": out.append("\t".repeat(depth) + node.data + "\n") diff --git a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd b/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd index aab18d5e..1ba72060 100644 --- a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd +++ b/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd @@ -36,7 +36,7 @@ func generate_script_from_current_window(bsd: BlockScriptData): script += _generate_script_from_entry_blocks(entry_statement, entry_blocks, init_func) if init_func.children: - script += InstructionTree.new().generate_text(init_func) + script += InstructionTree.generate_text(init_func) return script @@ -52,9 +52,8 @@ func _generate_script_from_entry_blocks(entry_statement: String, entry_blocks: A var next_block := entry_block.bottom_snap.get_snapped_block() if next_block != null: - var generator: InstructionTree = InstructionTree.new() var instruction_node: InstructionTree.TreeNode = next_block.get_instruction_node() - var to_append := generator.generate_text(instruction_node, 1) + var to_append := InstructionTree.generate_text(instruction_node, 1) script += to_append script += "\n" is_empty = false diff --git a/tests/test_instruction_tree.gd b/tests/test_instruction_tree.gd index d42ddcbc..acc819b2 100644 --- a/tests/test_instruction_tree.gd +++ b/tests/test_instruction_tree.gd @@ -1,22 +1,10 @@ extends GutTest ## Tests for InstructionTree -var tree: InstructionTree = null - - -func before_each(): - tree = InstructionTree.new() - - -func after_each(): - if tree != null: - tree.free() - tree = null - func test_single_node_text(): var node = InstructionTree.TreeNode.new("blah") - var text: String = tree.generate_text(node, 0) + var text: String = InstructionTree.generate_text(node, 0) assert_eq(text, "blah\n") @@ -24,7 +12,7 @@ func test_root_depth_text(): var node = InstructionTree.TreeNode.new("blah") var text: String for depth in range(5): - text = tree.generate_text(node, depth) + text = InstructionTree.generate_text(node, depth) assert_eq(text, "\t".repeat(depth) + "blah\n") @@ -34,7 +22,7 @@ func test_child_node_text(): var grandchild = InstructionTree.TreeNode.new("grandchild") parent.add_child(child) child.add_child(grandchild) - var text: String = tree.generate_text(parent, 0) + var text: String = InstructionTree.generate_text(parent, 0) assert_eq(text, "parent\n\tchild\n\t\tgrandchild\n") @@ -44,7 +32,7 @@ func test_sibling_node_text(): var sister = InstructionTree.TreeNode.new("sister") node.next = brother brother.next = sister - var text: String = tree.generate_text(node, 0) + var text: String = InstructionTree.generate_text(node, 0) assert_eq(text, "node\nbrother\nsister\n") @@ -63,5 +51,5 @@ func test_tree_node_text(): root.next = sibling sibling.add_child(nephew) - var text: String = tree.generate_text(root, 0) + var text: String = InstructionTree.generate_text(root, 0) assert_eq(text, "root\n\tchild1\n\t\tgrandchild\n\tchild2\nsibling\n\tnephew\n") From 433863297a7f424542180a39f20a7786f1e3926b Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Fri, 12 Jul 2024 12:52:56 -0600 Subject: [PATCH 054/423] Move script generation to InstructionTree Handling the script generation in the UI canvas code seems misplaced, and it depends on nothing in the UI except for the current canvas window. Move the generation to InstructionTree using an interface taking an array of Node. This will allow testing the code generation without using the block canvas. --- .../instruction_tree/instruction_tree.gd | 64 +++++++++++++++++++ .../node_block_canvas/node_block_canvas.gd | 64 +------------------ 2 files changed, 65 insertions(+), 63 deletions(-) diff --git a/addons/block_code/instruction_tree/instruction_tree.gd b/addons/block_code/instruction_tree/instruction_tree.gd index 1361eddc..703c7405 100644 --- a/addons/block_code/instruction_tree/instruction_tree.gd +++ b/addons/block_code/instruction_tree/instruction_tree.gd @@ -57,3 +57,67 @@ static func generate_text_recursive(node: TreeNode, depth: int, out: PackedStrin if node.next: generate_text_recursive(node.next, depth, out) + + +static func generate_script_from_nodes(nodes: Array[Node], bsd: BlockScriptData) -> String: + var entry_blocks_by_entry_statement: Dictionary = {} + + for block in nodes: + if !(block is Block): + continue + + if block is EntryBlock: + var entry_statement = block.get_entry_statement() + if not entry_blocks_by_entry_statement.has(entry_statement): + entry_blocks_by_entry_statement[entry_statement] = [] + entry_blocks_by_entry_statement[entry_statement].append(block) + + var script: String = "" + + script += "extends %s\n\n" % bsd.script_inherits + + for variable in bsd.variables: + script += "var %s: %s\n\n" % [variable.var_name, type_string(variable.var_type)] + + script += "\n" + + var init_func = TreeNode.new("func _init():") + + for entry_statement in entry_blocks_by_entry_statement: + var entry_blocks: Array[EntryBlock] + entry_blocks.assign(entry_blocks_by_entry_statement[entry_statement]) + script += _generate_script_from_entry_blocks(entry_statement, entry_blocks, init_func) + + if init_func.children: + script += generate_text(init_func) + + return script + + +static func _generate_script_from_entry_blocks(entry_statement: String, entry_blocks: Array[EntryBlock], init_func: TreeNode) -> String: + var script = entry_statement + "\n" + var signal_node: TreeNode + var is_empty = true + + InstructionTree.IDHandler.reset() + + for entry_block in entry_blocks: + var next_block := entry_block.bottom_snap.get_snapped_block() + + if next_block != null: + var instruction_node: TreeNode = next_block.get_instruction_node() + var to_append := generate_text(instruction_node, 1) + script += to_append + script += "\n" + is_empty = false + + if signal_node == null and entry_block.signal_name: + signal_node = TreeNode.new("{0}.connect(_on_{0})".format([entry_block.signal_name])) + + if signal_node: + init_func.add_child(signal_node) + + if is_empty: + script += "\tpass\n\n" + + return script diff --git a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd b/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd index 1ba72060..eddb2f9b 100644 --- a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd +++ b/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd @@ -5,66 +5,4 @@ extends BlockCanvas func generate_script_from_current_window(bsd: BlockScriptData): # TODO: implement multiple windows - var current_window := _window - - var entry_blocks_by_entry_statement: Dictionary = {} - - for block in current_window.get_children(): - if !(block is Block): - continue - - if block is EntryBlock: - var entry_statement = block.get_entry_statement() - if not entry_blocks_by_entry_statement.has(entry_statement): - entry_blocks_by_entry_statement[entry_statement] = [] - entry_blocks_by_entry_statement[entry_statement].append(block) - - var script: String = "" - - script += "extends %s\n\n" % bsd.script_inherits - - for variable in bsd.variables: - script += "var %s: %s\n\n" % [variable.var_name, type_string(variable.var_type)] - - script += "\n" - - var init_func = InstructionTree.TreeNode.new("func _init():") - - for entry_statement in entry_blocks_by_entry_statement: - var entry_blocks: Array[EntryBlock] - entry_blocks.assign(entry_blocks_by_entry_statement[entry_statement]) - script += _generate_script_from_entry_blocks(entry_statement, entry_blocks, init_func) - - if init_func.children: - script += InstructionTree.generate_text(init_func) - - return script - - -func _generate_script_from_entry_blocks(entry_statement: String, entry_blocks: Array[EntryBlock], init_func: InstructionTree.TreeNode) -> String: - var script = entry_statement + "\n" - var signal_node: InstructionTree.TreeNode - var is_empty = true - - InstructionTree.IDHandler.reset() - - for entry_block in entry_blocks: - var next_block := entry_block.bottom_snap.get_snapped_block() - - if next_block != null: - var instruction_node: InstructionTree.TreeNode = next_block.get_instruction_node() - var to_append := InstructionTree.generate_text(instruction_node, 1) - script += to_append - script += "\n" - is_empty = false - - if signal_node == null and entry_block.signal_name: - signal_node = InstructionTree.TreeNode.new("{0}.connect(_on_{0})".format([entry_block.signal_name])) - - if signal_node: - init_func.add_child(signal_node) - - if is_empty: - script += "\tpass\n\n" - - return script + return InstructionTree.generate_script_from_nodes(_window.get_children(), bsd) From 8b41b8d7edb278a2b5aead8a6ec29ea0d43795d9 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Fri, 12 Jul 2024 13:11:39 -0600 Subject: [PATCH 055/423] Remove NodeBlockCanvas NodeBlockCanvas extends BlockCanvas, but the only thing it was providing was the method to generate the script from the current window. Might as will just put that in BlockCanvas and drop the extension. --- addons/block_code/block_code_plugin.gd | 1 - .../ui/block_canvas/block_canvas.gd | 5 +++ .../ui/block_canvas/block_canvas.tscn | 4 +- .../node_block_canvas/node_block_canvas.gd | 8 ---- .../node_block_canvas/node_block_canvas.tscn | 7 ---- addons/block_code/ui/main_panel.gd | 8 ++-- addons/block_code/ui/main_panel.tscn | 40 +++++++++++++++---- docs/OVERVIEW.md | 18 ++++----- 8 files changed, 53 insertions(+), 38 deletions(-) delete mode 100644 addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd delete mode 100644 addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.tscn diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 2140879b..6a4e1380 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -24,7 +24,6 @@ const DISABLED_CLASSES := [ "StatementBlock", "DragDropArea", "SnapPoint", - "NodeBlockCanvas", "SerializedBlockTreeNodeArray", "SerializedBlockTreeNode", "SerializedBlock", diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 7e5737e8..11893f31 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -306,3 +306,8 @@ func set_mouse_override(override: bool): else: _mouse_override.mouse_filter = Control.MOUSE_FILTER_IGNORE _mouse_override.mouse_default_cursor_shape = Control.CURSOR_ARROW + + +func generate_script_from_current_window(bsd: BlockScriptData) -> String: + # TODO: implement multiple windows + return InstructionTree.generate_script_from_nodes(_window.get_children(), bsd) diff --git a/addons/block_code/ui/block_canvas/block_canvas.tscn b/addons/block_code/ui/block_canvas/block_canvas.tscn index 0513ee99..0f69316a 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.tscn +++ b/addons/block_code/ui/block_canvas/block_canvas.tscn @@ -3,7 +3,7 @@ [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/block_canvas.gd" id="1_tk8h2"] [ext_resource type="Texture2D" uid="uid://cmusxj1ppspnp" path="res://addons/block_code/block_code_node/block_code_node.svg" id="2_710vn"] -[sub_resource type="Image" id="Image_0aray"] +[sub_resource type="Image" id="Image_1nubg"] data = { "data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), "format": "RGBA8", @@ -13,7 +13,7 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_jgo72"] -image = SubResource("Image_0aray") +image = SubResource("Image_1nubg") [node name="BlockCanvas" type="MarginContainer"] anchors_preset = 15 diff --git a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd b/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd deleted file mode 100644 index eddb2f9b..00000000 --- a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd +++ /dev/null @@ -1,8 +0,0 @@ -@tool -class_name NodeBlockCanvas -extends BlockCanvas - - -func generate_script_from_current_window(bsd: BlockScriptData): - # TODO: implement multiple windows - return InstructionTree.generate_script_from_nodes(_window.get_children(), bsd) diff --git a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.tscn b/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.tscn deleted file mode 100644 index aca9efea..00000000 --- a/addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.tscn +++ /dev/null @@ -1,7 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://layefpj12yp2"] - -[ext_resource type="PackedScene" uid="uid://c6vumewgnfquy" path="res://addons/block_code/ui/block_canvas/block_canvas.tscn" id="1_dykhs"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd" id="2_qt35f"] - -[node name="NodeBlockCanvas" instance=ExtResource("1_dykhs")] -script = ExtResource("2_qt35f") diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index afc9ce61..fa7e9173 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -3,7 +3,7 @@ class_name MainPanel extends Control @onready var _picker: Picker = %Picker -@onready var _block_canvas: BlockCanvas = %NodeBlockCanvas +@onready var _block_canvas: BlockCanvas = %BlockCanvas @onready var _drag_manager: DragManager = %DragManager @onready var _title_bar: TitleBar = %TitleBar @onready var _delete_node_button: Button = %DeleteNodeButton @@ -192,7 +192,7 @@ func _on_collapse_button_pressed(): toggle_collapse() -func _on_node_block_canvas_add_block_code(): +func _on_block_canvas_add_block_code(): var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node var scene_root: Node = EditorInterface.get_edited_scene_root() @@ -214,7 +214,7 @@ func _on_node_block_canvas_add_block_code(): undo_redo.commit_action() -func _on_node_block_canvas_open_scene(): +func _on_block_canvas_open_scene(): var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node if edited_node == null or edited_node.owner == null: @@ -223,7 +223,7 @@ func _on_node_block_canvas_open_scene(): EditorInterface.open_scene_from_path(edited_node.scene_file_path) -func _on_node_block_canvas_replace_block_code(): +func _on_block_canvas_replace_block_code(): var edited_node: Node = EditorInterface.get_inspector().get_edited_object() as Node var scene_root: Node = EditorInterface.get_edited_scene_root() diff --git a/addons/block_code/ui/main_panel.tscn b/addons/block_code/ui/main_panel.tscn index 41bad753..c0554865 100644 --- a/addons/block_code/ui/main_panel.tscn +++ b/addons/block_code/ui/main_panel.tscn @@ -1,11 +1,35 @@ -[gd_scene load_steps=6 format=3 uid="uid://bq37yla8ya707"] +[gd_scene load_steps=10 format=3 uid="uid://bq37yla8ya707"] [ext_resource type="Script" path="res://addons/block_code/ui/main_panel.gd" id="1_u0xju"] [ext_resource type="PackedScene" uid="uid://dlabt3bgmpna2" path="res://addons/block_code/ui/picker/picker.tscn" id="2_hv5f3"] [ext_resource type="PackedScene" uid="uid://bm1183pm05p6a" path="res://addons/block_code/ui/title_bar/title_bar.tscn" id="2_k54yf"] -[ext_resource type="PackedScene" uid="uid://layefpj12yp2" path="res://addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.tscn" id="3_ml5y3"] +[ext_resource type="PackedScene" uid="uid://c6vumewgnfquy" path="res://addons/block_code/ui/block_canvas/block_canvas.tscn" id="4_cu87g"] [ext_resource type="PackedScene" uid="uid://cph1k5cfximbf" path="res://addons/block_code/drag_manager/drag_manager.tscn" id="4_yijtu"] +[sub_resource type="Image" id="Image_n7d73"] +data = { +"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 92, 92, 92, 64, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 92, 92, 92, 64, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 249, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 249, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 197, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 195, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 52, 90, 90, 90, 238, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 236, 92, 92, 92, 50, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 96, 96, 96, 24, 91, 91, 91, 101, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 91, 91, 91, 101, 100, 100, 100, 23, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), +"format": "RGBA8", +"height": 24, +"mipmaps": false, +"width": 24 +} + +[sub_resource type="ImageTexture" id="ImageTexture_mrr6q"] +image = SubResource("Image_n7d73") + +[sub_resource type="Image" id="Image_5ygfb"] +data = { +"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 92, 92, 92, 72, 91, 91, 91, 73, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 116, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 71, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 92, 92, 92, 75, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 201, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 119, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 247, 96, 96, 96, 40, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 91, 91, 91, 118, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 201, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 119, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 247, 96, 96, 96, 40, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 91, 91, 91, 118, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 201, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 91, 91, 91, 84, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 96, 96, 96, 40, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 91, 91, 91, 84, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 93, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 200, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 91, 91, 91, 118, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 119, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 248, 93, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 200, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 91, 91, 91, 118, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 119, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 248, 93, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 200, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 92, 92, 92, 75, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 116, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 71, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 71, 92, 92, 92, 72, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), +"format": "RGBA8", +"height": 24, +"mipmaps": false, +"width": 12 +} + +[sub_resource type="ImageTexture" id="ImageTexture_2e128"] +image = SubResource("Image_5ygfb") + [node name="MainPanel" type="MarginContainer"] anchors_preset = 15 anchor_right = 1.0 @@ -45,6 +69,7 @@ text = "Print Generated Script" unique_name_in_owner = true layout_mode = 2 tooltip_text = "Delete Block Code" +icon = SubResource("ImageTexture_mrr6q") [node name="MarginContainer" type="MarginContainer" parent="MarginContainer/HBoxContainer/ScriptVBox"] layout_mode = 2 @@ -67,7 +92,7 @@ theme_override_constants/margin_bottom = 4 [node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer"] layout_mode = 2 -[node name="NodeBlockCanvas" parent="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer" instance=ExtResource("3_ml5y3")] +[node name="BlockCanvas" parent="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer" instance=ExtResource("4_cu87g")] unique_name_in_owner = true layout_mode = 2 @@ -79,6 +104,7 @@ unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 8 tooltip_text = "Toggle Block Picker (Ctrl+BackSlash)" +icon = SubResource("ImageTexture_2e128") flat = true [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/BottomBar"] @@ -89,11 +115,11 @@ unique_name_in_owner = true layout_mode = 2 mouse_filter = 2 picker_path = NodePath("../PickerSplit/Picker") -block_canvas_path = NodePath("../PickerSplit/MarginContainer/VBoxContainer/NodeBlockCanvas") +block_canvas_path = NodePath("../PickerSplit/MarginContainer/VBoxContainer/BlockCanvas") [connection signal="pressed" from="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer/PrintScriptButton" to="." method="_on_print_script_button_pressed"] [connection signal="pressed" from="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer/DeleteNodeButton" to="." method="_on_delete_node_button_pressed"] -[connection signal="add_block_code" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/NodeBlockCanvas" to="." method="_on_node_block_canvas_add_block_code"] -[connection signal="open_scene" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/NodeBlockCanvas" to="." method="_on_node_block_canvas_open_scene"] -[connection signal="replace_block_code" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/NodeBlockCanvas" to="." method="_on_node_block_canvas_replace_block_code"] +[connection signal="add_block_code" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/BlockCanvas" to="." method="_on_block_canvas_add_block_code"] +[connection signal="open_scene" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/BlockCanvas" to="." method="_on_block_canvas_open_scene"] +[connection signal="replace_block_code" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/BlockCanvas" to="." method="_on_block_canvas_replace_block_code"] [connection signal="pressed" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/BottomBar/CollapseButton" to="." method="_on_collapse_button_pressed"] diff --git a/docs/OVERVIEW.md b/docs/OVERVIEW.md index e9d26852..38af939b 100644 --- a/docs/OVERVIEW.md +++ b/docs/OVERVIEW.md @@ -3,19 +3,19 @@ ## Data flow/Hierarchy 1. The plugin enters at `block_code_plugin.gd` (`BlockCodePlugin`) where the `MainPanel` is initialized and added as a main screen tab labeled "Block Code". - * The `MainPanel` contains a block `Picker`, a `NodeBlockCanvas`, a `TitleBar`, and a `DragManager`. + * The `MainPanel` contains a block `Picker`, a `BlockCanvas`, a `TitleBar`, and a `DragManager`. * The `Picker` contains a combined list of categories of blocks from the global blocks generated in `CategoryFactory`, and custom blocks defined in the class the script is attached to. - * The `NodeBlockCanvas` is where placed blocks live, and generates the code from the scene tree of blocks. + * The `BlockCanvas` is where placed blocks live, and generates the code from the scene tree of blocks. * The `TitleBar` displays some information about the block script. - * The `DragManager` determines how blocks are snapped, and what happens when you drag a block from either the `Picker` or the `NodeBlockCanvas` + * The `DragManager` determines how blocks are snapped, and what happens when you drag a block from either the `Picker` or the `BlockCanvas` -2. When a `BlockCode` node is selected, the `MainPanel` supplies the `Picker`, `NodeBlockCanvas`, and `TitleBar` with the `BlockScriptData` (BSD) attached to the `BlockCode` node you clicked. +2. When a `BlockCode` node is selected, the `MainPanel` supplies the `Picker`, `BlockCanvas`, and `TitleBar` with the `BlockScriptData` (BSD) attached to the `BlockCode` node you clicked. * The `Picker` will be loaded with blocks, and any custom blocks supplied by the parent of the `BlockCode` node you clicked. - * The `NodeBlockCanvas` will be populated with the block scene tree deserialized from the BSD (`BlockScriptData.block_trees`). + * The `BlockCanvas` will be populated with the block scene tree deserialized from the BSD (`BlockScriptData.block_trees`). * The `TitleBar` will be populated with the name of class the script inherits. * If the BSD is `null`, it will copy and load the default one. -3. When you click and drag a block from the `Picker`, the `DragManager` is signaled to copy the block and enables you to drag it to the `NodeBlockCanvas`. +3. When you click and drag a block from the `Picker`, the `DragManager` is signaled to copy the block and enables you to drag it to the `BlockCanvas`. 4. The `DragManager` looks for the closest compatible snap point within a certain range, and if it exists, will show a preview where your `Block` will go if you drop it. * Each `Block` has a `block_type` property, and so does each snap point. They must match to snap. @@ -25,7 +25,7 @@ 5. When the block script is modified, it will regenerate the BSD, and save it as an exported property of the `BlockCode` node you are working on. This way it gets saved to the scene. * The block script is modified when a block is moved, or a `ParameterInput`'s raw input has been changed. - * Code is generated whenever you modify the block in `NodeBlockCanvas`. + * Code is generated whenever you modify the block in `BlockCanvas`. 6. When you play the scene, each `BlockCode` node will attach a generated script from it's BSD to it's parent node. The `_ready` and `_process` methods will start normally. @@ -78,7 +78,7 @@ b.block_format = "On Process [delta: FLOAT]" * `/block_script_data/`: Contains the custom resource that persists each block script. Each resource saves the class it inherits from, the generated script, and the tree of `Block`s to load. * `/drag_manager/`: Should be in the `ui` folder, let's fix that. Handles dragging blocks across the canvas and picker. * `/inspector_plugin/`: An inspector plugin that adds a button to the inspector on `BlockCode` nodes to open the script. - * `/instruction_tree/`: A utility script that generates code from a tree of `TreeNode`s. This tree is created by `NodeBlockCanvas` and also recursively by the `Block`s themselves. + * `/instruction_tree/`: A utility script that generates code from a tree of `TreeNode`s. This tree is created by `BlockCanvas` and also recursively by the `Block`s themselves. * `/lib/`: Some scripts from GodotTours that label and expose some of the editor Control nodes so they can be interfaced with. * `/simple_nodes/`: Contains scenes for simple nodes that can be used in a simple game. E.g. `SimpleCharacter` comes with a sprite and collision, and exposes custom movement blocks. * `/types/`: Contains all things related to types in the addon. Types of blocks, casting, and variant to string type conversion. @@ -96,7 +96,7 @@ b.block_format = "On Process [delta: FLOAT]" * `/drag_drop_area/`: A simple node that signals on mouse down and up * `/parameter_input/`: An input for nodes to receive data from raw text, or from a snapped `ParameterBlock`. * `/snap_point/`: Node that the `DragManager` looks for when trying to snap new blocks. - * `/block_canvas/`: Contains the code for the `BlockCanvas` which loads and holds blocks on a canvas. Inherited by `NodeBlockCanvas` which can generate scripts for block scripts made for Godot `Node`s (which is all of the scripts ATM). Also contains resources for serializing blocks. + * `/block_canvas/`: Contains the code for the `BlockCanvas` which loads and holds blocks on a canvas. This can generate scripts for block scripts made for Godot `Node`s (which is all of the scripts ATM). Also contains resources for serializing blocks. * `/bsd_templates/`: Template block script data files for loading a default script. E.g. `_ready` and `_process` entry blocks already on canvas. * `/node_canvas/`: Deprecated * `/node_list/`: Deprecated From 6a11ebe7a1ee66ebdbbfda4eec21c37c179ab079 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Mon, 15 Jul 2024 10:01:14 -0600 Subject: [PATCH 056/423] Block: Handle bottom_snap property directly Godot knows how to serialize a reference to a node directly, so there's no need to store a path and restore the node manually. This is clearer, but it also means that bottom_snap can be used without waiting for it the Block to be ready. --- addons/block_code/ui/blocks/block/block.gd | 5 +---- addons/block_code/ui/blocks/control_block/control_block.tscn | 4 ++-- .../ui/blocks/statement_block/statement_block.tscn | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index c4c44e40..907e7077 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -21,16 +21,13 @@ signal modified @export var category: String ## The next block in the line of execution (can be null if end) -@export var bottom_snap_path: NodePath +@export var bottom_snap: SnapPoint ## The scope of the block (statement of matching entry block) @export var scope: String = "" -var bottom_snap: SnapPoint - func _ready(): - bottom_snap = get_node_or_null(bottom_snap_path) mouse_filter = Control.MOUSE_FILTER_IGNORE diff --git a/addons/block_code/ui/blocks/control_block/control_block.tscn b/addons/block_code/ui/blocks/control_block/control_block.tscn index 81790457..ee2675c0 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.tscn +++ b/addons/block_code/ui/blocks/control_block/control_block.tscn @@ -3,14 +3,14 @@ [ext_resource type="Script" path="res://addons/block_code/ui/blocks/control_block/control_block.gd" id="1_2hbir"] [ext_resource type="PackedScene" uid="uid://b1oge52xhjqnu" path="res://addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn" id="3_nhryi"] -[node name="ControlBlock" type="MarginContainer"] +[node name="ControlBlock" type="MarginContainer" node_paths=PackedStringArray("bottom_snap")] size_flags_horizontal = 0 mouse_filter = 2 script = ExtResource("1_2hbir") block_name = "control_block" label = "Control Block" color = Color(0.59979, 0.536348, 0.876215, 1) -bottom_snap_path = NodePath("VBoxContainer/SnapPoint") +bottom_snap = NodePath("VBoxContainer/SnapPoint") [node name="VBoxContainer" type="VBoxContainer" parent="."] layout_mode = 2 diff --git a/addons/block_code/ui/blocks/statement_block/statement_block.tscn b/addons/block_code/ui/blocks/statement_block/statement_block.tscn index 96ed6e48..5da5ac5a 100644 --- a/addons/block_code/ui/blocks/statement_block/statement_block.tscn +++ b/addons/block_code/ui/blocks/statement_block/statement_block.tscn @@ -5,13 +5,13 @@ [ext_resource type="PackedScene" uid="uid://c7puyxpqcq6xo" path="res://addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.tscn" id="2_owgdx"] [ext_resource type="PackedScene" uid="uid://b1oge52xhjqnu" path="res://addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn" id="3_5vaov"] -[node name="StatementBlock" type="MarginContainer"] +[node name="StatementBlock" type="MarginContainer" node_paths=PackedStringArray("bottom_snap")] size_flags_horizontal = 0 mouse_filter = 2 script = ExtResource("1_6wvlf") block_name = "statement_block" label = "StatementBlock" -bottom_snap_path = NodePath("VBoxContainer/SnapPoint") +bottom_snap = NodePath("VBoxContainer/SnapPoint") [node name="VBoxContainer" type="VBoxContainer" parent="."] layout_mode = 2 From eca64acd23dcce92f4d3e7e46884a599cc97df4a Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Mon, 15 Jul 2024 10:41:02 -0600 Subject: [PATCH 057/423] Remove unused NodeCanvas, NodeList and friends These have been unused since 9a3e010b4e4bab0c6a2c8f6bcbef2dd6382ad7db. They can be recovered from the history if needed again in the future. --- addons/block_code/block_code_plugin.gd | 6 -- .../block_code/ui/node_canvas/node_canvas.gd | 13 ---- .../ui/node_canvas/node_canvas.tscn | 9 --- .../node_list/node_class_list/all_nodes.tres | 16 ---- .../node_class_list/node_class/node_class.gd | 12 --- .../node_class_list/node_class_list.gd | 8 -- .../ui/node_list/node_data/node_data.gd | 45 ----------- .../ui/node_list/node_data/node_data.tscn | 56 -------------- addons/block_code/ui/node_list/node_list.gd | 75 ------------------- addons/block_code/ui/node_list/node_list.tscn | 55 -------------- .../ui/node_list/node_preview/node_preview.gd | 20 ----- .../node_list/node_preview/node_preview.tscn | 31 -------- docs/OVERVIEW.md | 2 - 13 files changed, 348 deletions(-) delete mode 100644 addons/block_code/ui/node_canvas/node_canvas.gd delete mode 100644 addons/block_code/ui/node_canvas/node_canvas.tscn delete mode 100644 addons/block_code/ui/node_list/node_class_list/all_nodes.tres delete mode 100644 addons/block_code/ui/node_list/node_class_list/node_class/node_class.gd delete mode 100644 addons/block_code/ui/node_list/node_class_list/node_class_list.gd delete mode 100644 addons/block_code/ui/node_list/node_data/node_data.gd delete mode 100644 addons/block_code/ui/node_list/node_data/node_data.tscn delete mode 100644 addons/block_code/ui/node_list/node_list.gd delete mode 100644 addons/block_code/ui/node_list/node_list.tscn delete mode 100644 addons/block_code/ui/node_list/node_preview/node_preview.gd delete mode 100644 addons/block_code/ui/node_list/node_preview/node_preview.tscn diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 6a4e1380..b45a84f4 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -30,12 +30,6 @@ const DISABLED_CLASSES := [ "PackedSceneTreeNodeArray", "PackedSceneTreeNode", "BlockCanvas", - "NodeCanvas", - "NodeClass", - "NodeClassList", - "NodeData", - "NodePreview", - "NodeList", "CategoryFactory", "BlockCategoryDisplay", "BlockCategory", diff --git a/addons/block_code/ui/node_canvas/node_canvas.gd b/addons/block_code/ui/node_canvas/node_canvas.gd deleted file mode 100644 index 5a48debe..00000000 --- a/addons/block_code/ui/node_canvas/node_canvas.gd +++ /dev/null @@ -1,13 +0,0 @@ -@tool -class_name NodeCanvas -extends MarginContainer - - -# Called when the node enters the scene tree for the first time. -func _ready(): - pass # Replace with function body. - - -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta): - pass diff --git a/addons/block_code/ui/node_canvas/node_canvas.tscn b/addons/block_code/ui/node_canvas/node_canvas.tscn deleted file mode 100644 index e4104579..00000000 --- a/addons/block_code/ui/node_canvas/node_canvas.tscn +++ /dev/null @@ -1,9 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://fu6r626trsix"] - -[ext_resource type="Script" path="res://addons/block_code/ui/node_canvas/node_canvas.gd" id="1_0iab1"] - -[node name="NodeCanvas" type="MarginContainer"] -script = ExtResource("1_0iab1") - -[node name="Panel" type="Panel" parent="."] -layout_mode = 2 diff --git a/addons/block_code/ui/node_list/node_class_list/all_nodes.tres b/addons/block_code/ui/node_list/node_class_list/all_nodes.tres deleted file mode 100644 index a941a822..00000000 --- a/addons/block_code/ui/node_list/node_class_list/all_nodes.tres +++ /dev/null @@ -1,16 +0,0 @@ -[gd_resource type="Resource" script_class="NodeClassList" load_steps=6 format=3 uid="uid://n32n5afl1m2o"] - -[ext_resource type="PackedScene" uid="uid://ddx1cd5q6t61o" path="res://addons/block_code/simple_nodes/simple_character/simple_character.tscn" id="1_auvp7"] -[ext_resource type="Script" path="res://addons/block_code/ui/node_list/node_class_list/node_class_list.gd" id="1_rrqs6"] -[ext_resource type="Texture2D" uid="uid://dr8e0tvfxjy1f" path="res://icon.svg" id="1_w5d0e"] -[ext_resource type="Script" path="res://addons/block_code/ui/node_list/node_class_list/node_class/node_class.gd" id="3_nor5m"] - -[sub_resource type="Resource" id="Resource_viq8c"] -script = ExtResource("3_nor5m") -node_class_name = "SimpleCharacter" -scene_ref = ExtResource("1_auvp7") -preview_icon = ExtResource("1_w5d0e") - -[resource] -script = ExtResource("1_rrqs6") -node_class_list = Array[ExtResource("3_nor5m")]([SubResource("Resource_viq8c"), SubResource("Resource_viq8c")]) diff --git a/addons/block_code/ui/node_list/node_class_list/node_class/node_class.gd b/addons/block_code/ui/node_list/node_class_list/node_class/node_class.gd deleted file mode 100644 index a140748f..00000000 --- a/addons/block_code/ui/node_list/node_class_list/node_class/node_class.gd +++ /dev/null @@ -1,12 +0,0 @@ -class_name NodeClass -extends Resource - -@export var node_class_name: String -@export var scene_ref: PackedScene -@export var preview_icon: Texture2D - - -func _init(p_node_class_name: String = "", p_scene_ref: PackedScene = null, p_preview_icon: Texture2D = null): - node_class_name = p_node_class_name - scene_ref = p_scene_ref - preview_icon = p_preview_icon diff --git a/addons/block_code/ui/node_list/node_class_list/node_class_list.gd b/addons/block_code/ui/node_list/node_class_list/node_class_list.gd deleted file mode 100644 index d673ecda..00000000 --- a/addons/block_code/ui/node_list/node_class_list/node_class_list.gd +++ /dev/null @@ -1,8 +0,0 @@ -class_name NodeClassList -extends Resource - -@export var node_class_list: Array[NodeClass] - - -func _init(p_node_class_list: Array[NodeClass] = []): - node_class_list = p_node_class_list diff --git a/addons/block_code/ui/node_list/node_data/node_data.gd b/addons/block_code/ui/node_list/node_data/node_data.gd deleted file mode 100644 index 25b527bc..00000000 --- a/addons/block_code/ui/node_list/node_data/node_data.gd +++ /dev/null @@ -1,45 +0,0 @@ -@tool -class_name NodeData -extends MarginContainer - -signal selected(me: NodeData) - -var node_name: String = "": - set = set_node_name - -var node_class_name: String = "" -var icon: Texture2D - -var node_selected: bool: - set = _set_node_selected - -@onready var _label = %Label -@onready var _icon = %Icon - - -func _ready(): - _icon.texture = icon - set_node_name(node_name) - _set_node_selected(false) - - -func _set_node_selected(_node_selected): - node_selected = _node_selected - $Outline.visible = _node_selected - - -func set_node_name(new_node_name: String): - node_name = new_node_name - - if is_node_ready(): - _label.text = node_name - - -func deselect(): - _set_node_selected(false) - - -func _on_select_pressed(): - get_tree().call_group("node_data", "deselect") - _set_node_selected(true) - selected.emit(self) diff --git a/addons/block_code/ui/node_list/node_data/node_data.tscn b/addons/block_code/ui/node_list/node_data/node_data.tscn deleted file mode 100644 index fa75196b..00000000 --- a/addons/block_code/ui/node_list/node_data/node_data.tscn +++ /dev/null @@ -1,56 +0,0 @@ -[gd_scene load_steps=5 format=3 uid="uid://cf6dqqs064xmh"] - -[ext_resource type="Script" path="res://addons/block_code/ui/node_list/node_data/node_data.gd" id="1_c1em0"] - -[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_1tm21"] - -[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_wyo85"] - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uhfnf"] -bg_color = Color(1, 1, 1, 0) -border_width_left = 2 -border_width_top = 2 -border_width_right = 2 -border_width_bottom = 2 -border_color = Color(0.144379, 0.67633, 0.825651, 1) -corner_radius_top_left = 2 -corner_radius_top_right = 2 -corner_radius_bottom_right = 2 -corner_radius_bottom_left = 2 - -[node name="NodeData" type="MarginContainer" groups=["node_data"]] -script = ExtResource("1_c1em0") - -[node name="VBoxContainer" type="VBoxContainer" parent="."] -layout_mode = 2 -size_flags_horizontal = 4 -size_flags_vertical = 4 - -[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer"] -custom_minimum_size = Vector2(100, 100) -layout_mode = 2 - -[node name="Icon" type="TextureRect" parent="VBoxContainer/CenterContainer"] -unique_name_in_owner = true -custom_minimum_size = Vector2(100, 100) -layout_mode = 2 -expand_mode = 1 -stretch_mode = 5 - -[node name="Label" type="Label" parent="VBoxContainer"] -unique_name_in_owner = true -layout_mode = 2 -horizontal_alignment = 1 - -[node name="Select" type="Button" parent="."] -layout_mode = 2 -theme_override_styles/normal = SubResource("StyleBoxEmpty_1tm21") -theme_override_styles/focus = SubResource("StyleBoxEmpty_wyo85") - -[node name="Outline" type="Panel" parent="."] -visible = false -layout_mode = 2 -mouse_filter = 2 -theme_override_styles/panel = SubResource("StyleBoxFlat_uhfnf") - -[connection signal="pressed" from="Select" to="." method="_on_select_pressed"] diff --git a/addons/block_code/ui/node_list/node_list.gd b/addons/block_code/ui/node_list/node_list.gd deleted file mode 100644 index 2d957264..00000000 --- a/addons/block_code/ui/node_list/node_list.gd +++ /dev/null @@ -1,75 +0,0 @@ -@tool -class_name NodeList -extends MarginContainer - -signal node_selected(node_data: NodeData) - -const NODE_CLASS_LIST: NodeClassList = preload("res://addons/block_code/ui/node_list/node_class_list/all_nodes.tres") - -var selected_node: NodeData = null - -@onready var _nodes := %Nodes -@onready var _node_class_list := %NodeClassList - - -func _ready(): - $Overlay.visible = false - - for node_class in NODE_CLASS_LIST.node_class_list: - var node_preview: NodePreview = preload("res://addons/block_code/ui/node_list/node_preview/node_preview.tscn").instantiate() - node_preview.label = node_class.node_class_name - node_preview.icon = node_class.preview_icon - node_preview.clicked.connect(func(): create_node(node_class)) - _node_class_list.add_child(node_preview) - - -func _on_create_node_pressed(): - $Overlay.visible = true - - -func create_node(node_class: NodeClass): - var node_data: NodeData = preload("res://addons/block_code/ui/node_list/node_data/node_data.tscn").instantiate() - - # Check for duplicate name - var node_name := "New node" - var new_node_name := node_name - var count = 1 - var unique := false - while !unique: - unique = true - - var nodes := get_nodes() - for node in nodes: - if node.node_name == new_node_name: - new_node_name = node_name + (" (%d)" % count) - count += 1 - unique = false - break - - node_data.node_name = new_node_name - node_data.node_class_name = node_class.node_class_name - node_data.icon = node_class.preview_icon - node_data.selected.connect(_node_selected) - %Nodes.add_child(node_data) - - $Overlay.visible = false - - -func _node_selected(node_data: NodeData): - selected_node = node_data - node_selected.emit(node_data) - - -func on_node_name_changed(new_node_name: String): - if selected_node: - selected_node.set_node_name(new_node_name) - - -func get_nodes() -> Array[NodeData]: - var children := %Nodes.get_children() - var nodes: Array[NodeData] = [] - for c in children: - if c is NodeData: - nodes.append(c) - - return nodes diff --git a/addons/block_code/ui/node_list/node_list.tscn b/addons/block_code/ui/node_list/node_list.tscn deleted file mode 100644 index e75b475c..00000000 --- a/addons/block_code/ui/node_list/node_list.tscn +++ /dev/null @@ -1,55 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://dctdq5611t3yl"] - -[ext_resource type="Script" path="res://addons/block_code/ui/node_list/node_list.gd" id="1_dchyw"] - -[node name="NodeList" type="MarginContainer"] -offset_right = 400.0 -offset_bottom = 300.0 -script = ExtResource("1_dchyw") - -[node name="Panel" type="Panel" parent="."] -layout_mode = 2 - -[node name="HBoxContainer" type="HBoxContainer" parent="."] -layout_mode = 2 - -[node name="Nodes" type="GridContainer" parent="HBoxContainer"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_horizontal = 3 -columns = 4 - -[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer"] -custom_minimum_size = Vector2(100, 0) -layout_mode = 2 - -[node name="CreateNode" type="Button" parent="HBoxContainer/VBoxContainer"] -layout_mode = 2 -text = "Create Node" - -[node name="Overlay" type="MarginContainer" parent="."] -visible = false -layout_mode = 2 - -[node name="Panel" type="Panel" parent="Overlay"] -layout_mode = 2 - -[node name="MarginContainer" type="MarginContainer" parent="Overlay"] -layout_mode = 2 -theme_override_constants/margin_left = 100 -theme_override_constants/margin_top = 100 -theme_override_constants/margin_right = 100 -theme_override_constants/margin_bottom = 100 - -[node name="VBoxContainer" type="VBoxContainer" parent="Overlay/MarginContainer"] -layout_mode = 2 - -[node name="Label" type="Label" parent="Overlay/MarginContainer/VBoxContainer"] -layout_mode = 2 -text = "Choose a node to create:" - -[node name="NodeClassList" type="VBoxContainer" parent="Overlay/MarginContainer/VBoxContainer"] -unique_name_in_owner = true -layout_mode = 2 - -[connection signal="pressed" from="HBoxContainer/VBoxContainer/CreateNode" to="." method="_on_create_node_pressed"] diff --git a/addons/block_code/ui/node_list/node_preview/node_preview.gd b/addons/block_code/ui/node_list/node_preview/node_preview.gd deleted file mode 100644 index a48c068e..00000000 --- a/addons/block_code/ui/node_list/node_preview/node_preview.gd +++ /dev/null @@ -1,20 +0,0 @@ -@tool -class_name NodePreview -extends MarginContainer - -signal clicked - -var label: String = "" -var icon: Texture2D - -@onready var _label = %Label -@onready var _icon = %Icon - - -func _ready(): - _label.text = label - _icon.texture = icon - - -func _on_button_pressed(): - clicked.emit() diff --git a/addons/block_code/ui/node_list/node_preview/node_preview.tscn b/addons/block_code/ui/node_list/node_preview/node_preview.tscn deleted file mode 100644 index 5404a98e..00000000 --- a/addons/block_code/ui/node_list/node_preview/node_preview.tscn +++ /dev/null @@ -1,31 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://5wi1lr7413kx"] - -[ext_resource type="Script" path="res://addons/block_code/ui/node_list/node_preview/node_preview.gd" id="1_50x03"] - -[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_1s3f0"] - -[node name="NodePreview" type="MarginContainer"] -anchors_preset = 10 -anchor_right = 1.0 -offset_bottom = 40.0 -grow_horizontal = 2 -script = ExtResource("1_50x03") - -[node name="HBoxContainer" type="HBoxContainer" parent="."] -layout_mode = 2 - -[node name="Icon" type="TextureRect" parent="HBoxContainer"] -unique_name_in_owner = true -layout_mode = 2 -expand_mode = 3 -stretch_mode = 4 - -[node name="Label" type="Label" parent="HBoxContainer"] -unique_name_in_owner = true -layout_mode = 2 - -[node name="Button" type="Button" parent="."] -layout_mode = 2 -theme_override_styles/normal = SubResource("StyleBoxEmpty_1s3f0") - -[connection signal="pressed" from="Button" to="." method="_on_button_pressed"] diff --git a/docs/OVERVIEW.md b/docs/OVERVIEW.md index 38af939b..67a6b074 100644 --- a/docs/OVERVIEW.md +++ b/docs/OVERVIEW.md @@ -98,8 +98,6 @@ b.block_format = "On Process [delta: FLOAT]" * `/snap_point/`: Node that the `DragManager` looks for when trying to snap new blocks. * `/block_canvas/`: Contains the code for the `BlockCanvas` which loads and holds blocks on a canvas. This can generate scripts for block scripts made for Godot `Node`s (which is all of the scripts ATM). Also contains resources for serializing blocks. * `/bsd_templates/`: Template block script data files for loading a default script. E.g. `_ready` and `_process` entry blocks already on canvas. - * `/node_canvas/`: Deprecated - * `/node_list/`: Deprecated * `/picker/`: Contains the picker scene, and code that generates the blocks that populate the picker. * `/categories/`: Contains `CategoryFactory` which generates the global block list programmatically from template blocks. * `/title_bar/`: Contains the title bar which should display the name of the current script and the node it inherits from. From 29692126057d556ccde28f5818114547a735f27b Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Sat, 13 Jul 2024 10:27:35 -0600 Subject: [PATCH 058/423] Set unique names for all blocks The block_name property isn't really used for anything, so the value isn't really critical. However, for debugging it's helpful if they're unique. Unique names also allow building a dictionary of the available blocks, which is useful when building a block script in code for testing. --- .../simple_character/simple_character.gd | 1 + .../simple_scoring/simple_scoring.gd | 2 + .../ui/picker/categories/category_factory.gd | 49 +++++++++++++++++++ tests/test_category_factory.gd | 9 ++++ 4 files changed, 61 insertions(+) diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index 8d19179b..7af653dc 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -104,6 +104,7 @@ static func get_custom_blocks() -> Array[Block]: # Movement b = CategoryFactory.BLOCKS["statement_block"].instantiate() + b.block_name = "simplecharacter_move" b.block_type = Types.BlockType.EXECUTE b.block_format = "Move with {player: OPTION} buttons as {kind: OPTION}" # TODO: delta here is assumed to be the parameter name of diff --git a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd index 552e2ce7..88c9a62b 100644 --- a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd +++ b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd @@ -56,6 +56,7 @@ static func get_custom_blocks() -> Array[Block]: for player in _POSITIONS_FOR_PLAYER: b = CategoryFactory.BLOCKS["statement_block"].instantiate() + b.block_name = "simplescoring_set_score" b.block_type = Types.BlockType.EXECUTE b.block_format = "Set player %s score to {score: INT}" % player b.statement = "score_%s = {score}" % _POSITIONS_FOR_PLAYER[player] @@ -63,6 +64,7 @@ static func get_custom_blocks() -> Array[Block]: block_list.append(b) b = CategoryFactory.BLOCKS["statement_block"].instantiate() + b.block_name = "simplescoring_change_score" b.block_type = Types.BlockType.EXECUTE b.block_format = "Change player %s score by {score: INT}" % player b.statement = "score_%s += {score}" % _POSITIONS_FOR_PLAYER[player] diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index bb617365..b492b954 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -193,6 +193,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "queue_free" b.block_format = "Queue Free" b.statement = "queue_free()" b.tooltip_text = "Queues this node to be deleted at the end of the current frame" @@ -203,6 +204,7 @@ static func get_general_blocks() -> Array[Block]: #region Loops b = BLOCKS["control_block"].instantiate() + b.block_name = "for_loop" b.block_formats = ["repeat {number: INT}"] b.statements = ["for __i in {number}:"] b.category = "Loops" @@ -210,6 +212,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["control_block"].instantiate() + b.block_name = "while_loop" b.block_formats = ["while {condition: BOOL}"] b.statements = ["while {condition}:"] b.category = "Loops" @@ -224,6 +227,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "await_scene_ready" b.block_format = "Await scene ready" b.statement = ( """ @@ -236,12 +240,14 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "break" b.block_format = "Break" b.statement = "break" b.category = "Loops" block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "continue" b.block_format = "Continue" b.statement = "continue" b.category = "Loops" @@ -251,6 +257,7 @@ static func get_general_blocks() -> Array[Block]: #region Logs b = BLOCKS["statement_block"].instantiate() + b.block_name = "print" b.block_format = "print {text: STRING}" b.statement = "print({text})" b.defaults = {"text": "Hello"} @@ -262,6 +269,7 @@ static func get_general_blocks() -> Array[Block]: #region Communication b = BLOCKS["entry_block"].instantiate() + b.block_name = "define_method" # HACK: make signals work with new entry nodes. NIL instead of STRING type allows # plain text input for function name. Should revamp signals later b.block_format = "Define method {method_name: NIL}" @@ -271,6 +279,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "call_group_method" b.block_format = "Call method {method_name: STRING} in group {group: STRING}" b.statement = "get_tree().call_group({group}, {method_name})" b.category = "Communication | Methods" @@ -278,6 +287,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "call_node_method" b.block_format = "Call method {method_name: STRING} in node {node_path: NODE_PATH}" b.statement = ( """ @@ -292,6 +302,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "add_to_group" b.block_format = "Add to group {group: STRING}" b.statement = "add_to_group({group})" b.category = "Communication | Groups" @@ -299,6 +310,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "add_node_to_group" b.block_format = "Add {node: NODE_PATH} to group {group: STRING}" b.statement = "get_node({node}).add_to_group({group})" b.category = "Communication | Groups" @@ -306,6 +318,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "remove_from_group" b.block_format = "Remove from group {group: STRING}" b.statement = "remove_from_group({group})" b.tooltip_text = "Remove this node from the group" @@ -313,6 +326,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "remove_node_from_group" b.block_format = "Remove {node: NODE_PATH} from group {group: STRING}" b.statement = "get_node({node}).remove_from_group({group})" b.tooltip_text = "Remove the node from the group" @@ -320,6 +334,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["parameter_block"].instantiate() + b.block_name = "is_in_group" b.variant_type = TYPE_BOOL b.block_format = "Is in group {group: STRING}" b.statement = "is_in_group({group})" @@ -328,6 +343,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["parameter_block"].instantiate() + b.block_name = "is_node_in_group" b.variant_type = TYPE_BOOL b.block_format = "Is {node: NODE_PATH} in group {group: STRING}" b.statement = "get_node({node}).is_in_group({group})" @@ -337,7 +353,9 @@ static func get_general_blocks() -> Array[Block]: #endregion #region Variables + b = BLOCKS["parameter_block"].instantiate() + b.block_name = "vector2" b.variant_type = TYPE_VECTOR2 b.block_format = "Vector2 x: {x: FLOAT} y: {y: FLOAT}" b.statement = "Vector2({x}, {y})" @@ -348,6 +366,7 @@ static func get_general_blocks() -> Array[Block]: #region Math b = BLOCKS["parameter_block"].instantiate() + b.block_name = "add_int" b.variant_type = TYPE_INT b.block_format = "{a: INT} + {b: INT}" b.statement = "({a} + {b})" @@ -355,6 +374,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["parameter_block"].instantiate() + b.block_name = "subtract_int" b.variant_type = TYPE_INT b.block_format = "{a: INT} - {b: INT}" b.statement = "({a} - {b})" @@ -362,6 +382,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["parameter_block"].instantiate() + b.block_name = "multiply_int" b.variant_type = TYPE_INT b.block_format = "{a: INT} * {b: INT}" b.statement = "({a} * {b})" @@ -369,6 +390,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["parameter_block"].instantiate() + b.block_name = "divide_int" b.variant_type = TYPE_INT b.block_format = "{a: INT} / {b: INT}" b.statement = "({a} / {b})" @@ -376,6 +398,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["parameter_block"].instantiate() + b.block_name = "pow_int" b.variant_type = TYPE_INT b.block_format = "{base: INT} ^ {exp: INT}" b.statement = "(pow({base}, {exp}))" @@ -386,18 +409,21 @@ static func get_general_blocks() -> Array[Block]: #region Logic b = BLOCKS["control_block"].instantiate() + b.block_name = "if" b.block_formats = ["if {condition: BOOL}"] b.statements = ["if {condition}:"] b.category = "Logic | Conditionals" block_list.append(b) b = BLOCKS["control_block"].instantiate() + b.block_name = "if_else" b.block_formats = ["if {condition: BOOL}", "else"] b.statements = ["if {condition}:", "else:"] b.category = "Logic | Conditionals" block_list.append(b) b = BLOCKS["parameter_block"].instantiate() + b.block_name = "compare_int" b.variant_type = TYPE_BOOL b.block_format = "{int1: INT} {op: OPTION} {int2: INT}" b.statement = "({int1} {op} {int2})" @@ -407,6 +433,7 @@ static func get_general_blocks() -> Array[Block]: for op in ["and", "or"]: b = BLOCKS["parameter_block"].instantiate() + b.block_name = op b.variant_type = TYPE_BOOL b.block_format = "{bool1: BOOL} %s {bool2: BOOL}" % op b.statement = "({bool1} %s {bool2})" % op @@ -414,6 +441,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["parameter_block"].instantiate() + b.block_name = "not" b.variant_type = TYPE_BOOL b.block_format = "Not {bool: BOOL}" b.statement = "(not {bool})" @@ -428,6 +456,7 @@ static func get_general_blocks() -> Array[Block]: #endregion #region Sounds b = BLOCKS["statement_block"].instantiate() + b.block_name = "load_sound" b.block_type = Types.BlockType.EXECUTE b.block_format = "Load file {file_path: STRING} as sound {name: STRING}" b.statement = ( @@ -444,6 +473,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "play_sound" b.block_type = Types.BlockType.EXECUTE b.block_format = "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}" b.statement = ( @@ -463,6 +493,7 @@ static func get_general_blocks() -> Array[Block]: #region Graphics b = BLOCKS["parameter_block"].instantiate() + b.block_name = "viewport_width" b.variant_type = TYPE_FLOAT b.block_format = "Viewport Width" b.statement = "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin.x / scale.x + get_viewport_rect().size.x / scale.x).call()" @@ -470,6 +501,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["parameter_block"].instantiate() + b.block_name = "viewport_height" b.variant_type = TYPE_FLOAT b.block_format = "Viewport Height" b.statement = "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin.y / scale.y + get_viewport_rect().size.y / scale.y).call()" @@ -477,6 +509,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) b = BLOCKS["parameter_block"].instantiate() + b.block_name = "viewport_center" b.variant_type = TYPE_VECTOR2 b.block_format = "Viewport Center" b.statement = "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()" @@ -497,18 +530,21 @@ static func property_to_blocklist(property: Dictionary) -> Array[Block]: var type_string: String = Types.VARIANT_TYPE_TO_STRING[variant_type] var b = BLOCKS["statement_block"].instantiate() + b.block_name = "set_prop_%s" % property.name b.block_format = "Set %s to {value: %s}" % [property.name.capitalize(), type_string] b.statement = "%s = {value}" % property.name b.category = property.category block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "change_prop_%s" % property.name b.block_format = "Change %s by {value: %s}" % [property.name.capitalize(), type_string] b.statement = "%s += {value}" % property.name b.category = property.category block_list.append(b) b = BLOCKS["parameter_block"].instantiate() + b.block_name = "get_prop_%s" % property.name b.variant_type = variant_type b.block_format = "%s" % property.name.capitalize() b.statement = "%s" % property.name @@ -555,6 +591,7 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: match _class_name: "Node2D": var b = BLOCKS["statement_block"].instantiate() + b.block_name = "node2d_rotation" b.block_format = "Set Rotation Degrees {angle: FLOAT}" b.statement = "rotation_degrees = {angle}" b.category = "Transform | Rotation" @@ -575,6 +612,7 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: "RigidBody2D": for verb in ["entered", "exited"]: var b = BLOCKS["entry_block"].instantiate() + b.block_name = "rigidbody2d_on_%s" % verb b.block_format = "On [body: NODE_PATH] %s" % [verb] # HACK: Blocks refer to nodes by path but the callback receives the node itself; # convert to path @@ -593,6 +631,7 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: block_list.append(b) var b = BLOCKS["statement_block"].instantiate() + b.block_name = "rigidbody2d_physics_position" b.block_format = "Set Physics Position {position: VECTOR2}" b.statement = ( """ @@ -615,6 +654,7 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: "AnimationPlayer": var b = BLOCKS["statement_block"].instantiate() + b.block_name = "animationplayer_play" b.block_format = "Play {animation: STRING} {direction: OPTION}" b.statement = ( """ @@ -633,6 +673,7 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "animationplayer_pause" b.block_format = "Pause" b.statement = "pause()" b.tooltip_text = "Pause the currently playing animation." @@ -640,6 +681,7 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "animationplayer_stop" b.block_format = "Stop" b.statement = "stop()" b.tooltip_text = "Stop the currently playing animation." @@ -647,6 +689,7 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: block_list.append(b) b = BLOCKS["parameter_block"].instantiate() + b.block_name = "animationplayer_is_playing" b.variant_type = TYPE_BOOL b.block_format = "Is playing" b.statement = "is_playing()" @@ -657,6 +700,7 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: "Area2D": for verb in ["entered", "exited"]: var b = BLOCKS["entry_block"].instantiate() + b.block_name = "area2d_on_%s" % verb b.block_format = "On [body: NODE_PATH] %s" % [verb] # HACK: Blocks refer to nodes by path but the callback receives the node itself; # convert to path @@ -676,6 +720,7 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: "CharacterBody2D": var b = BLOCKS["statement_block"].instantiate() + b.block_name = "characterbody2d_move" b.block_type = Types.BlockType.EXECUTE b.block_format = "Move with keys {up: STRING} {down: STRING} {left: STRING} {right: STRING} with speed {speed: VECTOR2}" b.statement = ( @@ -698,6 +743,7 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "characterbody2d_move_and_slide" b.block_type = Types.BlockType.EXECUTE b.block_format = "Move and slide" b.statement = "move_and_slide()" @@ -730,6 +776,7 @@ static func _get_input_blocks() -> Array[Block]: InputMap.load_from_project_settings() var block: Block = BLOCKS["parameter_block"].instantiate() + block.block_name = "is_action" block.variant_type = TYPE_BOOL block.block_format = "Is action {action_name: OPTION} {action: OPTION}" block.statement = 'Input.is_action_{action}("{action_name}")' @@ -753,6 +800,7 @@ static func get_variable_blocks(variables: Array[VariableResource]): var type_string: String = Types.VARIANT_TYPE_TO_STRING[variable.var_type] var b = BLOCKS["parameter_block"].instantiate() + b.block_name = "get_var_%s" % variable.var_name b.variant_type = variable.var_type b.block_format = variable.var_name b.statement = variable.var_name @@ -761,6 +809,7 @@ static func get_variable_blocks(variables: Array[VariableResource]): block_list.append(b) b = BLOCKS["statement_block"].instantiate() + b.block_name = "set_var_%s" % variable.var_name b.block_type = Types.BlockType.EXECUTE b.block_format = "Set %s to {value: %s}" % [variable.var_name, type_string] b.statement = "%s = {value}" % [variable.var_name] diff --git a/tests/test_category_factory.gd b/tests/test_category_factory.gd index 63b29930..42896a24 100644 --- a/tests/test_category_factory.gd +++ b/tests/test_category_factory.gd @@ -57,3 +57,12 @@ const class_category_names = [ func test_inherited_category_names(params = use_parameters(class_category_names)): assert_eq(get_class_category_names(params[0]), params[1]) + + +func test_unique_block_names(): + var blocks: Array[Block] = CategoryFactory.get_general_blocks() + var block_names: Dictionary + for block in blocks: + assert_does_not_have(block_names, block.block_name, "Block name %s is duplicated" % block.block_name) + block_names[block.block_name] = block + free_block_list(blocks) From 6ff5dbd361ef86fabcb373d387fbafc7dc59e537 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Fri, 12 Jul 2024 17:25:21 -0600 Subject: [PATCH 059/423] InstructionTree: Add tests for serializing scripts from Blocks This gets a little further to verifying how we get from Blocks to actual scripts. Parameter substitution isn't currently tested as that seems difficult to manage without the UI. --- tests/test_instruction_tree.gd | 163 +++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/tests/test_instruction_tree.gd b/tests/test_instruction_tree.gd index acc819b2..c38db13f 100644 --- a/tests/test_instruction_tree.gd +++ b/tests/test_instruction_tree.gd @@ -1,6 +1,34 @@ extends GutTest ## Tests for InstructionTree +var general_blocks: Dictionary + + +func build_block_map(block_map: Dictionary, blocks: Array[Block]): + assert_eq(block_map, {}) + for block in blocks: + assert_does_not_have(block_map, block.block_name, "Block name %s is duplicated" % block.block_name) + block_map[block.block_name] = block + + +func free_block_map(block_map: Dictionary): + for block in block_map.values(): + block.free() + block_map.clear() + assert_eq(block_map, {}) + + +func dup_node(node: Node) -> Node: + return node.duplicate(DUPLICATE_USE_INSTANTIATION) + + +func before_each(): + build_block_map(general_blocks, CategoryFactory.get_general_blocks()) + + +func after_each(): + free_block_map(general_blocks) + func test_single_node_text(): var node = InstructionTree.TreeNode.new("blah") @@ -53,3 +81,138 @@ func test_tree_node_text(): var text: String = InstructionTree.generate_text(root, 0) assert_eq(text, "root\n\tchild1\n\t\tgrandchild\n\tchild2\nsibling\n\tnephew\n") + + +func test_script_no_nodes(): + var bsd := BlockScriptData.new("Foo") + var script := InstructionTree.generate_script_from_nodes([], bsd) + assert_eq( + script, + ( + """\ + extends Foo + + + """ + . dedent() + ) + ) + + +func test_script_no_entry_blocks(): + var bsd := BlockScriptData.new("Foo") + var nodes: Array[Node] = [Node.new(), Node2D.new(), Control.new()] + var script := InstructionTree.generate_script_from_nodes(nodes, bsd) + assert_eq( + script, + ( + """\ + extends Foo + + + """ + . dedent() + ) + ) + for node in nodes: + node.free() + + +func test_basic_script(): + var ready_block: Block = dup_node(general_blocks["ready_block"]) + + var print_block: Block = dup_node(general_blocks["print"]) + # XXX: It seems like this should substitute {text} in the statement, + # but it doesn't. I can't make sense of StatementBlock. + # print_block.param_input_strings = {"text": "this is a test"} + # print_block._ready() + + # XXX: Why does insert_snapped_block add_child but not set snapped_block? + ready_block.bottom_snap.insert_snapped_block(print_block) + ready_block.bottom_snap.snapped_block = print_block + assert_true(ready_block.bottom_snap.has_snapped_block()) + assert_eq(ready_block.bottom_snap.get_snapped_block(), print_block) + + var bsd := BlockScriptData.new("Node2D") + var script := InstructionTree.generate_script_from_nodes([ready_block], bsd) + assert_eq( + script, + ( + """\ + extends Node2D + + + func _ready(): + print({text}) + + """ + . dedent() + ) + ) + + ready_block.free() + + +func test_multiple_entry_script(): + var ready_block: Block = dup_node(general_blocks["ready_block"]) + var print_block: Block = dup_node(general_blocks["print"]) + ready_block.bottom_snap.insert_snapped_block(print_block) + ready_block.bottom_snap.snapped_block = print_block + + var ready_block_2: Block = dup_node(ready_block) + + var bsd := BlockScriptData.new("Node2D") + var script := InstructionTree.generate_script_from_nodes([ready_block, ready_block_2], bsd) + assert_eq( + script, + ( + """\ + extends Node2D + + + func _ready(): + print({text}) + + print({text}) + + """ + . dedent() + ) + ) + + ready_block.free() + ready_block_2.free() + + +func test_signal_script(): + var area2d_blocks: Dictionary + build_block_map(area2d_blocks, CategoryFactory.get_inherited_blocks("Area2D")) + var entered_block: Block = dup_node(area2d_blocks["area2d_on_entered"]) + var print_block: Block = dup_node(general_blocks["print"]) + entered_block.bottom_snap.insert_snapped_block(print_block) + entered_block.bottom_snap.snapped_block = print_block + + var bsd := BlockScriptData.new("Area2D") + var script = InstructionTree.generate_script_from_nodes([entered_block], bsd) + assert_eq( + script, + ( + """\ + extends Area2D + + + + func _on_body_entered(_body: Node2D): + var body: NodePath = _body.get_path() + + print({text}) + + func _init(): + body_entered.connect(_on_body_entered) + """ + . dedent() + ) + ) + + entered_block.free() + free_block_map(area2d_blocks) From 4b25f21936c0c38294e987aa6a099865249dd1e9 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Tue, 16 Jul 2024 10:56:34 -0600 Subject: [PATCH 060/423] Pong: Fix scoring This appears to have been broken in 031b29e. In GoalAreaLeft, the checked group was changed from balls to walls. In GoalAreaRight, the checked group was changed from balls to the empty string. --- .../examples/pong_game/pong_game.tscn | 132 +++++++++--------- 1 file changed, 65 insertions(+), 67 deletions(-) diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index 02c6f96e..48fdc70d 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -441,7 +441,7 @@ func _init(): " version = 0 -[sub_resource type="Resource" id="Resource_tasas"] +[sub_resource type="Resource" id="Resource_foxq8"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -449,12 +449,12 @@ func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_pjafw"] +[sub_resource type="Resource" id="Resource_501iu"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_tasas") +serialized_block = SubResource("Resource_foxq8") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_he201"] +[sub_resource type="Resource" id="Resource_lc2mv"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -462,25 +462,25 @@ func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_ctark"] +[sub_resource type="Resource" id="Resource_usdsx"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_he201") +serialized_block = SubResource("Resource_lc2mv") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_gxxn8"] +[sub_resource type="Resource" id="Resource_yudev"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { -"group": "walls", +"group": "balls", "node": "" }]] -[sub_resource type="Resource" id="Resource_4t5fq"] +[sub_resource type="Resource" id="Resource_j8nlm"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_gxxn8") -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_ctark")]] +serialized_block = SubResource("Resource_yudev") +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_usdsx")]] -[sub_resource type="Resource" id="Resource_jyto7"] +[sub_resource type="Resource" id="Resource_rd5bb"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { @@ -488,12 +488,12 @@ serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock "method_name": "reset" }]] -[sub_resource type="Resource" id="Resource_ab5of"] +[sub_resource type="Resource" id="Resource_6j2n2"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_jyto7") +serialized_block = SubResource("Resource_rd5bb") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_j1imx"] +[sub_resource type="Resource" id="Resource_y52j6"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { @@ -501,24 +501,24 @@ serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock "method_name": "goal_left" }]] -[sub_resource type="Resource" id="Resource_8ipag"] +[sub_resource type="Resource" id="Resource_j6rsb"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_j1imx") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ab5of")]] +serialized_block = SubResource("Resource_y52j6") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_6j2n2")]] -[sub_resource type="Resource" id="Resource_288n2"] +[sub_resource type="Resource" id="Resource_oeuh1"] script = ExtResource("5_wr38c") block_class = &"ControlBlock" serialized_props = [["block_name", "control_block"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ "condition": false }]]] -[sub_resource type="Resource" id="Resource_glvow"] +[sub_resource type="Resource" id="Resource_jyu6m"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_288n2") -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_4t5fq")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_8ipag")]] +serialized_block = SubResource("Resource_oeuh1") +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_j8nlm")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_j6rsb")]] -[sub_resource type="Resource" id="Resource_0plda"] +[sub_resource type="Resource" id="Resource_v1q5h"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" serialized_props = [["block_name", "entry_block"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(98, 352)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " @@ -526,29 +526,28 @@ func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["defaults", {}], ["param_input_strings", {}], ["signal_name", "body_entered"]] -[sub_resource type="Resource" id="Resource_jwpt1"] +[sub_resource type="Resource" id="Resource_vj0qt"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_0plda") -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_pjafw")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_glvow")]] +serialized_block = SubResource("Resource_v1q5h") +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_501iu")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_jyu6m")]] -[sub_resource type="Resource" id="Resource_7qerp"] +[sub_resource type="Resource" id="Resource_6sikv"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_jwpt1")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_vj0qt")]) [sub_resource type="Resource" id="Resource_bx5ai"] script = ExtResource("7_uuuue") script_inherits = "Area2D" -block_trees = SubResource("Resource_7qerp") +block_trees = SubResource("Resource_6sikv") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends Area2D -var VAR_DICT := {} func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() - if get_node(body).is_in_group('walls'): + if get_node(body).is_in_group('balls'): get_tree().call_group('scoring', 'goal_left') get_tree().call_group('balls', 'reset') @@ -557,7 +556,7 @@ func _init(): " version = 0 -[sub_resource type="Resource" id="Resource_doveu"] +[sub_resource type="Resource" id="Resource_g8bbs"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -565,12 +564,12 @@ func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_xyxrn"] +[sub_resource type="Resource" id="Resource_by53e"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_doveu") +serialized_block = SubResource("Resource_g8bbs") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_cbo5a"] +[sub_resource type="Resource" id="Resource_ia057"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -578,63 +577,63 @@ func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_6fo05"] +[sub_resource type="Resource" id="Resource_214im"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_cbo5a") +serialized_block = SubResource("Resource_ia057") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_cwxay"] +[sub_resource type="Resource" id="Resource_mitgp"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { -"group": "", +"group": "balls", "node": "" }]] -[sub_resource type="Resource" id="Resource_hn47f"] +[sub_resource type="Resource" id="Resource_4c6cp"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_cwxay") -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_6fo05")]] +serialized_block = SubResource("Resource_mitgp") +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_214im")]] -[sub_resource type="Resource" id="Resource_2rjk3"] +[sub_resource type="Resource" id="Resource_kbjk3"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { -"group": "scoring", -"method_name": "goal_right" +"group": "balls", +"method_name": "reset" }]] -[sub_resource type="Resource" id="Resource_b6ghp"] +[sub_resource type="Resource" id="Resource_svw0g"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_2rjk3") +serialized_block = SubResource("Resource_kbjk3") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_hfvs8"] +[sub_resource type="Resource" id="Resource_ehxpt"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { -"group": "balls", -"method_name": "reset" +"group": "scoring", +"method_name": "goal_right" }]] -[sub_resource type="Resource" id="Resource_x60gt"] +[sub_resource type="Resource" id="Resource_8f3xk"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_hfvs8") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_b6ghp")]] +serialized_block = SubResource("Resource_ehxpt") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_svw0g")]] -[sub_resource type="Resource" id="Resource_6o2pm"] +[sub_resource type="Resource" id="Resource_cyk7y"] script = ExtResource("5_wr38c") block_class = &"ControlBlock" serialized_props = [["block_name", "control_block"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ "condition": false }]]] -[sub_resource type="Resource" id="Resource_y0f1u"] +[sub_resource type="Resource" id="Resource_gfghu"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_6o2pm") -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_hn47f")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_x60gt")]] +serialized_block = SubResource("Resource_cyk7y") +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_4c6cp")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_8f3xk")]] -[sub_resource type="Resource" id="Resource_pjlcp"] +[sub_resource type="Resource" id="Resource_ncxb3"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" serialized_props = [["block_name", "entry_block"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(195, 56)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " @@ -642,31 +641,30 @@ func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["defaults", {}], ["param_input_strings", {}], ["signal_name", "body_entered"]] -[sub_resource type="Resource" id="Resource_uj1xx"] +[sub_resource type="Resource" id="Resource_1nmq4"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_pjlcp") -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_xyxrn")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_y0f1u")]] +serialized_block = SubResource("Resource_ncxb3") +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_by53e")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_gfghu")]] -[sub_resource type="Resource" id="Resource_xphhp"] +[sub_resource type="Resource" id="Resource_d14wa"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_uj1xx")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_1nmq4")]) [sub_resource type="Resource" id="Resource_6drva"] script = ExtResource("7_uuuue") script_inherits = "Area2D" -block_trees = SubResource("Resource_xphhp") +block_trees = SubResource("Resource_d14wa") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends Area2D -var VAR_DICT := {} func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() - if get_node(body).is_in_group(''): - get_tree().call_group('balls', 'reset') + if get_node(body).is_in_group('balls'): get_tree().call_group('scoring', 'goal_right') + get_tree().call_group('balls', 'reset') func _init(): body_entered.connect(_on_body_entered) From 9146bd1b3668391ff6bcb2afac9068656c153afb Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Tue, 16 Jul 2024 16:19:33 +0100 Subject: [PATCH 061/423] Polyfill Node.is_part_of_edited_scene() Godot 4.3+ exposes `Node.is_part_of_edited_scene()` to GDScript, which is analogous to `Engine.is_editor_hint()` but determines whether the `@tool` script's node is itself being edited, as opposed to instantiated elsewhere in the editor. Reimplement this function in GDScript. https://phabricator.endlessm.com/T35540 Move node_is_part_of_edited_scene to new Util module This will allow it to be reused in other scenes which have the same problem as tooltip did. --- addons/block_code/ui/util.gd | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 addons/block_code/ui/util.gd diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd new file mode 100644 index 00000000..d4b80bd4 --- /dev/null +++ b/addons/block_code/ui/util.gd @@ -0,0 +1,6 @@ +extends Object + + +## Polyfill of Node.is_part_of_edited_scene(), available to GDScript in Godot 4.3+. +static func node_is_part_of_edited_scene(node: Node) -> bool: + return Engine.is_editor_hint() && node.is_inside_tree() && node.get_tree().edited_scene_root && node.get_tree().edited_scene_root.get_parent().is_ancestor_of(node) From d248c347e8269b9285a6f9f3a81bde7482c04785 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Tue, 16 Jul 2024 16:19:33 +0100 Subject: [PATCH 062/423] tooltip: Don't save style overrides to tooltip.tscn Previously, if you opened tooltip.tscn in the editor and hit Save, its `_ready()` method would persist the style overrides we use to apply the editor theme's fonts to the label. This isn't necessary, or desirable. Don't apply the style overrides if the tooltip scene itself is being edited. https://phabricator.endlessm.com/T35540 --- addons/block_code/ui/tooltip/tooltip.gd | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/addons/block_code/ui/tooltip/tooltip.gd b/addons/block_code/ui/tooltip/tooltip.gd index a0e44f26..5f165021 100644 --- a/addons/block_code/ui/tooltip/tooltip.gd +++ b/addons/block_code/ui/tooltip/tooltip.gd @@ -3,6 +3,8 @@ class_name Tooltip extends RichTextLabel ## Rich-text control for block tooltips that matches the built-in inspector's tooltips' font styles +const Util = preload("res://addons/block_code/ui/util.gd") + func override_font(font_name: StringName, editor_font_name: StringName) -> Font: var font = get_theme_font(editor_font_name, &"EditorFonts") @@ -10,7 +12,7 @@ func override_font(font_name: StringName, editor_font_name: StringName) -> Font: return font -func _ready(): +func override_fonts(): # Set fonts to match documentation tooltips in inspector override_font(&"normal_font", &"doc") override_font(&"mono_font", &"doc_source") @@ -22,3 +24,8 @@ func _ready(): bold_italics.set_base_font(italics) bold_italics.set_variation_embolden(1.2) add_theme_font_override(&"bold_italics_font", bold_italics) + + +func _ready(): + if not Util.node_is_part_of_edited_scene(self): + override_fonts() From 1b6d64b4f6d532139e29acb0d1cf9c4824ac9ced Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Tue, 16 Jul 2024 17:04:13 +0100 Subject: [PATCH 063/423] Don't recreate resources when editing plugin scenes Previously, opening and saving parameter_block.tscn (for example) in the editor would cause its StyleBoxFlat resource to be replaced by an identical sub_resource with a new unique identifier. This is because its _ready() function runs when the scene is being edited, and previously would unconditionally re-set the stylebox. This either causes needless diff churn, or requires extra work by the developer to discard that hunk. In each case, guard the change with `node_is_part_of_edited_scene`, and remove it from the saved scene. --- addons/block_code/ui/block_canvas/block_canvas.gd | 4 +++- .../block_code/ui/block_canvas/block_canvas.tscn | 15 +-------------- .../ui/blocks/parameter_block/parameter_block.gd | 11 +++++++---- .../blocks/parameter_block/parameter_block.tscn | 14 +------------- .../ui/picker/categories/block_category_button.gd | 10 ++++++---- .../picker/categories/block_category_button.tscn | 10 +--------- 6 files changed, 19 insertions(+), 45 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 11893f31..67d84557 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -2,6 +2,8 @@ class_name BlockCanvas extends MarginContainer +const Util = preload("res://addons/block_code/ui/util.gd") + const EXTEND_MARGIN: float = 800 const BLOCK_AUTO_PLACE_MARGIN: Vector2 = Vector2(25, 8) const DEFAULT_WINDOW_MARGIN: Vector2 = Vector2(25, 25) @@ -45,7 +47,7 @@ signal replace_block_code func _ready(): - if not _open_scene_button.icon: + if not _open_scene_button.icon and not Util.node_is_part_of_edited_scene(self): _open_scene_button.icon = _open_scene_icon _populate_block_scenes_by_class() diff --git a/addons/block_code/ui/block_canvas/block_canvas.tscn b/addons/block_code/ui/block_canvas/block_canvas.tscn index 0f69316a..21b27681 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.tscn +++ b/addons/block_code/ui/block_canvas/block_canvas.tscn @@ -1,20 +1,8 @@ -[gd_scene load_steps=5 format=3 uid="uid://c6vumewgnfquy"] +[gd_scene load_steps=3 format=3 uid="uid://c6vumewgnfquy"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/block_canvas.gd" id="1_tk8h2"] [ext_resource type="Texture2D" uid="uid://cmusxj1ppspnp" path="res://addons/block_code/block_code_node/block_code_node.svg" id="2_710vn"] -[sub_resource type="Image" id="Image_1nubg"] -data = { -"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), -"format": "RGBA8", -"height": 16, -"mipmaps": false, -"width": 16 -} - -[sub_resource type="ImageTexture" id="ImageTexture_jgo72"] -image = SubResource("Image_1nubg") - [node name="BlockCanvas" type="MarginContainer"] anchors_preset = 15 anchor_right = 1.0 @@ -142,7 +130,6 @@ layout_mode = 2 size_flags_horizontal = 4 theme_type_variation = &"InspectorActionButton" text = "Open in Editor" -icon = SubResource("ImageTexture_jgo72") [node name="ReplaceBlockCodeButton" type="Button" parent="SelectedNodeWithBlockCodeBox/ButtonsBox"] unique_name_in_owner = true diff --git a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd index 95a2b7b4..75b11b4a 100644 --- a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd +++ b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd @@ -2,6 +2,8 @@ class_name ParameterBlock extends Block +const Util = preload("res://addons/block_code/ui/util.gd") + @export var block_format: String = "" @export var statement: String = "" @export var variant_type: Variant.Type @@ -19,10 +21,11 @@ func _ready(): super() block_type = Types.BlockType.VALUE - var new_panel = _panel.get_theme_stylebox("panel").duplicate() - new_panel.bg_color = color - new_panel.border_color = color.darkened(0.2) - _panel.add_theme_stylebox_override("panel", new_panel) + if not Util.node_is_part_of_edited_scene(self): + var new_panel = _panel.get_theme_stylebox("panel").duplicate() + new_panel.bg_color = color + new_panel.border_color = color.darkened(0.2) + _panel.add_theme_stylebox_override("panel", new_panel) format() diff --git a/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn b/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn index 46cc8b65..fec7b57c 100644 --- a/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn +++ b/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn @@ -1,19 +1,8 @@ -[gd_scene load_steps=4 format=3 uid="uid://clipm2dd28jde"] +[gd_scene load_steps=3 format=3 uid="uid://clipm2dd28jde"] [ext_resource type="Script" path="res://addons/block_code/ui/blocks/parameter_block/parameter_block.gd" id="1_0hajy"] [ext_resource type="PackedScene" uid="uid://c7puyxpqcq6xo" path="res://addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.tscn" id="2_gy5co"] -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dbera"] -bg_color = Color(1, 1, 1, 1) -border_width_left = 3 -border_width_top = 3 -border_width_right = 3 -border_width_bottom = 3 -corner_radius_top_left = 16 -corner_radius_top_right = 16 -corner_radius_bottom_right = 16 -corner_radius_bottom_left = 16 - [node name="ParameterBlock" type="MarginContainer"] offset_right = 16.0 offset_bottom = 8.0 @@ -27,7 +16,6 @@ block_type = 3 [node name="Panel" type="Panel" parent="."] unique_name_in_owner = true layout_mode = 2 -theme_override_styles/panel = SubResource("StyleBoxFlat_dbera") [node name="DragDropArea" parent="." instance=ExtResource("2_gy5co")] layout_mode = 2 diff --git a/addons/block_code/ui/picker/categories/block_category_button.gd b/addons/block_code/ui/picker/categories/block_category_button.gd index 8fe8ad79..401873aa 100644 --- a/addons/block_code/ui/picker/categories/block_category_button.gd +++ b/addons/block_code/ui/picker/categories/block_category_button.gd @@ -2,6 +2,8 @@ class_name BlockCategoryButton extends MarginContainer +const Util = preload("res://addons/block_code/ui/util.gd") + signal selected var category: BlockCategory @@ -14,10 +16,10 @@ func _ready(): if not category: category = BlockCategory.new("Example", Color.RED) - var new_stylebox: StyleBoxFlat = _panel.get_theme_stylebox("panel").duplicate() - new_stylebox.bg_color = category.color - - _panel.add_theme_stylebox_override("panel", new_stylebox) + if not Util.node_is_part_of_edited_scene(self): + var new_stylebox: StyleBoxFlat = _panel.get_theme_stylebox("panel").duplicate() + new_stylebox.bg_color = category.color + _panel.add_theme_stylebox_override("panel", new_stylebox) _label.text = category.name diff --git a/addons/block_code/ui/picker/categories/block_category_button.tscn b/addons/block_code/ui/picker/categories/block_category_button.tscn index 33210926..f28962c3 100644 --- a/addons/block_code/ui/picker/categories/block_category_button.tscn +++ b/addons/block_code/ui/picker/categories/block_category_button.tscn @@ -1,14 +1,7 @@ -[gd_scene load_steps=7 format=3 uid="uid://bdtetj0gs45hv"] +[gd_scene load_steps=6 format=3 uid="uid://bdtetj0gs45hv"] [ext_resource type="Script" path="res://addons/block_code/ui/picker/categories/block_category_button.gd" id="1_pxxnl"] -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_eogpc"] -bg_color = Color(1, 0, 0, 1) -corner_radius_top_left = 100 -corner_radius_top_right = 100 -corner_radius_bottom_right = 100 -corner_radius_bottom_left = 100 - [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ousiv"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fyk0j"] @@ -39,7 +32,6 @@ theme_override_constants/margin_bottom = 8 [node name="Panel" type="Panel" parent="HBoxContainer/MarginContainer"] unique_name_in_owner = true layout_mode = 2 -theme_override_styles/panel = SubResource("StyleBoxFlat_eogpc") [node name="Label" type="Label" parent="HBoxContainer"] unique_name_in_owner = true From 6d017d0fb467e50a02d3a5b944d2f2b44b80d58b Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 16 Jul 2024 18:48:11 -0700 Subject: [PATCH 064/423] Change Simple node scripts to instantiate themselves To support users adding SimpleCharacter and SimpleScoring as nodes, instead of as child scenes, add an _init function for each which loads the appropriate scene file and instantiates it. https://phabricator.endlessm.com/T35545 --- .../simple_character/_simple_character.gd | 8 ++++++++ .../{simple_character.tscn => _simple_character.tscn} | 10 +++++----- .../simple_nodes/simple_character/simple_character.gd | 10 ++++++++++ .../simple_nodes/simple_scoring/_simple_scoring.gd | 8 ++++++++ .../{simple_scoring.tscn => _simple_scoring.tscn} | 4 ++-- .../simple_nodes/simple_scoring/simple_scoring.gd | 11 +++++++++++ 6 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 addons/block_code/simple_nodes/simple_character/_simple_character.gd rename addons/block_code/simple_nodes/simple_character/{simple_character.tscn => _simple_character.tscn} (56%) create mode 100644 addons/block_code/simple_nodes/simple_scoring/_simple_scoring.gd rename addons/block_code/simple_nodes/simple_scoring/{simple_scoring.tscn => _simple_scoring.tscn} (90%) diff --git a/addons/block_code/simple_nodes/simple_character/_simple_character.gd b/addons/block_code/simple_nodes/simple_character/_simple_character.gd new file mode 100644 index 00000000..b5438769 --- /dev/null +++ b/addons/block_code/simple_nodes/simple_character/_simple_character.gd @@ -0,0 +1,8 @@ +@tool +extends SimpleCharacter + + +func _init(): + # Disable the SimpleCharacter _init function. We expect this script is + # already bound to _simple_character.tscn. + pass diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.tscn b/addons/block_code/simple_nodes/simple_character/_simple_character.tscn similarity index 56% rename from addons/block_code/simple_nodes/simple_character/simple_character.tscn rename to addons/block_code/simple_nodes/simple_character/_simple_character.tscn index 692a2cff..03e429c2 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.tscn +++ b/addons/block_code/simple_nodes/simple_character/_simple_character.tscn @@ -1,14 +1,14 @@ [gd_scene load_steps=3 format=3 uid="uid://ddx1cd5q6t61o"] -[ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_character/simple_character.gd" id="1_oqwef"] +[ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_character/_simple_character.gd" id="1_idjqv"] -[sub_resource type="RectangleShape2D" id="RectangleShape2D_104qs"] -size = Vector2(16, 16) +[sub_resource type="RectangleShape2D" id="RectangleShape2D_ffh0f"] +size = Vector2(100, 100) [node name="SimpleCharacter" type="CharacterBody2D"] -script = ExtResource("1_oqwef") +script = ExtResource("1_idjqv") [node name="Sprite2D" type="Sprite2D" parent="."] [node name="CollisionShape2D" type="CollisionShape2D" parent="."] -shape = SubResource("RectangleShape2D_104qs") +shape = SubResource("RectangleShape2D_ffh0f") diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index 7af653dc..08471be2 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -52,6 +52,16 @@ func on_gravity_changed(new_gravity): gravity = new_gravity +func _init(): + if self.get_parent(): + return + + var node = preload("res://addons/block_code/simple_nodes/simple_character/_simple_character.tscn").instantiate() as Node + node.replace_by(self, true) + node.queue_free() + scene_file_path = "" + + func _ready(): add_to_group("affected_by_gravity") simple_setup() diff --git a/addons/block_code/simple_nodes/simple_scoring/_simple_scoring.gd b/addons/block_code/simple_nodes/simple_scoring/_simple_scoring.gd new file mode 100644 index 00000000..6c1476fa --- /dev/null +++ b/addons/block_code/simple_nodes/simple_scoring/_simple_scoring.gd @@ -0,0 +1,8 @@ +@tool +extends SimpleScoring + + +func _init(): + # Disable the SimpleScoring _init function. We expect this script is + # already bound to _simple_scoring.tscn. + pass diff --git a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.tscn b/addons/block_code/simple_nodes/simple_scoring/_simple_scoring.tscn similarity index 90% rename from addons/block_code/simple_nodes/simple_scoring/simple_scoring.tscn rename to addons/block_code/simple_nodes/simple_scoring/_simple_scoring.tscn index de623127..4d17dc83 100644 --- a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.tscn +++ b/addons/block_code/simple_nodes/simple_scoring/_simple_scoring.tscn @@ -1,9 +1,9 @@ [gd_scene load_steps=2 format=3 uid="uid://bis7afjjuwypq"] -[ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd" id="1_yyb01"] +[ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_scoring/_simple_scoring.gd" id="1_lc5bg"] [node name="SimpleScoring" type="CanvasLayer" groups=["hud"]] -script = ExtResource("1_yyb01") +script = ExtResource("1_lc5bg") [node name="PlayerLeftScore" type="Label" parent="."] unique_name_in_owner = true diff --git a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd index 88c9a62b..3d96007a 100644 --- a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd +++ b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd @@ -19,6 +19,17 @@ const _POSITIONS_FOR_PLAYER = { } +func _init(): + if self.get_parent(): + return + + var node = preload("res://addons/block_code/simple_nodes/simple_scoring/_simple_scoring.tscn").instantiate() as Node + node.replace_by(self, true) + node.queue_free() + print_tree_pretty() + scene_file_path = "" + + func get_custom_class(): return "SimpleScoring" From 5893a5a62e825bbf6ddd0e2e85717575e4abe6c6 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 16 Jul 2024 19:06:54 -0700 Subject: [PATCH 065/423] Replace scenes with named classes in pong_game.tscn https://phabricator.endlessm.com/T35545 --- addons/block_code/examples/pong_game/pong_game.tscn | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index 48fdc70d..71f77d15 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -2,15 +2,15 @@ [ext_resource type="PackedScene" uid="uid://cg8ibi18um3vg" path="res://addons/block_code/examples/pong_game/space.tscn" id="1_y56ac"] [ext_resource type="Script" path="res://addons/block_code/block_code_node/block_code.gd" id="3_6jaq8"] -[ext_resource type="PackedScene" uid="uid://ddx1cd5q6t61o" path="res://addons/block_code/simple_nodes/simple_character/simple_character.tscn" id="3_hjpbs"] +[ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_character/simple_character.gd" id="3_mdrcv"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node.gd" id="4_qtggh"] [ext_resource type="Texture2D" uid="uid://tplpgtnfeda0" path="res://addons/block_code/examples/pong_game/assets/paddle.png" id="4_ra7bh"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block.gd" id="5_wr38c"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node_array.gd" id="6_ppdc3"] [ext_resource type="Script" path="res://addons/block_code/block_script_data/block_script_data.gd" id="7_uuuue"] -[ext_resource type="PackedScene" uid="uid://bis7afjjuwypq" path="res://addons/block_code/simple_nodes/simple_scoring/simple_scoring.tscn" id="8_yg457"] [ext_resource type="PackedScene" uid="uid://c7l70grmkauij" path="res://addons/block_code/examples/pong_game/ball.tscn" id="9_xrqll"] [ext_resource type="PackedScene" uid="uid://fhoapg3anjsu" path="res://addons/block_code/examples/pong_game/goal_area.tscn" id="12_nqmxu"] +[ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd" id="13_tg3yk"] [sub_resource type="Resource" id="Resource_k6jw1"] script = ExtResource("5_wr38c") @@ -796,20 +796,22 @@ version = 0 [node name="Space" parent="." instance=ExtResource("1_y56ac")] -[node name="PaddleLeft" parent="." groups=["paddles"] instance=ExtResource("3_hjpbs")] +[node name="PaddleLeft" type="CharacterBody2D" parent="." groups=["paddles"]] modulate = Color(0.509804, 0.360784, 0.972549, 1) position = Vector2(64, 544) collision_mask = 5 +script = ExtResource("3_mdrcv") texture = ExtResource("4_ra7bh") [node name="BlockCode" type="Node" parent="PaddleLeft"] script = ExtResource("3_6jaq8") block_script = SubResource("Resource_qmak3") -[node name="PaddleRight" parent="." groups=["paddles"] instance=ExtResource("3_hjpbs")] +[node name="PaddleRight" type="CharacterBody2D" parent="." groups=["paddles"]] modulate = Color(0.509804, 0.360784, 0.972549, 1) position = Vector2(1856, 544) collision_mask = 5 +script = ExtResource("3_mdrcv") texture = ExtResource("4_ra7bh") [node name="BlockCode" type="Node" parent="PaddleRight"] @@ -839,8 +841,9 @@ position = Vector2(1984, 544) script = ExtResource("3_6jaq8") block_script = SubResource("Resource_6drva") -[node name="SimpleScoring" parent="." instance=ExtResource("8_yg457")] +[node name="SimpleScoring" type="CanvasLayer" parent="." groups=["hud"]] follow_viewport_enabled = true +script = ExtResource("13_tg3yk") [node name="BlockCode" type="Node" parent="SimpleScoring"] script = ExtResource("3_6jaq8") From 88d4af075a3e1b07cfe09828656d8885061277ca Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Wed, 17 Jul 2024 06:36:36 -0600 Subject: [PATCH 066/423] BlockCategory: Change type to RefCounted This way the objects are automatically freed when all references are dropped. Prior to this, running the tests warned about leaked objects: WARNING: ObjectDB instances leaked at exit (run with --verbose for details). at: cleanup (core/object/object.cpp:2209) ERROR: Resources still in use at exit (run with --verbose for details). at: clear (core/io/resource.cpp:492) --- addons/block_code/ui/picker/categories/block_category.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/block_code/ui/picker/categories/block_category.gd b/addons/block_code/ui/picker/categories/block_category.gd index 428d79c5..4cc9066f 100644 --- a/addons/block_code/ui/picker/categories/block_category.gd +++ b/addons/block_code/ui/picker/categories/block_category.gd @@ -1,5 +1,5 @@ class_name BlockCategory -extends Object +extends RefCounted var name: String var block_list: Array[Block] From d1e013de9709d9b9f89fb253c75994f27cf04e48 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Wed, 17 Jul 2024 11:23:17 -0600 Subject: [PATCH 067/423] Plugin: Skip block code node refresh after main panel freed When exiting the tree, the main panel is freed and should no longer be updated. This avoids the following error when shutting down: SCRIPT ERROR: Invalid call. Nonexistent function 'switch_block_code_node' in base 'Nil'. at: BlockCodePlugin._refresh_block_code_node (res://addons/block_code/block_code_plugin.gd:160) --- addons/block_code/block_code_plugin.gd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index b45a84f4..6180465d 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -155,7 +155,8 @@ func select_block_code_node(block_code: BlockCode): func _refresh_block_code_node(): - main_panel.switch_block_code_node(_selected_block_code) + if main_panel: + main_panel.switch_block_code_node(_selected_block_code) func _on_selected_block_code_changed(): From 431f1396c4c8d1d1f9ae05de8d0140ecdd3212cd Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Wed, 17 Jul 2024 12:16:23 -0600 Subject: [PATCH 068/423] Fix inspector plugin button In e0a4208, the method name was changed. --- addons/block_code/inspector_plugin/block_script_inspector.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/block_code/inspector_plugin/block_script_inspector.gd b/addons/block_code/inspector_plugin/block_script_inspector.gd index f40ef60b..73722d36 100644 --- a/addons/block_code/inspector_plugin/block_script_inspector.gd +++ b/addons/block_code/inspector_plugin/block_script_inspector.gd @@ -10,7 +10,7 @@ func _parse_begin(object): var button := Button.new() button.text = "Open Block Script" - button.pressed.connect(func(): BlockCodePlugin.main_panel.switch_script(block_code)) + button.pressed.connect(func(): BlockCodePlugin.main_panel.switch_block_code_node(block_code)) var container := MarginContainer.new() container.add_theme_constant_override("margin_bottom", 10) From 8988c0c05aaa1bfee8a087d7a0b1a0c296ef00f0 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Wed, 17 Jul 2024 12:25:56 -0600 Subject: [PATCH 069/423] Fix inspector plugin leak Handling the inspector plugin as a static variable of the BlockCode class means it can never be removed from inspector since we never know when all BlockCode instances have been destroyed. That means it had to be leaked as shown in the verbose Godot output: WARNING: ObjectDB instances leaked at exit (run with --verbose for details). at: cleanup (core/object/object.cpp:2209) Leaked instance: EditorPlugin:1833129019089 - Node name: Instead, add it once from the plugin entry point. That means it can also be removed when the plugin exits rather than being leaked. This follows the pattern documented in the Inspector Plugin tutorial[1]. 1. https://docs.godotengine.org/en/stable/tutorials/plugins/editor/inspector_plugins.html. --- addons/block_code/block_code_node/block_code.gd | 5 ----- addons/block_code/block_code_plugin.gd | 7 +++++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/addons/block_code/block_code_node/block_code.gd b/addons/block_code/block_code_node/block_code.gd index fc03f04f..eaafb088 100644 --- a/addons/block_code/block_code_node/block_code.gd +++ b/addons/block_code/block_code_node/block_code.gd @@ -4,7 +4,6 @@ class_name BlockCode extends Node @export var block_script: BlockScriptData = null -static var plugin func _ready(): @@ -31,10 +30,6 @@ func _enter_tree(): new_bsd.generated_script = new_bsd.generated_script.replace("INHERIT_DEFAULT", new_bsd.script_inherits) block_script = new_bsd - if plugin == null: - plugin = ClassDB.instantiate("EditorPlugin") - plugin.add_inspector_plugin(load("res://addons/block_code/inspector_plugin/block_script_inspector.gd").new()) - func _update_parent_script(): if Engine.is_editor_hint(): diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 6180465d..70ef59bf 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -6,6 +6,9 @@ const MainPanel := preload("res://addons/block_code/ui/main_panel.tscn") static var main_panel: MainPanel static var block_code_button: Button +const BlockInspectorPlugin := preload("res://addons/block_code/inspector_plugin/block_script_inspector.gd") +var block_inspector_plugin: BlockInspectorPlugin + var editor_inspector: EditorInspector var editor_selection: EditorSelection @@ -52,6 +55,8 @@ func _enter_tree(): main_panel = MainPanel.instantiate() main_panel.undo_redo = get_undo_redo() block_code_button = add_control_to_bottom_panel(main_panel, _get_plugin_name()) + block_inspector_plugin = BlockInspectorPlugin.new() + add_inspector_plugin(block_inspector_plugin) # Remove unwanted class nodes from create node old_feature_profile = EditorInterface.get_current_feature_profile() @@ -71,6 +76,8 @@ func _enter_tree(): func _exit_tree(): + remove_inspector_plugin(block_inspector_plugin) + if block_code_button: remove_control_from_bottom_panel(main_panel) block_code_button = null From 9f3f1a79b885f8e18a780b75830d742c42a0a744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 17 Jul 2024 10:14:48 -0300 Subject: [PATCH 070/423] Parameter input: change text modification logic Previously any text change was sending the modified signal, adding too many actions to the undo/redo history (one per typed character). This was also capturing shortcuts like Ctrl-Z for undoing and sending the modified signal, thus piling to the history, not going back. Instead, send the modified signal when the line edit is submitted (enter key pressed) or when it loses focus and the text has changed. Do this for the 3 line edit nodes. https://phabricator.endlessm.com/T35566 --- .../parameter_input/parameter_input.gd | 37 ++++++++++++++++++- .../parameter_input/parameter_input.tscn | 10 +++-- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd index 53e2938a..bf7ab425 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd +++ b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd @@ -31,6 +31,11 @@ var option: bool = false @onready var _bool_input := %BoolInput @onready var _bool_input_option := %BoolInputOption +# Used to submit the text when losing focus: +var _last_lineedit_submitted_text: String +var _last_x_lineedit_submitted_text: String +var _last_y_lineedit_submitted_text: String + func set_raw_input(raw_input): if option: @@ -93,6 +98,10 @@ func _ready(): snap_point.block_type = block_type snap_point.variant_type = variant_type + _last_lineedit_submitted_text = _line_edit.text + _last_x_lineedit_submitted_text = _x_line_edit.text + _last_y_lineedit_submitted_text = _y_line_edit.text + _update_visible_input() @@ -126,10 +135,36 @@ func get_string() -> String: return "%s" % input -func _on_line_edit_text_changed(new_text): +func _on_line_edit_text_submitted(new_text): + _last_lineedit_submitted_text = new_text + modified.emit() + + +func _on_line_edit_focus_exited(): + if _last_lineedit_submitted_text != _line_edit.text: + modified.emit() + + +func _on_x_line_edit_text_submitted(new_text): + _last_x_lineedit_submitted_text = new_text modified.emit() +func _on_x_line_edit_focus_exited(): + if _last_x_lineedit_submitted_text != _x_line_edit.text: + modified.emit() + + +func _on_y_line_edit_text_submitted(new_text): + _last_y_lineedit_submitted_text = new_text + modified.emit() + + +func _on_y_line_edit_focus_exited(): + if _last_y_lineedit_submitted_text != _y_line_edit.text: + modified.emit() + + func _update_visible_input(): if snap_point.has_snapped_block(): _switch_input(null) diff --git a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.tscn b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.tscn index 21aa43a1..4b0b2912 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.tscn +++ b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.tscn @@ -178,14 +178,16 @@ popup/item_1/id = 1 [node name="SnapPoint" parent="." instance=ExtResource("2_6esp3")] unique_name_in_owner = true layout_mode = 2 -mouse_filter = 2 block_type = 3 variant_type = 4 -[connection signal="text_changed" from="InputSwitcher/TextInput/LineEdit" to="." method="_on_line_edit_text_changed"] +[connection signal="focus_exited" from="InputSwitcher/TextInput/LineEdit" to="." method="_on_line_edit_focus_exited"] +[connection signal="text_submitted" from="InputSwitcher/TextInput/LineEdit" to="." method="_on_line_edit_text_submitted"] [connection signal="color_changed" from="InputSwitcher/ColorInput" to="." method="_on_color_input_color_changed"] [connection signal="item_selected" from="InputSwitcher/OptionInput" to="." method="_on_option_input_item_selected"] -[connection signal="text_changed" from="InputSwitcher/Vector2Input/HBoxContainer/XLineEdit" to="." method="_on_line_edit_text_changed"] -[connection signal="text_changed" from="InputSwitcher/Vector2Input/HBoxContainer/YLineEdit" to="." method="_on_line_edit_text_changed"] +[connection signal="focus_exited" from="InputSwitcher/Vector2Input/HBoxContainer/XLineEdit" to="." method="_on_x_line_edit_focus_exited"] +[connection signal="text_submitted" from="InputSwitcher/Vector2Input/HBoxContainer/XLineEdit" to="." method="_on_x_line_edit_text_submitted"] +[connection signal="focus_exited" from="InputSwitcher/Vector2Input/HBoxContainer/YLineEdit" to="." method="_on_y_line_edit_focus_exited"] +[connection signal="text_submitted" from="InputSwitcher/Vector2Input/HBoxContainer/YLineEdit" to="." method="_on_y_line_edit_text_submitted"] [connection signal="item_selected" from="InputSwitcher/BoolInput/BoolInputOption" to="." method="_on_option_input_item_selected"] [connection signal="snapped_block_changed" from="SnapPoint" to="." method="_on_snap_point_snapped_block_changed"] From 423a0638b5e55481bb8e3cb08322c6ad1226bf33 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Thu, 18 Jul 2024 13:15:29 +0100 Subject: [PATCH 071/423] Reinstate stylebox overrides MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This partially reverts commit 1b6d64b4f6d532139e29acb0d1cf9c4824ac9ced (“Don't recreate resources when editing plugin scenes”). I incorrectly believed that these were being fully recreated every time the scene is instantiated based on another element's stylebox, but in fact they are being used as a template and it is only the colour that is being adjusted. See discussion at https://github.com/endlessm/godot-block-coding/pull/138#discussion_r1681557942. --- .../ui/blocks/parameter_block/parameter_block.tscn | 14 +++++++++++++- .../picker/categories/block_category_button.tscn | 10 +++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn b/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn index fec7b57c..46cc8b65 100644 --- a/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn +++ b/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn @@ -1,8 +1,19 @@ -[gd_scene load_steps=3 format=3 uid="uid://clipm2dd28jde"] +[gd_scene load_steps=4 format=3 uid="uid://clipm2dd28jde"] [ext_resource type="Script" path="res://addons/block_code/ui/blocks/parameter_block/parameter_block.gd" id="1_0hajy"] [ext_resource type="PackedScene" uid="uid://c7puyxpqcq6xo" path="res://addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.tscn" id="2_gy5co"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dbera"] +bg_color = Color(1, 1, 1, 1) +border_width_left = 3 +border_width_top = 3 +border_width_right = 3 +border_width_bottom = 3 +corner_radius_top_left = 16 +corner_radius_top_right = 16 +corner_radius_bottom_right = 16 +corner_radius_bottom_left = 16 + [node name="ParameterBlock" type="MarginContainer"] offset_right = 16.0 offset_bottom = 8.0 @@ -16,6 +27,7 @@ block_type = 3 [node name="Panel" type="Panel" parent="."] unique_name_in_owner = true layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_dbera") [node name="DragDropArea" parent="." instance=ExtResource("2_gy5co")] layout_mode = 2 diff --git a/addons/block_code/ui/picker/categories/block_category_button.tscn b/addons/block_code/ui/picker/categories/block_category_button.tscn index f28962c3..33210926 100644 --- a/addons/block_code/ui/picker/categories/block_category_button.tscn +++ b/addons/block_code/ui/picker/categories/block_category_button.tscn @@ -1,7 +1,14 @@ -[gd_scene load_steps=6 format=3 uid="uid://bdtetj0gs45hv"] +[gd_scene load_steps=7 format=3 uid="uid://bdtetj0gs45hv"] [ext_resource type="Script" path="res://addons/block_code/ui/picker/categories/block_category_button.gd" id="1_pxxnl"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_eogpc"] +bg_color = Color(1, 0, 0, 1) +corner_radius_top_left = 100 +corner_radius_top_right = 100 +corner_radius_bottom_right = 100 +corner_radius_bottom_left = 100 + [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ousiv"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fyk0j"] @@ -32,6 +39,7 @@ theme_override_constants/margin_bottom = 8 [node name="Panel" type="Panel" parent="HBoxContainer/MarginContainer"] unique_name_in_owner = true layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_eogpc") [node name="Label" type="Label" parent="HBoxContainer"] unique_name_in_owner = true From 01ab76c54c654b46ae04355fee13fa195a22a54a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 16 Jul 2024 10:57:05 -0300 Subject: [PATCH 072/423] Serialization: Reuse serialized resources Add a resource property to blocks. The resource will be updated before building the tree. This mitigates having a huge diff in scenes with blocks for minimum changes like moving a block in the canvas. --- .../ui/block_canvas/block_canvas.gd | 29 ++++++++++++------- addons/block_code/ui/blocks/block/block.gd | 16 ++++++++++ addons/block_code/ui/main_panel.gd | 13 ++++----- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 67d84557..f6339fc6 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -40,6 +40,8 @@ var zoom: float: get: return _window.scale.x +var _undo_redo: EditorUndoRedoManager + signal reconnect_block(block: Block) signal add_block_code signal open_scene @@ -170,24 +172,29 @@ func load_tree(parent: Node, node: SerializedBlockTreeNode): load_tree(scene.get_node(c[0]), c[1]) -func get_canvas_block_trees() -> SerializedBlockTreeNodeArray: - var block_trees := SerializedBlockTreeNodeArray.new() +func rebuild_block_trees(undo_redo): + _undo_redo = undo_redo + _current_bsd.block_trees.array = [] for c in _window.get_children(): - block_trees.array.append(build_tree(c)) - - return block_trees + _current_bsd.block_trees.array.append(build_tree(c)) func build_tree(block: Block) -> SerializedBlockTreeNode: - var n = SerializedBlockTreeNode.new() - n.serialized_block = SerializedBlock.new(block.get_block_class(), block.get_serialized_props()) + var path_child_pairs = [] + block.update_resources(_undo_redo) for snap in find_snaps(block): - for c in snap.get_children(): - if c is Block: # Make sure to not include preview - n.path_child_pairs.append([block.get_path_to(snap), build_tree(c)]) + for child in snap.get_children(): + if not child is Block: # Make sure to not include preview + continue + path_child_pairs.append([block.get_path_to(snap), build_tree(child)]) + + if block.resource.path_child_pairs != path_child_pairs: + _undo_redo.add_undo_property(block.resource, "path_child_pairs", block.resource.path_child_pairs) + block.resource.path_child_pairs = path_child_pairs + _undo_redo.add_do_property(block.resource, "path_child_pairs", block.resource.path_child_pairs) - return n + return block.resource func find_snaps(node: Node) -> Array: diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 907e7077..d4fb86ee 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -26,6 +26,9 @@ signal modified ## The scope of the block (statement of matching entry block) @export var scope: String = "" +## The resource containing the block properties and the snapped blocks +@export var resource: SerializedBlockTreeNode + func _ready(): mouse_filter = Control.MOUSE_FILTER_IGNORE @@ -61,6 +64,19 @@ func get_instruction_node() -> InstructionTree.TreeNode: return node +func update_resources(undo_redo: EditorUndoRedoManager): + if resource == null: + var serialized_block = SerializedBlock.new(get_block_class(), get_serialized_props()) + resource = SerializedBlockTreeNode.new(serialized_block) + return + + var serialized_props = get_serialized_props() + if serialized_props != resource.serialized_block.serialized_props: + undo_redo.add_undo_property(resource.serialized_block, "serialized_props", resource.serialized_block.serialized_props) + resource.serialized_block.serialized_props = serialized_props + undo_redo.add_do_property(resource.serialized_block, "serialized_props", resource.serialized_block.serialized_props) + + # Override this method to add more serialized properties func get_serialized_props() -> Array: return serialize_props(["block_name", "label", "color", "block_type", "position", "scope"]) diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index fa7e9173..1ab4c53c 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -139,17 +139,14 @@ func save_script(): _current_block_code_node.block_script = block_script undo_redo.add_do_property(_current_block_code_node, "block_script", _current_block_code_node.block_script) - undo_redo.add_undo_property(_current_block_code_node.block_script, "block_trees", _current_block_code_node.block_script.block_trees) - undo_redo.add_undo_property(_current_block_code_node.block_script, "generated_script", _current_block_code_node.block_script.generated_script) - - var block_trees := _block_canvas.get_canvas_block_trees() + _block_canvas.rebuild_block_trees(undo_redo) var generated_script = _block_canvas.generate_script_from_current_window(block_script) - block_script.block_trees = block_trees - block_script.generated_script = generated_script + if generated_script != block_script.generated_script: + undo_redo.add_undo_property(_current_block_code_node.block_script, "generated_script", _current_block_code_node.block_script.generated_script) + block_script.generated_script = generated_script + undo_redo.add_do_property(_current_block_code_node.block_script, "generated_script", _current_block_code_node.block_script.generated_script) block_script.version = Constants.CURRENT_DATA_VERSION - undo_redo.add_do_property(_current_block_code_node.block_script, "block_trees", block_trees) - undo_redo.add_do_property(_current_block_code_node.block_script, "generated_script", generated_script) undo_redo.commit_action() From 0f5722bb9eb6e89293bdd7547d6a1a1b1370d644 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 16 Jul 2024 12:23:51 -0700 Subject: [PATCH 073/423] Mutate block_trees via UndoRedo action In block_canvas.gd, instead of modifying _current_bsd.block_trees.array outside of the UndoRedo action, use add_undo_property and add_do_property. --- addons/block_code/ui/block_canvas/block_canvas.gd | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index f6339fc6..099b9a2e 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -174,9 +174,11 @@ func load_tree(parent: Node, node: SerializedBlockTreeNode): func rebuild_block_trees(undo_redo): _undo_redo = undo_redo - _current_bsd.block_trees.array = [] + var block_trees_array = [] for c in _window.get_children(): - _current_bsd.block_trees.array.append(build_tree(c)) + block_trees_array.append(build_tree(c)) + undo_redo.add_undo_property(_current_bsd.block_trees, "array", _current_bsd.block_trees.array) + undo_redo.add_do_property(_current_bsd.block_trees, "array", block_trees_array) func build_tree(block: Block) -> SerializedBlockTreeNode: @@ -191,8 +193,7 @@ func build_tree(block: Block) -> SerializedBlockTreeNode: if block.resource.path_child_pairs != path_child_pairs: _undo_redo.add_undo_property(block.resource, "path_child_pairs", block.resource.path_child_pairs) - block.resource.path_child_pairs = path_child_pairs - _undo_redo.add_do_property(block.resource, "path_child_pairs", block.resource.path_child_pairs) + _undo_redo.add_do_property(block.resource, "path_child_pairs", path_child_pairs) return block.resource From b786cadb6f96d5636c044eb77c9334b2b9dbcbfa Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 16 Jul 2024 12:27:14 -0700 Subject: [PATCH 074/423] Use SnapPoint.get_snapped_block instead of get_children --- addons/block_code/ui/block_canvas/block_canvas.gd | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 099b9a2e..3f5baf29 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -186,10 +186,10 @@ func build_tree(block: Block) -> SerializedBlockTreeNode: block.update_resources(_undo_redo) for snap in find_snaps(block): - for child in snap.get_children(): - if not child is Block: # Make sure to not include preview - continue - path_child_pairs.append([block.get_path_to(snap), build_tree(child)]) + var snapped_block = snap.get_snapped_block() + if snapped_block == null: + continue + path_child_pairs.append([block.get_path_to(snap), build_tree(snapped_block)]) if block.resource.path_child_pairs != path_child_pairs: _undo_redo.add_undo_property(block.resource, "path_child_pairs", block.resource.path_child_pairs) @@ -198,10 +198,10 @@ func build_tree(block: Block) -> SerializedBlockTreeNode: return block.resource -func find_snaps(node: Node) -> Array: - var snaps := [] +func find_snaps(node: Node) -> Array[SnapPoint]: + var snaps: Array[SnapPoint] - if node.is_in_group("snap_point"): + if node.is_in_group("snap_point") and node is SnapPoint: snaps.append(node) else: for c in node.get_children(): From 53d5a4ab46151cb158305fef632c504f5cce679a Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 16 Jul 2024 12:27:52 -0700 Subject: [PATCH 075/423] Clean up property changes outside of UndoRedo actions --- addons/block_code/ui/blocks/block/block.gd | 3 +-- addons/block_code/ui/main_panel.gd | 11 +++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index d4fb86ee..5599719f 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -73,8 +73,7 @@ func update_resources(undo_redo: EditorUndoRedoManager): var serialized_props = get_serialized_props() if serialized_props != resource.serialized_block.serialized_props: undo_redo.add_undo_property(resource.serialized_block, "serialized_props", resource.serialized_block.serialized_props) - resource.serialized_block.serialized_props = serialized_props - undo_redo.add_do_property(resource.serialized_block, "serialized_props", resource.serialized_block.serialized_props) + undo_redo.add_do_property(resource.serialized_block, "serialized_props", serialized_props) # Override this method to add more serialized properties diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index 1ab4c53c..8a6620e5 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -128,7 +128,7 @@ func save_script(): var resource_path_split = block_script.resource_path.split("::", true, 1) var resource_scene = resource_path_split[0] - undo_redo.create_action("Modify %s's block code script" % _current_block_code_node.get_parent().name) + undo_redo.create_action("Modify %s's block code script" % _current_block_code_node.get_parent().name, UndoRedo.MERGE_DISABLE, _current_block_code_node) if resource_scene and resource_scene != scene_node.scene_file_path: # This resource is from another scene. Since the user is changing it @@ -136,15 +136,14 @@ func save_script(): # other scene file. undo_redo.add_undo_property(_current_block_code_node, "block_script", _current_block_code_node.block_script) block_script = block_script.duplicate(true) - _current_block_code_node.block_script = block_script - undo_redo.add_do_property(_current_block_code_node, "block_script", _current_block_code_node.block_script) + undo_redo.add_do_property(_current_block_code_node, "block_script", block_script) _block_canvas.rebuild_block_trees(undo_redo) var generated_script = _block_canvas.generate_script_from_current_window(block_script) if generated_script != block_script.generated_script: - undo_redo.add_undo_property(_current_block_code_node.block_script, "generated_script", _current_block_code_node.block_script.generated_script) - block_script.generated_script = generated_script - undo_redo.add_do_property(_current_block_code_node.block_script, "generated_script", _current_block_code_node.block_script.generated_script) + undo_redo.add_undo_property(block_script, "generated_script", block_script.generated_script) + undo_redo.add_do_property(block_script, "generated_script", generated_script) + block_script.version = Constants.CURRENT_DATA_VERSION undo_redo.commit_action() From 2ece94f966c5343eb0560f190523273a18eca626 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 16 Jul 2024 12:28:27 -0700 Subject: [PATCH 076/423] Do not reset canvas window when refreshing a BlockScript --- addons/block_code/ui/block_canvas/block_canvas.gd | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 3f5baf29..259ece35 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -100,8 +100,9 @@ func bsd_selected(bsd: BlockScriptData): var edited_node = EditorInterface.get_inspector().get_edited_object() as Node - _window.position = Vector2(0, 0) - zoom = 1 + if bsd != _current_bsd: + _window.position = Vector2(0, 0) + zoom = 1 _window.visible = false _zoom_label.visible = false From 22ef12191df5b9c5d319d8daa2f9aef2dab1b095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 17 Jul 2024 08:53:01 -0300 Subject: [PATCH 077/423] Block canvas: remove undo_redo property Pass it around. --- addons/block_code/ui/block_canvas/block_canvas.gd | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 259ece35..0dc6e320 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -40,8 +40,6 @@ var zoom: float: get: return _window.scale.x -var _undo_redo: EditorUndoRedoManager - signal reconnect_block(block: Block) signal add_block_code signal open_scene @@ -174,27 +172,26 @@ func load_tree(parent: Node, node: SerializedBlockTreeNode): func rebuild_block_trees(undo_redo): - _undo_redo = undo_redo var block_trees_array = [] for c in _window.get_children(): - block_trees_array.append(build_tree(c)) + block_trees_array.append(build_tree(c, undo_redo)) undo_redo.add_undo_property(_current_bsd.block_trees, "array", _current_bsd.block_trees.array) undo_redo.add_do_property(_current_bsd.block_trees, "array", block_trees_array) -func build_tree(block: Block) -> SerializedBlockTreeNode: +func build_tree(block: Block, undo_redo: EditorUndoRedoManager) -> SerializedBlockTreeNode: var path_child_pairs = [] - block.update_resources(_undo_redo) + block.update_resources(undo_redo) for snap in find_snaps(block): var snapped_block = snap.get_snapped_block() if snapped_block == null: continue - path_child_pairs.append([block.get_path_to(snap), build_tree(snapped_block)]) + path_child_pairs.append([block.get_path_to(snap), build_tree(snapped_block, undo_redo)]) if block.resource.path_child_pairs != path_child_pairs: - _undo_redo.add_undo_property(block.resource, "path_child_pairs", block.resource.path_child_pairs) - _undo_redo.add_do_property(block.resource, "path_child_pairs", path_child_pairs) + undo_redo.add_undo_property(block.resource, "path_child_pairs", block.resource.path_child_pairs) + undo_redo.add_do_property(block.resource, "path_child_pairs", path_child_pairs) return block.resource From 518fa9be3e74267a654d28bc6dd61ae9e79800d2 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Thu, 18 Jul 2024 10:43:50 -0600 Subject: [PATCH 078/423] Plugin: Only skip duplicate work when BlockCode nodes selected In dbd7643, an early return was added to avoid updating the UI when the same BlockCode node has been selected. When a non-BlockCode has been selected, the main panel needs to be told about it so that it can show some friendly messages about adding a BlockCode node. However, any non-BlockCode node is represented as null, which means that changes to a selected non-BlockCode node can't be differentiated. Skip the early return in that case. https://phabricator.endlessm.com/T35572 --- addons/block_code/block_code_plugin.gd | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 70ef59bf..8f297cf0 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -138,7 +138,10 @@ func _on_editor_inspector_edited_object_changed(): func select_block_code_node(block_code: BlockCode): - if block_code == _selected_block_code: + # Skip duplicate selection unless new node is null. That happens when any + # non-BlockCode node is selected and that needs to be passed through to the + # main panel. + if block_code and block_code == _selected_block_code: return if not is_block_code_editable(block_code): From b33f81cba8cbea5c8015d43c96f913915b9e0376 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Sat, 20 Jul 2024 10:24:06 -0600 Subject: [PATCH 079/423] BlockCanvas: Fix block node array typing Prior to 01ab76c, the block trees array was modified in place, which meant is was correctly typed as `Array[SerializedBlockTreeNode]`. Now it's being built from an untyped array, which breaks script generation. https://phabricator.endlessm.com/T35573 --- addons/block_code/ui/block_canvas/block_canvas.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 0dc6e320..c067e9ef 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -172,7 +172,7 @@ func load_tree(parent: Node, node: SerializedBlockTreeNode): func rebuild_block_trees(undo_redo): - var block_trees_array = [] + var block_trees_array: Array[SerializedBlockTreeNode] for c in _window.get_children(): block_trees_array.append(build_tree(c, undo_redo)) undo_redo.add_undo_property(_current_bsd.block_trees, "array", _current_bsd.block_trees.array) From c59e48e85d6287dbb00b1c2c75e34555ad640347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 22 Jul 2024 15:03:04 -0300 Subject: [PATCH 080/423] Revert "Block: Handle bottom_snap property directly" This reverts commit 6a11ebe7a1ee66ebdbbfda4eec21c37c179ab079. --- addons/block_code/ui/blocks/block/block.gd | 5 ++++- addons/block_code/ui/blocks/control_block/control_block.tscn | 4 ++-- .../ui/blocks/statement_block/statement_block.tscn | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 5599719f..cc181c02 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -21,7 +21,7 @@ signal modified @export var category: String ## The next block in the line of execution (can be null if end) -@export var bottom_snap: SnapPoint +@export var bottom_snap_path: NodePath ## The scope of the block (statement of matching entry block) @export var scope: String = "" @@ -29,8 +29,11 @@ signal modified ## The resource containing the block properties and the snapped blocks @export var resource: SerializedBlockTreeNode +var bottom_snap: SnapPoint + func _ready(): + bottom_snap = get_node_or_null(bottom_snap_path) mouse_filter = Control.MOUSE_FILTER_IGNORE diff --git a/addons/block_code/ui/blocks/control_block/control_block.tscn b/addons/block_code/ui/blocks/control_block/control_block.tscn index ee2675c0..81790457 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.tscn +++ b/addons/block_code/ui/blocks/control_block/control_block.tscn @@ -3,14 +3,14 @@ [ext_resource type="Script" path="res://addons/block_code/ui/blocks/control_block/control_block.gd" id="1_2hbir"] [ext_resource type="PackedScene" uid="uid://b1oge52xhjqnu" path="res://addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn" id="3_nhryi"] -[node name="ControlBlock" type="MarginContainer" node_paths=PackedStringArray("bottom_snap")] +[node name="ControlBlock" type="MarginContainer"] size_flags_horizontal = 0 mouse_filter = 2 script = ExtResource("1_2hbir") block_name = "control_block" label = "Control Block" color = Color(0.59979, 0.536348, 0.876215, 1) -bottom_snap = NodePath("VBoxContainer/SnapPoint") +bottom_snap_path = NodePath("VBoxContainer/SnapPoint") [node name="VBoxContainer" type="VBoxContainer" parent="."] layout_mode = 2 diff --git a/addons/block_code/ui/blocks/statement_block/statement_block.tscn b/addons/block_code/ui/blocks/statement_block/statement_block.tscn index 5da5ac5a..96ed6e48 100644 --- a/addons/block_code/ui/blocks/statement_block/statement_block.tscn +++ b/addons/block_code/ui/blocks/statement_block/statement_block.tscn @@ -5,13 +5,13 @@ [ext_resource type="PackedScene" uid="uid://c7puyxpqcq6xo" path="res://addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.tscn" id="2_owgdx"] [ext_resource type="PackedScene" uid="uid://b1oge52xhjqnu" path="res://addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn" id="3_5vaov"] -[node name="StatementBlock" type="MarginContainer" node_paths=PackedStringArray("bottom_snap")] +[node name="StatementBlock" type="MarginContainer"] size_flags_horizontal = 0 mouse_filter = 2 script = ExtResource("1_6wvlf") block_name = "statement_block" label = "StatementBlock" -bottom_snap = NodePath("VBoxContainer/SnapPoint") +bottom_snap_path = NodePath("VBoxContainer/SnapPoint") [node name="VBoxContainer" type="VBoxContainer" parent="."] layout_mode = 2 From 1431d512e928071dde101158fee51cd4e7e8aaf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 22 Jul 2024 17:07:40 -0300 Subject: [PATCH 081/423] Fix main_scene corruption Somehow the scene got corrupted, causing the following error when the plugin was loaded for the first time in a new project: > Failed to instantiate scene state of "res://addons/block_code/ui/main_panel.tscn", node count is 0. Make sure the PackedScene resource is valid. > res://addons/block_code/block_code_plugin.gd:56 - Invalid set index 'undo_redo' (on base: 'null instance') with value of type 'EditorUndoRedoManager'. > res://addons/block_code/block_code_plugin.gd:107 - Attempt to call function 'switch_scene' in base 'null instance' on a null instance. Fixed by simply opening the scene with the editor and saving it. https://phabricator.endlessm.com/T35574 --- addons/block_code/ui/main_panel.tscn | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/block_code/ui/main_panel.tscn b/addons/block_code/ui/main_panel.tscn index c0554865..71fed42b 100644 --- a/addons/block_code/ui/main_panel.tscn +++ b/addons/block_code/ui/main_panel.tscn @@ -6,7 +6,7 @@ [ext_resource type="PackedScene" uid="uid://c6vumewgnfquy" path="res://addons/block_code/ui/block_canvas/block_canvas.tscn" id="4_cu87g"] [ext_resource type="PackedScene" uid="uid://cph1k5cfximbf" path="res://addons/block_code/drag_manager/drag_manager.tscn" id="4_yijtu"] -[sub_resource type="Image" id="Image_n7d73"] +[sub_resource type="Image" id="Image_7y48q"] data = { "data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 92, 92, 92, 64, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 92, 92, 92, 64, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 249, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 249, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 197, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 195, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 52, 90, 90, 90, 238, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 236, 92, 92, 92, 50, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 96, 96, 96, 24, 91, 91, 91, 101, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 91, 91, 91, 101, 100, 100, 100, 23, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), "format": "RGBA8", @@ -16,9 +16,9 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_mrr6q"] -image = SubResource("Image_n7d73") +image = SubResource("Image_7y48q") -[sub_resource type="Image" id="Image_5ygfb"] +[sub_resource type="Image" id="Image_1l8vl"] data = { "data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 92, 92, 92, 72, 91, 91, 91, 73, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 116, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 71, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 92, 92, 92, 75, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 201, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 119, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 247, 96, 96, 96, 40, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 91, 91, 91, 118, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 201, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 119, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 247, 96, 96, 96, 40, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 91, 91, 91, 118, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 201, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 91, 91, 91, 84, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 96, 96, 96, 40, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 91, 91, 91, 84, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 93, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 200, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 91, 91, 91, 118, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 119, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 248, 93, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 200, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 91, 91, 91, 118, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 119, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 248, 93, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 200, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 92, 92, 92, 75, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 116, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 71, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 71, 92, 92, 92, 72, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), "format": "RGBA8", @@ -28,7 +28,7 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_2e128"] -image = SubResource("Image_5ygfb") +image = SubResource("Image_1l8vl") [node name="MainPanel" type="MarginContainer"] anchors_preset = 15 From 13cdca3ddfd0d1da24d79b6f50e36df6ee3ff2f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 23 Jul 2024 09:46:37 -0300 Subject: [PATCH 082/423] SimpleScoring: Remove print leftover --- addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd index 3d96007a..84908d4c 100644 --- a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd +++ b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd @@ -26,7 +26,6 @@ func _init(): var node = preload("res://addons/block_code/simple_nodes/simple_scoring/_simple_scoring.tscn").instantiate() as Node node.replace_by(self, true) node.queue_free() - print_tree_pretty() scene_file_path = "" From a064abb214c8dd3ef39f0f6de05d064b09a2913f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 23 Jul 2024 10:04:47 -0300 Subject: [PATCH 083/423] DragManager: Move Drag class to its own file --- addons/block_code/drag_manager/drag.gd | 196 ++++++++++++++++++ .../block_code/drag_manager/drag_manager.gd | 184 +--------------- 2 files changed, 198 insertions(+), 182 deletions(-) create mode 100644 addons/block_code/drag_manager/drag.gd diff --git a/addons/block_code/drag_manager/drag.gd b/addons/block_code/drag_manager/drag.gd new file mode 100644 index 00000000..4a3c9388 --- /dev/null +++ b/addons/block_code/drag_manager/drag.gd @@ -0,0 +1,196 @@ +@tool +extends Control + +const Constants = preload("res://addons/block_code/ui/constants.gd") +const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") + +var _block: Block +var _block_scope: String +var _block_canvas: BlockCanvas +var _preview_block: Control +var _snap_points: Array[Node] +var _delete_areas: Array[Rect2] +var action: DragManager.DragAction: + get: + return action + set(value): + if action != value: + action = value + _update_action_hint() + +var target_snap_point: SnapPoint: + get: + return target_snap_point + set(value): + if target_snap_point != value: + target_snap_point = value + _update_preview() + +var snap_block: Block: + get: + return target_snap_point.get_parent_block() if target_snap_point else null + + +func _init(block: Block, block_scope: String, offset: Vector2, block_canvas: BlockCanvas): + assert(block.get_parent() == null) + + add_child(block) + block.position = -offset + + _block = block + _block_scope = block_scope + _block_canvas = block_canvas + + +func set_snap_points(snap_points: Array[Node]): + _snap_points = snap_points.filter(_snaps_to) + + +func add_delete_area(delete_area: Rect2): + _delete_areas.append(delete_area) + + +func update_drag_state(): + global_position = get_global_mouse_position() + + if _block_canvas.is_mouse_over(): + scale = Vector2(_block_canvas.zoom, _block_canvas.zoom) + else: + scale = Vector2(1, 1) + + for rect in _delete_areas: + if rect.has_point(get_global_mouse_position()): + action = DragManager.DragAction.REMOVE + target_snap_point = null + return + + action = DragManager.DragAction.PLACE + + target_snap_point = _find_closest_snap_point() + + +func apply_drag() -> Block: + update_drag_state() + + if action == DragManager.DragAction.PLACE: + _place_block() + return _block + elif action == DragManager.DragAction.REMOVE: + _remove_block() + return null + else: + return null + + +func _remove_block(): + target_snap_point = null + _block.queue_free() + + +func _place_block(): + var canvas_rect: Rect2 = _block_canvas.get_global_rect() + + var position = _block.global_position - canvas_rect.position + + remove_child(_block) + + if target_snap_point: + # Snap the block to the point + var orphaned_block = target_snap_point.insert_snapped_block(_block) + if orphaned_block: + # Place the orphan block somewhere outside the snap point + _block_canvas.arrange_block(orphaned_block, snap_block) + else: + # Block goes on screen somewhere + _block_canvas.add_block(_block, position) + + target_snap_point = null + + +func _snaps_to(node: Node) -> bool: + var _snap_point: SnapPoint = node as SnapPoint + + if not _snap_point: + push_error("Warning: node %s is not of class SnapPoint." % node) + return false + + if not _block_canvas.is_ancestor_of(_snap_point): + # We only snap to blocks on the canvas: + return false + + if _block.block_type != _snap_point.block_type: + # We only snap to the same block type: + return false + + if _block.block_type == Types.BlockType.VALUE and not Types.can_cast(_block.variant_type, _snap_point.variant_type): + # We only snap Value blocks to snaps that can cast to same variant: + return false + + # Check if any parent node is this node + if _snap_point.is_ancestor_of(_block): + return false + + var top_block = _get_top_block_for_node(_snap_point) + + # Check if scope is valid + if _block_scope != "": + if top_block is EntryBlock: + if _block_scope != top_block.get_entry_statement(): + return false + elif top_block: + var tree_scope := DragManager.get_tree_scope(top_block) + if tree_scope != "" and _block_scope != tree_scope: + return false + + return true + + +func _find_closest_snap_point() -> Node: + var closest_snap_point: SnapPoint = null + var closest_distance: int + for snap_point in _snap_points: + var distance = _get_distance_to_snap_point(snap_point) + if distance > Constants.MINIMUM_SNAP_DISTANCE * _block_canvas.zoom: + continue + elif closest_snap_point == null or distance < closest_distance: + closest_snap_point = snap_point + closest_distance = distance + return closest_snap_point + + +func _get_top_block_for_node(node: Node) -> Block: + for top_block in _block_canvas.get_blocks(): + if top_block.is_ancestor_of(node): + return top_block + return null + + +func _get_distance_to_snap_point(snap_point: SnapPoint) -> float: + var from_global: Vector2 = _block.global_position + return from_global.distance_to(snap_point.global_position) + + +func _update_action_hint(): + match action: + DragManager.DragAction.REMOVE: + _block.modulate = Color(1.0, 1.0, 1.0, 0.5) + _: + _block.modulate = Color.WHITE + + +func _update_preview(): + if _preview_block: + _preview_block.queue_free() + _preview_block = null + + if target_snap_point: + # Make preview block + _preview_block = Control.new() + _preview_block.set_script(preload("res://addons/block_code/ui/blocks/utilities/background/background.gd")) + + _preview_block.color = Color(1, 1, 1, 0.5) + _preview_block.custom_minimum_size = _block.get_global_rect().size + _preview_block.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN + _preview_block.size_flags_vertical = Control.SIZE_SHRINK_BEGIN + + target_snap_point.add_child(_preview_block) diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index 8875b44b..b047d625 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -5,6 +5,8 @@ extends Control signal block_dropped signal block_modified +const Drag = preload("res://addons/block_code/drag_manager/drag.gd") + @export var picker_path: NodePath @export var block_canvas_path: NodePath @@ -12,188 +14,6 @@ const Constants = preload("res://addons/block_code/ui/constants.gd") enum DragAction { NONE, PLACE, REMOVE } - -class Drag: - extends Control - var _block: Block - var _block_scope: String - var _block_canvas: BlockCanvas - var _preview_block: Control - var _snap_points: Array[Node] - var _delete_areas: Array[Rect2] - var action: DragAction: - get: - return action - set(value): - if action != value: - action = value - _update_action_hint() - - var target_snap_point: SnapPoint: - get: - return target_snap_point - set(value): - if target_snap_point != value: - target_snap_point = value - _update_preview() - - var snap_block: Block: - get: - return target_snap_point.get_parent_block() if target_snap_point else null - - func _init(block: Block, block_scope: String, offset: Vector2, block_canvas: BlockCanvas): - assert(block.get_parent() == null) - - add_child(block) - block.position = -offset - - _block = block - _block_scope = block_scope - _block_canvas = block_canvas - - func set_snap_points(snap_points: Array[Node]): - _snap_points = snap_points.filter(_snaps_to) - - func add_delete_area(delete_area: Rect2): - _delete_areas.append(delete_area) - - func update_drag_state(): - global_position = get_global_mouse_position() - - if _block_canvas.is_mouse_over(): - scale = Vector2(_block_canvas.zoom, _block_canvas.zoom) - else: - scale = Vector2(1, 1) - - for rect in _delete_areas: - if rect.has_point(get_global_mouse_position()): - action = DragAction.REMOVE - target_snap_point = null - return - - action = DragAction.PLACE - - target_snap_point = _find_closest_snap_point() - - func apply_drag() -> Block: - update_drag_state() - - if action == DragAction.PLACE: - _place_block() - return _block - elif action == DragAction.REMOVE: - _remove_block() - return null - else: - return null - - func _remove_block(): - target_snap_point = null - _block.queue_free() - - func _place_block(): - var canvas_rect: Rect2 = _block_canvas.get_global_rect() - - var position = _block.global_position - canvas_rect.position - - remove_child(_block) - - if target_snap_point: - # Snap the block to the point - var orphaned_block = target_snap_point.insert_snapped_block(_block) - if orphaned_block: - # Place the orphan block somewhere outside the snap point - _block_canvas.arrange_block(orphaned_block, snap_block) - else: - # Block goes on screen somewhere - _block_canvas.add_block(_block, position) - - target_snap_point = null - - func _snaps_to(node: Node) -> bool: - var _snap_point: SnapPoint = node as SnapPoint - - if not _snap_point: - push_error("Warning: node %s is not of class SnapPoint." % node) - return false - - if not _block_canvas.is_ancestor_of(_snap_point): - # We only snap to blocks on the canvas: - return false - - if _block.block_type != _snap_point.block_type: - # We only snap to the same block type: - return false - - if _block.block_type == Types.BlockType.VALUE and not Types.can_cast(_block.variant_type, _snap_point.variant_type): - # We only snap Value blocks to snaps that can cast to same variant: - return false - - # Check if any parent node is this node - if _snap_point.is_ancestor_of(_block): - return false - - var top_block = _get_top_block_for_node(_snap_point) - - # Check if scope is valid - if _block_scope != "": - if top_block is EntryBlock: - if _block_scope != top_block.get_entry_statement(): - return false - elif top_block: - var tree_scope := DragManager.get_tree_scope(top_block) - if tree_scope != "" and _block_scope != tree_scope: - return false - - return true - - func _find_closest_snap_point() -> Node: - var closest_snap_point: SnapPoint = null - var closest_distance: int - for snap_point in _snap_points: - var distance = _get_distance_to_snap_point(snap_point) - if distance > Constants.MINIMUM_SNAP_DISTANCE * _block_canvas.zoom: - continue - elif closest_snap_point == null or distance < closest_distance: - closest_snap_point = snap_point - closest_distance = distance - return closest_snap_point - - func _get_top_block_for_node(node: Node) -> Block: - for top_block in _block_canvas.get_blocks(): - if top_block.is_ancestor_of(node): - return top_block - return null - - func _get_distance_to_snap_point(snap_point: SnapPoint) -> float: - var from_global: Vector2 = _block.global_position - return from_global.distance_to(snap_point.global_position) - - func _update_action_hint(): - match action: - DragAction.REMOVE: - _block.modulate = Color(1.0, 1.0, 1.0, 0.5) - _: - _block.modulate = Color.WHITE - - func _update_preview(): - if _preview_block: - _preview_block.queue_free() - _preview_block = null - - if target_snap_point: - # Make preview block - _preview_block = Control.new() - _preview_block.set_script(preload("res://addons/block_code/ui/blocks/utilities/background/background.gd")) - - _preview_block.color = Color(1, 1, 1, 0.5) - _preview_block.custom_minimum_size = _block.get_global_rect().size - _preview_block.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN - _preview_block.size_flags_vertical = Control.SIZE_SHRINK_BEGIN - - target_snap_point.add_child(_preview_block) - - var _picker: Picker var _block_canvas: BlockCanvas From 3267242cea4c24ed8636c1bcffbc3904959317af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 23 Jul 2024 10:09:38 -0300 Subject: [PATCH 084/423] DragManager: Remove class_name from internal scripts These are now always preloaded in the scripts that depend on them. Makes the plugin work again after enabling it. https://phabricator.endlessm.com/T35574 --- addons/block_code/block_code_plugin.gd | 2 -- addons/block_code/drag_manager/drag.gd | 14 ++++++++------ addons/block_code/drag_manager/drag_manager.gd | 3 --- addons/block_code/ui/block_canvas/block_canvas.gd | 1 + .../ui/blocks/control_block/control_block.gd | 1 + .../utilities/drag_drop_area/drag_drop_area.gd | 1 - addons/block_code/ui/main_panel.gd | 2 ++ 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 8f297cf0..705754ea 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -18,14 +18,12 @@ var old_feature_profile: String = "" const DISABLED_CLASSES := [ "BlockScriptData", - "DragManager", "InstructionTree", "Types", "Block", "ControlBlock", "ParameterBlock", "StatementBlock", - "DragDropArea", "SnapPoint", "SerializedBlockTreeNodeArray", "SerializedBlockTreeNode", diff --git a/addons/block_code/drag_manager/drag.gd b/addons/block_code/drag_manager/drag.gd index 4a3c9388..ec6ca67c 100644 --- a/addons/block_code/drag_manager/drag.gd +++ b/addons/block_code/drag_manager/drag.gd @@ -4,13 +4,15 @@ extends Control const Constants = preload("res://addons/block_code/ui/constants.gd") const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") +enum DragAction { NONE, PLACE, REMOVE } + var _block: Block var _block_scope: String var _block_canvas: BlockCanvas var _preview_block: Control var _snap_points: Array[Node] var _delete_areas: Array[Rect2] -var action: DragManager.DragAction: +var action: DragAction: get: return action set(value): @@ -60,11 +62,11 @@ func update_drag_state(): for rect in _delete_areas: if rect.has_point(get_global_mouse_position()): - action = DragManager.DragAction.REMOVE + action = DragAction.REMOVE target_snap_point = null return - action = DragManager.DragAction.PLACE + action = DragAction.PLACE target_snap_point = _find_closest_snap_point() @@ -72,10 +74,10 @@ func update_drag_state(): func apply_drag() -> Block: update_drag_state() - if action == DragManager.DragAction.PLACE: + if action == DragAction.PLACE: _place_block() return _block - elif action == DragManager.DragAction.REMOVE: + elif action == DragAction.REMOVE: _remove_block() return null else: @@ -172,7 +174,7 @@ func _get_distance_to_snap_point(snap_point: SnapPoint) -> float: func _update_action_hint(): match action: - DragManager.DragAction.REMOVE: + DragAction.REMOVE: _block.modulate = Color(1.0, 1.0, 1.0, 0.5) _: _block.modulate = Color.WHITE diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index b047d625..0dd7cde1 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -1,5 +1,4 @@ @tool -class_name DragManager extends Control signal block_dropped @@ -12,8 +11,6 @@ const Drag = preload("res://addons/block_code/drag_manager/drag.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") -enum DragAction { NONE, PLACE, REMOVE } - var _picker: Picker var _block_canvas: BlockCanvas diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index c067e9ef..763e9ca2 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -2,6 +2,7 @@ class_name BlockCanvas extends MarginContainer +const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") const Util = preload("res://addons/block_code/ui/util.gd") const EXTEND_MARGIN: float = 800 diff --git a/addons/block_code/ui/blocks/control_block/control_block.gd b/addons/block_code/ui/blocks/control_block/control_block.gd index 338bdb2e..8995b115 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.gd +++ b/addons/block_code/ui/blocks/control_block/control_block.gd @@ -3,6 +3,7 @@ class_name ControlBlock extends Block const Constants = preload("res://addons/block_code/ui/constants.gd") +const DragDropArea = preload("res://addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.gd") @export var block_formats: Array = [] @export var statements: Array = [] diff --git a/addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.gd b/addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.gd index 1697c7e1..8b68046d 100644 --- a/addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.gd +++ b/addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.gd @@ -1,5 +1,4 @@ @tool -class_name DragDropArea extends MarginContainer signal mouse_down diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index 8a6620e5..8d442e52 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -2,6 +2,8 @@ class_name MainPanel extends Control +const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") + @onready var _picker: Picker = %Picker @onready var _block_canvas: BlockCanvas = %BlockCanvas @onready var _drag_manager: DragManager = %DragManager From 9f3cd95f4b47575bd3d8f790e47d5637ba6a4f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 23 Jul 2024 13:44:22 -0300 Subject: [PATCH 085/423] Block: Add FIXME note for using SnapPoint directly Once this is fixed in 4.3. https://phabricator.endlessm.com/T35573 --- addons/block_code/ui/blocks/block/block.gd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index cc181c02..c508bc39 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -29,6 +29,9 @@ signal modified ## The resource containing the block properties and the snapped blocks @export var resource: SerializedBlockTreeNode +# FIXME: Add export to this variable and remove bottom_snap_path above. +# There is a bug in Godot 4.2 that prevents using SnapPoint directly: +# https://github.com/godotengine/godot/issues/82670 var bottom_snap: SnapPoint From f3cbacb3b4f80fb6d93b416ecb02f29a2c0f9210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 23 Jul 2024 10:41:32 -0300 Subject: [PATCH 086/423] Remove class_name from all other internal scripts Except for: - The resources: they must be classes - Block and subclasses: they are accessed by class using the ClassDB - SnapPoint: there is an "is SnapPoint" check - the CategoryFactory (bug in Godot 4.2.1) With this, the class is not registered by name in ClassDB and it can't be referenced directly in other scripts, it must be preloaded. Also, if the script extends Node or a subclass of Node, it won't appear in the UI to the end user when adding a node. Another advantage: it won't collide with classes defined by the end user in the project. Our current Types class has a good chance to conflict given the generic name. Also: delete PackedSceneTreeNode and PackedScene abandoned resources. --- addons/block_code/block_code_plugin.gd | 21 ++++--------------- addons/block_code/drag_manager/drag.gd | 2 ++ .../block_code/drag_manager/drag_manager.gd | 2 ++ .../block_script_inspector.gd | 2 ++ .../instruction_tree/instruction_tree.gd | 3 +-- .../simple_character/simple_character.gd | 3 +++ .../simple_scoring/simple_scoring.gd | 3 +++ addons/block_code/types/types.gd | 1 - .../ui/block_canvas/block_canvas.gd | 3 ++- .../ui/block_canvas/packed_scene_tree_node.gd | 5 ----- .../packed_scene_tree_node_array.gd | 4 ---- addons/block_code/ui/blocks/block/block.gd | 3 +++ .../blocks/statement_block/statement_block.gd | 5 ++++- .../parameter_input/parameter_input.gd | 3 ++- .../parameter_output/parameter_output.gd | 2 ++ .../blocks/utilities/snap_point/snap_point.gd | 2 ++ addons/block_code/ui/main_panel.gd | 5 ++++- .../ui/picker/categories/block_category.gd | 1 - .../categories/block_category_button.gd | 2 +- .../categories/block_category_display.gd | 3 ++- .../ui/picker/categories/category_factory.gd | 3 +++ .../create_variable_button.gd | 1 - .../create_variable_dialog.gd | 2 ++ .../variable_category_display.gd | 5 +++-- addons/block_code/ui/picker/picker.gd | 10 +++++++-- addons/block_code/ui/title_bar/title_bar.gd | 3 ++- tests/test_category_factory.gd | 2 ++ tests/test_instruction_tree.gd | 3 +++ 28 files changed, 62 insertions(+), 42 deletions(-) delete mode 100644 addons/block_code/ui/block_canvas/packed_scene_tree_node.gd delete mode 100644 addons/block_code/ui/block_canvas/packed_scene_tree_node_array.gd diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 705754ea..a744d364 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -1,8 +1,9 @@ @tool -class_name BlockCodePlugin extends EditorPlugin +const MainPanelScene := preload("res://addons/block_code/ui/main_panel.tscn") +const MainPanel = preload("res://addons/block_code/ui/main_panel.gd") +const Types = preload("res://addons/block_code/types/types.gd") -const MainPanel := preload("res://addons/block_code/ui/main_panel.tscn") static var main_panel: MainPanel static var block_code_button: Button @@ -18,8 +19,6 @@ var old_feature_profile: String = "" const DISABLED_CLASSES := [ "BlockScriptData", - "InstructionTree", - "Types", "Block", "ControlBlock", "ParameterBlock", @@ -28,19 +27,7 @@ const DISABLED_CLASSES := [ "SerializedBlockTreeNodeArray", "SerializedBlockTreeNode", "SerializedBlock", - "PackedSceneTreeNodeArray", - "PackedSceneTreeNode", - "BlockCanvas", "CategoryFactory", - "BlockCategoryDisplay", - "BlockCategory", - "Picker", - "TitleBar", - "MainPanel", - "BlockCodePlugin", - "BlockCategoryButton", - "CreateVariableButton", - "VariableCategoryDisplay" ] @@ -50,7 +37,7 @@ func _enter_tree(): editor_inspector = EditorInterface.get_inspector() editor_selection = EditorInterface.get_selection() - main_panel = MainPanel.instantiate() + main_panel = MainPanelScene.instantiate() main_panel.undo_redo = get_undo_redo() block_code_button = add_control_to_bottom_panel(main_panel, _get_plugin_name()) block_inspector_plugin = BlockInspectorPlugin.new() diff --git a/addons/block_code/drag_manager/drag.gd b/addons/block_code/drag_manager/drag.gd index ec6ca67c..efa830e6 100644 --- a/addons/block_code/drag_manager/drag.gd +++ b/addons/block_code/drag_manager/drag.gd @@ -1,8 +1,10 @@ @tool extends Control +const BlockCanvas = preload("res://addons/block_code/ui/block_canvas/block_canvas.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") +const Types = preload("res://addons/block_code/types/types.gd") enum DragAction { NONE, PLACE, REMOVE } diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index 0dd7cde1..fb070196 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -4,7 +4,9 @@ extends Control signal block_dropped signal block_modified +const BlockCanvas = preload("res://addons/block_code/ui/block_canvas/block_canvas.gd") const Drag = preload("res://addons/block_code/drag_manager/drag.gd") +const Picker = preload("res://addons/block_code/ui/picker/picker.gd") @export var picker_path: NodePath @export var block_canvas_path: NodePath diff --git a/addons/block_code/inspector_plugin/block_script_inspector.gd b/addons/block_code/inspector_plugin/block_script_inspector.gd index 73722d36..bb073fa4 100644 --- a/addons/block_code/inspector_plugin/block_script_inspector.gd +++ b/addons/block_code/inspector_plugin/block_script_inspector.gd @@ -1,5 +1,7 @@ extends EditorInspectorPlugin +const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd") + func _can_handle(object): return object is BlockCode diff --git a/addons/block_code/instruction_tree/instruction_tree.gd b/addons/block_code/instruction_tree/instruction_tree.gd index 703c7405..786bd8e5 100644 --- a/addons/block_code/instruction_tree/instruction_tree.gd +++ b/addons/block_code/instruction_tree/instruction_tree.gd @@ -1,4 +1,3 @@ -class_name InstructionTree extends Object @@ -99,7 +98,7 @@ static func _generate_script_from_entry_blocks(entry_statement: String, entry_bl var signal_node: TreeNode var is_empty = true - InstructionTree.IDHandler.reset() + IDHandler.reset() for entry_block in entry_blocks: var next_block := entry_block.bottom_snap.get_snapped_block() diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index 08471be2..d62913a3 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -2,6 +2,9 @@ class_name SimpleCharacter extends CharacterBody2D +const CategoryFactory = preload("res://addons/block_code/ui/picker/categories/category_factory.gd") +const Types = preload("res://addons/block_code/types/types.gd") + @export var texture: Texture2D: set = _set_texture diff --git a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd index 84908d4c..8bee47cc 100644 --- a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd +++ b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd @@ -2,6 +2,9 @@ class_name SimpleScoring extends CanvasLayer +const CategoryFactory = preload("res://addons/block_code/ui/picker/categories/category_factory.gd") +const Types = preload("res://addons/block_code/types/types.gd") + @export var score_left: int: set = _set_score_left diff --git a/addons/block_code/types/types.gd b/addons/block_code/types/types.gd index afe4c13e..d9f2b59c 100644 --- a/addons/block_code/types/types.gd +++ b/addons/block_code/types/types.gd @@ -1,4 +1,3 @@ -class_name Types extends Node enum BlockType { diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 763e9ca2..040e294f 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -1,8 +1,9 @@ @tool -class_name BlockCanvas extends MarginContainer +const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd") const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") +const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") const Util = preload("res://addons/block_code/ui/util.gd") const EXTEND_MARGIN: float = 800 diff --git a/addons/block_code/ui/block_canvas/packed_scene_tree_node.gd b/addons/block_code/ui/block_canvas/packed_scene_tree_node.gd deleted file mode 100644 index c20c3a78..00000000 --- a/addons/block_code/ui/block_canvas/packed_scene_tree_node.gd +++ /dev/null @@ -1,5 +0,0 @@ -class_name PackedSceneTreeNode -extends Resource - -@export var scene: PackedScene -@export var children: Array diff --git a/addons/block_code/ui/block_canvas/packed_scene_tree_node_array.gd b/addons/block_code/ui/block_canvas/packed_scene_tree_node_array.gd deleted file mode 100644 index 0c411bbd..00000000 --- a/addons/block_code/ui/block_canvas/packed_scene_tree_node_array.gd +++ /dev/null @@ -1,4 +0,0 @@ -class_name PackedSceneTreeNodeArray -extends Resource - -@export var array: Array[PackedSceneTreeNode] diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index cc181c02..2480869a 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -2,6 +2,9 @@ class_name Block extends MarginContainer +const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") +const Types = preload("res://addons/block_code/types/types.gd") + signal drag_started(block: Block) signal modified diff --git a/addons/block_code/ui/blocks/statement_block/statement_block.gd b/addons/block_code/ui/blocks/statement_block/statement_block.gd index 20aa2e58..cea6a6fc 100644 --- a/addons/block_code/ui/blocks/statement_block/statement_block.gd +++ b/addons/block_code/ui/blocks/statement_block/statement_block.gd @@ -2,6 +2,9 @@ class_name StatementBlock extends Block +const ParameterInput = preload("res://addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd") +const ParameterInputScene = preload("res://addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.tscn") + @export var block_format: String = "" @export var statement: String = "" @export var defaults: Dictionary = {} @@ -130,7 +133,7 @@ static func format_string(parent_block: Block, attach_to: Node, string: String, parameter_output.block = parent_block attach_to.add_child(parameter_output) else: - var parameter_input: ParameterInput = preload("res://addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.tscn").instantiate() + var parameter_input: ParameterInput = ParameterInputScene.instantiate() parameter_input.name = "ParameterInput%d" % start # Unique path parameter_input.placeholder = param_name if param_type != null: diff --git a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd index bf7ab425..7d28fcc9 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd +++ b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd @@ -1,7 +1,8 @@ @tool -class_name ParameterInput extends MarginContainer +const Types = preload("res://addons/block_code/types/types.gd") + signal modified @export var placeholder: String = "Parameter": diff --git a/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd b/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd index a8edf4df..0fb715cc 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd +++ b/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd @@ -2,6 +2,8 @@ class_name ParameterOutput extends MarginContainer +const Types = preload("res://addons/block_code/types/types.gd") + var block: Block var output_block: Block diff --git a/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd b/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd index a1780074..d4be8386 100644 --- a/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd +++ b/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd @@ -2,6 +2,8 @@ class_name SnapPoint extends MarginContainer +const Types = preload("res://addons/block_code/types/types.gd") + @export var block_type: Types.BlockType = Types.BlockType.EXECUTE @export var snapped_block: Block: diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index 8d442e52..ce628ce0 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -1,8 +1,11 @@ @tool -class_name MainPanel extends Control +const BlockCanvas = preload("res://addons/block_code/ui/block_canvas/block_canvas.gd") +const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd") const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") +const Picker = preload("res://addons/block_code/ui/picker/picker.gd") +const TitleBar = preload("res://addons/block_code/ui/title_bar/title_bar.gd") @onready var _picker: Picker = %Picker @onready var _block_canvas: BlockCanvas = %BlockCanvas diff --git a/addons/block_code/ui/picker/categories/block_category.gd b/addons/block_code/ui/picker/categories/block_category.gd index 4cc9066f..aee65cb7 100644 --- a/addons/block_code/ui/picker/categories/block_category.gd +++ b/addons/block_code/ui/picker/categories/block_category.gd @@ -1,4 +1,3 @@ -class_name BlockCategory extends RefCounted var name: String diff --git a/addons/block_code/ui/picker/categories/block_category_button.gd b/addons/block_code/ui/picker/categories/block_category_button.gd index 401873aa..ffc2dfb4 100644 --- a/addons/block_code/ui/picker/categories/block_category_button.gd +++ b/addons/block_code/ui/picker/categories/block_category_button.gd @@ -1,7 +1,7 @@ @tool -class_name BlockCategoryButton extends MarginContainer +const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") const Util = preload("res://addons/block_code/ui/util.gd") signal selected diff --git a/addons/block_code/ui/picker/categories/block_category_display.gd b/addons/block_code/ui/picker/categories/block_category_display.gd index 73e4bc89..ce85f620 100644 --- a/addons/block_code/ui/picker/categories/block_category_display.gd +++ b/addons/block_code/ui/picker/categories/block_category_display.gd @@ -1,7 +1,8 @@ @tool -class_name BlockCategoryDisplay extends MarginContainer +const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") + var category: BlockCategory @onready var _label := %Label diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index b492b954..2e07279f 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -1,6 +1,9 @@ class_name CategoryFactory extends Object +const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") +const Types = preload("res://addons/block_code/types/types.gd") + const BLOCKS: Dictionary = { "control_block": preload("res://addons/block_code/ui/blocks/control_block/control_block.tscn"), "parameter_block": preload("res://addons/block_code/ui/blocks/parameter_block/parameter_block.tscn"), diff --git a/addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd b/addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd index 85959cc9..3f69b2e2 100644 --- a/addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd +++ b/addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd @@ -1,5 +1,4 @@ @tool -class_name CreateVariableButton extends MarginContainer signal create_variable(var_name: String, var_type: String) diff --git a/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd index af1db397..61e5f417 100644 --- a/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd +++ b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd @@ -1,6 +1,8 @@ @tool extends ConfirmationDialog +const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd") + signal create_variable(var_name: String, var_type: String) @onready var _variable_input := %VariableInput diff --git a/addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd b/addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd index 03de2a0b..6f27bf3b 100644 --- a/addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd +++ b/addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd @@ -1,6 +1,7 @@ @tool -class_name VariableCategoryDisplay -extends BlockCategoryDisplay +extends "res://addons/block_code/ui/picker/categories/block_category_display.gd" + +const Types = preload("res://addons/block_code/types/types.gd") signal variable_created(variable: VariableResource) diff --git a/addons/block_code/ui/picker/picker.gd b/addons/block_code/ui/picker/picker.gd index a18e5d4b..d58c8061 100644 --- a/addons/block_code/ui/picker/picker.gd +++ b/addons/block_code/ui/picker/picker.gd @@ -1,7 +1,13 @@ @tool -class_name Picker extends MarginContainer +const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") +const BlockCategoryButtonScene = preload("res://addons/block_code/ui/picker/categories/block_category_button.tscn") +const BlockCategoryButton = preload("res://addons/block_code/ui/picker/categories/block_category_button.gd") +const BlockCategoryDisplay = preload("res://addons/block_code/ui/picker/categories/block_category_display.gd") +const CategoryFactory = preload("res://addons/block_code/ui/picker/categories/category_factory.gd") +const VariableCategoryDisplay = preload("res://addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd") + signal block_picked(block: Block) signal variable_created(variable: VariableResource) @@ -57,7 +63,7 @@ func init_picker(extra_blocks: Array[Block] = [], extra_categories: Array[BlockC for _category in block_categories: var category: BlockCategory = _category as BlockCategory - var block_category_button: BlockCategoryButton = preload("res://addons/block_code/ui/picker/categories/block_category_button.tscn").instantiate() + var block_category_button: BlockCategoryButton = BlockCategoryButtonScene.instantiate() block_category_button.category = category block_category_button.selected.connect(_category_selected) diff --git a/addons/block_code/ui/title_bar/title_bar.gd b/addons/block_code/ui/title_bar/title_bar.gd index 79531122..6f548374 100644 --- a/addons/block_code/ui/title_bar/title_bar.gd +++ b/addons/block_code/ui/title_bar/title_bar.gd @@ -1,7 +1,8 @@ @tool -class_name TitleBar extends MarginContainer +const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd") + signal node_name_changed(node_name: String) @onready var _block_code_icon = load("res://addons/block_code/block_code_node/block_code_node.svg") as Texture2D diff --git a/tests/test_category_factory.gd b/tests/test_category_factory.gd index 42896a24..186d97b4 100644 --- a/tests/test_category_factory.gd +++ b/tests/test_category_factory.gd @@ -1,6 +1,8 @@ extends GutTest ## Tests for CategoryFactory +const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") + func free_block_list(blocks: Array[Block]): var block: Block = blocks.pop_back() diff --git a/tests/test_instruction_tree.gd b/tests/test_instruction_tree.gd index c38db13f..e57ea7a6 100644 --- a/tests/test_instruction_tree.gd +++ b/tests/test_instruction_tree.gd @@ -1,6 +1,9 @@ extends GutTest ## Tests for InstructionTree +const CategoryFactory = preload("res://addons/block_code/ui/picker/categories/category_factory.gd") +const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") + var general_blocks: Dictionary From 626ab89b5c44cca8a597d8d02451dadc5f576c05 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Thu, 18 Jul 2024 16:29:17 -0600 Subject: [PATCH 087/423] Move DragManager.get_tree_scope to InstructionTree This static function has nothing to do with the DragManager class since it's simply walking a tree of Nodes and looking for a Block that has a non-empty scope property set. I'm not sure it really fits in InstructionTree either, but that's a better fit at least. This avoids some dependency issues between DragManager, its inner Drag class, and BlockCanvas. https://phabricator.endlessm.com/T35494 --- addons/block_code/drag_manager/drag.gd | 4 ++-- addons/block_code/drag_manager/drag_manager.gd | 16 ++-------------- .../instruction_tree/instruction_tree.gd | 13 +++++++++++++ .../block_code/ui/block_canvas/block_canvas.gd | 2 +- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/addons/block_code/drag_manager/drag.gd b/addons/block_code/drag_manager/drag.gd index efa830e6..2043b07e 100644 --- a/addons/block_code/drag_manager/drag.gd +++ b/addons/block_code/drag_manager/drag.gd @@ -3,7 +3,7 @@ extends Control const BlockCanvas = preload("res://addons/block_code/ui/block_canvas/block_canvas.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") -const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") +const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") const Types = preload("res://addons/block_code/types/types.gd") enum DragAction { NONE, PLACE, REMOVE } @@ -142,7 +142,7 @@ func _snaps_to(node: Node) -> bool: if _block_scope != top_block.get_entry_statement(): return false elif top_block: - var tree_scope := DragManager.get_tree_scope(top_block) + var tree_scope := InstructionTree.get_tree_scope(top_block) if tree_scope != "" and _block_scope != tree_scope: return false diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index fb070196..f8adf904 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -6,6 +6,7 @@ signal block_modified const BlockCanvas = preload("res://addons/block_code/ui/block_canvas/block_canvas.gd") const Drag = preload("res://addons/block_code/drag_manager/drag.gd") +const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") const Picker = preload("res://addons/block_code/ui/picker/picker.gd") @export var picker_path: NodePath @@ -49,7 +50,7 @@ func drag_block(block: Block, copied_from: Block = null): block.disconnect_signals() - var block_scope := get_tree_scope(block) + var block_scope := InstructionTree.get_tree_scope(block) if block_scope != "": _block_canvas.set_scope(block_scope) @@ -92,16 +93,3 @@ func connect_block_canvas_signals(block: Block): block.drag_started.connect(drag_block) if block.modified.get_connections().size() == 0: block.modified.connect(func(): block_modified.emit()) - - -## Returns the scope of the first non-empty scope child block -static func get_tree_scope(node: Node) -> String: - if node is Block: - if node.scope != "": - return node.scope - - for c in node.get_children(): - var scope := get_tree_scope(c) - if scope != "": - return scope - return "" diff --git a/addons/block_code/instruction_tree/instruction_tree.gd b/addons/block_code/instruction_tree/instruction_tree.gd index 786bd8e5..5e82c6b4 100644 --- a/addons/block_code/instruction_tree/instruction_tree.gd +++ b/addons/block_code/instruction_tree/instruction_tree.gd @@ -120,3 +120,16 @@ static func _generate_script_from_entry_blocks(entry_statement: String, entry_bl script += "\tpass\n\n" return script + + +## Returns the scope of the first non-empty scope child block +static func get_tree_scope(node: Node) -> String: + if node is Block: + if node.scope != "": + return node.scope + + for c in node.get_children(): + var scope := get_tree_scope(c) + if scope != "": + return scope + return "" diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 040e294f..3bee7382 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -218,7 +218,7 @@ func set_scope(scope: String): if scope == block.get_entry_statement(): valid = true else: - var tree_scope := DragManager.get_tree_scope(block) + var tree_scope := InstructionTree.get_tree_scope(block) if tree_scope == "" or scope == tree_scope: valid = true From 9aae2bb655037fb8bab71caf74a33eed0889c7f5 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Tue, 23 Jul 2024 15:50:46 -0600 Subject: [PATCH 088/423] Block: Add setter to manage bottom_snap Add a setter for bottom_snap_path so that bottom_snap can be set immediately without waiting for the node to become ready. This simplifies testing as the Block doesn't need to be added to a scene to work correctly. https://phabricator.endlessm.com/T35573 --- addons/block_code/ui/blocks/block/block.gd | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 2480869a..8f4832ff 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -24,7 +24,8 @@ signal modified @export var category: String ## The next block in the line of execution (can be null if end) -@export var bottom_snap_path: NodePath +@export var bottom_snap_path: NodePath: + set = _set_bottom_snap_path ## The scope of the block (statement of matching entry block) @export var scope: String = "" @@ -35,8 +36,12 @@ signal modified var bottom_snap: SnapPoint -func _ready(): +func _set_bottom_snap_path(value: NodePath): + bottom_snap_path = value bottom_snap = get_node_or_null(bottom_snap_path) + + +func _ready(): mouse_filter = Control.MOUSE_FILTER_IGNORE From f21368b39df7c15277708c6c7e529e9a6f4db9f8 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Wed, 24 Jul 2024 13:57:14 +0100 Subject: [PATCH 089/423] ci: Use asset lib action 0.6.0 All my PRs were merged & released so this is equivalent to the version we have been using from my fork. --- .github/workflows/godot-asset-library.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/godot-asset-library.yaml b/.github/workflows/godot-asset-library.yaml index 69c291b7..e57363a1 100644 --- a/.github/workflows/godot-asset-library.yaml +++ b/.github/workflows/godot-asset-library.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Push to Godot Asset Library - uses: wjt/godot-asset-lib-action@9cce3792b504bec69eb06b852b008d095e372f56 + uses: deep-entertainment/godot-asset-lib-action@v0.6.0 with: username: ${{ secrets.GODOT_ASSET_LIBRARY_USERNAME }} password: ${{ secrets.GODOT_ASSET_LIBRARY_PASSWORD }} From b02713067eaea3888a6e0f25c4a1c6e08893993d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 24 Jul 2024 10:43:06 -0300 Subject: [PATCH 090/423] ParameterInput: Validate text input before submit For float, int, and Vector2 types. If the text is not valid, reset to the last submitted text and don't emit the midified signal. --- .../parameter_input/parameter_input.gd | 50 +++++++++++-------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd index 7d28fcc9..8e603475 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd +++ b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd @@ -33,9 +33,11 @@ var option: bool = false @onready var _bool_input_option := %BoolInputOption # Used to submit the text when losing focus: -var _last_lineedit_submitted_text: String -var _last_x_lineedit_submitted_text: String -var _last_y_lineedit_submitted_text: String +@onready var _last_submitted_text = { + _line_edit: _line_edit.text, + _x_line_edit: _x_line_edit.text, + _y_line_edit: _y_line_edit.text, +} func set_raw_input(raw_input): @@ -99,10 +101,6 @@ func _ready(): snap_point.block_type = block_type snap_point.variant_type = variant_type - _last_lineedit_submitted_text = _line_edit.text - _last_x_lineedit_submitted_text = _x_line_edit.text - _last_y_lineedit_submitted_text = _y_line_edit.text - _update_visible_input() @@ -136,34 +134,44 @@ func get_string() -> String: return "%s" % input -func _on_line_edit_text_submitted(new_text): - _last_lineedit_submitted_text = new_text +func _validate_and_submit_edit_text(line_edit: Node, type: Variant.Type): + if _last_submitted_text[line_edit] == line_edit.text: + return + match type: + TYPE_FLOAT: + if not line_edit.text.is_valid_float(): + line_edit.text = _last_submitted_text[line_edit] + return + TYPE_INT: + if not line_edit.text.is_valid_int(): + line_edit.text = _last_submitted_text[line_edit] + return + _last_submitted_text[line_edit] = line_edit.text modified.emit() +func _on_line_edit_text_submitted(_new_text): + _validate_and_submit_edit_text(_line_edit, variant_type) + + func _on_line_edit_focus_exited(): - if _last_lineedit_submitted_text != _line_edit.text: - modified.emit() + _validate_and_submit_edit_text(_line_edit, variant_type) -func _on_x_line_edit_text_submitted(new_text): - _last_x_lineedit_submitted_text = new_text - modified.emit() +func _on_x_line_edit_text_submitted(_new_text): + _validate_and_submit_edit_text(_x_line_edit, TYPE_FLOAT) func _on_x_line_edit_focus_exited(): - if _last_x_lineedit_submitted_text != _x_line_edit.text: - modified.emit() + _validate_and_submit_edit_text(_x_line_edit, TYPE_FLOAT) -func _on_y_line_edit_text_submitted(new_text): - _last_y_lineedit_submitted_text = new_text - modified.emit() +func _on_y_line_edit_text_submitted(_new_text): + _validate_and_submit_edit_text(_y_line_edit, TYPE_FLOAT) func _on_y_line_edit_focus_exited(): - if _last_y_lineedit_submitted_text != _y_line_edit.text: - modified.emit() + _validate_and_submit_edit_text(_y_line_edit, TYPE_FLOAT) func _update_visible_input(): From e9ffc17f8ad8f4daf8c2f3333f921ded10657496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 24 Jul 2024 10:47:10 -0300 Subject: [PATCH 091/423] ParameterInput: Improve _switch_input function --- .../ui/blocks/utilities/parameter_input/parameter_input.gd | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd index 8e603475..95073a0e 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd +++ b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd @@ -193,15 +193,11 @@ func _update_visible_input(): func _switch_input(node: Node): for c in _input_switcher.get_children(): - c.visible = false - - if node: - node.visible = true + c.visible = c == node func _on_color_input_color_changed(color): _update_panel_bg_color(color) - modified.emit() From 98fa3b3f840dd48ea5b821ce58241391c76c92f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 24 Jul 2024 11:17:19 -0300 Subject: [PATCH 092/423] CategoryFactory: Use degrees for rotation We are not exposing PI or TAU constants. It's simpler to have a single way to set/change rotation as degrees. The Godot UI also has a degrees slider for Node2D rotation. rotation_degrees is a property, so remove the custom setter. --- .../block_code/ui/picker/categories/category_factory.gd | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 2e07279f..021d04b2 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -593,16 +593,9 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: match _class_name: "Node2D": - var b = BLOCKS["statement_block"].instantiate() - b.block_name = "node2d_rotation" - b.block_format = "Set Rotation Degrees {angle: FLOAT}" - b.statement = "rotation_degrees = {angle}" - b.category = "Transform | Rotation" - block_list.append(b) - props = { "position": "Transform | Position", - "rotation": "Transform | Rotation", + "rotation_degrees": "Transform | Rotation", "scale": "Transform | Scale", } From ce6f0a1be3eb2a9424c35dabe57d23252ffdba4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 24 Jul 2024 12:02:04 -0300 Subject: [PATCH 093/423] CategoryFactory: Add defaults to all blocks All possible blocks gain default values. So they can be used directly without having to type a value. And most importantly, so the script is not generated with syntax errors. The defaults are opinionated, they have to be. Eg. set scale to double size, change position so the node2d moves to the right-bottom. Also: remove "change by" block for modulate and visible properties. They don't make sense. https://phabricator.endlessm.com/T35562 --- .../ui/picker/categories/category_factory.gd | 90 +++++++++++++++---- 1 file changed, 71 insertions(+), 19 deletions(-) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 021d04b2..f4386b31 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -362,6 +362,7 @@ static func get_general_blocks() -> Array[Block]: b.variant_type = TYPE_VECTOR2 b.block_format = "Vector2 x: {x: FLOAT} y: {y: FLOAT}" b.statement = "Vector2({x}, {y})" + b.defaults = {"x": "0", "y": "0"} b.category = "Variables" block_list.append(b) @@ -373,6 +374,7 @@ static func get_general_blocks() -> Array[Block]: b.variant_type = TYPE_INT b.block_format = "{a: INT} + {b: INT}" b.statement = "({a} + {b})" + b.defaults = {"a": "1", "b": "1"} b.category = "Math" block_list.append(b) @@ -381,6 +383,7 @@ static func get_general_blocks() -> Array[Block]: b.variant_type = TYPE_INT b.block_format = "{a: INT} - {b: INT}" b.statement = "({a} - {b})" + b.defaults = {"a": "1", "b": "1"} b.category = "Math" block_list.append(b) @@ -389,6 +392,7 @@ static func get_general_blocks() -> Array[Block]: b.variant_type = TYPE_INT b.block_format = "{a: INT} * {b: INT}" b.statement = "({a} * {b})" + b.defaults = {"a": "1", "b": "1"} b.category = "Math" block_list.append(b) @@ -397,6 +401,7 @@ static func get_general_blocks() -> Array[Block]: b.variant_type = TYPE_INT b.block_format = "{a: INT} / {b: INT}" b.statement = "({a} / {b})" + b.defaults = {"a": "1", "b": "1"} b.category = "Math" block_list.append(b) @@ -405,6 +410,7 @@ static func get_general_blocks() -> Array[Block]: b.variant_type = TYPE_INT b.block_format = "{base: INT} ^ {exp: INT}" b.statement = "(pow({base}, {exp}))" + b.defaults = {"base": "1", "exp": "1"} b.category = "Math" block_list.append(b) @@ -413,14 +419,14 @@ static func get_general_blocks() -> Array[Block]: b = BLOCKS["control_block"].instantiate() b.block_name = "if" - b.block_formats = ["if {condition: BOOL}"] + b.block_formats = ["if {condition: BOOL}"] b.statements = ["if {condition}:"] b.category = "Logic | Conditionals" block_list.append(b) b = BLOCKS["control_block"].instantiate() b.block_name = "if_else" - b.block_formats = ["if {condition: BOOL}", "else"] + b.block_formats = ["if {condition: BOOL}", "else"] b.statements = ["if {condition}:", "else:"] b.category = "Logic | Conditionals" block_list.append(b) @@ -430,7 +436,11 @@ static func get_general_blocks() -> Array[Block]: b.variant_type = TYPE_BOOL b.block_format = "{int1: INT} {op: OPTION} {int2: INT}" b.statement = "({int1} {op} {int2})" - b.defaults = {"op": OptionData.new(["==", ">", "<", ">=", "<=", "!="])} + b.defaults = { + "op": OptionData.new(["==", ">", "<", ">=", "<=", "!="]), + "int1": "1", + "int2": "1", + } b.category = "Logic | Comparison" block_list.append(b) @@ -529,6 +539,20 @@ static func property_to_blocklist(property: Dictionary) -> Array[Block]: var variant_type = property.type + const FALLBACK_SET_FOR_TYPE = { + TYPE_INT: "0", + TYPE_FLOAT: "0", + TYPE_VECTOR2: "0, 0", + TYPE_COLOR: "DARK_ORANGE", + } + + const FALLBACK_CHANGE_FOR_TYPE = { + TYPE_INT: "1", + TYPE_FLOAT: "1", + TYPE_VECTOR2: "1, 1", + TYPE_COLOR: "DARK_ORANGE", + } + if variant_type: var type_string: String = Types.VARIANT_TYPE_TO_STRING[variant_type] @@ -536,15 +560,20 @@ static func property_to_blocklist(property: Dictionary) -> Array[Block]: b.block_name = "set_prop_%s" % property.name b.block_format = "Set %s to {value: %s}" % [property.name.capitalize(), type_string] b.statement = "%s = {value}" % property.name + var default_set = property.get("default_set", FALLBACK_SET_FOR_TYPE.get(variant_type, "")) + b.defaults = {"value": default_set} b.category = property.category block_list.append(b) - b = BLOCKS["statement_block"].instantiate() - b.block_name = "change_prop_%s" % property.name - b.block_format = "Change %s by {value: %s}" % [property.name.capitalize(), type_string] - b.statement = "%s += {value}" % property.name - b.category = property.category - block_list.append(b) + if property.get("has_change", true): + b = BLOCKS["statement_block"].instantiate() + b.block_name = "change_prop_%s" % property.name + b.block_format = "Change %s by {value: %s}" % [property.name.capitalize(), type_string] + b.statement = "%s += {value}" % property.name + var default_change = property.get("default_change", FALLBACK_CHANGE_FOR_TYPE[variant_type]) + b.defaults = {"value": default_change} + b.category = property.category + block_list.append(b) b = BLOCKS["parameter_block"].instantiate() b.block_name = "get_prop_%s" % property.name @@ -565,7 +594,7 @@ static func blocks_from_property_list(property_list: Array, selected_props: Dict for prop in property_list: if selected_property == prop.name: found_prop = prop - found_prop.category = selected_props[selected_property] + found_prop.merge(selected_props[selected_property]) break if found_prop: block_list.append_array(property_to_blocklist(found_prop)) @@ -594,15 +623,38 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: match _class_name: "Node2D": props = { - "position": "Transform | Position", - "rotation_degrees": "Transform | Rotation", - "scale": "Transform | Scale", + "position": + { + "category": "Transform | Position", + "default_set": "100, 100", + "default_change": "1, 1", + }, + "rotation_degrees": + { + "category": "Transform | Rotation", + "default_set": "45", + "default_change": "1", + }, + "scale": + { + "category": "Transform | Scale", + "default_set": "2, 2", + "default_change": "0.1, 0.1", + }, } "CanvasItem": props = { - "modulate": "Graphics | Modulate", - "visible": "Graphics | Visibility", + "modulate": + { + "category": "Graphics | Modulate", + "has_change": false, + }, + "visible": + { + "category": "Graphics | Visibility", + "has_change": false, + }, } "RigidBody2D": @@ -643,9 +695,9 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: block_list.append(b) props = { - "mass": "Physics | Mass", - "linear_velocity": "Physics | Velocity", - "angular_velocity": "Physics | Velocity", + "mass": {"category": "Physics | Mass"}, + "linear_velocity": {"category": "Physics | Velocity"}, + "angular_velocity": {"category": "Physics | Velocity"}, } "AnimationPlayer": @@ -747,7 +799,7 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: block_list.append(b) props = { - "velocity": "Physics | Velocity", + "velocity": {"category": "Physics | Velocity"}, } var prop_list = ClassDB.class_get_property_list(_class_name, true) From b81ddae9670953744e4019773361da8cabe3e576 Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Fri, 26 Jul 2024 10:55:13 -0600 Subject: [PATCH 094/423] Issue template: Add Block Coding version input --- .github/ISSUE_TEMPLATE/public.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/public.yml b/.github/ISSUE_TEMPLATE/public.yml index fd95efb4..96ca97bc 100644 --- a/.github/ISSUE_TEMPLATE/public.yml +++ b/.github/ISSUE_TEMPLATE/public.yml @@ -25,6 +25,13 @@ body: validations: required: true + - type: input + id: v + attributes: + label: Block Coding Plugin Version + description: What version of the plugin are you using? You can check in **Project** → **Project Settings** → **Plugins** + placeholder: e.g. Windows 11, Fedora Silverblue 39, Ubuntu 22.04, etc. + - type: input id: os attributes: From 289a09ee93a7a6d2022817af7c7b0824cb5f1ced Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Fri, 26 Jul 2024 10:55:53 -0600 Subject: [PATCH 095/423] Issue template: Correct plugin version placeholder text --- .github/ISSUE_TEMPLATE/public.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/public.yml b/.github/ISSUE_TEMPLATE/public.yml index 96ca97bc..68dafcc2 100644 --- a/.github/ISSUE_TEMPLATE/public.yml +++ b/.github/ISSUE_TEMPLATE/public.yml @@ -30,7 +30,7 @@ body: attributes: label: Block Coding Plugin Version description: What version of the plugin are you using? You can check in **Project** → **Project Settings** → **Plugins** - placeholder: e.g. Windows 11, Fedora Silverblue 39, Ubuntu 22.04, etc. + placeholder: e.g. v0.6.1 - type: input id: os From 6f7bb2d70e13a1a1de708a0b706a92e139ef052c Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Fri, 26 Jul 2024 11:00:20 -0600 Subject: [PATCH 096/423] Issue template: Add Godot version --- .github/ISSUE_TEMPLATE/public.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/public.yml b/.github/ISSUE_TEMPLATE/public.yml index 68dafcc2..4e749039 100644 --- a/.github/ISSUE_TEMPLATE/public.yml +++ b/.github/ISSUE_TEMPLATE/public.yml @@ -29,15 +29,22 @@ body: id: v attributes: label: Block Coding Plugin Version - description: What version of the plugin are you using? You can check in **Project** → **Project Settings** → **Plugins** - placeholder: e.g. v0.6.1 + description: What version of the plugin are you using? You can check in **Project** → **Project Settings** → **Plugins**. + placeholder: v0.0.0 + + - type: input + id: godot + attributes: + label: Godot Engine Version + description: What version of Godot are you using? You can copy it by clicking the version in **Help** → **About Godot…**. + placeholder: v0.0.0.stable - type: input id: os attributes: label: Operating System description: What specific OS and version are you seeing the problem on? - placeholder: e.g. Windows 11, Fedora Silverblue 39, Ubuntu 22.04, etc. + placeholder: Windows 11, Fedora Silverblue 39, Ubuntu 22.04, etc. - type: textarea id: logs From 7d04b49536bcd76fd6fad93f06acd31b4069c75b Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Fri, 26 Jul 2024 12:02:55 -0600 Subject: [PATCH 097/423] Category factory: Tweak tooltips "The following" was confusing to me; this makes it more clear by saying "Attached blocks" --- addons/block_code/ui/picker/categories/category_factory.gd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index f4386b31..2b229f90 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -175,7 +175,7 @@ static func get_general_blocks() -> Array[Block]: b.block_name = "ready_block" b.block_format = "On Ready" b.statement = "func _ready():" - b.tooltip_text = 'The following will be executed when the node is "ready"' + b.tooltip_text = 'Attached blocks will be executed once when the node is "ready"' b.category = "Lifecycle" block_list.append(b) @@ -183,7 +183,7 @@ static func get_general_blocks() -> Array[Block]: b.block_name = "process_block" b.block_format = "On Process" b.statement = "func _process(delta):" - b.tooltip_text = "The following will be executed during the processing step of the main loop" + b.tooltip_text = "Attached blocks will be executed during the processing step of the main loop" b.category = "Lifecycle" block_list.append(b) @@ -191,7 +191,7 @@ static func get_general_blocks() -> Array[Block]: b.block_name = "physics_process_block" b.block_format = "On Physics Process" b.statement = "func _physics_process(delta):" - b.tooltip_text = 'The following will be executed during the "physics" processing step of the main loop' + b.tooltip_text = 'Attached blocks will be executed during the "physics" processing step of the main loop' b.category = "Lifecycle" block_list.append(b) From 3008a05478cd5df01d175c0c4b4f73eaf6794be5 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Fri, 26 Jul 2024 23:03:11 -0600 Subject: [PATCH 098/423] Util: Make node_is_part_of_edited_scene safer When switching to a different scene in the editor, the previous edited scene root will no longer have a parent and you'll see a pile of "Cannot call method 'is_ancestor_of' on a null value." errors from Godot. Unroll the one liner to add the parent null check and use some intermediate variables to remove duplicate method calls. Note that the is_inside_tree() call is dropped since it's redundant to checking if get_tree() returns null. --- addons/block_code/ui/util.gd | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index d4b80bd4..46918d2f 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -3,4 +3,12 @@ extends Object ## Polyfill of Node.is_part_of_edited_scene(), available to GDScript in Godot 4.3+. static func node_is_part_of_edited_scene(node: Node) -> bool: - return Engine.is_editor_hint() && node.is_inside_tree() && node.get_tree().edited_scene_root && node.get_tree().edited_scene_root.get_parent().is_ancestor_of(node) + if not Engine.is_editor_hint(): + return false + + var tree := node.get_tree() + if not tree or not tree.edited_scene_root: + return false + + var edited_scene_parent := tree.edited_scene_root.get_parent() + return edited_scene_parent and edited_scene_parent.is_ancestor_of(node) From 319a8a148e0894c7bb213ebd94d93b4b464c7f96 Mon Sep 17 00:00:00 2001 From: Jian-Hong Pan Date: Fri, 26 Jul 2024 11:53:40 +0800 Subject: [PATCH 099/423] category_factory: Add stop audio feature https://phabricator.endlessm.com/T35582 --- .../ui/picker/categories/category_factory.gd | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 2b229f90..058cd7d8 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -502,6 +502,21 @@ static func get_general_blocks() -> Array[Block]: b.tooltip_text = "Play the audio stream with volume and pitch" b.category = "Sounds" block_list.append(b) + + b = BLOCKS["statement_block"].instantiate() + b.block_name = "stop_sound" + b.block_type = Types.BlockType.EXECUTE + b.block_format = "Stop the sound {name: STRING}" + b.statement = ( + """ + var __sound_node = get_node({name}) + __sound_node.stop() + """ + . dedent() + ) + b.tooltip_text = "Stop the audio stream" + b.category = "Sounds" + block_list.append(b) #endregion #region Graphics From fc8f192b03fee30916dc48c199c92b5c77fe28d5 Mon Sep 17 00:00:00 2001 From: Jian-Hong Pan Date: Fri, 26 Jul 2024 12:06:26 +0800 Subject: [PATCH 100/423] category_factory: Add pause and continue audio feature https://phabricator.endlessm.com/T35582 --- .../ui/picker/categories/category_factory.gd | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 058cd7d8..c28c4019 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -503,6 +503,25 @@ static func get_general_blocks() -> Array[Block]: b.category = "Sounds" block_list.append(b) + b = BLOCKS["statement_block"].instantiate() + b.block_name = "pause_continue_sound" + b.block_type = Types.BlockType.EXECUTE + b.block_format = "{pause: OPTION} the sound {name: STRING}" + b.statement = ( + """ + var __sound_node = get_node({name}) + if "{pause}" == "pause": + __sound_node.stream_paused = true + else: + __sound_node.stream_paused = false + """ + . dedent() + ) + b.defaults = {"pause": OptionData.new(["Pause", "Continue"])} + b.tooltip_text = "Pause/Continue the audio stream" + b.category = "Sounds" + block_list.append(b) + b = BLOCKS["statement_block"].instantiate() b.block_name = "stop_sound" b.block_type = Types.BlockType.EXECUTE From c83d96835551f110e2e7f962657374b50c4b586f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 30 Jul 2024 08:33:05 -0300 Subject: [PATCH 101/423] Block: Set bottom_snap_path when ready The bottom_snap must be set on ready, regardless of previously setting it. Regression from 9aae2bb6 Fixes: #172 --- addons/block_code/ui/blocks/block/block.gd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 17cbd008..5cb37baf 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -45,6 +45,8 @@ func _set_bottom_snap_path(value: NodePath): func _ready(): + if bottom_snap == null: + _set_bottom_snap_path(bottom_snap_path) mouse_filter = Control.MOUSE_FILTER_IGNORE From 29dd94394e304fd436779cf39ebdf11018a6e681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 29 Jul 2024 21:30:07 -0300 Subject: [PATCH 102/423] CategoryFactory: Fix Vector2 defaults If a space is left in the Y axis, the default doesn't work. This fixes a bug where focusing the Y side of a Vector2 input and then losing the focus ends with the " " string in the input, losing the default number. --- .../ui/picker/categories/category_factory.gd | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index c28c4019..14d03b7c 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -576,14 +576,14 @@ static func property_to_blocklist(property: Dictionary) -> Array[Block]: const FALLBACK_SET_FOR_TYPE = { TYPE_INT: "0", TYPE_FLOAT: "0", - TYPE_VECTOR2: "0, 0", + TYPE_VECTOR2: "0,0", TYPE_COLOR: "DARK_ORANGE", } const FALLBACK_CHANGE_FOR_TYPE = { TYPE_INT: "1", TYPE_FLOAT: "1", - TYPE_VECTOR2: "1, 1", + TYPE_VECTOR2: "1,1", TYPE_COLOR: "DARK_ORANGE", } @@ -660,8 +660,8 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: "position": { "category": "Transform | Position", - "default_set": "100, 100", - "default_change": "1, 1", + "default_set": "100,100", + "default_change": "1,1", }, "rotation_degrees": { @@ -672,8 +672,8 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: "scale": { "category": "Transform | Scale", - "default_set": "2, 2", - "default_change": "0.1, 0.1", + "default_set": "2,2", + "default_change": "0.1,0.1", }, } From 189725b3f0e4f480b43af72ea1f9547b8cae6156 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 30 Jul 2024 16:48:23 -0300 Subject: [PATCH 103/423] Block Canvas: Reuse saved block scene resource By simply assigning it to the scene resource property when loading the tree. Follow up of 01ab76c5 which already removed all resource regeneration except when loading the canvas. --- addons/block_code/ui/block_canvas/block_canvas.gd | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 3bee7382..f4d2733d 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -164,6 +164,7 @@ func load_tree(parent: Node, node: SerializedBlockTreeNode): var scene: Block = load(_block_scene_path).instantiate() for prop_pair in node.serialized_block.serialized_props: scene.set(prop_pair[0], prop_pair[1]) + scene.resource = node parent.add_child(scene) var scene_block: Block = scene as Block From c92f254f81d1e66021169207d68273d0698feb3e Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 30 Jul 2024 11:55:27 -0700 Subject: [PATCH 104/423] Improve ControlBlock background drawing Instead of reusing the background.gd script to draw a gutter in ControlBlock, define a new script (gutter.gd) specifically for that purpose. In the existing background.gd script, draw a left border which is expected to flow into the gutter if shift_top or shift_bottom is set. https://phabricator.endlessm.com/T35538 --- .../ui/blocks/control_block/control_block.gd | 16 +++++--- .../blocks/control_block/control_block.tscn | 7 ---- .../blocks/utilities/background/background.gd | 27 ++++++++++++-- .../ui/blocks/utilities/background/gutter.gd | 37 +++++++++++++++++++ 4 files changed, 70 insertions(+), 17 deletions(-) create mode 100644 addons/block_code/ui/blocks/utilities/background/gutter.gd diff --git a/addons/block_code/ui/blocks/control_block/control_block.gd b/addons/block_code/ui/blocks/control_block/control_block.gd index 8995b115..9083b7af 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.gd +++ b/addons/block_code/ui/blocks/control_block/control_block.gd @@ -13,15 +13,10 @@ var snaps: Array var param_name_input_pairs_array: Array var param_input_strings_array: Array # Only loaded from serialized -@onready var _background := %Background - func _ready(): super() - _background.color = color - _background.custom_minimum_size.x = Constants.CONTROL_MARGIN - format() if param_input_strings_array: @@ -148,9 +143,18 @@ func format(): snap_container.custom_minimum_size.x = 30 snap_container.custom_minimum_size.y = 30 snap_container.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN - snap_container.add_theme_constant_override("margin_left", Constants.CONTROL_MARGIN) + + var snap_gutter := Control.new() + snap_gutter.name = "Background" + snap_gutter.set_script(preload("res://addons/block_code/ui/blocks/utilities/background/gutter.gd")) + snap_gutter.custom_minimum_size.x = Constants.CONTROL_MARGIN + snap_gutter.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN + snap_gutter.size_flags_vertical = Control.SIZE_EXPAND_FILL + snap_gutter.color = color + snap_container.add_child(snap_gutter) var snap_point: SnapPoint = preload("res://addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn").instantiate() + snap_point.add_theme_constant_override("margin_left", Constants.CONTROL_MARGIN) snap_container.add_child(snap_point) snaps.append(snap_point) diff --git a/addons/block_code/ui/blocks/control_block/control_block.tscn b/addons/block_code/ui/blocks/control_block/control_block.tscn index 81790457..a482e11f 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.tscn +++ b/addons/block_code/ui/blocks/control_block/control_block.tscn @@ -27,13 +27,6 @@ mouse_filter = 2 theme_override_constants/margin_top = 30 theme_override_constants/margin_bottom = 30 -[node name="Background" type="ColorRect" parent="VBoxContainer/MarginContainer/MarginContainer"] -unique_name_in_owner = true -custom_minimum_size = Vector2(20, 0) -layout_mode = 2 -size_flags_horizontal = 0 -color = Color(0.59979, 0.536348, 0.876215, 1) - [node name="Rows" type="VBoxContainer" parent="VBoxContainer/MarginContainer"] unique_name_in_owner = true layout_mode = 2 diff --git a/addons/block_code/ui/blocks/utilities/background/background.gd b/addons/block_code/ui/blocks/utilities/background/background.gd index 0c61f669..e8aec7c1 100644 --- a/addons/block_code/ui/blocks/utilities/background/background.gd +++ b/addons/block_code/ui/blocks/utilities/background/background.gd @@ -60,7 +60,14 @@ func _draw(): fill_polygon.append(Vector2(0.0, 0.0)) var stroke_polygon: PackedVector2Array - stroke_polygon.append(Vector2(shift_top, 0.0)) + var edge_polygon: PackedVector2Array + var outline_middle = Constants.OUTLINE_WIDTH / 2 + + if shift_top > 0: + stroke_polygon.append(Vector2(shift_top - outline_middle, 0.0)) + else: + stroke_polygon.append(Vector2(shift_top, 0.0)) + if show_top: stroke_polygon.append(Vector2(Constants.KNOB_X + shift_top, 0.0)) stroke_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_top, Constants.KNOB_H)) @@ -74,9 +81,21 @@ func _draw(): stroke_polygon.append(Vector2(Constants.KNOB_X + Constants.KNOB_Z + shift_bottom, size.y + Constants.KNOB_H)) stroke_polygon.append(Vector2(Constants.KNOB_X + shift_bottom, size.y)) - stroke_polygon.append(Vector2(shift_bottom, size.y)) - if shift_top + shift_bottom == 0: - stroke_polygon.append(Vector2(0.0, 0.0)) + if shift_bottom > 0: + stroke_polygon.append(Vector2(shift_bottom - outline_middle, size.y)) + else: + stroke_polygon.append(Vector2(shift_bottom, size.y)) + + if shift_top > 0: + edge_polygon.append(Vector2(0.0, 0.0)) + else: + edge_polygon.append(Vector2(0.0, 0.0 - outline_middle)) + + if shift_bottom > 0: + edge_polygon.append(Vector2(0.0, size.y)) + else: + edge_polygon.append(Vector2(0.0, size.y + outline_middle)) draw_colored_polygon(fill_polygon, color) draw_polyline(stroke_polygon, outline_color, Constants.OUTLINE_WIDTH) + draw_polyline(edge_polygon, outline_color, Constants.OUTLINE_WIDTH) diff --git a/addons/block_code/ui/blocks/utilities/background/gutter.gd b/addons/block_code/ui/blocks/utilities/background/gutter.gd new file mode 100644 index 00000000..f449949f --- /dev/null +++ b/addons/block_code/ui/blocks/utilities/background/gutter.gd @@ -0,0 +1,37 @@ +@tool +extends Control + +const Constants = preload("res://addons/block_code/ui/constants.gd") + +var outline_color: Color + +@export var color: Color: + set = _set_color + + +func _set_color(new_color): + color = new_color + outline_color = color.darkened(0.2) + queue_redraw() + + +func _draw(): + var fill_polygon: PackedVector2Array + fill_polygon.append(Vector2(0.0, 0.0)) + fill_polygon.append(Vector2(size.x, 0.0)) + fill_polygon.append(Vector2(size.x, size.y)) + fill_polygon.append(Vector2(0.0, size.y)) + fill_polygon.append(Vector2(0.0, 0.0)) + + var left_polygon: PackedVector2Array + var right_polygon: PackedVector2Array + + left_polygon.append(Vector2(0.0, 0.0)) + left_polygon.append(Vector2(0.0, size.y)) + + right_polygon.append(Vector2(size.x, 0.0)) + right_polygon.append(Vector2(size.x, size.y)) + + draw_colored_polygon(fill_polygon, color) + draw_polyline(left_polygon, outline_color, Constants.OUTLINE_WIDTH) + draw_polyline(right_polygon, outline_color, Constants.OUTLINE_WIDTH) From d2495b0418c6ff82e4fd47753251d88de10a389a Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 31 Jul 2024 09:56:15 -0700 Subject: [PATCH 105/423] Use class instantiators for block background scripts https://phabricator.endlessm.com/T35538 --- addons/block_code/drag_manager/drag.gd | 4 ++-- .../ui/blocks/control_block/control_block.gd | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/addons/block_code/drag_manager/drag.gd b/addons/block_code/drag_manager/drag.gd index 2043b07e..8a667755 100644 --- a/addons/block_code/drag_manager/drag.gd +++ b/addons/block_code/drag_manager/drag.gd @@ -1,6 +1,7 @@ @tool extends Control +const Background = preload("res://addons/block_code/ui/blocks/utilities/background/background.gd") const BlockCanvas = preload("res://addons/block_code/ui/block_canvas/block_canvas.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") @@ -189,8 +190,7 @@ func _update_preview(): if target_snap_point: # Make preview block - _preview_block = Control.new() - _preview_block.set_script(preload("res://addons/block_code/ui/blocks/utilities/background/background.gd")) + _preview_block = Background.new() _preview_block.color = Color(1, 1, 1, 0.5) _preview_block.custom_minimum_size = _block.get_global_rect().size diff --git a/addons/block_code/ui/blocks/control_block/control_block.gd b/addons/block_code/ui/blocks/control_block/control_block.gd index 9083b7af..7d72e751 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.gd +++ b/addons/block_code/ui/blocks/control_block/control_block.gd @@ -2,8 +2,10 @@ class_name ControlBlock extends Block +const Background = preload("res://addons/block_code/ui/blocks/utilities/background/background.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") const DragDropArea = preload("res://addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.gd") +const Gutter = preload("res://addons/block_code/ui/blocks/utilities/background/gutter.gd") @export var block_formats: Array = [] @export var statements: Array = [] @@ -104,9 +106,8 @@ func format(): row.custom_minimum_size.y = 30 row.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN - var bg := Control.new() + var bg := Background.new() bg.name = "Background" - bg.set_script(preload("res://addons/block_code/ui/blocks/utilities/background/background.gd")) bg.color = color if i != 0: bg.shift_top = Constants.CONTROL_MARGIN @@ -144,9 +145,8 @@ func format(): snap_container.custom_minimum_size.y = 30 snap_container.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN - var snap_gutter := Control.new() + var snap_gutter := Gutter.new() snap_gutter.name = "Background" - snap_gutter.set_script(preload("res://addons/block_code/ui/blocks/utilities/background/gutter.gd")) snap_gutter.custom_minimum_size.x = Constants.CONTROL_MARGIN snap_gutter.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN snap_gutter.size_flags_vertical = Control.SIZE_EXPAND_FILL @@ -161,11 +161,10 @@ func format(): %Rows.add_child(snap_container) - var bg := Control.new() + var bg := Background.new() bg.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN bg.custom_minimum_size.x = 100 bg.custom_minimum_size.y = 30 - bg.set_script(preload("res://addons/block_code/ui/blocks/utilities/background/background.gd")) bg.color = color bg.shift_top = Constants.CONTROL_MARGIN %Rows.add_child(bg) From 73861397f6f78df03d863a066b33e8a693db8f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 31 Jul 2024 21:01:15 -0300 Subject: [PATCH 106/423] update-pong-game --- .../examples/pong_game/pong_game.tscn | 606 ++++++++++-------- 1 file changed, 344 insertions(+), 262 deletions(-) diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index 71f77d15..52a983d9 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=112 format=3 uid="uid://tf7b8c64ecc0"] +[gd_scene load_steps=129 format=3 uid="uid://tf7b8c64ecc0"] [ext_resource type="PackedScene" uid="uid://cg8ibi18um3vg" path="res://addons/block_code/examples/pong_game/space.tscn" id="1_y56ac"] [ext_resource type="Script" path="res://addons/block_code/block_code_node/block_code.gd" id="3_6jaq8"] @@ -7,125 +7,198 @@ [ext_resource type="Texture2D" uid="uid://tplpgtnfeda0" path="res://addons/block_code/examples/pong_game/assets/paddle.png" id="4_ra7bh"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block.gd" id="5_wr38c"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node_array.gd" id="6_ppdc3"] +[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="7_1f578"] [ext_resource type="Script" path="res://addons/block_code/block_script_data/block_script_data.gd" id="7_uuuue"] [ext_resource type="PackedScene" uid="uid://c7l70grmkauij" path="res://addons/block_code/examples/pong_game/ball.tscn" id="9_xrqll"] [ext_resource type="PackedScene" uid="uid://fhoapg3anjsu" path="res://addons/block_code/examples/pong_game/goal_area.tscn" id="12_nqmxu"] [ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd" id="13_tg3yk"] -[sub_resource type="Resource" id="Resource_k6jw1"] +[sub_resource type="Resource" id="Resource_7v74l"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.835294, 0.262745, 0.133333, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Move with player 1 buttons, speed {speed: VECTOR2}"], ["statement", "var dir = Vector2() -dir.x += float(Input.is_physical_key_pressed(KEY_D)) -dir.x -= float(Input.is_physical_key_pressed(KEY_A)) -dir.y += float(Input.is_physical_key_pressed(KEY_S)) -dir.y -= float(Input.is_physical_key_pressed(KEY_W)) -dir = dir.normalized() -velocity = dir*{speed} -move_and_slide()"], ["defaults", {}], ["param_input_strings", { -"speed": "0,1000" +serialized_props = [["block_name", "set_prop_speed"], ["label", "StatementBlock"], ["color", Color(0.647059, 0.694118, 0.760784, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Speed to {value: VECTOR2}"], ["statement", "speed = {value}"], ["defaults", { +"value": "0,0" +}], ["param_input_strings", { +"value": "0,1000" }]] -[sub_resource type="Resource" id="Resource_e61h1"] +[sub_resource type="Resource" id="Resource_trpau"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_k6jw1") +serialized_block = SubResource("Resource_7v74l") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_pm7ay"] +[sub_resource type="Resource" id="Resource_g57b7"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "process_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(174, 102)], ["scope", ""], ["block_format", "On Process"], ["statement", "func _process(delta):"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] +serialized_props = [["block_name", "ready_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(75, 50)], ["scope", ""], ["block_format", "On Ready"], ["statement", "func _ready():"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_uln40"] +[sub_resource type="Resource" id="Resource_5atf0"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_pm7ay") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_e61h1")]] +serialized_block = SubResource("Resource_g57b7") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_trpau")]] + +[sub_resource type="Resource" id="Resource_ykx8c"] +script = ExtResource("7_1f578") +selected = 0 +items = ["top-down", "platformer", "spaceship"] + +[sub_resource type="Resource" id="Resource_rv265"] +script = ExtResource("7_1f578") +selected = 0 +items = ["player_1", "player_2"] -[sub_resource type="Resource" id="Resource_4j61k"] +[sub_resource type="Resource" id="Resource_rsniy"] +script = ExtResource("7_1f578") +selected = 0 +items = ["top-down", "platformer", "spaceship"] + +[sub_resource type="Resource" id="Resource_daqtm"] +script = ExtResource("7_1f578") +selected = 0 +items = ["player_1", "player_2"] + +[sub_resource type="Resource" id="Resource_ttufp"] +script = ExtResource("5_wr38c") +block_class = &"StatementBlock" +serialized_props = [["block_name", "simplecharacter_move"], ["label", "StatementBlock"], ["color", Color(0.835294, 0.262745, 0.133333, 1)], ["block_type", 2], ["position", Vector2(-44, -18)], ["scope", ""], ["block_format", "Move with {player: OPTION} buttons as {kind: OPTION}"], ["statement", "move_with_player_buttons(\"{player}\", \"{kind}\", delta)"], ["defaults", { +"kind": SubResource("Resource_ykx8c"), +"player": SubResource("Resource_rv265") +}], ["param_input_strings", { +"kind": SubResource("Resource_rsniy"), +"player": SubResource("Resource_daqtm") +}]] + +[sub_resource type="Resource" id="Resource_24g32"] +script = ExtResource("4_qtggh") +serialized_block = SubResource("Resource_ttufp") +path_child_pairs = [] + +[sub_resource type="Resource" id="Resource_jjdkl"] +script = ExtResource("5_wr38c") +block_class = &"EntryBlock" +serialized_props = [["block_name", "process_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(75, 175)], ["scope", ""], ["block_format", "On Process"], ["statement", "func _process(delta):"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] + +[sub_resource type="Resource" id="Resource_oxdce"] +script = ExtResource("4_qtggh") +serialized_block = SubResource("Resource_jjdkl") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_24g32")]] + +[sub_resource type="Resource" id="Resource_lwf35"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_uln40")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_5atf0"), SubResource("Resource_oxdce")]) -[sub_resource type="Resource" id="Resource_qmak3"] +[sub_resource type="Resource" id="Resource_dhvli"] script = ExtResource("7_uuuue") script_inherits = "SimpleCharacter" -block_trees = SubResource("Resource_4j61k") +block_trees = SubResource("Resource_lwf35") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends SimpleCharacter -var VAR_DICT := {} + +func _ready(): + speed = Vector2(0,1000) func _process(delta): - var dir = Vector2() - dir.x += float(Input.is_physical_key_pressed(KEY_D)) - dir.x -= float(Input.is_physical_key_pressed(KEY_A)) - dir.y += float(Input.is_physical_key_pressed(KEY_S)) - dir.y -= float(Input.is_physical_key_pressed(KEY_W)) - dir = dir.normalized() - velocity = dir*Vector2(0,1000) - move_and_slide() + move_with_player_buttons(\"player_1\", \"top-down\", delta) " version = 0 -[sub_resource type="Resource" id="Resource_d4hry"] +[sub_resource type="Resource" id="Resource_sfqsw"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.835294, 0.262745, 0.133333, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Move with player 2 buttons, speed {speed: VECTOR2}"], ["statement", "var dir = Vector2() -dir.x += float(Input.is_physical_key_pressed(KEY_RIGHT)) -dir.x -= float(Input.is_physical_key_pressed(KEY_LEFT)) -dir.y += float(Input.is_physical_key_pressed(KEY_DOWN)) -dir.y -= float(Input.is_physical_key_pressed(KEY_UP)) -dir = dir.normalized() -velocity = dir*{speed} -move_and_slide()"], ["defaults", {}], ["param_input_strings", { -"speed": "0,1000" +serialized_props = [["block_name", "set_prop_speed"], ["label", "StatementBlock"], ["color", Color(0.647059, 0.694118, 0.760784, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Speed to {value: VECTOR2}"], ["statement", "speed = {value}"], ["defaults", { +"value": "0,0" +}], ["param_input_strings", { +"value": "0,1000" }]] -[sub_resource type="Resource" id="Resource_c0nei"] +[sub_resource type="Resource" id="Resource_iax81"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_d4hry") +serialized_block = SubResource("Resource_sfqsw") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_wrx2u"] +[sub_resource type="Resource" id="Resource_weya7"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "process_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(179, 149)], ["scope", ""], ["block_format", "On Process"], ["statement", "func _process(delta):"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] +serialized_props = [["block_name", "ready_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(-400, -75)], ["scope", ""], ["block_format", "On Ready"], ["statement", "func _ready():"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_75h61"] +[sub_resource type="Resource" id="Resource_bfsko"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_wrx2u") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_c0nei")]] +serialized_block = SubResource("Resource_weya7") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_iax81")]] -[sub_resource type="Resource" id="Resource_r5rk4"] +[sub_resource type="Resource" id="Resource_wv5rg"] +script = ExtResource("7_1f578") +selected = 0 +items = ["top-down", "platformer", "spaceship"] + +[sub_resource type="Resource" id="Resource_r4lu4"] +script = ExtResource("7_1f578") +selected = 0 +items = ["player_1", "player_2"] + +[sub_resource type="Resource" id="Resource_qhieq"] +script = ExtResource("7_1f578") +selected = 0 +items = ["top-down", "platformer", "spaceship"] + +[sub_resource type="Resource" id="Resource_mjeck"] +script = ExtResource("7_1f578") +selected = 1 +items = ["player_1", "player_2"] + +[sub_resource type="Resource" id="Resource_rag8u"] +script = ExtResource("5_wr38c") +block_class = &"StatementBlock" +serialized_props = [["block_name", "simplecharacter_move"], ["label", "StatementBlock"], ["color", Color(0.835294, 0.262745, 0.133333, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Move with {player: OPTION} buttons as {kind: OPTION}"], ["statement", "move_with_player_buttons(\"{player}\", \"{kind}\", delta)"], ["defaults", { +"kind": SubResource("Resource_wv5rg"), +"player": SubResource("Resource_r4lu4") +}], ["param_input_strings", { +"kind": SubResource("Resource_qhieq"), +"player": SubResource("Resource_mjeck") +}]] + +[sub_resource type="Resource" id="Resource_4a0ls"] +script = ExtResource("4_qtggh") +serialized_block = SubResource("Resource_rag8u") +path_child_pairs = [] + +[sub_resource type="Resource" id="Resource_m3ow7"] +script = ExtResource("5_wr38c") +block_class = &"EntryBlock" +serialized_props = [["block_name", "process_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(-400, 50)], ["scope", ""], ["block_format", "On Process"], ["statement", "func _process(delta):"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] + +[sub_resource type="Resource" id="Resource_57n2n"] +script = ExtResource("4_qtggh") +serialized_block = SubResource("Resource_m3ow7") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_4a0ls")]] + +[sub_resource type="Resource" id="Resource_cosx1"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_75h61")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_bfsko"), SubResource("Resource_57n2n")]) -[sub_resource type="Resource" id="Resource_lxj2y"] +[sub_resource type="Resource" id="Resource_krmii"] script = ExtResource("7_uuuue") script_inherits = "SimpleCharacter" -block_trees = SubResource("Resource_r5rk4") +block_trees = SubResource("Resource_cosx1") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends SimpleCharacter -var VAR_DICT := {} + +func _ready(): + speed = Vector2(0,1000) func _process(delta): - var dir = Vector2() - dir.x += float(Input.is_physical_key_pressed(KEY_RIGHT)) - dir.x -= float(Input.is_physical_key_pressed(KEY_LEFT)) - dir.y += float(Input.is_physical_key_pressed(KEY_DOWN)) - dir.y -= float(Input.is_physical_key_pressed(KEY_UP)) - dir = dir.normalized() - velocity = dir*Vector2(0,1000) - move_and_slide() + move_with_player_buttons(\"player_2\", \"top-down\", delta) " version = 0 -[sub_resource type="Resource" id="Resource_80onm"] +[sub_resource type="Resource" id="Resource_o1lqr"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " +serialized_props = [["block_name", "load_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " var __sound = AudioStreamPlayer.new() __sound.name = {name} __sound.set_stream(load({file_path})) @@ -135,15 +208,15 @@ add_child(__sound) "name": "score_sound" }]] -[sub_resource type="Resource" id="Resource_jfgyp"] +[sub_resource type="Resource" id="Resource_mipb3"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_80onm") +serialized_block = SubResource("Resource_o1lqr") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_0qgyx"] +[sub_resource type="Resource" id="Resource_648ge"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " +serialized_props = [["block_name", "load_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " var __sound = AudioStreamPlayer.new() __sound.name = {name} __sound.set_stream(load({file_path})) @@ -153,15 +226,15 @@ add_child(__sound) "name": "wall_hit" }]] -[sub_resource type="Resource" id="Resource_515lv"] +[sub_resource type="Resource" id="Resource_mvbi7"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_0qgyx") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_jfgyp")]] +serialized_block = SubResource("Resource_648ge") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_mipb3")]] -[sub_resource type="Resource" id="Resource_na8wd"] +[sub_resource type="Resource" id="Resource_i4exi"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " +serialized_props = [["block_name", "load_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " var __sound = AudioStreamPlayer.new() __sound.name = {name} __sound.set_stream(load({file_path})) @@ -171,22 +244,22 @@ add_child(__sound) "name": "paddle_hit" }]] -[sub_resource type="Resource" id="Resource_bku44"] +[sub_resource type="Resource" id="Resource_6dpro"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_na8wd") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_515lv")]] +serialized_block = SubResource("Resource_i4exi") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_mvbi7")]] -[sub_resource type="Resource" id="Resource_2m4ct"] +[sub_resource type="Resource" id="Resource_lds2e"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "ready_block"], ["label", "EntryBlock"], ["color", Color(0.980392, 0.34902, 0.337255, 1)], ["block_type", 1], ["position", Vector2(49, 42)], ["scope", ""], ["block_format", "On Ready"], ["statement", "func _ready():"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] +serialized_props = [["block_name", "ready_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(-125, 0)], ["scope", ""], ["block_format", "On Ready"], ["statement", "func _ready():"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_lfbxc"] +[sub_resource type="Resource" id="Resource_omh7u"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_2m4ct") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_bku44")]] +serialized_block = SubResource("Resource_lds2e") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_6dpro")]] -[sub_resource type="Resource" id="Resource_0sepo"] +[sub_resource type="Resource" id="Resource_2b0uo"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -194,12 +267,12 @@ func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_k5cwt"] +[sub_resource type="Resource" id="Resource_4mv67"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_0sepo") +serialized_block = SubResource("Resource_2b0uo") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_uucid"] +[sub_resource type="Resource" id="Resource_1bl8g"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -207,28 +280,28 @@ func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_64xkq"] +[sub_resource type="Resource" id="Resource_01vgy"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_uucid") +serialized_block = SubResource("Resource_1bl8g") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_76m34"] +[sub_resource type="Resource" id="Resource_ffbl6"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { +serialized_props = [["block_name", "is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { "group": "paddles", "node": "" }]] -[sub_resource type="Resource" id="Resource_fmoex"] +[sub_resource type="Resource" id="Resource_smrc0"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_76m34") -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_64xkq")]] +serialized_block = SubResource("Resource_ffbl6") +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_01vgy")]] -[sub_resource type="Resource" id="Resource_d7dfr"] +[sub_resource type="Resource" id="Resource_j0dm5"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " +serialized_props = [["block_name", "play_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(20, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " var __sound_node = get_node({name}) __sound_node.volume_db = {db} __sound_node.pitch_scale = {pitch} @@ -242,12 +315,12 @@ __sound_node.play() "pitch": "1.0" }]] -[sub_resource type="Resource" id="Resource_oqnor"] +[sub_resource type="Resource" id="Resource_earoq"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_d7dfr") +serialized_block = SubResource("Resource_j0dm5") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_uibbi"] +[sub_resource type="Resource" id="Resource_t0vy6"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -255,28 +328,28 @@ func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_7jqxw"] +[sub_resource type="Resource" id="Resource_e3mj1"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_uibbi") +serialized_block = SubResource("Resource_t0vy6") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_nchna"] +[sub_resource type="Resource" id="Resource_xnogu"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { +serialized_props = [["block_name", "is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { "group": "walls", "node": "" }]] -[sub_resource type="Resource" id="Resource_35nkf"] +[sub_resource type="Resource" id="Resource_njg3m"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_nchna") -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_7jqxw")]] +serialized_block = SubResource("Resource_xnogu") +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_e3mj1")]] -[sub_resource type="Resource" id="Resource_fywef"] +[sub_resource type="Resource" id="Resource_4eh0w"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " +serialized_props = [["block_name", "play_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(20, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " var __sound_node = get_node({name}) __sound_node.volume_db = {db} __sound_node.pitch_scale = {pitch} @@ -290,62 +363,62 @@ __sound_node.play() "pitch": "1.0" }]] -[sub_resource type="Resource" id="Resource_pucal"] +[sub_resource type="Resource" id="Resource_wijlv"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_fywef") +serialized_block = SubResource("Resource_4eh0w") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_8nvnv"] +[sub_resource type="Resource" id="Resource_4sgol"] script = ExtResource("5_wr38c") block_class = &"ControlBlock" -serialized_props = [["block_name", "control_block"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ +serialized_props = [["block_name", "if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ "condition": false }]]] -[sub_resource type="Resource" id="Resource_r8172"] +[sub_resource type="Resource" id="Resource_kknxb"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_8nvnv") -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_35nkf")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_pucal")]] +serialized_block = SubResource("Resource_4sgol") +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_njg3m")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_wijlv")]] -[sub_resource type="Resource" id="Resource_fl4h4"] +[sub_resource type="Resource" id="Resource_1qbgj"] script = ExtResource("5_wr38c") block_class = &"ControlBlock" -serialized_props = [["block_name", "control_block"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ +serialized_props = [["block_name", "if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ "condition": false }]]] -[sub_resource type="Resource" id="Resource_3xq0k"] +[sub_resource type="Resource" id="Resource_rop2b"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_fl4h4") -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_fmoex")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_oqnor")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_r8172")]] +serialized_block = SubResource("Resource_1qbgj") +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_smrc0")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_earoq")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_kknxb")]] -[sub_resource type="Resource" id="Resource_eiexb"] +[sub_resource type="Resource" id="Resource_kxhfs"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "entry_block"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(50, 226)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " +serialized_props = [["block_name", "rigidbody2d_on_entered"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(-125, 225)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() "], ["defaults", {}], ["param_input_strings", {}], ["signal_name", "body_entered"]] -[sub_resource type="Resource" id="Resource_gg652"] +[sub_resource type="Resource" id="Resource_i5kuh"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_eiexb") -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_k5cwt")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_3xq0k")]] +serialized_block = SubResource("Resource_kxhfs") +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_4mv67")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_rop2b")]] -[sub_resource type="Resource" id="Resource_py8f3"] +[sub_resource type="Resource" id="Resource_c2usj"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.0117647, 0.666667, 0.454902, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Viewport Center"], ["statement", "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()"], ["defaults", {}], ["variant_type", 5], ["param_input_strings", {}]] +serialized_props = [["block_name", "viewport_center"], ["label", "Param"], ["color", Color(0.0117647, 0.666667, 0.454902, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Viewport Center"], ["statement", "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()"], ["defaults", {}], ["variant_type", 5], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_kck4x"] +[sub_resource type="Resource" id="Resource_7dr6f"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_py8f3") +serialized_block = SubResource("Resource_c2usj") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_fyaul"] +[sub_resource type="Resource" id="Resource_yk1aj"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " +serialized_props = [["block_name", "play_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " var __sound_node = get_node({name}) __sound_node.volume_db = {db} __sound_node.pitch_scale = {pitch} @@ -359,43 +432,49 @@ __sound_node.play() "pitch": "1.0" }]] -[sub_resource type="Resource" id="Resource_1o8v3"] +[sub_resource type="Resource" id="Resource_rjl7j"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_fyaul") +serialized_block = SubResource("Resource_yk1aj") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_5fsso"] +[sub_resource type="Resource" id="Resource_18v3b"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.439216, 0.501961, 0.564706, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Physics Position {position: VECTOR2}"], ["statement", "PhysicsServer2D.body_set_state(get_rid(),PhysicsServer2D.BODY_STATE_TRANSFORM,Transform2D.IDENTITY.translated({position}))"], ["defaults", {}], ["param_input_strings", { -"position": "960,544" +serialized_props = [["block_name", "rigidbody2d_physics_position"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.396078, 0.517647, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Physics Position {position: VECTOR2}"], ["statement", " +PhysicsServer2D.body_set_state( + get_rid(), + PhysicsServer2D.BODY_STATE_TRANSFORM, + Transform2D.IDENTITY.translated({position}) +) +"], ["defaults", {}], ["param_input_strings", { +"position": "," }]] -[sub_resource type="Resource" id="Resource_uyy35"] +[sub_resource type="Resource" id="Resource_ctlxh"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_5fsso") -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_kck4x")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_1o8v3")]] +serialized_block = SubResource("Resource_18v3b") +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_7dr6f")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_rjl7j")]] -[sub_resource type="Resource" id="Resource_f3xvu"] +[sub_resource type="Resource" id="Resource_wpq1k"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "entry_block"], ["label", "EntryBlock"], ["color", Color(0.941176, 0.764706, 0, 1)], ["block_type", 1], ["position", Vector2(51, 616)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "define_method"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(-125, 650)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { "method_name": "reset" }], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_n4cap"] +[sub_resource type="Resource" id="Resource_aav67"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_f3xvu") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_uyy35")]] +serialized_block = SubResource("Resource_wpq1k") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ctlxh")]] -[sub_resource type="Resource" id="Resource_gn6n3"] +[sub_resource type="Resource" id="Resource_rccbr"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_lfbxc"), SubResource("Resource_gg652"), SubResource("Resource_n4cap")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_omh7u"), SubResource("Resource_i5kuh"), SubResource("Resource_aav67")]) -[sub_resource type="Resource" id="Resource_hnwk2"] +[sub_resource type="Resource" id="Resource_181ih"] script = ExtResource("7_uuuue") script_inherits = "RigidBody2D" -block_trees = SubResource("Resource_gn6n3") +block_trees = SubResource("Resource_rccbr") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends RigidBody2D @@ -430,7 +509,11 @@ func _on_body_entered(_body: Node): __sound_node_2.play() func reset(): - PhysicsServer2D.body_set_state(get_rid(),PhysicsServer2D.BODY_STATE_TRANSFORM,Transform2D.IDENTITY.translated((func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call())) + PhysicsServer2D.body_set_state( + get_rid(), + PhysicsServer2D.BODY_STATE_TRANSFORM, + Transform2D.IDENTITY.translated((func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()) + ) var __sound_node_1 = get_node('score_sound') __sound_node_1.volume_db = 0.0 __sound_node_1.pitch_scale = 1.0 @@ -441,7 +524,7 @@ func _init(): " version = 0 -[sub_resource type="Resource" id="Resource_foxq8"] +[sub_resource type="Resource" id="Resource_0k8hj"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -449,12 +532,12 @@ func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_501iu"] +[sub_resource type="Resource" id="Resource_rig6c"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_foxq8") +serialized_block = SubResource("Resource_0k8hj") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_lc2mv"] +[sub_resource type="Resource" id="Resource_t7w1d"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -462,83 +545,83 @@ func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_usdsx"] +[sub_resource type="Resource" id="Resource_ba0bv"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_lc2mv") +serialized_block = SubResource("Resource_t7w1d") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_yudev"] +[sub_resource type="Resource" id="Resource_jtjm4"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { +serialized_props = [["block_name", "is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { "group": "balls", "node": "" }]] -[sub_resource type="Resource" id="Resource_j8nlm"] +[sub_resource type="Resource" id="Resource_62spx"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_yudev") -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_usdsx")]] +serialized_block = SubResource("Resource_jtjm4") +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_ba0bv")]] -[sub_resource type="Resource" id="Resource_rd5bb"] +[sub_resource type="Resource" id="Resource_e25gs"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { "group": "balls", "method_name": "reset" }]] -[sub_resource type="Resource" id="Resource_6j2n2"] +[sub_resource type="Resource" id="Resource_k1bnq"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_rd5bb") +serialized_block = SubResource("Resource_e25gs") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_y52j6"] +[sub_resource type="Resource" id="Resource_3574g"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(20, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { "group": "scoring", "method_name": "goal_left" }]] -[sub_resource type="Resource" id="Resource_j6rsb"] +[sub_resource type="Resource" id="Resource_sgg3i"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_y52j6") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_6j2n2")]] +serialized_block = SubResource("Resource_3574g") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_k1bnq")]] -[sub_resource type="Resource" id="Resource_oeuh1"] +[sub_resource type="Resource" id="Resource_o07o5"] script = ExtResource("5_wr38c") block_class = &"ControlBlock" -serialized_props = [["block_name", "control_block"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ +serialized_props = [["block_name", "if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ "condition": false }]]] -[sub_resource type="Resource" id="Resource_jyu6m"] +[sub_resource type="Resource" id="Resource_ja7i6"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_oeuh1") -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_j8nlm")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_j6rsb")]] +serialized_block = SubResource("Resource_o07o5") +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_62spx")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_sgg3i")]] -[sub_resource type="Resource" id="Resource_v1q5h"] +[sub_resource type="Resource" id="Resource_8e6vl"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "entry_block"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(98, 352)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " +serialized_props = [["block_name", "area2d_on_entered"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(-125, -150)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["defaults", {}], ["param_input_strings", {}], ["signal_name", "body_entered"]] -[sub_resource type="Resource" id="Resource_vj0qt"] +[sub_resource type="Resource" id="Resource_dymgt"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_v1q5h") -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_501iu")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_jyu6m")]] +serialized_block = SubResource("Resource_8e6vl") +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_rig6c")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ja7i6")]] -[sub_resource type="Resource" id="Resource_6sikv"] +[sub_resource type="Resource" id="Resource_qatrc"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_vj0qt")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_dymgt")]) -[sub_resource type="Resource" id="Resource_bx5ai"] +[sub_resource type="Resource" id="Resource_1yrql"] script = ExtResource("7_uuuue") script_inherits = "Area2D" -block_trees = SubResource("Resource_6sikv") +block_trees = SubResource("Resource_qatrc") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends Area2D @@ -556,7 +639,7 @@ func _init(): " version = 0 -[sub_resource type="Resource" id="Resource_g8bbs"] +[sub_resource type="Resource" id="Resource_mvpfc"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -564,12 +647,12 @@ func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_by53e"] +[sub_resource type="Resource" id="Resource_v2e4o"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_g8bbs") +serialized_block = SubResource("Resource_mvpfc") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_ia057"] +[sub_resource type="Resource" id="Resource_lt2nr"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " @@ -577,83 +660,83 @@ func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_214im"] +[sub_resource type="Resource" id="Resource_6417q"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_ia057") +serialized_block = SubResource("Resource_lt2nr") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_mitgp"] +[sub_resource type="Resource" id="Resource_ppyp4"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { +serialized_props = [["block_name", "is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { "group": "balls", "node": "" }]] -[sub_resource type="Resource" id="Resource_4c6cp"] +[sub_resource type="Resource" id="Resource_i1hbe"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_mitgp") -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_214im")]] +serialized_block = SubResource("Resource_ppyp4") +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_6417q")]] -[sub_resource type="Resource" id="Resource_kbjk3"] +[sub_resource type="Resource" id="Resource_og2lu"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { "group": "balls", "method_name": "reset" }]] -[sub_resource type="Resource" id="Resource_svw0g"] +[sub_resource type="Resource" id="Resource_ox4cg"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_kbjk3") +serialized_block = SubResource("Resource_og2lu") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_ehxpt"] +[sub_resource type="Resource" id="Resource_fqtoj"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(20, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { "group": "scoring", "method_name": "goal_right" }]] -[sub_resource type="Resource" id="Resource_8f3xk"] +[sub_resource type="Resource" id="Resource_16dgc"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_ehxpt") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_svw0g")]] +serialized_block = SubResource("Resource_fqtoj") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ox4cg")]] -[sub_resource type="Resource" id="Resource_cyk7y"] +[sub_resource type="Resource" id="Resource_4gpkr"] script = ExtResource("5_wr38c") block_class = &"ControlBlock" -serialized_props = [["block_name", "control_block"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ +serialized_props = [["block_name", "if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ "condition": false }]]] -[sub_resource type="Resource" id="Resource_gfghu"] +[sub_resource type="Resource" id="Resource_cujjt"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_cyk7y") -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_4c6cp")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_8f3xk")]] +serialized_block = SubResource("Resource_4gpkr") +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_i1hbe")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_16dgc")]] -[sub_resource type="Resource" id="Resource_ncxb3"] +[sub_resource type="Resource" id="Resource_nkcib"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "entry_block"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(195, 56)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " +serialized_props = [["block_name", "area2d_on_entered"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(-150, -75)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["defaults", {}], ["param_input_strings", {}], ["signal_name", "body_entered"]] -[sub_resource type="Resource" id="Resource_1nmq4"] +[sub_resource type="Resource" id="Resource_kibpx"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_ncxb3") -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_by53e")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_gfghu")]] +serialized_block = SubResource("Resource_nkcib") +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_v2e4o")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_cujjt")]] -[sub_resource type="Resource" id="Resource_d14wa"] +[sub_resource type="Resource" id="Resource_rdqcq"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_1nmq4")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_kibpx")]) -[sub_resource type="Resource" id="Resource_6drva"] +[sub_resource type="Resource" id="Resource_nf08t"] script = ExtResource("7_uuuue") script_inherits = "Area2D" -block_trees = SubResource("Resource_d14wa") +block_trees = SubResource("Resource_rdqcq") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends Area2D @@ -671,112 +754,111 @@ func _init(): " version = 0 -[sub_resource type="Resource" id="Resource_nh5qb"] +[sub_resource type="Resource" id="Resource_esgb0"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.941176, 0.764706, 0, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["block_format", "Add to group {group: STRING}"], ["statement", "add_to_group({group})"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "add_to_group"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Add to group {group: STRING}"], ["statement", "add_to_group({group})"], ["defaults", {}], ["param_input_strings", { "group": "scoring" }]] -[sub_resource type="Resource" id="Resource_hugdn"] +[sub_resource type="Resource" id="Resource_2cvgo"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_nh5qb") +serialized_block = SubResource("Resource_esgb0") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_xhy0x"] +[sub_resource type="Resource" id="Resource_yt2jg"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.439216, 0.501961, 0.564706, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["block_format", "Set player 2 score to {score: INT}"], ["statement", "score_right = {score}"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "simplescoring_set_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set player 2 score to {score: INT}"], ["statement", "score_right = {score}"], ["defaults", {}], ["param_input_strings", { "score": "0" }]] -[sub_resource type="Resource" id="Resource_xqajo"] +[sub_resource type="Resource" id="Resource_qxyq6"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_xhy0x") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_hugdn")]] +serialized_block = SubResource("Resource_yt2jg") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_2cvgo")]] -[sub_resource type="Resource" id="Resource_sreck"] +[sub_resource type="Resource" id="Resource_dptse"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.439216, 0.501961, 0.564706, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["block_format", "Set player 1 score to {score: INT}"], ["statement", "score_left = {score}"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "simplescoring_set_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set player 1 score to {score: INT}"], ["statement", "score_left = {score}"], ["defaults", {}], ["param_input_strings", { "score": "0" }]] -[sub_resource type="Resource" id="Resource_cweom"] +[sub_resource type="Resource" id="Resource_6g2pn"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_sreck") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_xqajo")]] +serialized_block = SubResource("Resource_dptse") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_qxyq6")]] -[sub_resource type="Resource" id="Resource_3uk5q"] +[sub_resource type="Resource" id="Resource_u7gx0"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "ready_block"], ["label", "EntryBlock"], ["color", Color(0.980392, 0.34902, 0.337255, 1)], ["block_type", 1], ["position", Vector2(54, 47)], ["block_format", "On Ready"], ["statement", "func _ready():"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] +serialized_props = [["block_name", "ready_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(-350, -275)], ["scope", ""], ["block_format", "On Ready"], ["statement", "func _ready():"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_kt2b1"] +[sub_resource type="Resource" id="Resource_jlgm4"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_3uk5q") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_cweom")]] +serialized_block = SubResource("Resource_u7gx0") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_6g2pn")]] -[sub_resource type="Resource" id="Resource_2wg3j"] +[sub_resource type="Resource" id="Resource_ipq2j"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.439216, 0.501961, 0.564706, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["block_format", "Change player 1 score by {score: INT}"], ["statement", "score_left += {score}"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "simplescoring_change_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Change player 1 score by {score: INT}"], ["statement", "score_left += {score}"], ["defaults", {}], ["param_input_strings", { "score": "1" }]] -[sub_resource type="Resource" id="Resource_ngm2f"] +[sub_resource type="Resource" id="Resource_imfrt"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_2wg3j") +serialized_block = SubResource("Resource_ipq2j") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_l0tk7"] +[sub_resource type="Resource" id="Resource_uu4ng"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "entry_block"], ["label", "EntryBlock"], ["color", Color(0.941176, 0.764706, 0, 1)], ["block_type", 1], ["position", Vector2(499, 220)], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "define_method"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(-350, -50)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { "method_name": "goal_right" }], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_5315l"] +[sub_resource type="Resource" id="Resource_ed551"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_l0tk7") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ngm2f")]] +serialized_block = SubResource("Resource_uu4ng") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_imfrt")]] -[sub_resource type="Resource" id="Resource_g74qq"] +[sub_resource type="Resource" id="Resource_5qjag"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "statement_block"], ["label", "StatementBlock"], ["color", Color(0.439216, 0.501961, 0.564706, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["block_format", "Change player 2 score by {score: INT}"], ["statement", "score_right += {score}"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "simplescoring_change_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Change player 2 score by {score: INT}"], ["statement", "score_right += {score}"], ["defaults", {}], ["param_input_strings", { "score": "1" }]] -[sub_resource type="Resource" id="Resource_wvrb6"] +[sub_resource type="Resource" id="Resource_fyy20"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_g74qq") +serialized_block = SubResource("Resource_5qjag") path_child_pairs = [] -[sub_resource type="Resource" id="Resource_4337b"] +[sub_resource type="Resource" id="Resource_yxdgk"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "entry_block"], ["label", "EntryBlock"], ["color", Color(0.941176, 0.764706, 0, 1)], ["block_type", 1], ["position", Vector2(142, 273)], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", "define_method"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(-350, 75)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { "method_name": "goal_left" }], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_mgqxu"] +[sub_resource type="Resource" id="Resource_4v0rp"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_4337b") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_wvrb6")]] +serialized_block = SubResource("Resource_yxdgk") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_fyy20")]] -[sub_resource type="Resource" id="Resource_c8btv"] +[sub_resource type="Resource" id="Resource_g42ud"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_kt2b1"), SubResource("Resource_5315l"), SubResource("Resource_mgqxu")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_jlgm4"), SubResource("Resource_ed551"), SubResource("Resource_4v0rp")]) -[sub_resource type="Resource" id="Resource_k3sym"] +[sub_resource type="Resource" id="Resource_xe6aa"] script = ExtResource("7_uuuue") script_inherits = "SimpleScoring" -block_trees = SubResource("Resource_c8btv") +block_trees = SubResource("Resource_g42ud") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends SimpleScoring -var VAR_DICT := {} func _ready(): score_left = 0 @@ -805,7 +887,7 @@ texture = ExtResource("4_ra7bh") [node name="BlockCode" type="Node" parent="PaddleLeft"] script = ExtResource("3_6jaq8") -block_script = SubResource("Resource_qmak3") +block_script = SubResource("Resource_dhvli") [node name="PaddleRight" type="CharacterBody2D" parent="." groups=["paddles"]] modulate = Color(0.509804, 0.360784, 0.972549, 1) @@ -816,7 +898,7 @@ texture = ExtResource("4_ra7bh") [node name="BlockCode" type="Node" parent="PaddleRight"] script = ExtResource("3_6jaq8") -block_script = SubResource("Resource_lxj2y") +block_script = SubResource("Resource_krmii") [node name="Ball" parent="." instance=ExtResource("9_xrqll")] modulate = Color(0.511, 0.362, 0.972, 1) @@ -825,21 +907,21 @@ gravity_scale = 0.0 [node name="BlockCode" type="Node" parent="Ball"] script = ExtResource("3_6jaq8") -block_script = SubResource("Resource_hnwk2") +block_script = SubResource("Resource_181ih") [node name="GoalAreaLeft" parent="." groups=["goal", "goal_left"] instance=ExtResource("12_nqmxu")] position = Vector2(-64, 544) [node name="BlockCode" type="Node" parent="GoalAreaLeft"] script = ExtResource("3_6jaq8") -block_script = SubResource("Resource_bx5ai") +block_script = SubResource("Resource_1yrql") [node name="GoalAreaRight" parent="." groups=["goal", "goal_right"] instance=ExtResource("12_nqmxu")] position = Vector2(1984, 544) [node name="BlockCode" type="Node" parent="GoalAreaRight"] script = ExtResource("3_6jaq8") -block_script = SubResource("Resource_6drva") +block_script = SubResource("Resource_nf08t") [node name="SimpleScoring" type="CanvasLayer" parent="." groups=["hud"]] follow_viewport_enabled = true @@ -847,7 +929,7 @@ script = ExtResource("13_tg3yk") [node name="BlockCode" type="Node" parent="SimpleScoring"] script = ExtResource("3_6jaq8") -block_script = SubResource("Resource_k3sym") +block_script = SubResource("Resource_xe6aa") [node name="Camera2D" type="Camera2D" parent="."] position = Vector2(960, 540) From 047ec47e6ab4e206dd9a4ba5fdcb5b2e64b9cd77 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Thu, 1 Aug 2024 07:41:02 -0600 Subject: [PATCH 107/423] Fix InstructionTree and Block circular dependency Since 4338632 there's been a circular dependency between InstructionTree and Block that manifests as a script error due to a non-existent resource in a seemingly unrelated object. Several components use InstructionTree.TreeNode including Block, and prior to 4338632 there were no references to any non-native classes. Split out the block tree functions to a new BlockTreeUtil class so that InstructionTree no longer contains references to Block. --- addons/block_code/drag_manager/drag.gd | 3 +- .../block_code/drag_manager/drag_manager.gd | 3 +- .../instruction_tree/instruction_tree.gd | 77 ------------------ .../ui/block_canvas/block_canvas.gd | 5 +- addons/block_code/ui/block_tree_util.gd | 80 +++++++++++++++++++ tests/test_instruction_tree.gd | 11 +-- 6 files changed, 93 insertions(+), 86 deletions(-) create mode 100644 addons/block_code/ui/block_tree_util.gd diff --git a/addons/block_code/drag_manager/drag.gd b/addons/block_code/drag_manager/drag.gd index 8a667755..62404532 100644 --- a/addons/block_code/drag_manager/drag.gd +++ b/addons/block_code/drag_manager/drag.gd @@ -3,6 +3,7 @@ extends Control const Background = preload("res://addons/block_code/ui/blocks/utilities/background/background.gd") const BlockCanvas = preload("res://addons/block_code/ui/block_canvas/block_canvas.gd") +const BlockTreeUtil = preload("res://addons/block_code/ui/block_tree_util.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") const Types = preload("res://addons/block_code/types/types.gd") @@ -143,7 +144,7 @@ func _snaps_to(node: Node) -> bool: if _block_scope != top_block.get_entry_statement(): return false elif top_block: - var tree_scope := InstructionTree.get_tree_scope(top_block) + var tree_scope := BlockTreeUtil.get_tree_scope(top_block) if tree_scope != "" and _block_scope != tree_scope: return false diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index f8adf904..a1727cf9 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -5,6 +5,7 @@ signal block_dropped signal block_modified const BlockCanvas = preload("res://addons/block_code/ui/block_canvas/block_canvas.gd") +const BlockTreeUtil = preload("res://addons/block_code/ui/block_tree_util.gd") const Drag = preload("res://addons/block_code/drag_manager/drag.gd") const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") const Picker = preload("res://addons/block_code/ui/picker/picker.gd") @@ -50,7 +51,7 @@ func drag_block(block: Block, copied_from: Block = null): block.disconnect_signals() - var block_scope := InstructionTree.get_tree_scope(block) + var block_scope := BlockTreeUtil.get_tree_scope(block) if block_scope != "": _block_canvas.set_scope(block_scope) diff --git a/addons/block_code/instruction_tree/instruction_tree.gd b/addons/block_code/instruction_tree/instruction_tree.gd index 5e82c6b4..0b6d5011 100644 --- a/addons/block_code/instruction_tree/instruction_tree.gd +++ b/addons/block_code/instruction_tree/instruction_tree.gd @@ -56,80 +56,3 @@ static func generate_text_recursive(node: TreeNode, depth: int, out: PackedStrin if node.next: generate_text_recursive(node.next, depth, out) - - -static func generate_script_from_nodes(nodes: Array[Node], bsd: BlockScriptData) -> String: - var entry_blocks_by_entry_statement: Dictionary = {} - - for block in nodes: - if !(block is Block): - continue - - if block is EntryBlock: - var entry_statement = block.get_entry_statement() - if not entry_blocks_by_entry_statement.has(entry_statement): - entry_blocks_by_entry_statement[entry_statement] = [] - entry_blocks_by_entry_statement[entry_statement].append(block) - - var script: String = "" - - script += "extends %s\n\n" % bsd.script_inherits - - for variable in bsd.variables: - script += "var %s: %s\n\n" % [variable.var_name, type_string(variable.var_type)] - - script += "\n" - - var init_func = TreeNode.new("func _init():") - - for entry_statement in entry_blocks_by_entry_statement: - var entry_blocks: Array[EntryBlock] - entry_blocks.assign(entry_blocks_by_entry_statement[entry_statement]) - script += _generate_script_from_entry_blocks(entry_statement, entry_blocks, init_func) - - if init_func.children: - script += generate_text(init_func) - - return script - - -static func _generate_script_from_entry_blocks(entry_statement: String, entry_blocks: Array[EntryBlock], init_func: TreeNode) -> String: - var script = entry_statement + "\n" - var signal_node: TreeNode - var is_empty = true - - IDHandler.reset() - - for entry_block in entry_blocks: - var next_block := entry_block.bottom_snap.get_snapped_block() - - if next_block != null: - var instruction_node: TreeNode = next_block.get_instruction_node() - var to_append := generate_text(instruction_node, 1) - script += to_append - script += "\n" - is_empty = false - - if signal_node == null and entry_block.signal_name: - signal_node = TreeNode.new("{0}.connect(_on_{0})".format([entry_block.signal_name])) - - if signal_node: - init_func.add_child(signal_node) - - if is_empty: - script += "\tpass\n\n" - - return script - - -## Returns the scope of the first non-empty scope child block -static func get_tree_scope(node: Node) -> String: - if node is Block: - if node.scope != "": - return node.scope - - for c in node.get_children(): - var scope := get_tree_scope(c) - if scope != "": - return scope - return "" diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index f4d2733d..867afeed 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -2,6 +2,7 @@ extends MarginContainer const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd") +const BlockTreeUtil = preload("res://addons/block_code/ui/block_tree_util.gd") const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") const Util = preload("res://addons/block_code/ui/util.gd") @@ -219,7 +220,7 @@ func set_scope(scope: String): if scope == block.get_entry_statement(): valid = true else: - var tree_scope := InstructionTree.get_tree_scope(block) + var tree_scope := BlockTreeUtil.get_tree_scope(block) if tree_scope == "" or scope == tree_scope: valid = true @@ -321,4 +322,4 @@ func set_mouse_override(override: bool): func generate_script_from_current_window(bsd: BlockScriptData) -> String: # TODO: implement multiple windows - return InstructionTree.generate_script_from_nodes(_window.get_children(), bsd) + return BlockTreeUtil.generate_script_from_nodes(_window.get_children(), bsd) diff --git a/addons/block_code/ui/block_tree_util.gd b/addons/block_code/ui/block_tree_util.gd new file mode 100644 index 00000000..7e547a05 --- /dev/null +++ b/addons/block_code/ui/block_tree_util.gd @@ -0,0 +1,80 @@ +extends Object + +const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") + + +static func generate_script_from_nodes(nodes: Array[Node], bsd: BlockScriptData) -> String: + var entry_blocks_by_entry_statement: Dictionary = {} + + for block in nodes: + if !(block is Block): + continue + + if block is EntryBlock: + var entry_statement = block.get_entry_statement() + if not entry_blocks_by_entry_statement.has(entry_statement): + entry_blocks_by_entry_statement[entry_statement] = [] + entry_blocks_by_entry_statement[entry_statement].append(block) + + var script: String = "" + + script += "extends %s\n\n" % bsd.script_inherits + + for variable in bsd.variables: + script += "var %s: %s\n\n" % [variable.var_name, type_string(variable.var_type)] + + script += "\n" + + var init_func = InstructionTree.TreeNode.new("func _init():") + + for entry_statement in entry_blocks_by_entry_statement: + var entry_blocks: Array[EntryBlock] + entry_blocks.assign(entry_blocks_by_entry_statement[entry_statement]) + script += _generate_script_from_entry_blocks(entry_statement, entry_blocks, init_func) + + if init_func.children: + script += InstructionTree.generate_text(init_func) + + return script + + +static func _generate_script_from_entry_blocks(entry_statement: String, entry_blocks: Array[EntryBlock], init_func: InstructionTree.TreeNode) -> String: + var script = entry_statement + "\n" + var signal_node: InstructionTree.TreeNode + var is_empty = true + + InstructionTree.IDHandler.reset() + + for entry_block in entry_blocks: + var next_block := entry_block.bottom_snap.get_snapped_block() + + if next_block != null: + var instruction_node: InstructionTree.TreeNode = next_block.get_instruction_node() + var to_append := InstructionTree.generate_text(instruction_node, 1) + script += to_append + script += "\n" + is_empty = false + + if signal_node == null and entry_block.signal_name: + signal_node = InstructionTree.TreeNode.new("{0}.connect(_on_{0})".format([entry_block.signal_name])) + + if signal_node: + init_func.add_child(signal_node) + + if is_empty: + script += "\tpass\n\n" + + return script + + +## Returns the scope of the first non-empty scope child block +static func get_tree_scope(node: Node) -> String: + if node is Block: + if node.scope != "": + return node.scope + + for c in node.get_children(): + var scope := get_tree_scope(c) + if scope != "": + return scope + return "" diff --git a/tests/test_instruction_tree.gd b/tests/test_instruction_tree.gd index e57ea7a6..d715c0b4 100644 --- a/tests/test_instruction_tree.gd +++ b/tests/test_instruction_tree.gd @@ -1,6 +1,7 @@ extends GutTest ## Tests for InstructionTree +const BlockTreeUtil = preload("res://addons/block_code/ui/block_tree_util.gd") const CategoryFactory = preload("res://addons/block_code/ui/picker/categories/category_factory.gd") const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") @@ -88,7 +89,7 @@ func test_tree_node_text(): func test_script_no_nodes(): var bsd := BlockScriptData.new("Foo") - var script := InstructionTree.generate_script_from_nodes([], bsd) + var script := BlockTreeUtil.generate_script_from_nodes([], bsd) assert_eq( script, ( @@ -105,7 +106,7 @@ func test_script_no_nodes(): func test_script_no_entry_blocks(): var bsd := BlockScriptData.new("Foo") var nodes: Array[Node] = [Node.new(), Node2D.new(), Control.new()] - var script := InstructionTree.generate_script_from_nodes(nodes, bsd) + var script := BlockTreeUtil.generate_script_from_nodes(nodes, bsd) assert_eq( script, ( @@ -137,7 +138,7 @@ func test_basic_script(): assert_eq(ready_block.bottom_snap.get_snapped_block(), print_block) var bsd := BlockScriptData.new("Node2D") - var script := InstructionTree.generate_script_from_nodes([ready_block], bsd) + var script := BlockTreeUtil.generate_script_from_nodes([ready_block], bsd) assert_eq( script, ( @@ -165,7 +166,7 @@ func test_multiple_entry_script(): var ready_block_2: Block = dup_node(ready_block) var bsd := BlockScriptData.new("Node2D") - var script := InstructionTree.generate_script_from_nodes([ready_block, ready_block_2], bsd) + var script := BlockTreeUtil.generate_script_from_nodes([ready_block, ready_block_2], bsd) assert_eq( script, ( @@ -196,7 +197,7 @@ func test_signal_script(): entered_block.bottom_snap.snapped_block = print_block var bsd := BlockScriptData.new("Area2D") - var script = InstructionTree.generate_script_from_nodes([entered_block], bsd) + var script = BlockTreeUtil.generate_script_from_nodes([entered_block], bsd) assert_eq( script, ( From 9d62ccdc398af2a87dc30c01a57083bb5e15c64a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 26 Jul 2024 13:15:37 -0300 Subject: [PATCH 108/423] Add block definition resource The block definition must have a unique name and a type. It will be used to instantiate Block scenes. https://phabricator.endlessm.com/T35536 --- addons/block_code/block_definition.gd | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 addons/block_code/block_definition.gd diff --git a/addons/block_code/block_definition.gd b/addons/block_code/block_definition.gd new file mode 100644 index 00000000..e8ba7027 --- /dev/null +++ b/addons/block_code/block_definition.gd @@ -0,0 +1,21 @@ +extends Resource + +const Types = preload("res://addons/block_code/types/types.gd") + +var name: StringName +var type: Types.BlockType +var description: String +var category: String + +var label_template: String +var code_template: String +var defaults: Dictionary = {} + +## Only for blocks of type Types.ENTRY. If non-empty, this block defines a +## callback that will be connected to the signal with this name. +var signal_name: String = "" + + +func _init(p_name: StringName, p_type: Types.BlockType): + name = p_name + type = p_type From 410fd7d8d2f466edf89be365ed4bb788b6c84788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 26 Jul 2024 13:23:49 -0300 Subject: [PATCH 109/423] Add Blocks Catalog The catalog is where block definitions are loaded. For now, only "On Ready" and "Print" block definitions are ported. https://phabricator.endlessm.com/T35536 --- addons/block_code/blocks_catalog.gd | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 addons/block_code/blocks_catalog.gd diff --git a/addons/block_code/blocks_catalog.gd b/addons/block_code/blocks_catalog.gd new file mode 100644 index 00000000..92b60878 --- /dev/null +++ b/addons/block_code/blocks_catalog.gd @@ -0,0 +1,38 @@ +extends Object + +const BlockDefinition = preload("res://addons/block_code/block_definition.gd") +const Types = preload("res://addons/block_code/types/types.gd") + +static var _created: bool = false +static var _catalog: Dictionary + + +static func setup(): + if _created: + return + + _catalog = {} + var block_definition: BlockDefinition = BlockDefinition.new(&"ready_block", Types.BlockType.ENTRY) + block_definition.label_template = "On Ready" + block_definition.code_template = "func _ready():" + block_definition.description = 'Attached blocks will be executed once when the node is "ready"' + block_definition.category = "Lifecycle" + _catalog[&"ready_block"] = block_definition + + block_definition = BlockDefinition.new(&"print", Types.BlockType.EXECUTE) + block_definition.label_template = "print {text: STRING}" + block_definition.code_template = "print({text})" + block_definition.defaults = {"text": "Hello"} + block_definition.description = "Print the text to output" + block_definition.category = "Log" + _catalog[&"print"] = block_definition + + _created = true + + +static func get_block(block_name: StringName): + return _catalog.get(block_name) + + +static func has_block(block_name: StringName): + return block_name in _catalog From 87ed823f640a47fe5216c91b52cb1d556f7d562a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 26 Jul 2024 13:27:50 -0300 Subject: [PATCH 110/423] Util: Instantiate Block scene from catalog Given a block unique name, instantiate a Block scene from the block definition in the catalog. https://phabricator.endlessm.com/T35536 --- addons/block_code/ui/util.gd | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index 46918d2f..53dd91d0 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -1,5 +1,34 @@ extends Object +const BlockDefinition = preload("res://addons/block_code/block_definition.gd") +const BlocksCatalog = preload("res://addons/block_code/blocks_catalog.gd") +const Types = preload("res://addons/block_code/types/types.gd") + +const SCENE_PER_TYPE = { + Types.BlockType.ENTRY: preload("res://addons/block_code/ui/blocks/entry_block/entry_block.tscn"), + Types.BlockType.EXECUTE: preload("res://addons/block_code/ui/blocks/statement_block/statement_block.tscn"), +} + + +static func instantiate_block(block_name: StringName) -> Block: + BlocksCatalog.setup() + var block_definition: BlockDefinition = BlocksCatalog.get_block(block_name) + if block_definition == null: + push_error("The block %s is not in the catalog yet!" % block_name) + return + + var scene = SCENE_PER_TYPE[block_definition.type] + var b = scene.instantiate() + b.block_name = block_definition.name + b.block_format = block_definition.label_template + b.statement = block_definition.code_template + b.defaults = block_definition.defaults + b.tooltip_text = block_definition.description + b.category = block_definition.category + if block_definition.type == Types.BlockType.ENTRY and block_definition.signal_name != "": + b.signal_name = block_definition.signal_name + return b + ## Polyfill of Node.is_part_of_edited_scene(), available to GDScript in Godot 4.3+. static func node_is_part_of_edited_scene(node: Node) -> bool: From 690136c86621726b6350aeb2273f3a8ed51516cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 26 Jul 2024 13:35:11 -0300 Subject: [PATCH 111/423] CategoryFactory: Instantiate blocks from definition For now only "On Ready" and "Print" blocks are ported. https://phabricator.endlessm.com/T35536 --- .../ui/picker/categories/category_factory.gd | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 14d03b7c..848d5301 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -3,6 +3,7 @@ extends Object const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") const Types = preload("res://addons/block_code/types/types.gd") +const Util = preload("res://addons/block_code/ui/util.gd") const BLOCKS: Dictionary = { "control_block": preload("res://addons/block_code/ui/blocks/control_block/control_block.tscn"), @@ -171,12 +172,7 @@ static func get_general_blocks() -> Array[Block]: #region Lifecycle - b = BLOCKS["entry_block"].instantiate() - b.block_name = "ready_block" - b.block_format = "On Ready" - b.statement = "func _ready():" - b.tooltip_text = 'Attached blocks will be executed once when the node is "ready"' - b.category = "Lifecycle" + b = Util.instantiate_block(&"ready_block") block_list.append(b) b = BLOCKS["entry_block"].instantiate() @@ -259,13 +255,7 @@ static func get_general_blocks() -> Array[Block]: #endregion #region Logs - b = BLOCKS["statement_block"].instantiate() - b.block_name = "print" - b.block_format = "print {text: STRING}" - b.statement = "print({text})" - b.defaults = {"text": "Hello"} - b.tooltip_text = "Print the text to output" - b.category = "Log" + b = Util.instantiate_block(&"print") block_list.append(b) #endregion From edb88a687baef7e755ebe50558e7fd06750ad9ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 26 Jul 2024 13:38:15 -0300 Subject: [PATCH 112/423] Block scene: Change block_name property Change type to StringName, to match the block model. And remove the empty string default because it's mandatory. https://phabricator.endlessm.com/T35536 --- addons/block_code/ui/blocks/block/block.gd | 2 +- addons/block_code/ui/blocks/control_block/control_block.tscn | 2 +- addons/block_code/ui/blocks/entry_block/entry_block.tscn | 3 +-- .../block_code/ui/blocks/parameter_block/parameter_block.tscn | 4 ++-- .../block_code/ui/blocks/statement_block/statement_block.tscn | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 5cb37baf..59000d03 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -9,7 +9,7 @@ signal drag_started(block: Block) signal modified ## Name of the block to be referenced by others in search -@export var block_name: String = "" +@export var block_name: StringName ## Label of block (optionally used to draw block labels) @export var label: String = "" diff --git a/addons/block_code/ui/blocks/control_block/control_block.tscn b/addons/block_code/ui/blocks/control_block/control_block.tscn index a482e11f..6e77f7d6 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.tscn +++ b/addons/block_code/ui/blocks/control_block/control_block.tscn @@ -7,7 +7,7 @@ size_flags_horizontal = 0 mouse_filter = 2 script = ExtResource("1_2hbir") -block_name = "control_block" +block_name = &"control_block" label = "Control Block" color = Color(0.59979, 0.536348, 0.876215, 1) bottom_snap_path = NodePath("VBoxContainer/SnapPoint") diff --git a/addons/block_code/ui/blocks/entry_block/entry_block.tscn b/addons/block_code/ui/blocks/entry_block/entry_block.tscn index 6abed53e..49774a00 100644 --- a/addons/block_code/ui/blocks/entry_block/entry_block.tscn +++ b/addons/block_code/ui/blocks/entry_block/entry_block.tscn @@ -6,8 +6,7 @@ [node name="EntryBlock" instance=ExtResource("1_byjbb")] script = ExtResource("2_3ik8h") signal_name = "" -defaults = {} -block_name = "entry_block" +block_name = &"entry_block" label = "EntryBlock" block_type = 1 diff --git a/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn b/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn index 46cc8b65..5700ae20 100644 --- a/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn +++ b/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn @@ -18,9 +18,9 @@ corner_radius_bottom_left = 16 offset_right = 16.0 offset_bottom = 8.0 size_flags_horizontal = 0 +mouse_filter = 2 script = ExtResource("1_0hajy") -defaults = null -block_name = "parameter_block" +block_name = &"parameter_block" label = "Param" block_type = 3 diff --git a/addons/block_code/ui/blocks/statement_block/statement_block.tscn b/addons/block_code/ui/blocks/statement_block/statement_block.tscn index 96ed6e48..7463bf4f 100644 --- a/addons/block_code/ui/blocks/statement_block/statement_block.tscn +++ b/addons/block_code/ui/blocks/statement_block/statement_block.tscn @@ -9,7 +9,7 @@ size_flags_horizontal = 0 mouse_filter = 2 script = ExtResource("1_6wvlf") -block_name = "statement_block" +block_name = &"statement_block" label = "StatementBlock" bottom_snap_path = NodePath("VBoxContainer/SnapPoint") From 5a772b796c7eee7077d10f0b4ecbea73b07be311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 26 Jul 2024 13:52:05 -0300 Subject: [PATCH 113/423] Block resource: Add name and position Name, position, and children blocks are the only properties needed to be stored. The rest can be derived from the definition. And leave a TODO note for removing the serialization once the port is complete. https://phabricator.endlessm.com/T35536 --- .../ui/block_canvas/serialized_block_tree_node.gd | 10 ++++++++-- addons/block_code/ui/blocks/block/block.gd | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/addons/block_code/ui/block_canvas/serialized_block_tree_node.gd b/addons/block_code/ui/block_canvas/serialized_block_tree_node.gd index b524715c..9f4b95fd 100644 --- a/addons/block_code/ui/block_canvas/serialized_block_tree_node.gd +++ b/addons/block_code/ui/block_canvas/serialized_block_tree_node.gd @@ -1,10 +1,16 @@ class_name SerializedBlockTreeNode extends Resource -@export var serialized_block: SerializedBlock +@export var name: StringName +@export var position: Vector2 @export var path_child_pairs: Array +# TODO: Remove once the data/UI decouple is done. +@export var serialized_block: SerializedBlock + -func _init(p_serialized_block: SerializedBlock = null, p_path_child_pairs: Array = []): +func _init(p_name: StringName, p_position: Vector2 = Vector2.ZERO, p_serialized_block: SerializedBlock = null, p_path_child_pairs: Array = []): + name = p_name + position = p_position serialized_block = p_serialized_block path_child_pairs = p_path_child_pairs diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 59000d03..9cec804d 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -83,7 +83,7 @@ func get_instruction_node() -> InstructionTree.TreeNode: func update_resources(undo_redo: EditorUndoRedoManager): if resource == null: var serialized_block = SerializedBlock.new(get_block_class(), get_serialized_props()) - resource = SerializedBlockTreeNode.new(serialized_block) + resource = SerializedBlockTreeNode.new(block_name, position, serialized_block) return var serialized_props = get_serialized_props() From 6e17904dc1a9a1c92adbcda5941275dc25f7e146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 29 Jul 2024 16:54:41 -0300 Subject: [PATCH 114/423] Block resource: Update position from Block scene Position is not part of the serialized properties anymore. https://phabricator.endlessm.com/T35536 --- addons/block_code/ui/blocks/block/block.gd | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 9cec804d..bd5ee194 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -86,7 +86,12 @@ func update_resources(undo_redo: EditorUndoRedoManager): resource = SerializedBlockTreeNode.new(block_name, position, serialized_block) return + if resource.position != position: + undo_redo.add_undo_property(resource, "position", resource.position) + undo_redo.add_do_property(resource, "position", position) + var serialized_props = get_serialized_props() + if serialized_props != resource.serialized_block.serialized_props: undo_redo.add_undo_property(resource.serialized_block, "serialized_props", resource.serialized_block.serialized_props) undo_redo.add_do_property(resource.serialized_block, "serialized_props", serialized_props) From 97cd48f385d3438ea7ba77c577a5228fc4d73660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 26 Jul 2024 13:59:34 -0300 Subject: [PATCH 115/423] BlockCanvas: Use block definitions when loading And fallback to the previous behavior if the block isn't ported to the catalog yet. The scene position is set to the resource position. https://phabricator.endlessm.com/T35536 --- addons/block_code/ui/block_canvas/block_canvas.gd | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 867afeed..d34c4139 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -161,10 +161,16 @@ func clear_canvas(): func load_tree(parent: Node, node: SerializedBlockTreeNode): - var _block_scene_path = _block_scenes_by_class[node.serialized_block.block_class] - var scene: Block = load(_block_scene_path).instantiate() + var scene: Block = Util.instantiate_block(node.name) + + # TODO: Remove once the data/UI decouple is done. + if scene == null: + var _block_scene_path = _block_scenes_by_class[node.serialized_block.block_class] + scene = load(_block_scene_path).instantiate() for prop_pair in node.serialized_block.serialized_props: scene.set(prop_pair[0], prop_pair[1]) + + scene.position = node.position scene.resource = node parent.add_child(scene) From 13e57004bc53cc2953c7b5841648094d352301d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 26 Jul 2024 14:54:33 -0300 Subject: [PATCH 116/423] Block scenes: Remove most serialized properties For Block, StatementBlock and EntryBlock classes. Only if the block is in the block catalog. Otherwise keep the previous behavior. The exceptions are: - Color: it should be derived from the category, but needs refactoring - Scope: may be handled in a different way --- addons/block_code/ui/blocks/block/block.gd | 9 ++++++++- addons/block_code/ui/blocks/entry_block/entry_block.gd | 3 ++- .../ui/blocks/statement_block/statement_block.gd | 3 ++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index bd5ee194..6818b76d 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -2,6 +2,7 @@ class_name Block extends MarginContainer +const BlocksCatalog = preload("res://addons/block_code/blocks_catalog.gd") const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") const Types = preload("res://addons/block_code/types/types.gd") @@ -99,7 +100,13 @@ func update_resources(undo_redo: EditorUndoRedoManager): # Override this method to add more serialized properties func get_serialized_props() -> Array: - return serialize_props(["block_name", "label", "color", "block_type", "position", "scope"]) + if not BlocksCatalog.has_block(block_name): + return serialize_props(["block_name", "label", "color", "block_type", "position", "scope"]) + + # TODO: Remove remaining serialization: + # - Derive color from category. + # - Handle scope in a different way? + return serialize_props(["color", "scope"]) func _to_string(): diff --git a/addons/block_code/ui/blocks/entry_block/entry_block.gd b/addons/block_code/ui/blocks/entry_block/entry_block.gd index 3b53937b..0659d4bc 100644 --- a/addons/block_code/ui/blocks/entry_block/entry_block.gd +++ b/addons/block_code/ui/blocks/entry_block/entry_block.gd @@ -30,5 +30,6 @@ func get_entry_statement() -> String: func get_serialized_props() -> Array: var props := super() - props.append_array(serialize_props(["signal_name"])) + if not BlocksCatalog.has_block(block_name): + props.append_array(serialize_props(["signal_name"])) return props diff --git a/addons/block_code/ui/blocks/statement_block/statement_block.gd b/addons/block_code/ui/blocks/statement_block/statement_block.gd index cea6a6fc..fb920108 100644 --- a/addons/block_code/ui/blocks/statement_block/statement_block.gd +++ b/addons/block_code/ui/blocks/statement_block/statement_block.gd @@ -36,7 +36,8 @@ func _on_drag_drop_area_mouse_down(): func get_serialized_props() -> Array: var props := super() - props.append_array(serialize_props(["block_format", "statement", "defaults"])) + if not BlocksCatalog.has_block(block_name): + props.append_array(serialize_props(["block_format", "statement", "defaults"])) var _param_input_strings: Dictionary = {} for pair in param_name_input_pairs: From 46f1db2dcf3b0ae3a7ad073c28301991083ff4fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 26 Jul 2024 15:20:22 -0300 Subject: [PATCH 117/423] Update template Block resource To the new format. --- .../ui/bsd_templates/default_blocktrees.tres | 29 ------------------ .../ui/bsd_templates/default_bsd.tres | 30 +++++++++++++++---- 2 files changed, 25 insertions(+), 34 deletions(-) delete mode 100644 addons/block_code/ui/bsd_templates/default_blocktrees.tres diff --git a/addons/block_code/ui/bsd_templates/default_blocktrees.tres b/addons/block_code/ui/bsd_templates/default_blocktrees.tres deleted file mode 100644 index fef4c4a1..00000000 --- a/addons/block_code/ui/bsd_templates/default_blocktrees.tres +++ /dev/null @@ -1,29 +0,0 @@ -[gd_resource type="Resource" script_class="SerializedBlockTreeNodeArray" load_steps=8 format=3 uid="uid://djn5nejdsfu2a"] - -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node.gd" id="1_mfn7y"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block.gd" id="2_qtg7h"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node_array.gd" id="3_jo5dc"] - -[sub_resource type="Resource" id="Resource_lonji"] -script = ExtResource("2_qtg7h") -block_class = &"EntryBlock" -serialized_props = [["block_name", "ready_block"], ["label", "EntryBlock"], ["color", Color(0.980392, 0.34902, 0.337255, 1)], ["block_type", 2], ["position", Vector2(54, 47)], ["block_format", "On Ready"], ["statement", "func _ready():"], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_uxduk"] -script = ExtResource("1_mfn7y") -serialized_block = SubResource("Resource_lonji") -path_child_pairs = [] - -[sub_resource type="Resource" id="Resource_8uoy7"] -script = ExtResource("2_qtg7h") -block_class = &"EntryBlock" -serialized_props = [["block_name", "process_block"], ["label", "EntryBlock"], ["color", Color(0.980392, 0.34902, 0.337255, 1)], ["block_type", 2], ["position", Vector2(525, 48)], ["block_format", "On Process"], ["statement", "func _process(delta):"], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_qsjc2"] -script = ExtResource("1_mfn7y") -serialized_block = SubResource("Resource_8uoy7") -path_child_pairs = [] - -[resource] -script = ExtResource("3_jo5dc") -array = Array[ExtResource("1_mfn7y")]([SubResource("Resource_uxduk"), SubResource("Resource_qsjc2")]) diff --git a/addons/block_code/ui/bsd_templates/default_bsd.tres b/addons/block_code/ui/bsd_templates/default_bsd.tres index ebb149e2..5bfa7671 100644 --- a/addons/block_code/ui/bsd_templates/default_bsd.tres +++ b/addons/block_code/ui/bsd_templates/default_bsd.tres @@ -1,10 +1,30 @@ -[gd_resource type="Resource" script_class="BlockScriptData" load_steps=3 format=3 uid="uid://dit7fykhl3h48"] +[gd_resource type="Resource" script_class="BlockScriptData" load_steps=8 format=3 uid="uid://dit7fykhl3h48"] -[ext_resource type="Script" path="res://addons/block_code/block_script_data/block_script_data.gd" id="1_h8ggn"] -[ext_resource type="Resource" uid="uid://djn5nejdsfu2a" path="res://addons/block_code/ui/bsd_templates/default_blocktrees.tres" id="1_y70fv"] +[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node.gd" id="1_barc5"] +[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block.gd" id="2_cgfpx"] +[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node_array.gd" id="3_gx4d7"] +[ext_resource type="Script" path="res://addons/block_code/block_script_data/block_script_data.gd" id="4_cqq7x"] + +[sub_resource type="Resource" id="Resource_b0aen"] +script = ExtResource("2_cgfpx") +block_class = &"EntryBlock" +serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", ""], ["param_input_strings", {}]] + +[sub_resource type="Resource" id="Resource_1h6wi"] +script = ExtResource("1_barc5") +name = &"ready_block" +position = Vector2(54, 47) +path_child_pairs = [] +serialized_block = SubResource("Resource_b0aen") + +[sub_resource type="Resource" id="Resource_nkub8"] +script = ExtResource("3_gx4d7") +array = Array[ExtResource("1_barc5")]([SubResource("Resource_1h6wi")]) [resource] -script = ExtResource("1_h8ggn") +script = ExtResource("4_cqq7x") script_inherits = "INHERIT_DEFAULT" -block_trees = ExtResource("1_y70fv") +block_trees = SubResource("Resource_nkub8") +variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends INHERIT_DEFAULT" +version = 0 From ca1c8eb0ce48add8fddb33c9c4e3eb03837a50d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 30 Jul 2024 14:06:55 -0300 Subject: [PATCH 118/423] Update Pong game example --- .../examples/pong_game/pong_game.tscn | 758 ++++++++++-------- 1 file changed, 427 insertions(+), 331 deletions(-) diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index 52a983d9..fb71cd4f 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -7,90 +7,98 @@ [ext_resource type="Texture2D" uid="uid://tplpgtnfeda0" path="res://addons/block_code/examples/pong_game/assets/paddle.png" id="4_ra7bh"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block.gd" id="5_wr38c"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node_array.gd" id="6_ppdc3"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="7_1f578"] +[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="7_3q6bj"] [ext_resource type="Script" path="res://addons/block_code/block_script_data/block_script_data.gd" id="7_uuuue"] [ext_resource type="PackedScene" uid="uid://c7l70grmkauij" path="res://addons/block_code/examples/pong_game/ball.tscn" id="9_xrqll"] [ext_resource type="PackedScene" uid="uid://fhoapg3anjsu" path="res://addons/block_code/examples/pong_game/goal_area.tscn" id="12_nqmxu"] [ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd" id="13_tg3yk"] -[sub_resource type="Resource" id="Resource_7v74l"] +[sub_resource type="Resource" id="Resource_860cl"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "set_prop_speed"], ["label", "StatementBlock"], ["color", Color(0.647059, 0.694118, 0.760784, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Speed to {value: VECTOR2}"], ["statement", "speed = {value}"], ["defaults", { -"value": "0,0" +serialized_props = [["block_name", &"set_prop_speed"], ["label", "StatementBlock"], ["color", Color(0.647059, 0.694118, 0.760784, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Speed to {value: VECTOR2}"], ["statement", "speed = {value}"], ["defaults", { +"value": "0, 0" }], ["param_input_strings", { "value": "0,1000" }]] -[sub_resource type="Resource" id="Resource_trpau"] +[sub_resource type="Resource" id="Resource_q65fe"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_7v74l") +name = &"set_prop_speed" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_860cl") -[sub_resource type="Resource" id="Resource_g57b7"] +[sub_resource type="Resource" id="Resource_q1vhx"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "ready_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(75, 50)], ["scope", ""], ["block_format", "On Ready"], ["statement", "func _ready():"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] +serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", ""], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_5atf0"] +[sub_resource type="Resource" id="Resource_yiq7s"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_g57b7") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_trpau")]] +name = &"ready_block" +position = Vector2(75, 175) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_q65fe")]] +serialized_block = SubResource("Resource_q1vhx") -[sub_resource type="Resource" id="Resource_ykx8c"] -script = ExtResource("7_1f578") +[sub_resource type="Resource" id="Resource_a45un"] +script = ExtResource("7_3q6bj") selected = 0 items = ["top-down", "platformer", "spaceship"] -[sub_resource type="Resource" id="Resource_rv265"] -script = ExtResource("7_1f578") +[sub_resource type="Resource" id="Resource_ldmk0"] +script = ExtResource("7_3q6bj") selected = 0 items = ["player_1", "player_2"] -[sub_resource type="Resource" id="Resource_rsniy"] -script = ExtResource("7_1f578") +[sub_resource type="Resource" id="Resource_604n7"] +script = ExtResource("7_3q6bj") selected = 0 items = ["top-down", "platformer", "spaceship"] -[sub_resource type="Resource" id="Resource_daqtm"] -script = ExtResource("7_1f578") +[sub_resource type="Resource" id="Resource_h8b8o"] +script = ExtResource("7_3q6bj") selected = 0 items = ["player_1", "player_2"] -[sub_resource type="Resource" id="Resource_ttufp"] +[sub_resource type="Resource" id="Resource_d3xtc"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "simplecharacter_move"], ["label", "StatementBlock"], ["color", Color(0.835294, 0.262745, 0.133333, 1)], ["block_type", 2], ["position", Vector2(-44, -18)], ["scope", ""], ["block_format", "Move with {player: OPTION} buttons as {kind: OPTION}"], ["statement", "move_with_player_buttons(\"{player}\", \"{kind}\", delta)"], ["defaults", { -"kind": SubResource("Resource_ykx8c"), -"player": SubResource("Resource_rv265") +serialized_props = [["block_name", &"simplecharacter_move"], ["label", "StatementBlock"], ["color", Color(0.835294, 0.262745, 0.133333, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Move with {player: OPTION} buttons as {kind: OPTION}"], ["statement", "move_with_player_buttons(\"{player}\", \"{kind}\", delta)"], ["defaults", { +"kind": SubResource("Resource_a45un"), +"player": SubResource("Resource_ldmk0") }], ["param_input_strings", { -"kind": SubResource("Resource_rsniy"), -"player": SubResource("Resource_daqtm") +"kind": SubResource("Resource_604n7"), +"player": SubResource("Resource_h8b8o") }]] -[sub_resource type="Resource" id="Resource_24g32"] +[sub_resource type="Resource" id="Resource_7x3sw"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_ttufp") +name = &"simplecharacter_move" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_d3xtc") -[sub_resource type="Resource" id="Resource_jjdkl"] +[sub_resource type="Resource" id="Resource_x6ddv"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "process_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(75, 175)], ["scope", ""], ["block_format", "On Process"], ["statement", "func _process(delta):"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] +serialized_props = [["block_name", &"process_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(75, 300)], ["scope", ""], ["block_format", "On Process"], ["statement", "func _process(delta):"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_oxdce"] +[sub_resource type="Resource" id="Resource_0m462"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_jjdkl") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_24g32")]] +name = &"process_block" +position = Vector2(75, 300) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_7x3sw")]] +serialized_block = SubResource("Resource_x6ddv") -[sub_resource type="Resource" id="Resource_lwf35"] +[sub_resource type="Resource" id="Resource_a04yd"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_5atf0"), SubResource("Resource_oxdce")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_yiq7s"), SubResource("Resource_0m462")]) -[sub_resource type="Resource" id="Resource_dhvli"] +[sub_resource type="Resource" id="Resource_m2svk"] script = ExtResource("7_uuuue") script_inherits = "SimpleCharacter" -block_trees = SubResource("Resource_lwf35") +block_trees = SubResource("Resource_a04yd") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends SimpleCharacter @@ -104,84 +112,92 @@ func _process(delta): " version = 0 -[sub_resource type="Resource" id="Resource_sfqsw"] +[sub_resource type="Resource" id="Resource_isc56"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "set_prop_speed"], ["label", "StatementBlock"], ["color", Color(0.647059, 0.694118, 0.760784, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Speed to {value: VECTOR2}"], ["statement", "speed = {value}"], ["defaults", { -"value": "0,0" +serialized_props = [["block_name", &"set_prop_speed"], ["label", "StatementBlock"], ["color", Color(0.647059, 0.694118, 0.760784, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Speed to {value: VECTOR2}"], ["statement", "speed = {value}"], ["defaults", { +"value": "0, 0" }], ["param_input_strings", { "value": "0,1000" }]] -[sub_resource type="Resource" id="Resource_iax81"] +[sub_resource type="Resource" id="Resource_ttkrd"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_sfqsw") +name = &"set_prop_speed" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_isc56") -[sub_resource type="Resource" id="Resource_weya7"] +[sub_resource type="Resource" id="Resource_06s7w"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "ready_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(-400, -75)], ["scope", ""], ["block_format", "On Ready"], ["statement", "func _ready():"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] +serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", ""], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_bfsko"] +[sub_resource type="Resource" id="Resource_hrubs"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_weya7") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_iax81")]] +name = &"ready_block" +position = Vector2(50, 175) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ttkrd")]] +serialized_block = SubResource("Resource_06s7w") -[sub_resource type="Resource" id="Resource_wv5rg"] -script = ExtResource("7_1f578") +[sub_resource type="Resource" id="Resource_y2msu"] +script = ExtResource("7_3q6bj") selected = 0 items = ["top-down", "platformer", "spaceship"] -[sub_resource type="Resource" id="Resource_r4lu4"] -script = ExtResource("7_1f578") +[sub_resource type="Resource" id="Resource_wq8lu"] +script = ExtResource("7_3q6bj") selected = 0 items = ["player_1", "player_2"] -[sub_resource type="Resource" id="Resource_qhieq"] -script = ExtResource("7_1f578") +[sub_resource type="Resource" id="Resource_cqi0p"] +script = ExtResource("7_3q6bj") selected = 0 items = ["top-down", "platformer", "spaceship"] -[sub_resource type="Resource" id="Resource_mjeck"] -script = ExtResource("7_1f578") +[sub_resource type="Resource" id="Resource_1apud"] +script = ExtResource("7_3q6bj") selected = 1 items = ["player_1", "player_2"] -[sub_resource type="Resource" id="Resource_rag8u"] +[sub_resource type="Resource" id="Resource_bl8w1"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "simplecharacter_move"], ["label", "StatementBlock"], ["color", Color(0.835294, 0.262745, 0.133333, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Move with {player: OPTION} buttons as {kind: OPTION}"], ["statement", "move_with_player_buttons(\"{player}\", \"{kind}\", delta)"], ["defaults", { -"kind": SubResource("Resource_wv5rg"), -"player": SubResource("Resource_r4lu4") +serialized_props = [["block_name", &"simplecharacter_move"], ["label", "StatementBlock"], ["color", Color(0.835294, 0.262745, 0.133333, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Move with {player: OPTION} buttons as {kind: OPTION}"], ["statement", "move_with_player_buttons(\"{player}\", \"{kind}\", delta)"], ["defaults", { +"kind": SubResource("Resource_y2msu"), +"player": SubResource("Resource_wq8lu") }], ["param_input_strings", { -"kind": SubResource("Resource_qhieq"), -"player": SubResource("Resource_mjeck") +"kind": SubResource("Resource_cqi0p"), +"player": SubResource("Resource_1apud") }]] -[sub_resource type="Resource" id="Resource_4a0ls"] +[sub_resource type="Resource" id="Resource_enqe8"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_rag8u") +name = &"simplecharacter_move" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_bl8w1") -[sub_resource type="Resource" id="Resource_m3ow7"] +[sub_resource type="Resource" id="Resource_3wgnl"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "process_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(-400, 50)], ["scope", ""], ["block_format", "On Process"], ["statement", "func _process(delta):"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] +serialized_props = [["block_name", &"process_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(50, 300)], ["scope", ""], ["block_format", "On Process"], ["statement", "func _process(delta):"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_57n2n"] +[sub_resource type="Resource" id="Resource_s8vl4"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_m3ow7") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_4a0ls")]] +name = &"process_block" +position = Vector2(50, 300) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_enqe8")]] +serialized_block = SubResource("Resource_3wgnl") -[sub_resource type="Resource" id="Resource_cosx1"] +[sub_resource type="Resource" id="Resource_y05sx"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_bfsko"), SubResource("Resource_57n2n")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_hrubs"), SubResource("Resource_s8vl4")]) -[sub_resource type="Resource" id="Resource_krmii"] +[sub_resource type="Resource" id="Resource_ysbi4"] script = ExtResource("7_uuuue") script_inherits = "SimpleCharacter" -block_trees = SubResource("Resource_cosx1") +block_trees = SubResource("Resource_y05sx") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends SimpleCharacter @@ -195,10 +211,10 @@ func _process(delta): " version = 0 -[sub_resource type="Resource" id="Resource_o1lqr"] +[sub_resource type="Resource" id="Resource_rf047"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "load_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " +serialized_props = [["block_name", &"load_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " var __sound = AudioStreamPlayer.new() __sound.name = {name} __sound.set_stream(load({file_path})) @@ -208,15 +224,17 @@ add_child(__sound) "name": "score_sound" }]] -[sub_resource type="Resource" id="Resource_mipb3"] +[sub_resource type="Resource" id="Resource_d34ke"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_o1lqr") +name = &"load_sound" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_rf047") -[sub_resource type="Resource" id="Resource_648ge"] +[sub_resource type="Resource" id="Resource_md4i5"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "load_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " +serialized_props = [["block_name", &"load_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " var __sound = AudioStreamPlayer.new() __sound.name = {name} __sound.set_stream(load({file_path})) @@ -226,15 +244,17 @@ add_child(__sound) "name": "wall_hit" }]] -[sub_resource type="Resource" id="Resource_mvbi7"] +[sub_resource type="Resource" id="Resource_roxh4"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_648ge") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_mipb3")]] +name = &"load_sound" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_d34ke")]] +serialized_block = SubResource("Resource_md4i5") -[sub_resource type="Resource" id="Resource_i4exi"] +[sub_resource type="Resource" id="Resource_4luvu"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "load_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " +serialized_props = [["block_name", &"load_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " var __sound = AudioStreamPlayer.new() __sound.name = {name} __sound.set_stream(load({file_path})) @@ -244,64 +264,144 @@ add_child(__sound) "name": "paddle_hit" }]] -[sub_resource type="Resource" id="Resource_6dpro"] +[sub_resource type="Resource" id="Resource_gywyt"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_i4exi") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_mvbi7")]] +name = &"load_sound" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_roxh4")]] +serialized_block = SubResource("Resource_4luvu") -[sub_resource type="Resource" id="Resource_lds2e"] +[sub_resource type="Resource" id="Resource_b0aen"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "ready_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(-125, 0)], ["scope", ""], ["block_format", "On Ready"], ["statement", "func _ready():"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] +serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", ""], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_omh7u"] +[sub_resource type="Resource" id="Resource_1h6wi"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_lds2e") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_6dpro")]] +name = &"ready_block" +position = Vector2(54, 47) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_gywyt")]] +serialized_block = SubResource("Resource_b0aen") -[sub_resource type="Resource" id="Resource_2b0uo"] +[sub_resource type="Resource" id="Resource_05cdj"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " +serialized_props = [["block_name", &"viewport_center"], ["label", "Param"], ["color", Color(0.0117647, 0.666667, 0.454902, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Viewport Center"], ["statement", "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()"], ["defaults", {}], ["variant_type", 5], ["param_input_strings", {}]] + +[sub_resource type="Resource" id="Resource_kt3qw"] +script = ExtResource("4_qtggh") +name = &"viewport_center" +position = Vector2(0, 0) +path_child_pairs = [] +serialized_block = SubResource("Resource_05cdj") + +[sub_resource type="Resource" id="Resource_uob83"] +script = ExtResource("5_wr38c") +block_class = &"StatementBlock" +serialized_props = [["block_name", &"play_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " +var __sound_node = get_node({name}) +__sound_node.volume_db = {db} +__sound_node.pitch_scale = {pitch} +__sound_node.play() +"], ["defaults", { +"db": "0.0", +"pitch": "1.0" +}], ["param_input_strings", { +"db": "0.0", +"name": "score_sound", +"pitch": "1.0" +}]] + +[sub_resource type="Resource" id="Resource_oawyp"] +script = ExtResource("4_qtggh") +name = &"play_sound" +position = Vector2(0, 0) +path_child_pairs = [] +serialized_block = SubResource("Resource_uob83") + +[sub_resource type="Resource" id="Resource_5x1be"] +script = ExtResource("5_wr38c") +block_class = &"StatementBlock" +serialized_props = [["block_name", &"rigidbody2d_physics_position"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.396078, 0.517647, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Physics Position {position: VECTOR2}"], ["statement", " +PhysicsServer2D.body_set_state( + get_rid(), + PhysicsServer2D.BODY_STATE_TRANSFORM, + Transform2D.IDENTITY.translated({position}) +) +"], ["defaults", {}], ["param_input_strings", { +"position": "," +}]] + +[sub_resource type="Resource" id="Resource_ftveg"] +script = ExtResource("4_qtggh") +name = &"rigidbody2d_physics_position" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_kt3qw")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_oawyp")]] +serialized_block = SubResource("Resource_5x1be") + +[sub_resource type="Resource" id="Resource_sp3a4"] +script = ExtResource("5_wr38c") +block_class = &"EntryBlock" +serialized_props = [["block_name", &"define_method"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(50, 275)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { +"method_name": "reset" +}], ["signal_name", ""]] + +[sub_resource type="Resource" id="Resource_gmlt0"] +script = ExtResource("4_qtggh") +name = &"define_method" +position = Vector2(50, 275) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ftveg")]] +serialized_block = SubResource("Resource_sp3a4") + +[sub_resource type="Resource" id="Resource_r1gqk"] +script = ExtResource("5_wr38c") +block_class = &"ParameterBlock" +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_4mv67"] +[sub_resource type="Resource" id="Resource_gj1nu"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_2b0uo") +name = &"parameter_block" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_r1gqk") -[sub_resource type="Resource" id="Resource_1bl8g"] +[sub_resource type="Resource" id="Resource_ri33r"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_01vgy"] +[sub_resource type="Resource" id="Resource_7qpii"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_1bl8g") +name = &"parameter_block" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_ri33r") -[sub_resource type="Resource" id="Resource_ffbl6"] +[sub_resource type="Resource" id="Resource_s7b4y"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { +serialized_props = [["block_name", &"is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { "group": "paddles", "node": "" }]] -[sub_resource type="Resource" id="Resource_smrc0"] +[sub_resource type="Resource" id="Resource_xsgv2"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_ffbl6") -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_01vgy")]] +name = &"is_node_in_group" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_7qpii")]] +serialized_block = SubResource("Resource_s7b4y") -[sub_resource type="Resource" id="Resource_j0dm5"] +[sub_resource type="Resource" id="Resource_bh5jo"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "play_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(20, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " +serialized_props = [["block_name", &"play_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " var __sound_node = get_node({name}) __sound_node.volume_db = {db} __sound_node.pitch_scale = {pitch} @@ -315,41 +415,47 @@ __sound_node.play() "pitch": "1.0" }]] -[sub_resource type="Resource" id="Resource_earoq"] +[sub_resource type="Resource" id="Resource_ic2jq"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_j0dm5") +name = &"play_sound" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_bh5jo") -[sub_resource type="Resource" id="Resource_t0vy6"] +[sub_resource type="Resource" id="Resource_mgvpf"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_e3mj1"] +[sub_resource type="Resource" id="Resource_mbuv7"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_t0vy6") +name = &"parameter_block" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_mgvpf") -[sub_resource type="Resource" id="Resource_xnogu"] +[sub_resource type="Resource" id="Resource_rc730"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { +serialized_props = [["block_name", &"is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { "group": "walls", "node": "" }]] -[sub_resource type="Resource" id="Resource_njg3m"] +[sub_resource type="Resource" id="Resource_fgryt"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_xnogu") -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_e3mj1")]] +name = &"is_node_in_group" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_mbuv7")]] +serialized_block = SubResource("Resource_rc730") -[sub_resource type="Resource" id="Resource_4eh0w"] +[sub_resource type="Resource" id="Resource_71yrt"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "play_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(20, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " +serialized_props = [["block_name", &"play_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " var __sound_node = get_node({name}) __sound_node.volume_db = {db} __sound_node.pitch_scale = {pitch} @@ -363,118 +469,64 @@ __sound_node.play() "pitch": "1.0" }]] -[sub_resource type="Resource" id="Resource_wijlv"] +[sub_resource type="Resource" id="Resource_f3xwp"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_4eh0w") +name = &"play_sound" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_71yrt") -[sub_resource type="Resource" id="Resource_4sgol"] +[sub_resource type="Resource" id="Resource_wkj8h"] script = ExtResource("5_wr38c") block_class = &"ControlBlock" -serialized_props = [["block_name", "if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ +serialized_props = [["block_name", &"if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ "condition": false }]]] -[sub_resource type="Resource" id="Resource_kknxb"] +[sub_resource type="Resource" id="Resource_qmdbv"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_4sgol") -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_njg3m")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_wijlv")]] +name = &"if" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_fgryt")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_f3xwp")]] +serialized_block = SubResource("Resource_wkj8h") -[sub_resource type="Resource" id="Resource_1qbgj"] +[sub_resource type="Resource" id="Resource_dwd2k"] script = ExtResource("5_wr38c") block_class = &"ControlBlock" -serialized_props = [["block_name", "if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ +serialized_props = [["block_name", &"if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ "condition": false }]]] -[sub_resource type="Resource" id="Resource_rop2b"] +[sub_resource type="Resource" id="Resource_rs6a0"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_1qbgj") -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_smrc0")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_earoq")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_kknxb")]] +name = &"if" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_xsgv2")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_ic2jq")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_qmdbv")]] +serialized_block = SubResource("Resource_dwd2k") -[sub_resource type="Resource" id="Resource_kxhfs"] +[sub_resource type="Resource" id="Resource_7mdg3"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "rigidbody2d_on_entered"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(-125, 225)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " +serialized_props = [["block_name", &"rigidbody2d_on_entered"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(50, 475)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() "], ["defaults", {}], ["param_input_strings", {}], ["signal_name", "body_entered"]] -[sub_resource type="Resource" id="Resource_i5kuh"] -script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_kxhfs") -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_4mv67")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_rop2b")]] - -[sub_resource type="Resource" id="Resource_c2usj"] -script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["block_name", "viewport_center"], ["label", "Param"], ["color", Color(0.0117647, 0.666667, 0.454902, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Viewport Center"], ["statement", "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()"], ["defaults", {}], ["variant_type", 5], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_7dr6f"] -script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_c2usj") -path_child_pairs = [] - -[sub_resource type="Resource" id="Resource_yk1aj"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["block_name", "play_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " -var __sound_node = get_node({name}) -__sound_node.volume_db = {db} -__sound_node.pitch_scale = {pitch} -__sound_node.play() -"], ["defaults", { -"db": "0.0", -"pitch": "1.0" -}], ["param_input_strings", { -"db": "0.0", -"name": "score_sound", -"pitch": "1.0" -}]] - -[sub_resource type="Resource" id="Resource_rjl7j"] -script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_yk1aj") -path_child_pairs = [] - -[sub_resource type="Resource" id="Resource_18v3b"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["block_name", "rigidbody2d_physics_position"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.396078, 0.517647, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Physics Position {position: VECTOR2}"], ["statement", " -PhysicsServer2D.body_set_state( - get_rid(), - PhysicsServer2D.BODY_STATE_TRANSFORM, - Transform2D.IDENTITY.translated({position}) -) -"], ["defaults", {}], ["param_input_strings", { -"position": "," -}]] - -[sub_resource type="Resource" id="Resource_ctlxh"] +[sub_resource type="Resource" id="Resource_tyrtu"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_18v3b") -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_7dr6f")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_rjl7j")]] +name = &"rigidbody2d_on_entered" +position = Vector2(50, 475) +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_gj1nu")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_rs6a0")]] +serialized_block = SubResource("Resource_7mdg3") -[sub_resource type="Resource" id="Resource_wpq1k"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["block_name", "define_method"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(-125, 650)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { -"method_name": "reset" -}], ["signal_name", ""]] - -[sub_resource type="Resource" id="Resource_aav67"] -script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_wpq1k") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ctlxh")]] - -[sub_resource type="Resource" id="Resource_rccbr"] +[sub_resource type="Resource" id="Resource_t48yv"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_omh7u"), SubResource("Resource_i5kuh"), SubResource("Resource_aav67")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_1h6wi"), SubResource("Resource_gmlt0"), SubResource("Resource_tyrtu")]) -[sub_resource type="Resource" id="Resource_181ih"] +[sub_resource type="Resource" id="Resource_6m2mk"] script = ExtResource("7_uuuue") script_inherits = "RigidBody2D" -block_trees = SubResource("Resource_rccbr") +block_trees = SubResource("Resource_t48yv") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends RigidBody2D @@ -493,6 +545,17 @@ func _ready(): __sound_3.set_stream(load('res://addons/block_code/examples/pong_game/assets/score.ogg')) add_child(__sound_3) +func reset(): + PhysicsServer2D.body_set_state( + get_rid(), + PhysicsServer2D.BODY_STATE_TRANSFORM, + Transform2D.IDENTITY.translated((func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()) + ) + var __sound_node_1 = get_node('score_sound') + __sound_node_1.volume_db = 0.0 + __sound_node_1.pitch_scale = 1.0 + __sound_node_1.play() + func _on_body_entered(_body: Node): var body: NodePath = _body.get_path() @@ -508,120 +571,123 @@ func _on_body_entered(_body: Node): __sound_node_2.pitch_scale = 1.0 __sound_node_2.play() -func reset(): - PhysicsServer2D.body_set_state( - get_rid(), - PhysicsServer2D.BODY_STATE_TRANSFORM, - Transform2D.IDENTITY.translated((func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()) - ) - var __sound_node_1 = get_node('score_sound') - __sound_node_1.volume_db = 0.0 - __sound_node_1.pitch_scale = 1.0 - __sound_node_1.play() - func _init(): body_entered.connect(_on_body_entered) " version = 0 -[sub_resource type="Resource" id="Resource_0k8hj"] +[sub_resource type="Resource" id="Resource_itmch"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_rig6c"] +[sub_resource type="Resource" id="Resource_3wodo"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_0k8hj") +name = &"parameter_block" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_itmch") -[sub_resource type="Resource" id="Resource_t7w1d"] +[sub_resource type="Resource" id="Resource_wo02o"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_ba0bv"] +[sub_resource type="Resource" id="Resource_dcwek"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_t7w1d") +name = &"parameter_block" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_wo02o") -[sub_resource type="Resource" id="Resource_jtjm4"] +[sub_resource type="Resource" id="Resource_ma3m2"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { +serialized_props = [["block_name", &"is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { "group": "balls", "node": "" }]] -[sub_resource type="Resource" id="Resource_62spx"] +[sub_resource type="Resource" id="Resource_bny5u"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_jtjm4") -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_ba0bv")]] +name = &"is_node_in_group" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_dcwek")]] +serialized_block = SubResource("Resource_ma3m2") -[sub_resource type="Resource" id="Resource_e25gs"] +[sub_resource type="Resource" id="Resource_dkm1h"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", &"call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { "group": "balls", "method_name": "reset" }]] -[sub_resource type="Resource" id="Resource_k1bnq"] +[sub_resource type="Resource" id="Resource_57tvt"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_e25gs") +name = &"call_group_method" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_dkm1h") -[sub_resource type="Resource" id="Resource_3574g"] +[sub_resource type="Resource" id="Resource_lm5iy"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(20, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", &"call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { "group": "scoring", "method_name": "goal_left" }]] -[sub_resource type="Resource" id="Resource_sgg3i"] +[sub_resource type="Resource" id="Resource_26pqe"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_3574g") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_k1bnq")]] +name = &"call_group_method" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_57tvt")]] +serialized_block = SubResource("Resource_lm5iy") -[sub_resource type="Resource" id="Resource_o07o5"] +[sub_resource type="Resource" id="Resource_yd7xk"] script = ExtResource("5_wr38c") block_class = &"ControlBlock" -serialized_props = [["block_name", "if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ +serialized_props = [["block_name", &"if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ "condition": false }]]] -[sub_resource type="Resource" id="Resource_ja7i6"] +[sub_resource type="Resource" id="Resource_wva5q"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_o07o5") -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_62spx")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_sgg3i")]] +name = &"if" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_bny5u")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_26pqe")]] +serialized_block = SubResource("Resource_yd7xk") -[sub_resource type="Resource" id="Resource_8e6vl"] +[sub_resource type="Resource" id="Resource_fufky"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "area2d_on_entered"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(-125, -150)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " +serialized_props = [["block_name", &"area2d_on_entered"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(100, 50)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["defaults", {}], ["param_input_strings", {}], ["signal_name", "body_entered"]] -[sub_resource type="Resource" id="Resource_dymgt"] +[sub_resource type="Resource" id="Resource_fkj3e"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_8e6vl") -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_rig6c")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ja7i6")]] +name = &"area2d_on_entered" +position = Vector2(100, 50) +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_3wodo")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_wva5q")]] +serialized_block = SubResource("Resource_fufky") -[sub_resource type="Resource" id="Resource_qatrc"] +[sub_resource type="Resource" id="Resource_v6too"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_dymgt")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_fkj3e")]) -[sub_resource type="Resource" id="Resource_1yrql"] +[sub_resource type="Resource" id="Resource_4xylj"] script = ExtResource("7_uuuue") script_inherits = "Area2D" -block_trees = SubResource("Resource_qatrc") +block_trees = SubResource("Resource_v6too") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends Area2D @@ -639,104 +705,118 @@ func _init(): " version = 0 -[sub_resource type="Resource" id="Resource_mvpfc"] +[sub_resource type="Resource" id="Resource_8h48s"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_v2e4o"] +[sub_resource type="Resource" id="Resource_0x61c"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_mvpfc") +name = &"parameter_block" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_8h48s") -[sub_resource type="Resource" id="Resource_lt2nr"] +[sub_resource type="Resource" id="Resource_n8f73"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_6417q"] +[sub_resource type="Resource" id="Resource_tnwiy"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_lt2nr") +name = &"parameter_block" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_n8f73") -[sub_resource type="Resource" id="Resource_ppyp4"] +[sub_resource type="Resource" id="Resource_lurjo"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", "is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { +serialized_props = [["block_name", &"is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { "group": "balls", "node": "" }]] -[sub_resource type="Resource" id="Resource_i1hbe"] +[sub_resource type="Resource" id="Resource_j6idn"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_ppyp4") -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_6417q")]] +name = &"is_node_in_group" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_tnwiy")]] +serialized_block = SubResource("Resource_lurjo") -[sub_resource type="Resource" id="Resource_og2lu"] +[sub_resource type="Resource" id="Resource_y2wc6"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", &"call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { "group": "balls", "method_name": "reset" }]] -[sub_resource type="Resource" id="Resource_ox4cg"] +[sub_resource type="Resource" id="Resource_krykp"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_og2lu") +name = &"call_group_method" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_y2wc6") -[sub_resource type="Resource" id="Resource_fqtoj"] +[sub_resource type="Resource" id="Resource_daagb"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(20, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", &"call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { "group": "scoring", "method_name": "goal_right" }]] -[sub_resource type="Resource" id="Resource_16dgc"] +[sub_resource type="Resource" id="Resource_klxbs"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_fqtoj") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ox4cg")]] +name = &"call_group_method" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_krykp")]] +serialized_block = SubResource("Resource_daagb") -[sub_resource type="Resource" id="Resource_4gpkr"] +[sub_resource type="Resource" id="Resource_twkoi"] script = ExtResource("5_wr38c") block_class = &"ControlBlock" -serialized_props = [["block_name", "if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ +serialized_props = [["block_name", &"if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ "condition": false }]]] -[sub_resource type="Resource" id="Resource_cujjt"] +[sub_resource type="Resource" id="Resource_1a3km"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_4gpkr") -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_i1hbe")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_16dgc")]] +name = &"if" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_j6idn")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_klxbs")]] +serialized_block = SubResource("Resource_twkoi") -[sub_resource type="Resource" id="Resource_nkcib"] +[sub_resource type="Resource" id="Resource_c4had"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "area2d_on_entered"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(-150, -75)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " +serialized_props = [["block_name", &"area2d_on_entered"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(75, 50)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " func _on_body_entered(_body: Node2D): var body: NodePath = _body.get_path() "], ["defaults", {}], ["param_input_strings", {}], ["signal_name", "body_entered"]] -[sub_resource type="Resource" id="Resource_kibpx"] +[sub_resource type="Resource" id="Resource_qtw4n"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_nkcib") -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_v2e4o")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_cujjt")]] +name = &"area2d_on_entered" +position = Vector2(75, 50) +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_0x61c")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_1a3km")]] +serialized_block = SubResource("Resource_c4had") -[sub_resource type="Resource" id="Resource_rdqcq"] +[sub_resource type="Resource" id="Resource_14gac"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_kibpx")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_qtw4n")]) -[sub_resource type="Resource" id="Resource_nf08t"] +[sub_resource type="Resource" id="Resource_xoc8a"] script = ExtResource("7_uuuue") script_inherits = "Area2D" -block_trees = SubResource("Resource_rdqcq") +block_trees = SubResource("Resource_14gac") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends Area2D @@ -754,108 +834,124 @@ func _init(): " version = 0 -[sub_resource type="Resource" id="Resource_esgb0"] +[sub_resource type="Resource" id="Resource_tqdqf"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "add_to_group"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Add to group {group: STRING}"], ["statement", "add_to_group({group})"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", &"add_to_group"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Add to group {group: STRING}"], ["statement", "add_to_group({group})"], ["defaults", {}], ["param_input_strings", { "group": "scoring" }]] -[sub_resource type="Resource" id="Resource_2cvgo"] +[sub_resource type="Resource" id="Resource_uxpim"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_esgb0") +name = &"add_to_group" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_tqdqf") -[sub_resource type="Resource" id="Resource_yt2jg"] +[sub_resource type="Resource" id="Resource_yuj6e"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "simplescoring_set_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set player 2 score to {score: INT}"], ["statement", "score_right = {score}"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", &"simplescoring_set_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set player 2 score to {score: INT}"], ["statement", "score_right = {score}"], ["defaults", {}], ["param_input_strings", { "score": "0" }]] -[sub_resource type="Resource" id="Resource_qxyq6"] +[sub_resource type="Resource" id="Resource_oar78"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_yt2jg") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_2cvgo")]] +name = &"simplescoring_set_score" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_uxpim")]] +serialized_block = SubResource("Resource_yuj6e") -[sub_resource type="Resource" id="Resource_dptse"] +[sub_resource type="Resource" id="Resource_gkoq3"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "simplescoring_set_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set player 1 score to {score: INT}"], ["statement", "score_left = {score}"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", &"simplescoring_set_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set player 1 score to {score: INT}"], ["statement", "score_left = {score}"], ["defaults", {}], ["param_input_strings", { "score": "0" }]] -[sub_resource type="Resource" id="Resource_6g2pn"] +[sub_resource type="Resource" id="Resource_8xxm3"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_dptse") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_qxyq6")]] +name = &"simplescoring_set_score" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_oar78")]] +serialized_block = SubResource("Resource_gkoq3") -[sub_resource type="Resource" id="Resource_u7gx0"] +[sub_resource type="Resource" id="Resource_g3mty"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "ready_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(-350, -275)], ["scope", ""], ["block_format", "On Ready"], ["statement", "func _ready():"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] +serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", ""], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_jlgm4"] +[sub_resource type="Resource" id="Resource_njwj4"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_u7gx0") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_6g2pn")]] +name = &"ready_block" +position = Vector2(54, 47) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_8xxm3")]] +serialized_block = SubResource("Resource_g3mty") -[sub_resource type="Resource" id="Resource_ipq2j"] +[sub_resource type="Resource" id="Resource_3j7i4"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "simplescoring_change_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Change player 1 score by {score: INT}"], ["statement", "score_left += {score}"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", &"simplescoring_change_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Change player 1 score by {score: INT}"], ["statement", "score_left += {score}"], ["defaults", {}], ["param_input_strings", { "score": "1" }]] -[sub_resource type="Resource" id="Resource_imfrt"] +[sub_resource type="Resource" id="Resource_ntjp0"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_ipq2j") +name = &"simplescoring_change_score" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_3j7i4") -[sub_resource type="Resource" id="Resource_uu4ng"] +[sub_resource type="Resource" id="Resource_2e0ed"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "define_method"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(-350, -50)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", &"define_method"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(50, 300)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { "method_name": "goal_right" }], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_ed551"] +[sub_resource type="Resource" id="Resource_t8g7r"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_uu4ng") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_imfrt")]] +name = &"define_method" +position = Vector2(50, 300) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ntjp0")]] +serialized_block = SubResource("Resource_2e0ed") -[sub_resource type="Resource" id="Resource_5qjag"] +[sub_resource type="Resource" id="Resource_cxj82"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", "simplescoring_change_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Change player 2 score by {score: INT}"], ["statement", "score_right += {score}"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", &"simplescoring_change_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Change player 2 score by {score: INT}"], ["statement", "score_right += {score}"], ["defaults", {}], ["param_input_strings", { "score": "1" }]] -[sub_resource type="Resource" id="Resource_fyy20"] +[sub_resource type="Resource" id="Resource_c17ry"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_5qjag") +name = &"simplescoring_change_score" +position = Vector2(0, 0) path_child_pairs = [] +serialized_block = SubResource("Resource_cxj82") -[sub_resource type="Resource" id="Resource_yxdgk"] +[sub_resource type="Resource" id="Resource_udc68"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["block_name", "define_method"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(-350, 75)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["block_name", &"define_method"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(50, 450)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { "method_name": "goal_left" }], ["signal_name", ""]] -[sub_resource type="Resource" id="Resource_4v0rp"] +[sub_resource type="Resource" id="Resource_v2aur"] script = ExtResource("4_qtggh") -serialized_block = SubResource("Resource_yxdgk") -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_fyy20")]] +name = &"define_method" +position = Vector2(50, 450) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_c17ry")]] +serialized_block = SubResource("Resource_udc68") -[sub_resource type="Resource" id="Resource_g42ud"] +[sub_resource type="Resource" id="Resource_cu24c"] script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_jlgm4"), SubResource("Resource_ed551"), SubResource("Resource_4v0rp")]) +array = Array[ExtResource("4_qtggh")]([SubResource("Resource_njwj4"), SubResource("Resource_t8g7r"), SubResource("Resource_v2aur")]) -[sub_resource type="Resource" id="Resource_xe6aa"] +[sub_resource type="Resource" id="Resource_q418f"] script = ExtResource("7_uuuue") script_inherits = "SimpleScoring" -block_trees = SubResource("Resource_g42ud") +block_trees = SubResource("Resource_cu24c") variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends SimpleScoring @@ -887,7 +983,7 @@ texture = ExtResource("4_ra7bh") [node name="BlockCode" type="Node" parent="PaddleLeft"] script = ExtResource("3_6jaq8") -block_script = SubResource("Resource_dhvli") +block_script = SubResource("Resource_m2svk") [node name="PaddleRight" type="CharacterBody2D" parent="." groups=["paddles"]] modulate = Color(0.509804, 0.360784, 0.972549, 1) @@ -898,7 +994,7 @@ texture = ExtResource("4_ra7bh") [node name="BlockCode" type="Node" parent="PaddleRight"] script = ExtResource("3_6jaq8") -block_script = SubResource("Resource_krmii") +block_script = SubResource("Resource_ysbi4") [node name="Ball" parent="." instance=ExtResource("9_xrqll")] modulate = Color(0.511, 0.362, 0.972, 1) @@ -907,21 +1003,21 @@ gravity_scale = 0.0 [node name="BlockCode" type="Node" parent="Ball"] script = ExtResource("3_6jaq8") -block_script = SubResource("Resource_181ih") +block_script = SubResource("Resource_6m2mk") [node name="GoalAreaLeft" parent="." groups=["goal", "goal_left"] instance=ExtResource("12_nqmxu")] position = Vector2(-64, 544) [node name="BlockCode" type="Node" parent="GoalAreaLeft"] script = ExtResource("3_6jaq8") -block_script = SubResource("Resource_1yrql") +block_script = SubResource("Resource_4xylj") [node name="GoalAreaRight" parent="." groups=["goal", "goal_right"] instance=ExtResource("12_nqmxu")] position = Vector2(1984, 544) [node name="BlockCode" type="Node" parent="GoalAreaRight"] script = ExtResource("3_6jaq8") -block_script = SubResource("Resource_nf08t") +block_script = SubResource("Resource_xoc8a") [node name="SimpleScoring" type="CanvasLayer" parent="." groups=["hud"]] follow_viewport_enabled = true @@ -929,7 +1025,7 @@ script = ExtResource("13_tg3yk") [node name="BlockCode" type="Node" parent="SimpleScoring"] script = ExtResource("3_6jaq8") -block_script = SubResource("Resource_xe6aa") +block_script = SubResource("Resource_q418f") [node name="Camera2D" type="Camera2D" parent="."] position = Vector2(960, 540) From 56c20312a044bb6c51dfb54776b83bddf56a673c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 31 Jul 2024 21:24:15 -0300 Subject: [PATCH 119/423] fixup! Add Blocks Catalog --- addons/block_code/blocks_catalog.gd | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/addons/block_code/blocks_catalog.gd b/addons/block_code/blocks_catalog.gd index 92b60878..8593ff71 100644 --- a/addons/block_code/blocks_catalog.gd +++ b/addons/block_code/blocks_catalog.gd @@ -3,12 +3,11 @@ extends Object const BlockDefinition = preload("res://addons/block_code/block_definition.gd") const Types = preload("res://addons/block_code/types/types.gd") -static var _created: bool = false static var _catalog: Dictionary static func setup(): - if _created: + if _catalog: return _catalog = {} @@ -27,8 +26,6 @@ static func setup(): block_definition.category = "Log" _catalog[&"print"] = block_definition - _created = true - static func get_block(block_name: StringName): return _catalog.get(block_name) From 30402266a94b0fa460233a312d00a883b4bffa6b Mon Sep 17 00:00:00 2001 From: Gustavo Lopes Date: Wed, 31 Jul 2024 23:05:39 -0300 Subject: [PATCH 120/423] Show generated script in a window Replace printing the generated script to the output. Display it in a separate window instead. --- addons/block_code/block_code_plugin.gd | 14 ++++ addons/block_code/ui/main_panel.gd | 9 +- addons/block_code/ui/main_panel.tscn | 14 ++-- .../ui/script_window/script_window.gd | 15 ++++ .../ui/script_window/script_window.tscn | 84 +++++++++++++++++++ 5 files changed, 127 insertions(+), 9 deletions(-) create mode 100644 addons/block_code/ui/script_window/script_window.gd create mode 100644 addons/block_code/ui/script_window/script_window.tscn diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index a744d364..4a4f9b3d 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -3,6 +3,7 @@ extends EditorPlugin const MainPanelScene := preload("res://addons/block_code/ui/main_panel.tscn") const MainPanel = preload("res://addons/block_code/ui/main_panel.gd") const Types = preload("res://addons/block_code/types/types.gd") +const ScriptWindow := preload("res://addons/block_code/ui/script_window/script_window.tscn") static var main_panel: MainPanel static var block_code_button: Button @@ -38,6 +39,7 @@ func _enter_tree(): editor_selection = EditorInterface.get_selection() main_panel = MainPanelScene.instantiate() + main_panel.script_window_requested.connect(script_window_requested) main_panel.undo_redo = get_undo_redo() block_code_button = add_control_to_bottom_panel(main_panel, _get_plugin_name()) block_inspector_plugin = BlockInspectorPlugin.new() @@ -60,6 +62,18 @@ func _enter_tree(): EditorInterface.set_current_feature_profile("block_code") +func script_window_requested(script: String): + var script_window = ScriptWindow.instantiate() + script_window.script_content = script + + EditorInterface.get_base_control().add_child(script_window) + + await script_window.close_requested + + script_window.queue_free() + script_window = null + + func _exit_tree(): remove_inspector_plugin(block_inspector_plugin) diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index ce628ce0..4807b95e 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -1,6 +1,8 @@ @tool extends Control +signal script_window_requested(script: String) + const BlockCanvas = preload("res://addons/block_code/ui/block_canvas/block_canvas.gd") const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd") const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") @@ -58,8 +60,11 @@ func _on_undo_redo_version_changed(): _block_canvas.bsd_selected(block_script) -func _on_print_script_button_pressed(): - _print_generated_script() +func _on_show_script_button_pressed(): + var block_script: BlockScriptData = _current_block_code_node.block_script + var script: String = _block_canvas.generate_script_from_current_window(block_script) + + script_window_requested.emit(script) func _on_delete_node_button_pressed(): diff --git a/addons/block_code/ui/main_panel.tscn b/addons/block_code/ui/main_panel.tscn index 71fed42b..78520466 100644 --- a/addons/block_code/ui/main_panel.tscn +++ b/addons/block_code/ui/main_panel.tscn @@ -6,7 +6,7 @@ [ext_resource type="PackedScene" uid="uid://c6vumewgnfquy" path="res://addons/block_code/ui/block_canvas/block_canvas.tscn" id="4_cu87g"] [ext_resource type="PackedScene" uid="uid://cph1k5cfximbf" path="res://addons/block_code/drag_manager/drag_manager.tscn" id="4_yijtu"] -[sub_resource type="Image" id="Image_7y48q"] +[sub_resource type="Image" id="Image_p76b5"] data = { "data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 92, 92, 92, 64, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 92, 92, 92, 64, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 128, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 128, 90, 90, 90, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 249, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 192, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 192, 90, 90, 90, 249, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 197, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 195, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 52, 90, 90, 90, 238, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 236, 92, 92, 92, 50, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 96, 96, 96, 24, 91, 91, 91, 101, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 90, 90, 90, 128, 91, 91, 91, 101, 100, 100, 100, 23, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), "format": "RGBA8", @@ -16,9 +16,9 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_mrr6q"] -image = SubResource("Image_7y48q") +image = SubResource("Image_p76b5") -[sub_resource type="Image" id="Image_1l8vl"] +[sub_resource type="Image" id="Image_jif7k"] data = { "data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 92, 92, 92, 72, 91, 91, 91, 73, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 116, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 71, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 92, 92, 92, 75, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 201, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 119, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 247, 96, 96, 96, 40, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 91, 91, 91, 118, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 201, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 119, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 247, 96, 96, 96, 40, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 91, 91, 91, 118, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 201, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 91, 91, 91, 84, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 96, 96, 96, 40, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 91, 91, 91, 84, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 93, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 200, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 91, 91, 91, 118, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 119, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 248, 93, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 200, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 91, 91, 91, 118, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 119, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 248, 93, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 170, 170, 170, 3, 90, 90, 90, 200, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 200, 170, 170, 170, 3, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 93, 93, 41, 90, 90, 90, 248, 90, 90, 90, 255, 90, 90, 90, 255, 92, 92, 92, 75, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 116, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 71, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 90, 90, 90, 71, 92, 92, 92, 72, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), "format": "RGBA8", @@ -28,7 +28,7 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_2e128"] -image = SubResource("Image_1l8vl") +image = SubResource("Image_jif7k") [node name="MainPanel" type="MarginContainer"] anchors_preset = 15 @@ -60,10 +60,10 @@ unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 -[node name="PrintScriptButton" type="Button" parent="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer"] +[node name="ShowScriptButton" type="Button" parent="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer"] layout_mode = 2 size_flags_horizontal = 0 -text = "Print Generated Script" +text = "Show Generated Script" [node name="DeleteNodeButton" type="Button" parent="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer"] unique_name_in_owner = true @@ -117,7 +117,7 @@ mouse_filter = 2 picker_path = NodePath("../PickerSplit/Picker") block_canvas_path = NodePath("../PickerSplit/MarginContainer/VBoxContainer/BlockCanvas") -[connection signal="pressed" from="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer/PrintScriptButton" to="." method="_on_print_script_button_pressed"] +[connection signal="pressed" from="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer/ShowScriptButton" to="." method="_on_show_script_button_pressed"] [connection signal="pressed" from="MarginContainer/HBoxContainer/ScriptVBox/HBoxContainer/DeleteNodeButton" to="." method="_on_delete_node_button_pressed"] [connection signal="add_block_code" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/BlockCanvas" to="." method="_on_block_canvas_add_block_code"] [connection signal="open_scene" from="MarginContainer/HBoxContainer/ScriptVBox/MarginContainer/PickerSplit/MarginContainer/VBoxContainer/BlockCanvas" to="." method="_on_block_canvas_open_scene"] diff --git a/addons/block_code/ui/script_window/script_window.gd b/addons/block_code/ui/script_window/script_window.gd new file mode 100644 index 00000000..77b09dd8 --- /dev/null +++ b/addons/block_code/ui/script_window/script_window.gd @@ -0,0 +1,15 @@ +@tool +extends Window + +var script_content: String = "" + +@onready var script_label: TextEdit = $Margin/VBox/ColorRect/Scroll/Margin/Code + + +func _ready(): + popup_centered() + script_label.text = script_content.replace("\t", " ") + + +func _on_copy_code_pressed(): + DisplayServer.clipboard_set(script_content) diff --git a/addons/block_code/ui/script_window/script_window.tscn b/addons/block_code/ui/script_window/script_window.tscn new file mode 100644 index 00000000..b275d5cb --- /dev/null +++ b/addons/block_code/ui/script_window/script_window.tscn @@ -0,0 +1,84 @@ +[gd_scene load_steps=4 format=3 uid="uid://v3nopbe4l0ph"] + +[ext_resource type="Script" path="res://addons/block_code/ui/script_window/script_window.gd" id="1_jja22"] + +[sub_resource type="SystemFont" id="SystemFont_r6ct2"] +font_names = PackedStringArray("DejaVu Sans Mono") + +[sub_resource type="CodeHighlighter" id="CodeHighlighter_yvmnf"] +number_color = Color(0.498039, 0.760784, 0.686275, 1) +symbol_color = Color(0.803922, 0.811765, 0.823529, 1) +function_color = Color(0.290196, 0.576471, 0.819608, 1) +member_variable_color = Color(0.615686, 0.729412, 0.831373, 1) +keyword_colors = { +"and": Color(1, 0.439216, 0.521569, 1), +"elif": Color(1, 0.54902, 0.8, 1), +"else": Color(1, 0.54902, 0.8, 1), +"extends": Color(1, 0.439216, 0.521569, 1), +"for": Color(1, 0.54902, 0.8, 1), +"func": Color(1, 0.439216, 0.521569, 1), +"if": Color(1, 0.54902, 0.8, 1), +"not": Color(1, 0.439216, 0.521569, 1), +"or": Color(1, 0.439216, 0.521569, 1), +"return": Color(1, 0.54902, 0.8, 1), +"var": Color(1, 0.439216, 0.521569, 1) +} +color_regions = { +"\" \"": Color(1, 0.929412, 0.627451, 1), +"' '": Color(1, 0.929412, 0.627451, 1) +} + +[node name="ScriptWindow" type="Window"] +title = "Block Code Generated GDScript" +initial_position = 1 +size = Vector2i(750, 750) +transient = true +script = ExtResource("1_jja22") + +[node name="Margin" type="MarginContainer" parent="."] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 25 +theme_override_constants/margin_top = 25 +theme_override_constants/margin_right = 25 +theme_override_constants/margin_bottom = 25 + +[node name="VBox" type="VBoxContainer" parent="Margin"] +layout_mode = 2 + +[node name="CopyCode" type="Button" parent="Margin/VBox"] +layout_mode = 2 +text = "Copy" + +[node name="ColorRect" type="ColorRect" parent="Margin/VBox"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +color = Color(0.172833, 0.172833, 0.172833, 1) + +[node name="Scroll" type="ScrollContainer" parent="Margin/VBox/ColorRect"] +layout_mode = 2 +offset_top = -27.0 +offset_right = 700.0 +offset_bottom = 673.0 + +[node name="Margin" type="MarginContainer" parent="Margin/VBox/ColorRect/Scroll"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_constants/margin_left = 35 +theme_override_constants/margin_top = 55 +theme_override_constants/margin_right = 35 +theme_override_constants/margin_bottom = 35 + +[node name="Code" type="TextEdit" parent="Margin/VBox/ColorRect/Scroll/Margin"] +layout_mode = 2 +theme_override_colors/background_color = Color(0.144063, 0.144063, 0.144062, 1) +theme_override_fonts/font = SubResource("SystemFont_r6ct2") +editable = false +syntax_highlighter = SubResource("CodeHighlighter_yvmnf") + +[connection signal="pressed" from="Margin/VBox/CopyCode" to="." method="_on_copy_code_pressed"] From 356b5c87e59d2f6eab568d2adc1bee0212dfd450 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Fri, 19 Jul 2024 09:22:43 -0600 Subject: [PATCH 121/423] Build Simple node scenes in code The method to instantiate a scene internally in 6d017d0 is clever, but the real classes and internal classes create a circular dependency that cause import errors. Since there are only a couple child nodes that are significantly updated by the exported variables, just create the whole scene in code. There should be no functional changes besides dropping the internal scenes. The only change is that the simple nodes can only be added as a node type and not by the scene file. I don't think that will be missed. https://phabricator.endlessm.com/T35494 --- .../examples/pong_game/pong_game.tscn | 4 +- .../simple_character/_simple_character.gd | 8 --- .../simple_character/_simple_character.tscn | 14 ---- .../simple_character/simple_character.gd | 56 +++++++++------- .../simple_scoring/_simple_scoring.gd | 8 --- .../simple_scoring/_simple_scoring.tscn | 30 --------- .../simple_scoring/simple_scoring.gd | 66 ++++++++++++++----- 7 files changed, 82 insertions(+), 104 deletions(-) delete mode 100644 addons/block_code/simple_nodes/simple_character/_simple_character.gd delete mode 100644 addons/block_code/simple_nodes/simple_character/_simple_character.tscn delete mode 100644 addons/block_code/simple_nodes/simple_scoring/_simple_scoring.gd delete mode 100644 addons/block_code/simple_nodes/simple_scoring/_simple_scoring.tscn diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index 52a983d9..36dc5b8b 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -878,7 +878,7 @@ version = 0 [node name="Space" parent="." instance=ExtResource("1_y56ac")] -[node name="PaddleLeft" type="CharacterBody2D" parent="." groups=["paddles"]] +[node name="PaddleLeft" type="CharacterBody2D" parent="." groups=["affected_by_gravity", "paddles"]] modulate = Color(0.509804, 0.360784, 0.972549, 1) position = Vector2(64, 544) collision_mask = 5 @@ -889,7 +889,7 @@ texture = ExtResource("4_ra7bh") script = ExtResource("3_6jaq8") block_script = SubResource("Resource_dhvli") -[node name="PaddleRight" type="CharacterBody2D" parent="." groups=["paddles"]] +[node name="PaddleRight" type="CharacterBody2D" parent="." groups=["affected_by_gravity", "paddles"]] modulate = Color(0.509804, 0.360784, 0.972549, 1) position = Vector2(1856, 544) collision_mask = 5 diff --git a/addons/block_code/simple_nodes/simple_character/_simple_character.gd b/addons/block_code/simple_nodes/simple_character/_simple_character.gd deleted file mode 100644 index b5438769..00000000 --- a/addons/block_code/simple_nodes/simple_character/_simple_character.gd +++ /dev/null @@ -1,8 +0,0 @@ -@tool -extends SimpleCharacter - - -func _init(): - # Disable the SimpleCharacter _init function. We expect this script is - # already bound to _simple_character.tscn. - pass diff --git a/addons/block_code/simple_nodes/simple_character/_simple_character.tscn b/addons/block_code/simple_nodes/simple_character/_simple_character.tscn deleted file mode 100644 index 03e429c2..00000000 --- a/addons/block_code/simple_nodes/simple_character/_simple_character.tscn +++ /dev/null @@ -1,14 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://ddx1cd5q6t61o"] - -[ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_character/_simple_character.gd" id="1_idjqv"] - -[sub_resource type="RectangleShape2D" id="RectangleShape2D_ffh0f"] -size = Vector2(100, 100) - -[node name="SimpleCharacter" type="CharacterBody2D"] -script = ExtResource("1_idjqv") - -[node name="Sprite2D" type="Sprite2D" parent="."] - -[node name="CollisionShape2D" type="CollisionShape2D" parent="."] -shape = SubResource("RectangleShape2D_ffh0f") diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index d62913a3..4ab02ad3 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -8,8 +8,7 @@ const Types = preload("res://addons/block_code/types/types.gd") @export var texture: Texture2D: set = _set_texture -@export var speed: Vector2 = Vector2(300, 300): - set = _set_speed +@export var speed: Vector2 = Vector2(300, 300) const PLAYER_KEYS = { "player_1": @@ -28,6 +27,9 @@ const PLAYER_KEYS = { } } +var sprite: Sprite2D +var collision: CollisionShape2D + # Get the gravity from the project settings to be synced with RigidBody nodes. var gravity = ProjectSettings.get_setting("physics/2d/default_gravity") @@ -36,18 +38,13 @@ var _jumping = false func _set_texture(new_texture): texture = new_texture - - if not is_node_ready(): - return - - $Sprite2D.texture = texture - var shape = RectangleShape2D.new() - shape.size = Vector2(100, 100) if texture == null else texture.get_size() - $CollisionShape2D.shape = shape + if is_node_ready(): + _texture_updated() -func _set_speed(new_speed): - speed = new_speed +func _texture_updated(): + sprite.texture = texture + collision.shape.size = Vector2(100, 100) if texture == null else texture.get_size() ## Nodes in the "affected_by_gravity" group will receive gravity changes: @@ -55,24 +52,33 @@ func on_gravity_changed(new_gravity): gravity = new_gravity -func _init(): - if self.get_parent(): - return - - var node = preload("res://addons/block_code/simple_nodes/simple_character/_simple_character.tscn").instantiate() as Node - node.replace_by(self, true) - node.queue_free() - scene_file_path = "" - - func _ready(): - add_to_group("affected_by_gravity") simple_setup() func simple_setup(): - _set_texture(texture) - _set_speed(speed) + add_to_group("affected_by_gravity", true) + + sprite = Sprite2D.new() + sprite.name = &"Sprite2D" + add_child(sprite) + + collision = CollisionShape2D.new() + collision.name = &"CollisionShape2D" + collision.shape = RectangleShape2D.new() + add_child(collision) + + _texture_updated() + + +func _exit_tree(): + if collision: + collision.queue_free() + collision = null + + if sprite: + sprite.queue_free() + sprite = null func get_custom_class(): diff --git a/addons/block_code/simple_nodes/simple_scoring/_simple_scoring.gd b/addons/block_code/simple_nodes/simple_scoring/_simple_scoring.gd deleted file mode 100644 index 6c1476fa..00000000 --- a/addons/block_code/simple_nodes/simple_scoring/_simple_scoring.gd +++ /dev/null @@ -1,8 +0,0 @@ -@tool -extends SimpleScoring - - -func _init(): - # Disable the SimpleScoring _init function. We expect this script is - # already bound to _simple_scoring.tscn. - pass diff --git a/addons/block_code/simple_nodes/simple_scoring/_simple_scoring.tscn b/addons/block_code/simple_nodes/simple_scoring/_simple_scoring.tscn deleted file mode 100644 index 4d17dc83..00000000 --- a/addons/block_code/simple_nodes/simple_scoring/_simple_scoring.tscn +++ /dev/null @@ -1,30 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://bis7afjjuwypq"] - -[ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_scoring/_simple_scoring.gd" id="1_lc5bg"] - -[node name="SimpleScoring" type="CanvasLayer" groups=["hud"]] -script = ExtResource("1_lc5bg") - -[node name="PlayerLeftScore" type="Label" parent="."] -unique_name_in_owner = true -offset_left = 240.0 -offset_right = 717.0 -offset_bottom = 1080.0 -pivot_offset = Vector2(240, 176) -size_flags_horizontal = 3 -size_flags_vertical = 1 -theme_override_font_sizes/font_size = 200 -text = "0" -horizontal_alignment = 1 - -[node name="PlayerRightScore" type="Label" parent="."] -unique_name_in_owner = true -offset_left = 1200.0 -offset_right = 1677.0 -offset_bottom = 1080.0 -pivot_offset = Vector2(240, 176) -size_flags_horizontal = 3 -size_flags_vertical = 1 -theme_override_font_sizes/font_size = 200 -text = "0" -horizontal_alignment = 1 diff --git a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd index 8bee47cc..b70cfc37 100644 --- a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd +++ b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd @@ -11,10 +11,7 @@ const Types = preload("res://addons/block_code/types/types.gd") @export var score_right: int: set = _set_score_right -@onready var _score_labels = { - "left": %PlayerLeftScore, - "right": %PlayerRightScore, -} +var _score_labels: Dictionary const _POSITIONS_FOR_PLAYER = { "1": "left", @@ -22,14 +19,53 @@ const _POSITIONS_FOR_PLAYER = { } -func _init(): - if self.get_parent(): - return +func _create_score_label(player: String) -> Label: + var label := Label.new() + + var x_pos: int + match player: + "left": + x_pos = 240 + "right": + x_pos = 1200 + _: + push_error('Unrecognized SimpleScoring player "%s"' % player) + + label.name = &"Player%sScore" % player.capitalize() + label.set_size(Vector2(477, 1080)) + label.set_position(Vector2(x_pos, 0)) + label.pivot_offset = Vector2(240, 176) + label.size_flags_horizontal = Control.SizeFlags.SIZE_EXPAND_FILL + label.size_flags_vertical = Control.SizeFlags.SIZE_FILL + label.add_theme_font_size_override("font_size", 200) + label.text = "0" + label.horizontal_alignment = HorizontalAlignment.HORIZONTAL_ALIGNMENT_CENTER + + return label + + +func _ready(): + simple_setup() + + +func simple_setup(): + add_to_group("hud", true) + + var left_label := _create_score_label("left") + _score_labels["left"] = left_label + _update_label("left", score_left) + add_child(left_label) + + var right_label := _create_score_label("right") + _score_labels["right"] = right_label + _update_label("right", score_right) + add_child(right_label) + - var node = preload("res://addons/block_code/simple_nodes/simple_scoring/_simple_scoring.tscn").instantiate() as Node - node.replace_by(self, true) - node.queue_free() - scene_file_path = "" +func _exit_tree(): + for label in _score_labels.values(): + label.queue_free() + _score_labels.clear() func get_custom_class(): @@ -38,17 +74,13 @@ func get_custom_class(): func _set_score_left(new_score_left): score_left = new_score_left - if not is_node_ready(): - await ready - if score_left: + if score_left and is_node_ready(): _update_label("left", score_left) func _set_score_right(new_score_right): score_right = new_score_right - if not is_node_ready(): - await ready - if score_right: + if score_right and is_node_ready(): _update_label("right", score_right) From 87f802b611b4f48a89a27744ac788e84853126a8 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Fri, 26 Jul 2024 13:54:53 -0600 Subject: [PATCH 122/423] Block: Allow to grab focus Set the focus mode on Blocks so they can process input events. When dragged on the canvas, set the dropped block to be focused. Note the subtle interaction between FocusMode.FOCUS_ALL, which allows focusing by mouse click, and MouseFilter.MOUSE_FILTER_IGNORE, which filters out mouse click events. The combination means that the mouse click will be handled in Godot for focusing the block, but the mouse click can't be processed in _gui_input(). --- addons/block_code/drag_manager/drag_manager.gd | 1 + addons/block_code/ui/blocks/block/block.gd | 1 + addons/block_code/ui/blocks/control_block/control_block.tscn | 1 + addons/block_code/ui/blocks/entry_block/entry_block.tscn | 1 + addons/block_code/ui/blocks/parameter_block/parameter_block.tscn | 1 + addons/block_code/ui/blocks/statement_block/statement_block.tscn | 1 + 6 files changed, 6 insertions(+) diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index a1727cf9..138dcb9b 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -80,6 +80,7 @@ func drag_ended(): if block: connect_block_canvas_signals(block) + block.grab_focus() _block_canvas.release_scope() diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 6818b76d..5b9ef894 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -48,6 +48,7 @@ func _set_bottom_snap_path(value: NodePath): func _ready(): if bottom_snap == null: _set_bottom_snap_path(bottom_snap_path) + focus_mode = FocusMode.FOCUS_ALL mouse_filter = Control.MOUSE_FILTER_IGNORE diff --git a/addons/block_code/ui/blocks/control_block/control_block.tscn b/addons/block_code/ui/blocks/control_block/control_block.tscn index 6e77f7d6..e45c85d6 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.tscn +++ b/addons/block_code/ui/blocks/control_block/control_block.tscn @@ -5,6 +5,7 @@ [node name="ControlBlock" type="MarginContainer"] size_flags_horizontal = 0 +focus_mode = 2 mouse_filter = 2 script = ExtResource("1_2hbir") block_name = &"control_block" diff --git a/addons/block_code/ui/blocks/entry_block/entry_block.tscn b/addons/block_code/ui/blocks/entry_block/entry_block.tscn index 49774a00..50c2f0b6 100644 --- a/addons/block_code/ui/blocks/entry_block/entry_block.tscn +++ b/addons/block_code/ui/blocks/entry_block/entry_block.tscn @@ -4,6 +4,7 @@ [ext_resource type="Script" path="res://addons/block_code/ui/blocks/entry_block/entry_block.gd" id="2_3ik8h"] [node name="EntryBlock" instance=ExtResource("1_byjbb")] +focus_mode = 2 script = ExtResource("2_3ik8h") signal_name = "" block_name = &"entry_block" diff --git a/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn b/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn index 5700ae20..5e38f402 100644 --- a/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn +++ b/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn @@ -18,6 +18,7 @@ corner_radius_bottom_left = 16 offset_right = 16.0 offset_bottom = 8.0 size_flags_horizontal = 0 +focus_mode = 2 mouse_filter = 2 script = ExtResource("1_0hajy") block_name = &"parameter_block" diff --git a/addons/block_code/ui/blocks/statement_block/statement_block.tscn b/addons/block_code/ui/blocks/statement_block/statement_block.tscn index 7463bf4f..f5507555 100644 --- a/addons/block_code/ui/blocks/statement_block/statement_block.tscn +++ b/addons/block_code/ui/blocks/statement_block/statement_block.tscn @@ -7,6 +7,7 @@ [node name="StatementBlock" type="MarginContainer"] size_flags_horizontal = 0 +focus_mode = 2 mouse_filter = 2 script = ExtResource("1_6wvlf") block_name = &"statement_block" From aeb4d5971db4443714182744157478b0a1d82008 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Fri, 26 Jul 2024 13:56:04 -0600 Subject: [PATCH 123/423] Block: Allow deleting with Delete button Allow a Block to be deleted with a confirmation dialog when the Delete key is pressed. However, when the Block is in the picker (rather than the canvas), it shouldn't be deleted. Add a flag to disable deleting and restore it when a drag completes. Furthermore, when it shouldn't be deleted, stop propagating the Delete key so it doesn't try to delete the whole BlockCode node. Fixes: #162 --- .../block_code/drag_manager/drag_manager.gd | 3 ++ addons/block_code/ui/blocks/block/block.gd | 44 +++++++++++++++++++ addons/block_code/ui/picker/picker.gd | 3 ++ 3 files changed, 50 insertions(+) diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index 138dcb9b..c12dd984 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -82,6 +82,9 @@ func drag_ended(): connect_block_canvas_signals(block) block.grab_focus() + # Allow the block to be deleted now that it's on the canvas. + block.can_delete = true + _block_canvas.release_scope() drag.queue_free() diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 5b9ef894..53bbb467 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -39,6 +39,9 @@ signal modified # https://github.com/godotengine/godot/issues/82670 var bottom_snap: SnapPoint +## Whether the block can be deleted by the Delete key. +var can_delete: bool = true + func _set_bottom_snap_path(value: NodePath): bottom_snap_path = value @@ -52,6 +55,36 @@ func _ready(): mouse_filter = Control.MOUSE_FILTER_IGNORE +func _gui_input(event): + if event is InputEventKey: + if event.pressed and event.keycode == KEY_DELETE: + # Always accept the Delete key so it doesn't propagate to the + # BlockCode node in the scene tree. + accept_event() + + if not can_delete: + return + + var dialog := ConfirmationDialog.new() + var num_blocks = _count_child_blocks(self) + 1 + # FIXME: Maybe this should use block_name or label, but that + # requires one to be both unique and human friendly. + if num_blocks > 1: + dialog.dialog_text = "Delete %d blocks?" % num_blocks + else: + dialog.dialog_text = "Delete block?" + dialog.confirmed.connect(remove_from_tree) + EditorInterface.popup_dialog_centered(dialog) + + +func remove_from_tree(): + var parent = get_parent() + if parent: + parent.remove_child(self) + queue_free() + modified.emit() + + static func get_block_class(): push_error("Unimplemented.") @@ -125,3 +158,14 @@ func _make_custom_tooltip(for_text) -> Control: var tooltip = preload("res://addons/block_code/ui/tooltip/tooltip.tscn").instantiate() tooltip.text = for_text return tooltip + + +func _count_child_blocks(node: Node) -> int: + var count = 0 + + for child in node.get_children(): + if child is SnapPoint and child.has_snapped_block(): + count += 1 + count += _count_child_blocks(child) + + return count diff --git a/addons/block_code/ui/picker/picker.gd b/addons/block_code/ui/picker/picker.gd index d58c8061..d68d8370 100644 --- a/addons/block_code/ui/picker/picker.gd +++ b/addons/block_code/ui/picker/picker.gd @@ -85,6 +85,9 @@ func init_picker(extra_blocks: Array[Block] = [], extra_categories: Array[BlockC var block: Block = _block as Block block.drag_started.connect(_block_picked) + # Don't allow the block to be deleted while in the picker. + block.can_delete = false + _block_scroll.scroll_vertical = 0 From e41a2bef7b6dfaf807894dd6837ec8f7db33a3f3 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 31 Jul 2024 18:38:57 -0700 Subject: [PATCH 124/423] Move get_parent_block to BlockTreeUtil --- addons/block_code/drag_manager/drag.gd | 2 +- addons/block_code/ui/block_tree_util.gd | 8 ++++++++ .../ui/blocks/utilities/snap_point/snap_point.gd | 7 ------- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/addons/block_code/drag_manager/drag.gd b/addons/block_code/drag_manager/drag.gd index 62404532..7017c8c4 100644 --- a/addons/block_code/drag_manager/drag.gd +++ b/addons/block_code/drag_manager/drag.gd @@ -34,7 +34,7 @@ var target_snap_point: SnapPoint: var snap_block: Block: get: - return target_snap_point.get_parent_block() if target_snap_point else null + return BlockTreeUtil.get_parent_block(target_snap_point) if target_snap_point else null func _init(block: Block, block_scope: String, offset: Vector2, block_canvas: BlockCanvas): diff --git a/addons/block_code/ui/block_tree_util.gd b/addons/block_code/ui/block_tree_util.gd index 7e547a05..acd1a3da 100644 --- a/addons/block_code/ui/block_tree_util.gd +++ b/addons/block_code/ui/block_tree_util.gd @@ -78,3 +78,11 @@ static func get_tree_scope(node: Node) -> String: if scope != "": return scope return "" + + +## Get the nearest Block node that is a parent of the provided node. +static func get_parent_block(node: Node) -> Block: + var parent = node.get_parent() + while parent and not parent is Block: + parent = parent.get_parent() + return parent as Block diff --git a/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd b/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd index d4be8386..8b39f4b5 100644 --- a/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd +++ b/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd @@ -29,13 +29,6 @@ func _ready(): _update_snapped_block_from_children() -func get_parent_block() -> Block: - var parent = get_parent() - while parent and not parent is Block: - parent = parent.get_parent() - return parent as Block - - func _update_snapped_block_from_children(): # Temporary migration to set the snapped_block property based on children # of this node. From 854330dc97bd07b70a4d785eebbb0613d11ec967 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 31 Jul 2024 18:40:38 -0700 Subject: [PATCH 125/423] Change Background border color when block is focused --- .../ui/blocks/utilities/background/background.gd | 12 ++++++++++-- .../ui/blocks/utilities/background/gutter.gd | 12 ++++++++++-- addons/block_code/ui/constants.gd | 2 ++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/addons/block_code/ui/blocks/utilities/background/background.gd b/addons/block_code/ui/blocks/utilities/background/background.gd index e8aec7c1..adf74799 100644 --- a/addons/block_code/ui/blocks/utilities/background/background.gd +++ b/addons/block_code/ui/blocks/utilities/background/background.gd @@ -1,9 +1,11 @@ @tool extends Control +const BlockTreeUtil = preload("res://addons/block_code/ui/block_tree_util.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") var outline_color: Color +var parent_block: Block @export var color: Color: set = _set_color @@ -41,6 +43,12 @@ func _set_shift_bottom(new_shift_bottom): queue_redraw() +func _ready(): + parent_block = BlockTreeUtil.get_parent_block(self) + parent_block.focus_entered.connect(queue_redraw) + parent_block.focus_exited.connect(queue_redraw) + + func _draw(): var fill_polygon: PackedVector2Array fill_polygon.append(Vector2(0.0, 0.0)) @@ -97,5 +105,5 @@ func _draw(): edge_polygon.append(Vector2(0.0, size.y + outline_middle)) draw_colored_polygon(fill_polygon, color) - draw_polyline(stroke_polygon, outline_color, Constants.OUTLINE_WIDTH) - draw_polyline(edge_polygon, outline_color, Constants.OUTLINE_WIDTH) + draw_polyline(stroke_polygon, Constants.FOCUS_BORDER_COLOR if parent_block.has_focus() else outline_color, Constants.OUTLINE_WIDTH) + draw_polyline(edge_polygon, Constants.FOCUS_BORDER_COLOR if parent_block.has_focus() else outline_color, Constants.OUTLINE_WIDTH) diff --git a/addons/block_code/ui/blocks/utilities/background/gutter.gd b/addons/block_code/ui/blocks/utilities/background/gutter.gd index f449949f..30e09a95 100644 --- a/addons/block_code/ui/blocks/utilities/background/gutter.gd +++ b/addons/block_code/ui/blocks/utilities/background/gutter.gd @@ -1,9 +1,11 @@ @tool extends Control +const BlockTreeUtil = preload("res://addons/block_code/ui/block_tree_util.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") var outline_color: Color +var parent_block: Block @export var color: Color: set = _set_color @@ -15,6 +17,12 @@ func _set_color(new_color): queue_redraw() +func _ready(): + parent_block = BlockTreeUtil.get_parent_block(self) + parent_block.focus_entered.connect(queue_redraw) + parent_block.focus_exited.connect(queue_redraw) + + func _draw(): var fill_polygon: PackedVector2Array fill_polygon.append(Vector2(0.0, 0.0)) @@ -33,5 +41,5 @@ func _draw(): right_polygon.append(Vector2(size.x, size.y)) draw_colored_polygon(fill_polygon, color) - draw_polyline(left_polygon, outline_color, Constants.OUTLINE_WIDTH) - draw_polyline(right_polygon, outline_color, Constants.OUTLINE_WIDTH) + draw_polyline(left_polygon, Constants.FOCUS_BORDER_COLOR if parent_block.has_focus() else outline_color, Constants.OUTLINE_WIDTH) + draw_polyline(right_polygon, Constants.FOCUS_BORDER_COLOR if parent_block.has_focus() else outline_color, Constants.OUTLINE_WIDTH) diff --git a/addons/block_code/ui/constants.gd b/addons/block_code/ui/constants.gd index 88d6d9ab..dcb65e23 100644 --- a/addons/block_code/ui/constants.gd +++ b/addons/block_code/ui/constants.gd @@ -9,3 +9,5 @@ const KNOB_Z = 5.0 const CONTROL_MARGIN = 20.0 const OUTLINE_WIDTH = 3.0 const MINIMUM_SNAP_DISTANCE = 80.0 + +const FOCUS_BORDER_COLOR = Color(225, 242, 0) From 4f9899654fa497a901d82c17f6f686e3c91ce739 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 31 Jul 2024 18:41:21 -0700 Subject: [PATCH 126/423] Add a focus style override for ParameterBlock --- .../blocks/parameter_block/parameter_block.gd | 25 ++++++++++++++++--- .../parameter_block/parameter_block.tscn | 2 ++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd index 75b11b4a..247e3051 100644 --- a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd +++ b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd @@ -2,6 +2,7 @@ class_name ParameterBlock extends Block +const Constants = preload("res://addons/block_code/ui/constants.gd") const Util = preload("res://addons/block_code/ui/util.gd") @export var block_format: String = "" @@ -16,16 +17,24 @@ var param_name_input_pairs: Array var param_input_strings: Dictionary # Only loaded from serialized var spawned_by: ParameterOutput +var _panel_normal: StyleBox +var _panel_focus: StyleBox + func _ready(): super() + _panel_normal = _panel.get_theme_stylebox("panel").duplicate() + _panel_normal.bg_color = color + _panel_normal.border_color = color.darkened(0.2) + + _panel_focus = _panel.get_theme_stylebox("panel").duplicate() + _panel_focus.bg_color = color + _panel_focus.border_color = Constants.FOCUS_BORDER_COLOR + block_type = Types.BlockType.VALUE if not Util.node_is_part_of_edited_scene(self): - var new_panel = _panel.get_theme_stylebox("panel").duplicate() - new_panel.bg_color = color - new_panel.border_color = color.darkened(0.2) - _panel.add_theme_stylebox_override("panel", new_panel) + _panel.add_theme_stylebox_override("panel", _panel_normal) format() @@ -73,3 +82,11 @@ static func get_scene_path(): func format(): param_name_input_pairs = StatementBlock.format_string(self, %HBoxContainer, block_format, defaults) + + +func _on_focus_entered(): + _panel.add_theme_stylebox_override("panel", _panel_focus) + + +func _on_focus_exited(): + _panel.add_theme_stylebox_override("panel", _panel_normal) diff --git a/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn b/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn index 5e38f402..2e901cd9 100644 --- a/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn +++ b/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn @@ -47,4 +47,6 @@ unique_name_in_owner = true layout_mode = 2 mouse_filter = 2 +[connection signal="focus_entered" from="." to="." method="_on_focus_entered"] +[connection signal="focus_exited" from="." to="." method="_on_focus_exited"] [connection signal="mouse_down" from="DragDropArea" to="." method="_on_drag_drop_area_mouse_down"] From c27dafa6463d63f086aae199c5dbcc3c3c202b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 31 Jul 2024 10:01:27 -0300 Subject: [PATCH 127/423] Rename SerializedBlock to BlockSerializedProperties And move it to a new serialization/ folder. This resouce will be removed when there are no more properties to serialize, so add a TODO comment. --- addons/block_code/block_code_plugin.gd | 2 +- .../examples/pong_game/pong_game.tscn | 98 +++++++++---------- .../block_serialized_properties.gd} | 4 +- .../ui/block_canvas/block_canvas.gd | 14 +-- .../serialized_block_tree_node.gd | 6 +- addons/block_code/ui/blocks/block/block.gd | 10 +- .../ui/bsd_templates/default_bsd.tres | 4 +- 7 files changed, 70 insertions(+), 68 deletions(-) rename addons/block_code/{ui/block_canvas/serialized_block.gd => serialization/block_serialized_properties.gd} (68%) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 4a4f9b3d..56dbf34c 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -27,7 +27,7 @@ const DISABLED_CLASSES := [ "SnapPoint", "SerializedBlockTreeNodeArray", "SerializedBlockTreeNode", - "SerializedBlock", + "BlockSerializedProperties", "CategoryFactory", ] diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index fb71cd4f..309df2fc 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -5,7 +5,7 @@ [ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_character/simple_character.gd" id="3_mdrcv"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node.gd" id="4_qtggh"] [ext_resource type="Texture2D" uid="uid://tplpgtnfeda0" path="res://addons/block_code/examples/pong_game/assets/paddle.png" id="4_ra7bh"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block.gd" id="5_wr38c"] +[ext_resource type="Script" path="res://addons/block_code/serialization/block_serialized_properties.gd" id="5_wr38c"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node_array.gd" id="6_ppdc3"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="7_3q6bj"] [ext_resource type="Script" path="res://addons/block_code/block_script_data/block_script_data.gd" id="7_uuuue"] @@ -27,7 +27,7 @@ script = ExtResource("4_qtggh") name = &"set_prop_speed" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_860cl") +block_serialized_properties = SubResource("Resource_860cl") [sub_resource type="Resource" id="Resource_q1vhx"] script = ExtResource("5_wr38c") @@ -39,7 +39,7 @@ script = ExtResource("4_qtggh") name = &"ready_block" position = Vector2(75, 175) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_q65fe")]] -serialized_block = SubResource("Resource_q1vhx") +block_serialized_properties = SubResource("Resource_q1vhx") [sub_resource type="Resource" id="Resource_a45un"] script = ExtResource("7_3q6bj") @@ -77,7 +77,7 @@ script = ExtResource("4_qtggh") name = &"simplecharacter_move" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_d3xtc") +block_serialized_properties = SubResource("Resource_d3xtc") [sub_resource type="Resource" id="Resource_x6ddv"] script = ExtResource("5_wr38c") @@ -89,7 +89,7 @@ script = ExtResource("4_qtggh") name = &"process_block" position = Vector2(75, 300) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_7x3sw")]] -serialized_block = SubResource("Resource_x6ddv") +block_serialized_properties = SubResource("Resource_x6ddv") [sub_resource type="Resource" id="Resource_a04yd"] script = ExtResource("6_ppdc3") @@ -126,7 +126,7 @@ script = ExtResource("4_qtggh") name = &"set_prop_speed" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_isc56") +block_serialized_properties = SubResource("Resource_isc56") [sub_resource type="Resource" id="Resource_06s7w"] script = ExtResource("5_wr38c") @@ -138,7 +138,7 @@ script = ExtResource("4_qtggh") name = &"ready_block" position = Vector2(50, 175) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ttkrd")]] -serialized_block = SubResource("Resource_06s7w") +block_serialized_properties = SubResource("Resource_06s7w") [sub_resource type="Resource" id="Resource_y2msu"] script = ExtResource("7_3q6bj") @@ -176,7 +176,7 @@ script = ExtResource("4_qtggh") name = &"simplecharacter_move" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_bl8w1") +block_serialized_properties = SubResource("Resource_bl8w1") [sub_resource type="Resource" id="Resource_3wgnl"] script = ExtResource("5_wr38c") @@ -188,7 +188,7 @@ script = ExtResource("4_qtggh") name = &"process_block" position = Vector2(50, 300) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_enqe8")]] -serialized_block = SubResource("Resource_3wgnl") +block_serialized_properties = SubResource("Resource_3wgnl") [sub_resource type="Resource" id="Resource_y05sx"] script = ExtResource("6_ppdc3") @@ -229,7 +229,7 @@ script = ExtResource("4_qtggh") name = &"load_sound" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_rf047") +block_serialized_properties = SubResource("Resource_rf047") [sub_resource type="Resource" id="Resource_md4i5"] script = ExtResource("5_wr38c") @@ -249,7 +249,7 @@ script = ExtResource("4_qtggh") name = &"load_sound" position = Vector2(0, 0) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_d34ke")]] -serialized_block = SubResource("Resource_md4i5") +block_serialized_properties = SubResource("Resource_md4i5") [sub_resource type="Resource" id="Resource_4luvu"] script = ExtResource("5_wr38c") @@ -269,7 +269,7 @@ script = ExtResource("4_qtggh") name = &"load_sound" position = Vector2(0, 0) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_roxh4")]] -serialized_block = SubResource("Resource_4luvu") +block_serialized_properties = SubResource("Resource_4luvu") [sub_resource type="Resource" id="Resource_b0aen"] script = ExtResource("5_wr38c") @@ -281,7 +281,7 @@ script = ExtResource("4_qtggh") name = &"ready_block" position = Vector2(54, 47) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_gywyt")]] -serialized_block = SubResource("Resource_b0aen") +block_serialized_properties = SubResource("Resource_b0aen") [sub_resource type="Resource" id="Resource_05cdj"] script = ExtResource("5_wr38c") @@ -293,7 +293,7 @@ script = ExtResource("4_qtggh") name = &"viewport_center" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_05cdj") +block_serialized_properties = SubResource("Resource_05cdj") [sub_resource type="Resource" id="Resource_uob83"] script = ExtResource("5_wr38c") @@ -317,7 +317,7 @@ script = ExtResource("4_qtggh") name = &"play_sound" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_uob83") +block_serialized_properties = SubResource("Resource_uob83") [sub_resource type="Resource" id="Resource_5x1be"] script = ExtResource("5_wr38c") @@ -337,7 +337,7 @@ script = ExtResource("4_qtggh") name = &"rigidbody2d_physics_position" position = Vector2(0, 0) path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_kt3qw")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_oawyp")]] -serialized_block = SubResource("Resource_5x1be") +block_serialized_properties = SubResource("Resource_5x1be") [sub_resource type="Resource" id="Resource_sp3a4"] script = ExtResource("5_wr38c") @@ -351,7 +351,7 @@ script = ExtResource("4_qtggh") name = &"define_method" position = Vector2(50, 275) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ftveg")]] -serialized_block = SubResource("Resource_sp3a4") +block_serialized_properties = SubResource("Resource_sp3a4") [sub_resource type="Resource" id="Resource_r1gqk"] script = ExtResource("5_wr38c") @@ -366,7 +366,7 @@ script = ExtResource("4_qtggh") name = &"parameter_block" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_r1gqk") +block_serialized_properties = SubResource("Resource_r1gqk") [sub_resource type="Resource" id="Resource_ri33r"] script = ExtResource("5_wr38c") @@ -381,7 +381,7 @@ script = ExtResource("4_qtggh") name = &"parameter_block" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_ri33r") +block_serialized_properties = SubResource("Resource_ri33r") [sub_resource type="Resource" id="Resource_s7b4y"] script = ExtResource("5_wr38c") @@ -396,7 +396,7 @@ script = ExtResource("4_qtggh") name = &"is_node_in_group" position = Vector2(0, 0) path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_7qpii")]] -serialized_block = SubResource("Resource_s7b4y") +block_serialized_properties = SubResource("Resource_s7b4y") [sub_resource type="Resource" id="Resource_bh5jo"] script = ExtResource("5_wr38c") @@ -420,7 +420,7 @@ script = ExtResource("4_qtggh") name = &"play_sound" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_bh5jo") +block_serialized_properties = SubResource("Resource_bh5jo") [sub_resource type="Resource" id="Resource_mgvpf"] script = ExtResource("5_wr38c") @@ -435,7 +435,7 @@ script = ExtResource("4_qtggh") name = &"parameter_block" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_mgvpf") +block_serialized_properties = SubResource("Resource_mgvpf") [sub_resource type="Resource" id="Resource_rc730"] script = ExtResource("5_wr38c") @@ -450,7 +450,7 @@ script = ExtResource("4_qtggh") name = &"is_node_in_group" position = Vector2(0, 0) path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_mbuv7")]] -serialized_block = SubResource("Resource_rc730") +block_serialized_properties = SubResource("Resource_rc730") [sub_resource type="Resource" id="Resource_71yrt"] script = ExtResource("5_wr38c") @@ -474,7 +474,7 @@ script = ExtResource("4_qtggh") name = &"play_sound" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_71yrt") +block_serialized_properties = SubResource("Resource_71yrt") [sub_resource type="Resource" id="Resource_wkj8h"] script = ExtResource("5_wr38c") @@ -488,7 +488,7 @@ script = ExtResource("4_qtggh") name = &"if" position = Vector2(0, 0) path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_fgryt")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_f3xwp")]] -serialized_block = SubResource("Resource_wkj8h") +block_serialized_properties = SubResource("Resource_wkj8h") [sub_resource type="Resource" id="Resource_dwd2k"] script = ExtResource("5_wr38c") @@ -502,7 +502,7 @@ script = ExtResource("4_qtggh") name = &"if" position = Vector2(0, 0) path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_xsgv2")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_ic2jq")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_qmdbv")]] -serialized_block = SubResource("Resource_dwd2k") +block_serialized_properties = SubResource("Resource_dwd2k") [sub_resource type="Resource" id="Resource_7mdg3"] script = ExtResource("5_wr38c") @@ -517,7 +517,7 @@ script = ExtResource("4_qtggh") name = &"rigidbody2d_on_entered" position = Vector2(50, 475) path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_gj1nu")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_rs6a0")]] -serialized_block = SubResource("Resource_7mdg3") +block_serialized_properties = SubResource("Resource_7mdg3") [sub_resource type="Resource" id="Resource_t48yv"] script = ExtResource("6_ppdc3") @@ -589,7 +589,7 @@ script = ExtResource("4_qtggh") name = &"parameter_block" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_itmch") +block_serialized_properties = SubResource("Resource_itmch") [sub_resource type="Resource" id="Resource_wo02o"] script = ExtResource("5_wr38c") @@ -604,7 +604,7 @@ script = ExtResource("4_qtggh") name = &"parameter_block" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_wo02o") +block_serialized_properties = SubResource("Resource_wo02o") [sub_resource type="Resource" id="Resource_ma3m2"] script = ExtResource("5_wr38c") @@ -619,7 +619,7 @@ script = ExtResource("4_qtggh") name = &"is_node_in_group" position = Vector2(0, 0) path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_dcwek")]] -serialized_block = SubResource("Resource_ma3m2") +block_serialized_properties = SubResource("Resource_ma3m2") [sub_resource type="Resource" id="Resource_dkm1h"] script = ExtResource("5_wr38c") @@ -634,7 +634,7 @@ script = ExtResource("4_qtggh") name = &"call_group_method" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_dkm1h") +block_serialized_properties = SubResource("Resource_dkm1h") [sub_resource type="Resource" id="Resource_lm5iy"] script = ExtResource("5_wr38c") @@ -649,7 +649,7 @@ script = ExtResource("4_qtggh") name = &"call_group_method" position = Vector2(0, 0) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_57tvt")]] -serialized_block = SubResource("Resource_lm5iy") +block_serialized_properties = SubResource("Resource_lm5iy") [sub_resource type="Resource" id="Resource_yd7xk"] script = ExtResource("5_wr38c") @@ -663,7 +663,7 @@ script = ExtResource("4_qtggh") name = &"if" position = Vector2(0, 0) path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_bny5u")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_26pqe")]] -serialized_block = SubResource("Resource_yd7xk") +block_serialized_properties = SubResource("Resource_yd7xk") [sub_resource type="Resource" id="Resource_fufky"] script = ExtResource("5_wr38c") @@ -678,7 +678,7 @@ script = ExtResource("4_qtggh") name = &"area2d_on_entered" position = Vector2(100, 50) path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_3wodo")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_wva5q")]] -serialized_block = SubResource("Resource_fufky") +block_serialized_properties = SubResource("Resource_fufky") [sub_resource type="Resource" id="Resource_v6too"] script = ExtResource("6_ppdc3") @@ -718,7 +718,7 @@ script = ExtResource("4_qtggh") name = &"parameter_block" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_8h48s") +block_serialized_properties = SubResource("Resource_8h48s") [sub_resource type="Resource" id="Resource_n8f73"] script = ExtResource("5_wr38c") @@ -733,7 +733,7 @@ script = ExtResource("4_qtggh") name = &"parameter_block" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_n8f73") +block_serialized_properties = SubResource("Resource_n8f73") [sub_resource type="Resource" id="Resource_lurjo"] script = ExtResource("5_wr38c") @@ -748,7 +748,7 @@ script = ExtResource("4_qtggh") name = &"is_node_in_group" position = Vector2(0, 0) path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_tnwiy")]] -serialized_block = SubResource("Resource_lurjo") +block_serialized_properties = SubResource("Resource_lurjo") [sub_resource type="Resource" id="Resource_y2wc6"] script = ExtResource("5_wr38c") @@ -763,7 +763,7 @@ script = ExtResource("4_qtggh") name = &"call_group_method" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_y2wc6") +block_serialized_properties = SubResource("Resource_y2wc6") [sub_resource type="Resource" id="Resource_daagb"] script = ExtResource("5_wr38c") @@ -778,7 +778,7 @@ script = ExtResource("4_qtggh") name = &"call_group_method" position = Vector2(0, 0) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_krykp")]] -serialized_block = SubResource("Resource_daagb") +block_serialized_properties = SubResource("Resource_daagb") [sub_resource type="Resource" id="Resource_twkoi"] script = ExtResource("5_wr38c") @@ -792,7 +792,7 @@ script = ExtResource("4_qtggh") name = &"if" position = Vector2(0, 0) path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_j6idn")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_klxbs")]] -serialized_block = SubResource("Resource_twkoi") +block_serialized_properties = SubResource("Resource_twkoi") [sub_resource type="Resource" id="Resource_c4had"] script = ExtResource("5_wr38c") @@ -807,7 +807,7 @@ script = ExtResource("4_qtggh") name = &"area2d_on_entered" position = Vector2(75, 50) path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_0x61c")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_1a3km")]] -serialized_block = SubResource("Resource_c4had") +block_serialized_properties = SubResource("Resource_c4had") [sub_resource type="Resource" id="Resource_14gac"] script = ExtResource("6_ppdc3") @@ -846,7 +846,7 @@ script = ExtResource("4_qtggh") name = &"add_to_group" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_tqdqf") +block_serialized_properties = SubResource("Resource_tqdqf") [sub_resource type="Resource" id="Resource_yuj6e"] script = ExtResource("5_wr38c") @@ -860,7 +860,7 @@ script = ExtResource("4_qtggh") name = &"simplescoring_set_score" position = Vector2(0, 0) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_uxpim")]] -serialized_block = SubResource("Resource_yuj6e") +block_serialized_properties = SubResource("Resource_yuj6e") [sub_resource type="Resource" id="Resource_gkoq3"] script = ExtResource("5_wr38c") @@ -874,7 +874,7 @@ script = ExtResource("4_qtggh") name = &"simplescoring_set_score" position = Vector2(0, 0) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_oar78")]] -serialized_block = SubResource("Resource_gkoq3") +block_serialized_properties = SubResource("Resource_gkoq3") [sub_resource type="Resource" id="Resource_g3mty"] script = ExtResource("5_wr38c") @@ -886,7 +886,7 @@ script = ExtResource("4_qtggh") name = &"ready_block" position = Vector2(54, 47) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_8xxm3")]] -serialized_block = SubResource("Resource_g3mty") +block_serialized_properties = SubResource("Resource_g3mty") [sub_resource type="Resource" id="Resource_3j7i4"] script = ExtResource("5_wr38c") @@ -900,7 +900,7 @@ script = ExtResource("4_qtggh") name = &"simplescoring_change_score" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_3j7i4") +block_serialized_properties = SubResource("Resource_3j7i4") [sub_resource type="Resource" id="Resource_2e0ed"] script = ExtResource("5_wr38c") @@ -914,7 +914,7 @@ script = ExtResource("4_qtggh") name = &"define_method" position = Vector2(50, 300) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ntjp0")]] -serialized_block = SubResource("Resource_2e0ed") +block_serialized_properties = SubResource("Resource_2e0ed") [sub_resource type="Resource" id="Resource_cxj82"] script = ExtResource("5_wr38c") @@ -928,7 +928,7 @@ script = ExtResource("4_qtggh") name = &"simplescoring_change_score" position = Vector2(0, 0) path_child_pairs = [] -serialized_block = SubResource("Resource_cxj82") +block_serialized_properties = SubResource("Resource_cxj82") [sub_resource type="Resource" id="Resource_udc68"] script = ExtResource("5_wr38c") @@ -942,7 +942,7 @@ script = ExtResource("4_qtggh") name = &"define_method" position = Vector2(50, 450) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_c17ry")]] -serialized_block = SubResource("Resource_udc68") +block_serialized_properties = SubResource("Resource_udc68") [sub_resource type="Resource" id="Resource_cu24c"] script = ExtResource("6_ppdc3") diff --git a/addons/block_code/ui/block_canvas/serialized_block.gd b/addons/block_code/serialization/block_serialized_properties.gd similarity index 68% rename from addons/block_code/ui/block_canvas/serialized_block.gd rename to addons/block_code/serialization/block_serialized_properties.gd index 30a54349..2841c6ca 100644 --- a/addons/block_code/ui/block_canvas/serialized_block.gd +++ b/addons/block_code/serialization/block_serialized_properties.gd @@ -1,6 +1,8 @@ -class_name SerializedBlock +class_name BlockSerializedProperties extends Resource +# TODO: Remove this class after removing the remaining serialization. + @export var block_class: StringName @export var serialized_props: Array diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index d34c4139..1fe30e6b 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -143,7 +143,7 @@ func bsd_selected(bsd: BlockScriptData): func _load_bsd(bsd: BlockScriptData): - for tree in bsd.block_trees.array: + for tree in bsd.block_trees: load_tree(_window, tree) @@ -165,9 +165,9 @@ func load_tree(parent: Node, node: SerializedBlockTreeNode): # TODO: Remove once the data/UI decouple is done. if scene == null: - var _block_scene_path = _block_scenes_by_class[node.serialized_block.block_class] + var _block_scene_path = _block_scenes_by_class[node.block_serialized_properties.block_class] scene = load(_block_scene_path).instantiate() - for prop_pair in node.serialized_block.serialized_props: + for prop_pair in node.block_serialized_properties.serialized_props: scene.set(prop_pair[0], prop_pair[1]) scene.position = node.position @@ -182,11 +182,11 @@ func load_tree(parent: Node, node: SerializedBlockTreeNode): func rebuild_block_trees(undo_redo): - var block_trees_array: Array[SerializedBlockTreeNode] + var block_trees: Array[SerializedBlockTreeNode] for c in _window.get_children(): - block_trees_array.append(build_tree(c, undo_redo)) - undo_redo.add_undo_property(_current_bsd.block_trees, "array", _current_bsd.block_trees.array) - undo_redo.add_do_property(_current_bsd.block_trees, "array", block_trees_array) + block_trees.append(build_tree(c, undo_redo)) + undo_redo.add_undo_property(_current_bsd, "block_trees", _current_bsd.block_trees) + undo_redo.add_do_property(_current_bsd, "block_trees", block_trees) func build_tree(block: Block, undo_redo: EditorUndoRedoManager) -> SerializedBlockTreeNode: diff --git a/addons/block_code/ui/block_canvas/serialized_block_tree_node.gd b/addons/block_code/ui/block_canvas/serialized_block_tree_node.gd index 9f4b95fd..03c23902 100644 --- a/addons/block_code/ui/block_canvas/serialized_block_tree_node.gd +++ b/addons/block_code/ui/block_canvas/serialized_block_tree_node.gd @@ -6,11 +6,11 @@ extends Resource @export var path_child_pairs: Array # TODO: Remove once the data/UI decouple is done. -@export var serialized_block: SerializedBlock +@export var block_serialized_properties: BlockSerializedProperties -func _init(p_name: StringName, p_position: Vector2 = Vector2.ZERO, p_serialized_block: SerializedBlock = null, p_path_child_pairs: Array = []): +func _init(p_name: StringName, p_position: Vector2 = Vector2.ZERO, p_block_serialized_properties: BlockSerializedProperties = null, p_path_child_pairs: Array = []): name = p_name position = p_position - serialized_block = p_serialized_block + block_serialized_properties = p_block_serialized_properties path_child_pairs = p_path_child_pairs diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 53bbb467..12057942 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -117,8 +117,8 @@ func get_instruction_node() -> InstructionTree.TreeNode: func update_resources(undo_redo: EditorUndoRedoManager): if resource == null: - var serialized_block = SerializedBlock.new(get_block_class(), get_serialized_props()) - resource = SerializedBlockTreeNode.new(block_name, position, serialized_block) + var block_serialized_properties = BlockSerializedProperties.new(get_block_class(), get_serialized_props()) + resource = SerializedBlockTreeNode.new(block_name, position, block_serialized_properties) return if resource.position != position: @@ -127,9 +127,9 @@ func update_resources(undo_redo: EditorUndoRedoManager): var serialized_props = get_serialized_props() - if serialized_props != resource.serialized_block.serialized_props: - undo_redo.add_undo_property(resource.serialized_block, "serialized_props", resource.serialized_block.serialized_props) - undo_redo.add_do_property(resource.serialized_block, "serialized_props", serialized_props) + if serialized_props != resource.block_serialized_properties.serialized_props: + undo_redo.add_undo_property(resource.block_serialized_properties, "serialized_props", resource.block_serialized_properties.serialized_props) + undo_redo.add_do_property(resource.block_serialized_properties, "serialized_props", serialized_props) # Override this method to add more serialized properties diff --git a/addons/block_code/ui/bsd_templates/default_bsd.tres b/addons/block_code/ui/bsd_templates/default_bsd.tres index 5bfa7671..e01d935e 100644 --- a/addons/block_code/ui/bsd_templates/default_bsd.tres +++ b/addons/block_code/ui/bsd_templates/default_bsd.tres @@ -1,7 +1,7 @@ [gd_resource type="Resource" script_class="BlockScriptData" load_steps=8 format=3 uid="uid://dit7fykhl3h48"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node.gd" id="1_barc5"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block.gd" id="2_cgfpx"] +[ext_resource type="Script" path="res://addons/block_code/serialization/block_serialized_properties.gd" id="2_cgfpx"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node_array.gd" id="3_gx4d7"] [ext_resource type="Script" path="res://addons/block_code/block_script_data/block_script_data.gd" id="4_cqq7x"] @@ -15,7 +15,7 @@ script = ExtResource("1_barc5") name = &"ready_block" position = Vector2(54, 47) path_child_pairs = [] -serialized_block = SubResource("Resource_b0aen") +block_serialized_properties = SubResource("Resource_b0aen") [sub_resource type="Resource" id="Resource_nkub8"] script = ExtResource("3_gx4d7") From e84d99151de4db1a17036437b096accc17b07296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 31 Jul 2024 11:11:37 -0300 Subject: [PATCH 128/423] Remove SerializedBlockTreeNodeArray This resource only had an array property which can be replaced by directly using Array[SerializedBlockTreeNode] --- addons/block_code/block_code_plugin.gd | 1 - .../block_script_data/block_script_data.gd | 4 +- .../examples/pong_game/pong_game.tscn | 39 ++++--------------- .../serialized_block_tree_node_array.gd | 8 ---- .../ui/bsd_templates/default_bsd.tres | 9 +---- 5 files changed, 11 insertions(+), 50 deletions(-) delete mode 100644 addons/block_code/ui/block_canvas/serialized_block_tree_node_array.gd diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 56dbf34c..89cbc2ff 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -25,7 +25,6 @@ const DISABLED_CLASSES := [ "ParameterBlock", "StatementBlock", "SnapPoint", - "SerializedBlockTreeNodeArray", "SerializedBlockTreeNode", "BlockSerializedProperties", "CategoryFactory", diff --git a/addons/block_code/block_script_data/block_script_data.gd b/addons/block_code/block_script_data/block_script_data.gd index 3502ca73..7cc4811f 100644 --- a/addons/block_code/block_script_data/block_script_data.gd +++ b/addons/block_code/block_script_data/block_script_data.gd @@ -2,13 +2,13 @@ class_name BlockScriptData extends Resource @export var script_inherits: String -@export var block_trees: SerializedBlockTreeNodeArray +@export var block_trees: Array[SerializedBlockTreeNode] @export var variables: Array[VariableResource] @export var generated_script: String @export var version: int -func _init(p_script_inherits: String = "", p_block_trees: SerializedBlockTreeNodeArray = null, p_variables: Array[VariableResource] = [], p_generated_script: String = "", p_version = 0): +func _init(p_script_inherits: String = "", p_block_trees: Array[SerializedBlockTreeNode] = [], p_variables: Array[VariableResource] = [], p_generated_script: String = "", p_version = 0): script_inherits = p_script_inherits block_trees = p_block_trees generated_script = p_generated_script diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index 309df2fc..dfe3ade4 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=129 format=3 uid="uid://tf7b8c64ecc0"] +[gd_scene load_steps=122 format=3 uid="uid://tf7b8c64ecc0"] [ext_resource type="PackedScene" uid="uid://cg8ibi18um3vg" path="res://addons/block_code/examples/pong_game/space.tscn" id="1_y56ac"] [ext_resource type="Script" path="res://addons/block_code/block_code_node/block_code.gd" id="3_6jaq8"] @@ -6,7 +6,6 @@ [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node.gd" id="4_qtggh"] [ext_resource type="Texture2D" uid="uid://tplpgtnfeda0" path="res://addons/block_code/examples/pong_game/assets/paddle.png" id="4_ra7bh"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_serialized_properties.gd" id="5_wr38c"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node_array.gd" id="6_ppdc3"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="7_3q6bj"] [ext_resource type="Script" path="res://addons/block_code/block_script_data/block_script_data.gd" id="7_uuuue"] [ext_resource type="PackedScene" uid="uid://c7l70grmkauij" path="res://addons/block_code/examples/pong_game/ball.tscn" id="9_xrqll"] @@ -91,14 +90,10 @@ position = Vector2(75, 300) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_7x3sw")]] block_serialized_properties = SubResource("Resource_x6ddv") -[sub_resource type="Resource" id="Resource_a04yd"] -script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_yiq7s"), SubResource("Resource_0m462")]) - [sub_resource type="Resource" id="Resource_m2svk"] script = ExtResource("7_uuuue") script_inherits = "SimpleCharacter" -block_trees = SubResource("Resource_a04yd") +block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_yiq7s"), SubResource("Resource_0m462")]) variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends SimpleCharacter @@ -190,14 +185,10 @@ position = Vector2(50, 300) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_enqe8")]] block_serialized_properties = SubResource("Resource_3wgnl") -[sub_resource type="Resource" id="Resource_y05sx"] -script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_hrubs"), SubResource("Resource_s8vl4")]) - [sub_resource type="Resource" id="Resource_ysbi4"] script = ExtResource("7_uuuue") script_inherits = "SimpleCharacter" -block_trees = SubResource("Resource_y05sx") +block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_hrubs"), SubResource("Resource_s8vl4")]) variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends SimpleCharacter @@ -519,14 +510,10 @@ position = Vector2(50, 475) path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_gj1nu")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_rs6a0")]] block_serialized_properties = SubResource("Resource_7mdg3") -[sub_resource type="Resource" id="Resource_t48yv"] -script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_1h6wi"), SubResource("Resource_gmlt0"), SubResource("Resource_tyrtu")]) - [sub_resource type="Resource" id="Resource_6m2mk"] script = ExtResource("7_uuuue") script_inherits = "RigidBody2D" -block_trees = SubResource("Resource_t48yv") +block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_1h6wi"), SubResource("Resource_gmlt0"), SubResource("Resource_tyrtu")]) variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends RigidBody2D @@ -680,14 +667,10 @@ position = Vector2(100, 50) path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_3wodo")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_wva5q")]] block_serialized_properties = SubResource("Resource_fufky") -[sub_resource type="Resource" id="Resource_v6too"] -script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_fkj3e")]) - [sub_resource type="Resource" id="Resource_4xylj"] script = ExtResource("7_uuuue") script_inherits = "Area2D" -block_trees = SubResource("Resource_v6too") +block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_fkj3e")]) variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends Area2D @@ -809,14 +792,10 @@ position = Vector2(75, 50) path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_0x61c")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_1a3km")]] block_serialized_properties = SubResource("Resource_c4had") -[sub_resource type="Resource" id="Resource_14gac"] -script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_qtw4n")]) - [sub_resource type="Resource" id="Resource_xoc8a"] script = ExtResource("7_uuuue") script_inherits = "Area2D" -block_trees = SubResource("Resource_14gac") +block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_qtw4n")]) variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends Area2D @@ -944,14 +923,10 @@ position = Vector2(50, 450) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_c17ry")]] block_serialized_properties = SubResource("Resource_udc68") -[sub_resource type="Resource" id="Resource_cu24c"] -script = ExtResource("6_ppdc3") -array = Array[ExtResource("4_qtggh")]([SubResource("Resource_njwj4"), SubResource("Resource_t8g7r"), SubResource("Resource_v2aur")]) - [sub_resource type="Resource" id="Resource_q418f"] script = ExtResource("7_uuuue") script_inherits = "SimpleScoring" -block_trees = SubResource("Resource_cu24c") +block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_njwj4"), SubResource("Resource_t8g7r"), SubResource("Resource_v2aur")]) variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends SimpleScoring diff --git a/addons/block_code/ui/block_canvas/serialized_block_tree_node_array.gd b/addons/block_code/ui/block_canvas/serialized_block_tree_node_array.gd deleted file mode 100644 index 7d78cfb2..00000000 --- a/addons/block_code/ui/block_canvas/serialized_block_tree_node_array.gd +++ /dev/null @@ -1,8 +0,0 @@ -class_name SerializedBlockTreeNodeArray -extends Resource - -@export var array: Array[SerializedBlockTreeNode] - - -func _init(p_array: Array[SerializedBlockTreeNode] = []): - array = p_array diff --git a/addons/block_code/ui/bsd_templates/default_bsd.tres b/addons/block_code/ui/bsd_templates/default_bsd.tres index e01d935e..991bc0af 100644 --- a/addons/block_code/ui/bsd_templates/default_bsd.tres +++ b/addons/block_code/ui/bsd_templates/default_bsd.tres @@ -1,8 +1,7 @@ -[gd_resource type="Resource" script_class="BlockScriptData" load_steps=8 format=3 uid="uid://dit7fykhl3h48"] +[gd_resource type="Resource" script_class="BlockScriptData" load_steps=6 format=3 uid="uid://dit7fykhl3h48"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node.gd" id="1_barc5"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_serialized_properties.gd" id="2_cgfpx"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node_array.gd" id="3_gx4d7"] [ext_resource type="Script" path="res://addons/block_code/block_script_data/block_script_data.gd" id="4_cqq7x"] [sub_resource type="Resource" id="Resource_b0aen"] @@ -17,14 +16,10 @@ position = Vector2(54, 47) path_child_pairs = [] block_serialized_properties = SubResource("Resource_b0aen") -[sub_resource type="Resource" id="Resource_nkub8"] -script = ExtResource("3_gx4d7") -array = Array[ExtResource("1_barc5")]([SubResource("Resource_1h6wi")]) - [resource] script = ExtResource("4_cqq7x") script_inherits = "INHERIT_DEFAULT" -block_trees = SubResource("Resource_nkub8") +block_trees = Array[ExtResource("1_barc5")]([SubResource("Resource_1h6wi")]) variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) generated_script = "extends INHERIT_DEFAULT" version = 0 From 01456017c9060edd957b9eb138c198c936048bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 31 Jul 2024 11:15:02 -0300 Subject: [PATCH 129/423] Rename SerializedBlockTreeNode to BlockSerialization And move it to the serialization/ folder. --- addons/block_code/block_code_plugin.gd | 2 +- addons/block_code/block_script_data/block_script_data.gd | 4 ++-- addons/block_code/examples/pong_game/pong_game.tscn | 2 +- .../block_serialization.gd} | 2 +- addons/block_code/ui/block_canvas/block_canvas.gd | 6 +++--- addons/block_code/ui/blocks/block/block.gd | 4 ++-- addons/block_code/ui/bsd_templates/default_bsd.tres | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) rename addons/block_code/{ui/block_canvas/serialized_block_tree_node.gd => serialization/block_serialization.gd} (93%) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index 89cbc2ff..b4351523 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -25,7 +25,7 @@ const DISABLED_CLASSES := [ "ParameterBlock", "StatementBlock", "SnapPoint", - "SerializedBlockTreeNode", + "BlockSerialization", "BlockSerializedProperties", "CategoryFactory", ] diff --git a/addons/block_code/block_script_data/block_script_data.gd b/addons/block_code/block_script_data/block_script_data.gd index 7cc4811f..f4bdf554 100644 --- a/addons/block_code/block_script_data/block_script_data.gd +++ b/addons/block_code/block_script_data/block_script_data.gd @@ -2,13 +2,13 @@ class_name BlockScriptData extends Resource @export var script_inherits: String -@export var block_trees: Array[SerializedBlockTreeNode] +@export var block_trees: Array[BlockSerialization] @export var variables: Array[VariableResource] @export var generated_script: String @export var version: int -func _init(p_script_inherits: String = "", p_block_trees: Array[SerializedBlockTreeNode] = [], p_variables: Array[VariableResource] = [], p_generated_script: String = "", p_version = 0): +func _init(p_script_inherits: String = "", p_block_trees: Array[BlockSerialization] = [], p_variables: Array[VariableResource] = [], p_generated_script: String = "", p_version = 0): script_inherits = p_script_inherits block_trees = p_block_trees generated_script = p_generated_script diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index dfe3ade4..27dd2307 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -3,7 +3,7 @@ [ext_resource type="PackedScene" uid="uid://cg8ibi18um3vg" path="res://addons/block_code/examples/pong_game/space.tscn" id="1_y56ac"] [ext_resource type="Script" path="res://addons/block_code/block_code_node/block_code.gd" id="3_6jaq8"] [ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_character/simple_character.gd" id="3_mdrcv"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node.gd" id="4_qtggh"] +[ext_resource type="Script" path="res://addons/block_code/serialization/block_serialization.gd" id="4_qtggh"] [ext_resource type="Texture2D" uid="uid://tplpgtnfeda0" path="res://addons/block_code/examples/pong_game/assets/paddle.png" id="4_ra7bh"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_serialized_properties.gd" id="5_wr38c"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="7_3q6bj"] diff --git a/addons/block_code/ui/block_canvas/serialized_block_tree_node.gd b/addons/block_code/serialization/block_serialization.gd similarity index 93% rename from addons/block_code/ui/block_canvas/serialized_block_tree_node.gd rename to addons/block_code/serialization/block_serialization.gd index 03c23902..433ca567 100644 --- a/addons/block_code/ui/block_canvas/serialized_block_tree_node.gd +++ b/addons/block_code/serialization/block_serialization.gd @@ -1,4 +1,4 @@ -class_name SerializedBlockTreeNode +class_name BlockSerialization extends Resource @export var name: StringName diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 1fe30e6b..2f3bc2a9 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -160,7 +160,7 @@ func clear_canvas(): child.queue_free() -func load_tree(parent: Node, node: SerializedBlockTreeNode): +func load_tree(parent: Node, node: BlockSerialization): var scene: Block = Util.instantiate_block(node.name) # TODO: Remove once the data/UI decouple is done. @@ -182,14 +182,14 @@ func load_tree(parent: Node, node: SerializedBlockTreeNode): func rebuild_block_trees(undo_redo): - var block_trees: Array[SerializedBlockTreeNode] + var block_trees: Array[BlockSerialization] for c in _window.get_children(): block_trees.append(build_tree(c, undo_redo)) undo_redo.add_undo_property(_current_bsd, "block_trees", _current_bsd.block_trees) undo_redo.add_do_property(_current_bsd, "block_trees", block_trees) -func build_tree(block: Block, undo_redo: EditorUndoRedoManager) -> SerializedBlockTreeNode: +func build_tree(block: Block, undo_redo: EditorUndoRedoManager) -> BlockSerialization: var path_child_pairs = [] block.update_resources(undo_redo) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 12057942..9458537f 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -32,7 +32,7 @@ signal modified @export var scope: String = "" ## The resource containing the block properties and the snapped blocks -@export var resource: SerializedBlockTreeNode +@export var resource: BlockSerialization # FIXME: Add export to this variable and remove bottom_snap_path above. # There is a bug in Godot 4.2 that prevents using SnapPoint directly: @@ -118,7 +118,7 @@ func get_instruction_node() -> InstructionTree.TreeNode: func update_resources(undo_redo: EditorUndoRedoManager): if resource == null: var block_serialized_properties = BlockSerializedProperties.new(get_block_class(), get_serialized_props()) - resource = SerializedBlockTreeNode.new(block_name, position, block_serialized_properties) + resource = BlockSerialization.new(block_name, position, block_serialized_properties) return if resource.position != position: diff --git a/addons/block_code/ui/bsd_templates/default_bsd.tres b/addons/block_code/ui/bsd_templates/default_bsd.tres index 991bc0af..97145b1b 100644 --- a/addons/block_code/ui/bsd_templates/default_bsd.tres +++ b/addons/block_code/ui/bsd_templates/default_bsd.tres @@ -1,6 +1,6 @@ [gd_resource type="Resource" script_class="BlockScriptData" load_steps=6 format=3 uid="uid://dit7fykhl3h48"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/serialized_block_tree_node.gd" id="1_barc5"] +[ext_resource type="Script" path="res://addons/block_code/serialization/block_serialization.gd" id="1_barc5"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_serialized_properties.gd" id="2_cgfpx"] [ext_resource type="Script" path="res://addons/block_code/block_script_data/block_script_data.gd" id="4_cqq7x"] From 2e41a68f26d90625ced19dafa9e9775e7ecf4b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 31 Jul 2024 12:35:04 -0300 Subject: [PATCH 130/423] Rename BlockScriptData to BlockScriptSerialization And move it to the serialization/ folder Also: remove abandoned function scene_has_bsd_nodes() from block canvas. --- .../block_code/block_code_node/block_code.gd | 10 +++--- addons/block_code/block_code_plugin.gd | 2 +- .../examples/pong_game/pong_game.tscn | 2 +- .../block_script_serialization.gd} | 2 +- .../ui/block_canvas/block_canvas.gd | 35 ++++++++----------- addons/block_code/ui/block_tree_util.gd | 6 ++-- .../ui/bsd_templates/default_bsd.tres | 4 +-- addons/block_code/ui/main_panel.gd | 24 ++++++------- .../create_variable_dialog.gd | 6 ++-- addons/block_code/ui/picker/picker.gd | 10 +++--- addons/block_code/ui/title_bar/title_bar.gd | 10 +++--- tests/test_instruction_tree.gd | 30 ++++++++-------- 12 files changed, 67 insertions(+), 74 deletions(-) rename addons/block_code/{block_script_data/block_script_data.gd => serialization/block_script_serialization.gd} (93%) diff --git a/addons/block_code/block_code_node/block_code.gd b/addons/block_code/block_code_node/block_code.gd index eaafb088..9e9fa334 100644 --- a/addons/block_code/block_code_node/block_code.gd +++ b/addons/block_code/block_code_node/block_code.gd @@ -3,7 +3,7 @@ class_name BlockCode extends Node -@export var block_script: BlockScriptData = null +@export var block_script: BlockScriptSerialization = null func _ready(): @@ -25,10 +25,10 @@ func _enter_tree(): # Create script if block_script == null: - var new_bsd: BlockScriptData = load("res://addons/block_code/ui/bsd_templates/default_bsd.tres").duplicate(true) - new_bsd.script_inherits = _get_custom_or_native_class(get_parent()) - new_bsd.generated_script = new_bsd.generated_script.replace("INHERIT_DEFAULT", new_bsd.script_inherits) - block_script = new_bsd + var new_block_script: BlockScriptSerialization = load("res://addons/block_code/ui/bsd_templates/default_bsd.tres").duplicate(true) + new_block_script.script_inherits = _get_custom_or_native_class(get_parent()) + new_block_script.generated_script = new_block_script.generated_script.replace("INHERIT_DEFAULT", new_block_script.script_inherits) + block_script = new_block_script func _update_parent_script(): diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index b4351523..f7e0ac8a 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -19,7 +19,6 @@ var _selected_block_code: BlockCode var old_feature_profile: String = "" const DISABLED_CLASSES := [ - "BlockScriptData", "Block", "ControlBlock", "ParameterBlock", @@ -27,6 +26,7 @@ const DISABLED_CLASSES := [ "SnapPoint", "BlockSerialization", "BlockSerializedProperties", + "BlockScriptSerialization", "CategoryFactory", ] diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index 27dd2307..17654396 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -7,7 +7,7 @@ [ext_resource type="Texture2D" uid="uid://tplpgtnfeda0" path="res://addons/block_code/examples/pong_game/assets/paddle.png" id="4_ra7bh"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_serialized_properties.gd" id="5_wr38c"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="7_3q6bj"] -[ext_resource type="Script" path="res://addons/block_code/block_script_data/block_script_data.gd" id="7_uuuue"] +[ext_resource type="Script" path="res://addons/block_code/serialization/block_script_serialization.gd" id="7_uuuue"] [ext_resource type="PackedScene" uid="uid://c7l70grmkauij" path="res://addons/block_code/examples/pong_game/ball.tscn" id="9_xrqll"] [ext_resource type="PackedScene" uid="uid://fhoapg3anjsu" path="res://addons/block_code/examples/pong_game/goal_area.tscn" id="12_nqmxu"] [ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd" id="13_tg3yk"] diff --git a/addons/block_code/block_script_data/block_script_data.gd b/addons/block_code/serialization/block_script_serialization.gd similarity index 93% rename from addons/block_code/block_script_data/block_script_data.gd rename to addons/block_code/serialization/block_script_serialization.gd index f4bdf554..74be0856 100644 --- a/addons/block_code/block_script_data/block_script_data.gd +++ b/addons/block_code/serialization/block_script_serialization.gd @@ -1,4 +1,4 @@ -class_name BlockScriptData +class_name BlockScriptSerialization extends Resource @export var script_inherits: String diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 2f3bc2a9..bb7ae4ec 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -33,7 +33,7 @@ const ZOOM_FACTOR: float = 1.1 @onready var _mouse_override: Control = %MouseOverride @onready var _zoom_label: Label = %ZoomLabel -var _current_bsd: BlockScriptData +var _current_block_script: BlockScriptSerialization var _block_scenes_by_class = {} var _panning := false var zoom: float: @@ -96,12 +96,12 @@ func set_child(n: Node): set_child(c) -func bsd_selected(bsd: BlockScriptData): +func block_script_selected(block_script: BlockScriptSerialization): clear_canvas() var edited_node = EditorInterface.get_inspector().get_edited_object() as Node - if bsd != _current_bsd: + if block_script != _current_block_script: _window.position = Vector2(0, 0) zoom = 1 @@ -115,18 +115,18 @@ func bsd_selected(bsd: BlockScriptData): _open_scene_button.disabled = true _replace_block_code_button.disabled = true - if bsd != null: - _load_bsd(bsd) + if block_script != null: + _load_block_script(block_script) _window.visible = true _zoom_label.visible = true - if bsd != _current_bsd: + if block_script != _current_block_script: reset_window_position() elif edited_node == null: _empty_box.visible = true elif BlockCodePlugin.node_has_block_code(edited_node): # If the selected node has a block code node, but BlockCodePlugin didn't - # provide it to bsd_selected, we assume the block code itself is not + # provide it to block_script_selected, we assume the block code itself is not # editable. In that case, provide options to either edit the node's # scene file, or override the BlockCode node. This is mostly to avoid # creating a situation where a node has multiple BlockCode nodes. @@ -139,21 +139,14 @@ func bsd_selected(bsd: BlockScriptData): _selected_node_label.text = _selected_node_label_format.format({"node": edited_node.name}) _add_block_code_button.disabled = false - _current_bsd = bsd + _current_block_script = block_script -func _load_bsd(bsd: BlockScriptData): - for tree in bsd.block_trees: +func _load_block_script(block_script: BlockScriptSerialization): + for tree in block_script.block_trees: load_tree(_window, tree) -func scene_has_bsd_nodes() -> bool: - var scene_root = EditorInterface.get_edited_scene_root() - if not scene_root: - return false - return scene_root.find_children("*", "BlockCode").size() > 0 - - func clear_canvas(): for child in _window.get_children(): _window.remove_child(child) @@ -185,8 +178,8 @@ func rebuild_block_trees(undo_redo): var block_trees: Array[BlockSerialization] for c in _window.get_children(): block_trees.append(build_tree(c, undo_redo)) - undo_redo.add_undo_property(_current_bsd, "block_trees", _current_bsd.block_trees) - undo_redo.add_do_property(_current_bsd, "block_trees", block_trees) + undo_redo.add_undo_property(_current_block_script, "block_trees", _current_block_script.block_trees) + undo_redo.add_do_property(_current_block_script, "block_trees", block_trees) func build_tree(block: Block, undo_redo: EditorUndoRedoManager) -> BlockSerialization: @@ -326,6 +319,6 @@ func set_mouse_override(override: bool): _mouse_override.mouse_default_cursor_shape = Control.CURSOR_ARROW -func generate_script_from_current_window(bsd: BlockScriptData) -> String: +func generate_script_from_current_window(block_script: BlockScriptSerialization) -> String: # TODO: implement multiple windows - return BlockTreeUtil.generate_script_from_nodes(_window.get_children(), bsd) + return BlockTreeUtil.generate_script_from_nodes(_window.get_children(), block_script) diff --git a/addons/block_code/ui/block_tree_util.gd b/addons/block_code/ui/block_tree_util.gd index acd1a3da..d5ebf718 100644 --- a/addons/block_code/ui/block_tree_util.gd +++ b/addons/block_code/ui/block_tree_util.gd @@ -3,7 +3,7 @@ extends Object const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") -static func generate_script_from_nodes(nodes: Array[Node], bsd: BlockScriptData) -> String: +static func generate_script_from_nodes(nodes: Array[Node], block_script: BlockScriptSerialization) -> String: var entry_blocks_by_entry_statement: Dictionary = {} for block in nodes: @@ -18,9 +18,9 @@ static func generate_script_from_nodes(nodes: Array[Node], bsd: BlockScriptData) var script: String = "" - script += "extends %s\n\n" % bsd.script_inherits + script += "extends %s\n\n" % block_script.script_inherits - for variable in bsd.variables: + for variable in block_script.variables: script += "var %s: %s\n\n" % [variable.var_name, type_string(variable.var_type)] script += "\n" diff --git a/addons/block_code/ui/bsd_templates/default_bsd.tres b/addons/block_code/ui/bsd_templates/default_bsd.tres index 97145b1b..ca5ee151 100644 --- a/addons/block_code/ui/bsd_templates/default_bsd.tres +++ b/addons/block_code/ui/bsd_templates/default_bsd.tres @@ -1,8 +1,8 @@ -[gd_resource type="Resource" script_class="BlockScriptData" load_steps=6 format=3 uid="uid://dit7fykhl3h48"] +[gd_resource type="Resource" script_class="BlockScriptSerialization" load_steps=6 format=3 uid="uid://dit7fykhl3h48"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_serialization.gd" id="1_barc5"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_serialized_properties.gd" id="2_cgfpx"] -[ext_resource type="Script" path="res://addons/block_code/block_script_data/block_script_data.gd" id="4_cqq7x"] +[ext_resource type="Script" path="res://addons/block_code/serialization/block_script_serialization.gd" id="4_cqq7x"] [sub_resource type="Resource" id="Resource_b0aen"] script = ExtResource("2_cgfpx") diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index 4807b95e..810f378e 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -54,14 +54,14 @@ func _on_undo_redo_version_changed(): if _current_block_code_node == null: return - var block_script: BlockScriptData = _current_block_code_node.block_script - _picker.bsd_selected(block_script) - _title_bar.bsd_selected(block_script) - _block_canvas.bsd_selected(block_script) + var block_script: BlockScriptSerialization = _current_block_code_node.block_script + _picker.block_script_selected(block_script) + _title_bar.block_script_selected(block_script) + _block_canvas.block_script_selected(block_script) func _on_show_script_button_pressed(): - var block_script: BlockScriptData = _current_block_code_node.block_script + var block_script: BlockScriptSerialization = _current_block_code_node.block_script var script: String = _block_canvas.generate_script_from_current_window(block_script) script_window_requested.emit(script) @@ -112,14 +112,14 @@ func switch_scene(scene_root: Node): func switch_block_code_node(block_code_node: BlockCode): - var block_script: BlockScriptData = block_code_node.block_script if block_code_node else null + var block_script: BlockScriptSerialization = block_code_node.block_script if block_code_node else null _current_block_code_node = block_code_node _delete_node_button.disabled = _current_block_code_node == null if _current_block_code_node != null: _try_migration() - _picker.bsd_selected(block_script) - _title_bar.bsd_selected(block_script) - _block_canvas.bsd_selected(block_script) + _picker.block_script_selected(block_script) + _title_bar.block_script_selected(block_script) + _block_canvas.block_script_selected(block_script) func save_script(): @@ -133,7 +133,7 @@ func save_script(): print("Block code for {node} is not editable.".format({"node": _current_block_code_node})) return - var block_script: BlockScriptData = _current_block_code_node.block_script + var block_script: BlockScriptSerialization = _current_block_code_node.block_script var resource_path_split = block_script.resource_path.split("::", true, 1) var resource_scene = resource_path_split[0] @@ -180,7 +180,7 @@ func _input(event): func _print_generated_script(): if _current_block_code_node == null: return - var block_script: BlockScriptData = _current_block_code_node.block_script + var block_script: BlockScriptSerialization = _current_block_code_node.block_script var script: String = _block_canvas.generate_script_from_current_window(block_script) print(script) print("Debug script! (not saved)") @@ -266,7 +266,7 @@ func _create_variable(variable: VariableResource): print("No script loaded to add variable to.") return - var block_script: BlockScriptData = _current_block_code_node.block_script + var block_script: BlockScriptSerialization = _current_block_code_node.block_script undo_redo.create_action("Create variable %s in %s's block code script" % [variable.var_name, _current_block_code_node.get_parent().name]) undo_redo.add_undo_property(_current_block_code_node.block_script, "variables", _current_block_code_node.block_script.variables) diff --git a/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd index 61e5f417..cc3957a2 100644 --- a/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd +++ b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd @@ -58,9 +58,9 @@ func check_errors(new_var_name: String) -> bool: var duplicate_variable_name := false var current_block_code = BlockCodePlugin.main_panel._current_block_code_node if current_block_code: - var current_bsd = current_block_code.block_script - if current_bsd: - for variable in current_bsd.variables: + var current_block_script = current_block_code.block_script + if current_block_script: + for variable in current_block_script.variables: if variable.var_name == new_var_name: duplicate_variable_name = true break diff --git a/addons/block_code/ui/picker/picker.gd b/addons/block_code/ui/picker/picker.gd index d68d8370..490956e3 100644 --- a/addons/block_code/ui/picker/picker.gd +++ b/addons/block_code/ui/picker/picker.gd @@ -20,8 +20,8 @@ var scroll_tween: Tween var _variable_category_display: VariableCategoryDisplay = null -func bsd_selected(bsd: BlockScriptData): - if not bsd: +func block_script_selected(block_script: BlockScriptSerialization): + if not block_script: reset_picker() return @@ -29,9 +29,9 @@ func bsd_selected(bsd: BlockScriptData): var categories_to_add: Array[BlockCategory] = [] # By default, assume the class is built-in. - var parent_class: String = bsd.script_inherits + var parent_class: String = block_script.script_inherits for class_dict in ProjectSettings.get_global_class_list(): - if class_dict.class == bsd.script_inherits: + if class_dict.class == block_script.script_inherits: var script = load(class_dict.path) if script.has_method("get_custom_categories"): categories_to_add = script.get_custom_categories() @@ -43,7 +43,7 @@ func bsd_selected(bsd: BlockScriptData): blocks_to_add.append_array(CategoryFactory.get_inherited_blocks(parent_class)) init_picker(blocks_to_add, categories_to_add) - reload_variables(bsd.variables) + reload_variables(block_script.variables) func reset_picker(): diff --git a/addons/block_code/ui/title_bar/title_bar.gd b/addons/block_code/ui/title_bar/title_bar.gd index 6f548374..710c4344 100644 --- a/addons/block_code/ui/title_bar/title_bar.gd +++ b/addons/block_code/ui/title_bar/title_bar.gd @@ -19,10 +19,10 @@ func scene_selected(scene_root: Node): _update_node_option_button_items() var current_block_code = _editor_inspector.get_edited_object() as BlockCode if not current_block_code: - bsd_selected(null) + block_script_selected(null) -func bsd_selected(bsd: BlockScriptData): +func block_script_selected(block_script: BlockScriptSerialization): # TODO: We should listen for property changes in all BlockCode nodes and # their parents. As a workaround for the UI displaying stale data, # we'll crudely update the list of BlockCode nodes whenever the @@ -30,7 +30,7 @@ func bsd_selected(bsd: BlockScriptData): _update_node_option_button_items() - var select_index = _get_index_for_bsd(bsd) + var select_index = _get_block_script_index(block_script) if _node_option_button.selected != select_index: _node_option_button.select(select_index) @@ -54,10 +54,10 @@ func _update_node_option_button_items(): _node_option_button.set_item_metadata(node_item_index, block_code) -func _get_index_for_bsd(bsd: BlockScriptData) -> int: +func _get_block_script_index(block_script: BlockScriptSerialization) -> int: for index in range(_node_option_button.item_count): var block_code_node = _node_option_button.get_item_metadata(index) - if block_code_node.block_script == bsd: + if block_code_node.block_script == block_script: return index return -1 diff --git a/tests/test_instruction_tree.gd b/tests/test_instruction_tree.gd index d715c0b4..680b127d 100644 --- a/tests/test_instruction_tree.gd +++ b/tests/test_instruction_tree.gd @@ -88,10 +88,10 @@ func test_tree_node_text(): func test_script_no_nodes(): - var bsd := BlockScriptData.new("Foo") - var script := BlockTreeUtil.generate_script_from_nodes([], bsd) + var block_script := BlockScriptSerialization.new("Foo") + var text_script := BlockTreeUtil.generate_script_from_nodes([], block_script) assert_eq( - script, + text_script, ( """\ extends Foo @@ -104,11 +104,11 @@ func test_script_no_nodes(): func test_script_no_entry_blocks(): - var bsd := BlockScriptData.new("Foo") + var block_script := BlockScriptSerialization.new("Foo") var nodes: Array[Node] = [Node.new(), Node2D.new(), Control.new()] - var script := BlockTreeUtil.generate_script_from_nodes(nodes, bsd) + var text_script := BlockTreeUtil.generate_script_from_nodes(nodes, block_script) assert_eq( - script, + text_script, ( """\ extends Foo @@ -137,10 +137,10 @@ func test_basic_script(): assert_true(ready_block.bottom_snap.has_snapped_block()) assert_eq(ready_block.bottom_snap.get_snapped_block(), print_block) - var bsd := BlockScriptData.new("Node2D") - var script := BlockTreeUtil.generate_script_from_nodes([ready_block], bsd) + var block_script := BlockScriptSerialization.new("Node2D") + var text_script := BlockTreeUtil.generate_script_from_nodes([ready_block], block_script) assert_eq( - script, + text_script, ( """\ extends Node2D @@ -165,10 +165,10 @@ func test_multiple_entry_script(): var ready_block_2: Block = dup_node(ready_block) - var bsd := BlockScriptData.new("Node2D") - var script := BlockTreeUtil.generate_script_from_nodes([ready_block, ready_block_2], bsd) + var block_script := BlockScriptSerialization.new("Node2D") + var text_script := BlockTreeUtil.generate_script_from_nodes([ready_block, ready_block_2], block_script) assert_eq( - script, + text_script, ( """\ extends Node2D @@ -196,10 +196,10 @@ func test_signal_script(): entered_block.bottom_snap.insert_snapped_block(print_block) entered_block.bottom_snap.snapped_block = print_block - var bsd := BlockScriptData.new("Area2D") - var script = BlockTreeUtil.generate_script_from_nodes([entered_block], bsd) + var block_script := BlockScriptSerialization.new("Area2D") + var text_script = BlockTreeUtil.generate_script_from_nodes([entered_block], block_script) assert_eq( - script, + text_script, ( """\ extends Area2D From 50b2fd7fddd79cf6bf18cf09f7da60a03adb6a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 31 Jul 2024 13:49:49 -0300 Subject: [PATCH 131/423] Rename default_bsd.tres to default_block_script.tres And move it to the serialization/ folder. --- addons/block_code/block_code_node/block_code.gd | 2 +- .../default_block_script.tres} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename addons/block_code/{ui/bsd_templates/default_bsd.tres => serialization/default_block_script.tres} (100%) diff --git a/addons/block_code/block_code_node/block_code.gd b/addons/block_code/block_code_node/block_code.gd index 9e9fa334..97f81e7d 100644 --- a/addons/block_code/block_code_node/block_code.gd +++ b/addons/block_code/block_code_node/block_code.gd @@ -25,7 +25,7 @@ func _enter_tree(): # Create script if block_script == null: - var new_block_script: BlockScriptSerialization = load("res://addons/block_code/ui/bsd_templates/default_bsd.tres").duplicate(true) + var new_block_script: BlockScriptSerialization = load("res://addons/block_code/serialization/default_block_script.tres").duplicate(true) new_block_script.script_inherits = _get_custom_or_native_class(get_parent()) new_block_script.generated_script = new_block_script.generated_script.replace("INHERIT_DEFAULT", new_block_script.script_inherits) block_script = new_block_script diff --git a/addons/block_code/ui/bsd_templates/default_bsd.tres b/addons/block_code/serialization/default_block_script.tres similarity index 100% rename from addons/block_code/ui/bsd_templates/default_bsd.tres rename to addons/block_code/serialization/default_block_script.tres From d23a3c708ce3b4d084c6655ea53b930bfe00a82b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 2 Aug 2024 11:49:47 -0300 Subject: [PATCH 132/423] Block types: Add a new block type for control blocks This will be used in upcoming changes. --- addons/block_code/types/types.gd | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/block_code/types/types.gd b/addons/block_code/types/types.gd index d9f2b59c..c622698b 100644 --- a/addons/block_code/types/types.gd +++ b/addons/block_code/types/types.gd @@ -5,6 +5,7 @@ enum BlockType { ENTRY, EXECUTE, VALUE, + CONTROL, } const VARIANT_TYPE_TO_STRING: Dictionary = { From 0eed646a6ce1d2d2b99f786f116541542e2b85da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 2 Aug 2024 12:00:53 -0300 Subject: [PATCH 133/423] Block types: Rename EXECUTE to STATEMENT For matching the block scene name. --- addons/block_code/blocks_catalog.gd | 2 +- .../simple_character/simple_character.gd | 2 +- .../simple_nodes/simple_scoring/simple_scoring.gd | 4 ++-- addons/block_code/types/types.gd | 2 +- addons/block_code/ui/blocks/block/block.gd | 2 +- .../ui/blocks/statement_block/statement_block.gd | 2 +- .../ui/blocks/utilities/snap_point/snap_point.gd | 2 +- .../ui/picker/categories/category_factory.gd | 14 +++++++------- addons/block_code/ui/util.gd | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/addons/block_code/blocks_catalog.gd b/addons/block_code/blocks_catalog.gd index 8593ff71..a5225ede 100644 --- a/addons/block_code/blocks_catalog.gd +++ b/addons/block_code/blocks_catalog.gd @@ -18,7 +18,7 @@ static func setup(): block_definition.category = "Lifecycle" _catalog[&"ready_block"] = block_definition - block_definition = BlockDefinition.new(&"print", Types.BlockType.EXECUTE) + block_definition = BlockDefinition.new(&"print", Types.BlockType.STATEMENT) block_definition.label_template = "print {text: STRING}" block_definition.code_template = "print({text})" block_definition.defaults = {"text": "Hello"} diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index d62913a3..73ca8925 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -118,7 +118,7 @@ static func get_custom_blocks() -> Array[Block]: # Movement b = CategoryFactory.BLOCKS["statement_block"].instantiate() b.block_name = "simplecharacter_move" - b.block_type = Types.BlockType.EXECUTE + b.block_type = Types.BlockType.STATEMENT b.block_format = "Move with {player: OPTION} buttons as {kind: OPTION}" # TODO: delta here is assumed to be the parameter name of # the _process or _physics_process method: diff --git a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd index 8bee47cc..0dd88609 100644 --- a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd +++ b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd @@ -70,7 +70,7 @@ static func get_custom_blocks() -> Array[Block]: for player in _POSITIONS_FOR_PLAYER: b = CategoryFactory.BLOCKS["statement_block"].instantiate() b.block_name = "simplescoring_set_score" - b.block_type = Types.BlockType.EXECUTE + b.block_type = Types.BlockType.STATEMENT b.block_format = "Set player %s score to {score: INT}" % player b.statement = "score_%s = {score}" % _POSITIONS_FOR_PLAYER[player] b.category = "Info | Score" @@ -78,7 +78,7 @@ static func get_custom_blocks() -> Array[Block]: b = CategoryFactory.BLOCKS["statement_block"].instantiate() b.block_name = "simplescoring_change_score" - b.block_type = Types.BlockType.EXECUTE + b.block_type = Types.BlockType.STATEMENT b.block_format = "Change player %s score by {score: INT}" % player b.statement = "score_%s += {score}" % _POSITIONS_FOR_PLAYER[player] b.category = "Info | Score" diff --git a/addons/block_code/types/types.gd b/addons/block_code/types/types.gd index c622698b..fe73e757 100644 --- a/addons/block_code/types/types.gd +++ b/addons/block_code/types/types.gd @@ -3,7 +3,7 @@ extends Node enum BlockType { NONE, ENTRY, - EXECUTE, + STATEMENT, VALUE, CONTROL, } diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 9458537f..d36127bb 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -19,7 +19,7 @@ signal modified @export var color: Color = Color(1., 1., 1.) ## Type of block to check if can be attached to snap point -@export var block_type: Types.BlockType = Types.BlockType.EXECUTE +@export var block_type: Types.BlockType = Types.BlockType.STATEMENT ## Category to add the block to @export var category: String diff --git a/addons/block_code/ui/blocks/statement_block/statement_block.gd b/addons/block_code/ui/blocks/statement_block/statement_block.gd index fb920108..a39ce705 100644 --- a/addons/block_code/ui/blocks/statement_block/statement_block.gd +++ b/addons/block_code/ui/blocks/statement_block/statement_block.gd @@ -19,7 +19,7 @@ var param_input_strings: Dictionary # Only loaded from serialized func _ready(): super() - if block_type != Types.BlockType.EXECUTE: + if block_type != Types.BlockType.STATEMENT: _background.show_top = false _background.color = color diff --git a/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd b/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd index 8b39f4b5..6b80f786 100644 --- a/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd +++ b/addons/block_code/ui/blocks/utilities/snap_point/snap_point.gd @@ -4,7 +4,7 @@ extends MarginContainer const Types = preload("res://addons/block_code/types/types.gd") -@export var block_type: Types.BlockType = Types.BlockType.EXECUTE +@export var block_type: Types.BlockType = Types.BlockType.STATEMENT @export var snapped_block: Block: get: diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 848d5301..d5e06b4e 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -460,7 +460,7 @@ static func get_general_blocks() -> Array[Block]: #region Sounds b = BLOCKS["statement_block"].instantiate() b.block_name = "load_sound" - b.block_type = Types.BlockType.EXECUTE + b.block_type = Types.BlockType.STATEMENT b.block_format = "Load file {file_path: STRING} as sound {name: STRING}" b.statement = ( """ @@ -477,7 +477,7 @@ static func get_general_blocks() -> Array[Block]: b = BLOCKS["statement_block"].instantiate() b.block_name = "play_sound" - b.block_type = Types.BlockType.EXECUTE + b.block_type = Types.BlockType.STATEMENT b.block_format = "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}" b.statement = ( """ @@ -495,7 +495,7 @@ static func get_general_blocks() -> Array[Block]: b = BLOCKS["statement_block"].instantiate() b.block_name = "pause_continue_sound" - b.block_type = Types.BlockType.EXECUTE + b.block_type = Types.BlockType.STATEMENT b.block_format = "{pause: OPTION} the sound {name: STRING}" b.statement = ( """ @@ -514,7 +514,7 @@ static func get_general_blocks() -> Array[Block]: b = BLOCKS["statement_block"].instantiate() b.block_name = "stop_sound" - b.block_type = Types.BlockType.EXECUTE + b.block_type = Types.BlockType.STATEMENT b.block_format = "Stop the sound {name: STRING}" b.statement = ( """ @@ -793,7 +793,7 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: "CharacterBody2D": var b = BLOCKS["statement_block"].instantiate() b.block_name = "characterbody2d_move" - b.block_type = Types.BlockType.EXECUTE + b.block_type = Types.BlockType.STATEMENT b.block_format = "Move with keys {up: STRING} {down: STRING} {left: STRING} {right: STRING} with speed {speed: VECTOR2}" b.statement = ( "var dir = Vector2()\n" @@ -816,7 +816,7 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: b = BLOCKS["statement_block"].instantiate() b.block_name = "characterbody2d_move_and_slide" - b.block_type = Types.BlockType.EXECUTE + b.block_type = Types.BlockType.STATEMENT b.block_format = "Move and slide" b.statement = "move_and_slide()" b.category = "Physics | Velocity" @@ -882,7 +882,7 @@ static func get_variable_blocks(variables: Array[VariableResource]): b = BLOCKS["statement_block"].instantiate() b.block_name = "set_var_%s" % variable.var_name - b.block_type = Types.BlockType.EXECUTE + b.block_type = Types.BlockType.STATEMENT b.block_format = "Set %s to {value: %s}" % [variable.var_name, type_string] b.statement = "%s = {value}" % [variable.var_name] b.color = BUILTIN_PROPS["Variables"].color diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index 53dd91d0..3d57f87e 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -6,7 +6,7 @@ const Types = preload("res://addons/block_code/types/types.gd") const SCENE_PER_TYPE = { Types.BlockType.ENTRY: preload("res://addons/block_code/ui/blocks/entry_block/entry_block.tscn"), - Types.BlockType.EXECUTE: preload("res://addons/block_code/ui/blocks/statement_block/statement_block.tscn"), + Types.BlockType.STATEMENT: preload("res://addons/block_code/ui/blocks/statement_block/statement_block.tscn"), } From b970b43b2bca3ff41a38de6e3c67dbdec6c1a7ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 5 Aug 2024 13:48:33 -0300 Subject: [PATCH 134/423] Move block_definition and blocks_catalog To a new code_generation subfolder. --- addons/block_code/{ => code_generation}/block_definition.gd | 0 addons/block_code/{ => code_generation}/blocks_catalog.gd | 2 +- addons/block_code/ui/blocks/block/block.gd | 2 +- addons/block_code/ui/util.gd | 4 ++-- 4 files changed, 4 insertions(+), 4 deletions(-) rename addons/block_code/{ => code_generation}/block_definition.gd (100%) rename addons/block_code/{ => code_generation}/blocks_catalog.gd (91%) diff --git a/addons/block_code/block_definition.gd b/addons/block_code/code_generation/block_definition.gd similarity index 100% rename from addons/block_code/block_definition.gd rename to addons/block_code/code_generation/block_definition.gd diff --git a/addons/block_code/blocks_catalog.gd b/addons/block_code/code_generation/blocks_catalog.gd similarity index 91% rename from addons/block_code/blocks_catalog.gd rename to addons/block_code/code_generation/blocks_catalog.gd index a5225ede..ec961c71 100644 --- a/addons/block_code/blocks_catalog.gd +++ b/addons/block_code/code_generation/blocks_catalog.gd @@ -1,6 +1,6 @@ extends Object -const BlockDefinition = preload("res://addons/block_code/block_definition.gd") +const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") const Types = preload("res://addons/block_code/types/types.gd") static var _catalog: Dictionary diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index d36127bb..6d97c605 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -2,7 +2,7 @@ class_name Block extends MarginContainer -const BlocksCatalog = preload("res://addons/block_code/blocks_catalog.gd") +const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") const Types = preload("res://addons/block_code/types/types.gd") diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index 3d57f87e..dddbe87b 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -1,7 +1,7 @@ extends Object -const BlockDefinition = preload("res://addons/block_code/block_definition.gd") -const BlocksCatalog = preload("res://addons/block_code/blocks_catalog.gd") +const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") +const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") const Types = preload("res://addons/block_code/types/types.gd") const SCENE_PER_TYPE = { From 700620b8b57dc863e5ab59ee8208a53efe0ac204 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 7 Aug 2024 15:49:56 -0700 Subject: [PATCH 135/423] Use modulate instead of font color override for zoom label This fixes the zoom label being difficult to see with certain editor themes. https://github.com/endlessm/godot-block-coding/issues/187 --- addons/block_code/ui/block_canvas/block_canvas.tscn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.tscn b/addons/block_code/ui/block_canvas/block_canvas.tscn index 21b27681..0a35216f 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.tscn +++ b/addons/block_code/ui/block_canvas/block_canvas.tscn @@ -60,8 +60,8 @@ theme_override_constants/margin_bottom = 4 [node name="ZoomLabel" type="Label" parent="WindowContainer/Overlay/MarginContainer"] unique_name_in_owner = true +modulate = Color(1, 1, 1, 0.470588) layout_mode = 2 -theme_override_colors/font_color = Color(1, 1, 1, 0.196078) theme_override_font_sizes/font_size = 24 text = "1x" horizontal_alignment = 2 From 06aa75da7539077afa519e1c8d85479eb10b0a91 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 7 Aug 2024 15:51:26 -0700 Subject: [PATCH 136/423] Reset the editor when the zoom label is clicked https://github.com/endlessm/godot-block-coding/issues/186 --- addons/block_code/ui/block_canvas/block_canvas.gd | 13 +++++++++---- addons/block_code/ui/block_canvas/block_canvas.tscn | 6 +++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index bb7ae4ec..8fe07107 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -31,7 +31,7 @@ const ZOOM_FACTOR: float = 1.1 @onready var _open_scene_icon = _open_scene_button.get_theme_icon("Load", "EditorIcons") @onready var _mouse_override: Control = %MouseOverride -@onready var _zoom_label: Label = %ZoomLabel +@onready var _zoom_button: Button = %ZoomButton var _current_block_script: BlockScriptSerialization var _block_scenes_by_class = {} @@ -39,7 +39,7 @@ var _panning := false var zoom: float: set(value): _window.scale = Vector2(value, value) - _zoom_label.text = "%.1fx" % value + _zoom_button.text = "%.1fx" % value get: return _window.scale.x @@ -106,7 +106,7 @@ func block_script_selected(block_script: BlockScriptSerialization): zoom = 1 _window.visible = false - _zoom_label.visible = false + _zoom_button.visible = false _empty_box.visible = false _selected_node_box.visible = false @@ -118,7 +118,7 @@ func block_script_selected(block_script: BlockScriptSerialization): if block_script != null: _load_block_script(block_script) _window.visible = true - _zoom_label.visible = true + _zoom_button.visible = true if block_script != _current_block_script: reset_window_position() @@ -322,3 +322,8 @@ func set_mouse_override(override: bool): func generate_script_from_current_window(block_script: BlockScriptSerialization) -> String: # TODO: implement multiple windows return BlockTreeUtil.generate_script_from_nodes(_window.get_children(), block_script) + + +func _on_zoom_button_pressed(): + zoom = 1.0 + reset_window_position() diff --git a/addons/block_code/ui/block_canvas/block_canvas.tscn b/addons/block_code/ui/block_canvas/block_canvas.tscn index 0a35216f..0d3e8e4c 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.tscn +++ b/addons/block_code/ui/block_canvas/block_canvas.tscn @@ -58,13 +58,12 @@ theme_override_constants/margin_top = 4 theme_override_constants/margin_right = 4 theme_override_constants/margin_bottom = 4 -[node name="ZoomLabel" type="Label" parent="WindowContainer/Overlay/MarginContainer"] +[node name="ZoomButton" type="Button" parent="WindowContainer/Overlay/MarginContainer"] unique_name_in_owner = true modulate = Color(1, 1, 1, 0.470588) layout_mode = 2 +focus_mode = 0 theme_override_font_sizes/font_size = 24 -text = "1x" -horizontal_alignment = 2 [node name="MouseOverride" type="MarginContainer" parent="."] unique_name_in_owner = true @@ -139,6 +138,7 @@ theme_type_variation = &"InspectorActionButton" text = "Override Block Code" icon = ExtResource("2_710vn") +[connection signal="pressed" from="WindowContainer/Overlay/MarginContainer/ZoomButton" to="." method="_on_zoom_button_pressed"] [connection signal="pressed" from="SelectedNodeBox/ButtonsBox/AddBlockCodeButton" to="." method="_on_add_block_code_button_pressed"] [connection signal="pressed" from="SelectedNodeWithBlockCodeBox/ButtonsBox/OpenSceneButton" to="." method="_on_open_scene_button_pressed"] [connection signal="pressed" from="SelectedNodeWithBlockCodeBox/ButtonsBox/ReplaceBlockCodeButton" to="." method="_on_replace_block_code_button_pressed"] From b0eb0760d839990ee531ddd7240fee28b7fe1a08 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Wed, 7 Aug 2024 15:46:12 -0400 Subject: [PATCH 137/423] Add variant type corresponding to OBJECT --- addons/block_code/types/types.gd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/block_code/types/types.gd b/addons/block_code/types/types.gd index fe73e757..aab4bf79 100644 --- a/addons/block_code/types/types.gd +++ b/addons/block_code/types/types.gd @@ -16,6 +16,7 @@ const VARIANT_TYPE_TO_STRING: Dictionary = { TYPE_VECTOR2: "VECTOR2", TYPE_COLOR: "COLOR", TYPE_NODE_PATH: "NODE_PATH", + TYPE_OBJECT: "OBJECT", TYPE_NIL: "NIL", } @@ -27,6 +28,7 @@ const STRING_TO_VARIANT_TYPE: Dictionary = { "VECTOR2": TYPE_VECTOR2, "COLOR": TYPE_COLOR, "NODE_PATH": TYPE_NODE_PATH, + "OBJECT": TYPE_OBJECT, "NIL": TYPE_NIL, } From f5ce15e3ac7c9492bcbf8615cfbc16425e9f4fa1 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Thu, 8 Aug 2024 16:40:02 -0400 Subject: [PATCH 138/423] Modify BlockDefinition resource Export variables and refactor properties Make it a tool script so that this resource can execute code in the editor (will be useful for overloading etc. in the future) --- .../code_generation/block_definition.gd | 44 +++++++++++++++---- .../code_generation/blocks_catalog.gd | 12 +++-- addons/block_code/ui/util.gd | 2 +- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/addons/block_code/code_generation/block_definition.gd b/addons/block_code/code_generation/block_definition.gd index e8ba7027..6ae6ce68 100644 --- a/addons/block_code/code_generation/block_definition.gd +++ b/addons/block_code/code_generation/block_definition.gd @@ -1,21 +1,47 @@ +@tool + extends Resource const Types = preload("res://addons/block_code/types/types.gd") -var name: StringName -var type: Types.BlockType -var description: String -var category: String +@export var name: StringName +@export var description: String +@export var category: String + +@export var type: Types.BlockType +@export var variant_type: Variant.Type -var label_template: String -var code_template: String -var defaults: Dictionary = {} +@export var display_template: String +@export var code_template: String +@export var defaults: Dictionary ## Only for blocks of type Types.ENTRY. If non-empty, this block defines a ## callback that will be connected to the signal with this name. -var signal_name: String = "" +@export var signal_name: String + +## Empty except for blocks that have a defined scope +@export var scope: String -func _init(p_name: StringName, p_type: Types.BlockType): +func _init( + p_name: StringName = &"", + p_description: String = "", + p_category: String = "", + p_type: Types.BlockType = Types.BlockType.STATEMENT, + p_variant_type: Variant.Type = TYPE_NIL, + p_display_template: String = "", + p_code_template: String = "", + p_defaults = {}, + p_signal_name: String = "", + p_scope: String = "", +): name = p_name + description = p_description + category = p_category type = p_type + variant_type = p_variant_type + display_template = p_display_template + code_template = p_code_template + defaults = p_defaults + signal_name = p_signal_name + scope = p_scope diff --git a/addons/block_code/code_generation/blocks_catalog.gd b/addons/block_code/code_generation/blocks_catalog.gd index ec961c71..8ceda199 100644 --- a/addons/block_code/code_generation/blocks_catalog.gd +++ b/addons/block_code/code_generation/blocks_catalog.gd @@ -11,15 +11,19 @@ static func setup(): return _catalog = {} - var block_definition: BlockDefinition = BlockDefinition.new(&"ready_block", Types.BlockType.ENTRY) - block_definition.label_template = "On Ready" + var block_definition: BlockDefinition = BlockDefinition.new() + block_definition.name = &"ready_block" + block_definition.type = Types.BlockType.ENTRY + block_definition.display_template = "On Ready" block_definition.code_template = "func _ready():" block_definition.description = 'Attached blocks will be executed once when the node is "ready"' block_definition.category = "Lifecycle" _catalog[&"ready_block"] = block_definition - block_definition = BlockDefinition.new(&"print", Types.BlockType.STATEMENT) - block_definition.label_template = "print {text: STRING}" + block_definition = BlockDefinition.new() + block_definition.name = &"print" + block_definition.type = Types.BlockType.STATEMENT + block_definition.display_template = "print {text: STRING}" block_definition.code_template = "print({text})" block_definition.defaults = {"text": "Hello"} block_definition.description = "Print the text to output" diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index dddbe87b..5184726b 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -20,7 +20,7 @@ static func instantiate_block(block_name: StringName) -> Block: var scene = SCENE_PER_TYPE[block_definition.type] var b = scene.instantiate() b.block_name = block_definition.name - b.block_format = block_definition.label_template + b.block_format = block_definition.display_template b.statement = block_definition.code_template b.defaults = block_definition.defaults b.tooltip_text = block_definition.description From e7debbbece5bb4ae1ef0fdfa43519c73a9125218 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Thu, 8 Aug 2024 17:05:09 -0400 Subject: [PATCH 139/423] Add saved block definition resources for non-generated blocks --- .../communication/add_node_to_group.tres | 16 +++++++++++++ .../blocks/communication/add_to_group.tres | 15 ++++++++++++ .../communication/call_method_group.tres | 15 ++++++++++++ .../communication/call_method_node.tres | 15 ++++++++++++ .../blocks/communication/define_method.tres | 16 +++++++++++++ .../blocks/communication/is_in_group.tres | 15 ++++++++++++ .../communication/is_node_in_group.tres | 15 ++++++++++++ .../communication/remove_from_group.tres | 15 ++++++++++++ .../communication/remove_node_from_group.tres | 15 ++++++++++++ .../blocks/lifecycle/physics_process.tres | 15 ++++++++++++ .../block_code/blocks/lifecycle/process.tres | 15 ++++++++++++ .../blocks/lifecycle/queue_free.tres | 15 ++++++++++++ addons/block_code/blocks/lifecycle/ready.tres | 15 ++++++++++++ addons/block_code/blocks/log/concat.tres | 15 ++++++++++++ addons/block_code/blocks/log/print.tres | 16 +++++++++++++ addons/block_code/blocks/logic/and.tres | 16 +++++++++++++ addons/block_code/blocks/logic/compare.tres | 24 +++++++++++++++++++ addons/block_code/blocks/logic/else.tres | 15 ++++++++++++ addons/block_code/blocks/logic/else_if.tres | 15 ++++++++++++ addons/block_code/blocks/logic/if.tres | 15 ++++++++++++ addons/block_code/blocks/logic/not.tres | 16 +++++++++++++ addons/block_code/blocks/logic/or.tres | 16 +++++++++++++ addons/block_code/blocks/loops/break.tres | 15 ++++++++++++ addons/block_code/blocks/loops/continue.tres | 15 ++++++++++++ addons/block_code/blocks/loops/for.tres | 15 ++++++++++++ addons/block_code/blocks/loops/while.tres | 15 ++++++++++++ addons/block_code/blocks/math/add.tres | 16 +++++++++++++ addons/block_code/blocks/math/divide.tres | 16 +++++++++++++ addons/block_code/blocks/math/multiply.tres | 16 +++++++++++++ addons/block_code/blocks/math/pow.tres | 16 +++++++++++++ addons/block_code/blocks/math/subtract.tres | 16 +++++++++++++ .../block_code/blocks/variables/vector2.tres | 19 +++++++++++++++ 32 files changed, 504 insertions(+) create mode 100644 addons/block_code/blocks/communication/add_node_to_group.tres create mode 100644 addons/block_code/blocks/communication/add_to_group.tres create mode 100644 addons/block_code/blocks/communication/call_method_group.tres create mode 100644 addons/block_code/blocks/communication/call_method_node.tres create mode 100644 addons/block_code/blocks/communication/define_method.tres create mode 100644 addons/block_code/blocks/communication/is_in_group.tres create mode 100644 addons/block_code/blocks/communication/is_node_in_group.tres create mode 100644 addons/block_code/blocks/communication/remove_from_group.tres create mode 100644 addons/block_code/blocks/communication/remove_node_from_group.tres create mode 100644 addons/block_code/blocks/lifecycle/physics_process.tres create mode 100644 addons/block_code/blocks/lifecycle/process.tres create mode 100644 addons/block_code/blocks/lifecycle/queue_free.tres create mode 100644 addons/block_code/blocks/lifecycle/ready.tres create mode 100644 addons/block_code/blocks/log/concat.tres create mode 100644 addons/block_code/blocks/log/print.tres create mode 100644 addons/block_code/blocks/logic/and.tres create mode 100644 addons/block_code/blocks/logic/compare.tres create mode 100644 addons/block_code/blocks/logic/else.tres create mode 100644 addons/block_code/blocks/logic/else_if.tres create mode 100644 addons/block_code/blocks/logic/if.tres create mode 100644 addons/block_code/blocks/logic/not.tres create mode 100644 addons/block_code/blocks/logic/or.tres create mode 100644 addons/block_code/blocks/loops/break.tres create mode 100644 addons/block_code/blocks/loops/continue.tres create mode 100644 addons/block_code/blocks/loops/for.tres create mode 100644 addons/block_code/blocks/loops/while.tres create mode 100644 addons/block_code/blocks/math/add.tres create mode 100644 addons/block_code/blocks/math/divide.tres create mode 100644 addons/block_code/blocks/math/multiply.tres create mode 100644 addons/block_code/blocks/math/pow.tres create mode 100644 addons/block_code/blocks/math/subtract.tres create mode 100644 addons/block_code/blocks/variables/vector2.tres diff --git a/addons/block_code/blocks/communication/add_node_to_group.tres b/addons/block_code/blocks/communication/add_node_to_group.tres new file mode 100644 index 00000000..b4ea7d66 --- /dev/null +++ b/addons/block_code/blocks/communication/add_node_to_group.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://bpvefei72nh3a"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_5qal7"] + +[resource] +script = ExtResource("1_5qal7") +name = &"add_node_to_group" +description = "Add the node into the group" +category = "Communication | Groups" +type = 2 +variant_type = 0 +display_template = "Add {node: OBJECT} to group {group: STRING}" +code_template = "{node}.add_to_group({group})" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/communication/add_to_group.tres b/addons/block_code/blocks/communication/add_to_group.tres new file mode 100644 index 00000000..a7dcb889 --- /dev/null +++ b/addons/block_code/blocks/communication/add_to_group.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://bvrmau8atjx1x"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_bcm71"] + +[resource] +script = ExtResource("1_bcm71") +name = &"add_to_group" +type = 2 +variant_type = 0 +display_template = "Add to group {group: STRING}" +code_template = "add_to_group({group})" +description = "Add this node into the group" +category = "Communication | Groups" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/communication/call_method_group.tres b/addons/block_code/blocks/communication/call_method_group.tres new file mode 100644 index 00000000..5df2fe2f --- /dev/null +++ b/addons/block_code/blocks/communication/call_method_group.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://c15vtdfihdxb8"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_mlm68"] + +[resource] +script = ExtResource("1_mlm68") +name = &"call_method_group" +type = 2 +variant_type = 0 +display_template = "Call method {method_name: STRING} in group {group: STRING}" +code_template = "get_tree().call_group({group}, {method_name})" +description = "Calls the method/function on each member of the given group" +category = "Communication | Methods" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/communication/call_method_node.tres b/addons/block_code/blocks/communication/call_method_node.tres new file mode 100644 index 00000000..5ed916df --- /dev/null +++ b/addons/block_code/blocks/communication/call_method_node.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://c04j5flmimjvf"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_pg363"] + +[resource] +script = ExtResource("1_pg363") +name = &"call_method_node" +type = 2 +variant_type = 0 +display_template = "Call method {method_name: STRING} on node {node: OBJECT}" +code_template = "{node}.call({method_name})" +description = "Calls the method/function of the given node" +category = "Communication | Methods" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/communication/define_method.tres b/addons/block_code/blocks/communication/define_method.tres new file mode 100644 index 00000000..5679c761 --- /dev/null +++ b/addons/block_code/blocks/communication/define_method.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://7r2b2griss3i"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_6e473"] + +[resource] +script = ExtResource("1_6e473") +name = &"define_method" +description = "Define a method/function with following code_templates" +category = "Communication | Methods" +type = 1 +variant_type = 0 +display_template = "Define method {method_name: NIL}" +code_template = "func {method_name}():" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/communication/is_in_group.tres b/addons/block_code/blocks/communication/is_in_group.tres new file mode 100644 index 00000000..0b38920a --- /dev/null +++ b/addons/block_code/blocks/communication/is_in_group.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://q4cnstftvsiu"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_tjyq5"] + +[resource] +script = ExtResource("1_tjyq5") +name = &"is_in_group" +description = "Is this node in the group" +category = "Communication | Groups" +type = 3 +variant_type = 1 +display_template = "Is in group {group: STRING}" +code_template = "is_in_group({group})" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/communication/is_node_in_group.tres b/addons/block_code/blocks/communication/is_node_in_group.tres new file mode 100644 index 00000000..3639b336 --- /dev/null +++ b/addons/block_code/blocks/communication/is_node_in_group.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://bbtdxeey74x67"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_5krrs"] + +[resource] +script = ExtResource("1_5krrs") +name = &"is_node_in_group" +description = "Is the node in the group" +category = "Communication | Groups" +type = 3 +variant_type = 1 +display_template = "Is {node: OBJECT} in group {group: STRING}" +code_template = "{node}.is_in_group({group})" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/communication/remove_from_group.tres b/addons/block_code/blocks/communication/remove_from_group.tres new file mode 100644 index 00000000..7e20f653 --- /dev/null +++ b/addons/block_code/blocks/communication/remove_from_group.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://dgenw5wyqorvq"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_cdwef"] + +[resource] +script = ExtResource("1_cdwef") +name = &"remove_from_group" +type = 2 +variant_type = 0 +display_template = "Remove from group {group: STRING}" +code_template = "remove_from_group({group})" +description = "Remove this node from the group" +category = "Communication | Groups" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/communication/remove_node_from_group.tres b/addons/block_code/blocks/communication/remove_node_from_group.tres new file mode 100644 index 00000000..9b132bed --- /dev/null +++ b/addons/block_code/blocks/communication/remove_node_from_group.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://b2dwk77hnri8y"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_pec24"] + +[resource] +script = ExtResource("1_pec24") +name = &"remove_node_from_group" +type = 2 +variant_type = 0 +display_template = "Remove {node: OBJECT} from group {group: STRING}" +code_template = "{node}.remove_from_group({group})" +description = "Remove the node from the group" +category = "Communication | Groups" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/lifecycle/physics_process.tres b/addons/block_code/blocks/lifecycle/physics_process.tres new file mode 100644 index 00000000..9042e139 --- /dev/null +++ b/addons/block_code/blocks/lifecycle/physics_process.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://bxl7n4tkf1mvd"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_s0hq0"] + +[resource] +script = ExtResource("1_s0hq0") +name = &"physics_process" +type = 1 +variant_type = 0 +display_template = "On Physics Process" +code_template = "func _physics_process(delta):" +description = "The following will be executed during the \"physics\" processing step of the main loop" +category = "Lifecycle" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/lifecycle/process.tres b/addons/block_code/blocks/lifecycle/process.tres new file mode 100644 index 00000000..7bb2ee83 --- /dev/null +++ b/addons/block_code/blocks/lifecycle/process.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://chioedvp50013"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_pmina"] + +[resource] +script = ExtResource("1_pmina") +name = &"process" +type = 1 +variant_type = 0 +display_template = "On Process" +code_template = "func _process(delta):" +description = "The following will be executed during the processing step of the main loop" +category = "Lifecycle" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/lifecycle/queue_free.tres b/addons/block_code/blocks/lifecycle/queue_free.tres new file mode 100644 index 00000000..2c65bdf4 --- /dev/null +++ b/addons/block_code/blocks/lifecycle/queue_free.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://4hj5b3xaiuy8"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_75fle"] + +[resource] +script = ExtResource("1_75fle") +name = &"queue_free" +type = 2 +variant_type = 0 +display_template = "Queue Free" +code_template = "queue_free()" +description = "Queues this node to be deleted at the end of the current frame" +category = "Lifecycle" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/lifecycle/ready.tres b/addons/block_code/blocks/lifecycle/ready.tres new file mode 100644 index 00000000..1455b0ae --- /dev/null +++ b/addons/block_code/blocks/lifecycle/ready.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://dgwfoepoejlom"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_vk0xk"] + +[resource] +script = ExtResource("1_vk0xk") +name = &"ready" +type = 1 +variant_type = 0 +display_template = "On Ready" +code_template = "func _ready():" +description = "The following will be executed when the node is \"ready\"" +category = "Lifecycle" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/log/concat.tres b/addons/block_code/blocks/log/concat.tres new file mode 100644 index 00000000..744bd5a7 --- /dev/null +++ b/addons/block_code/blocks/log/concat.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://cb6ux0amdhhlw"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_lstbo"] + +[resource] +script = ExtResource("1_lstbo") +name = &"concat" +description = "" +category = "Log" +type = 3 +variant_type = 4 +display_template = "{string1: STRING} + {string2: STRING}" +code_template = "{string1} + {string2}" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/log/print.tres b/addons/block_code/blocks/log/print.tres new file mode 100644 index 00000000..b0e85240 --- /dev/null +++ b/addons/block_code/blocks/log/print.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://barxsapb8tl0r"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_0lih2"] + +[resource] +script = ExtResource("1_0lih2") +name = &"print" +description = "Print the text to output" +category = "Log" +type = 2 +variant_type = 0 +display_template = "Print {text: STRING}" +code_template = "print({text})" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/logic/and.tres b/addons/block_code/blocks/logic/and.tres new file mode 100644 index 00000000..c333138f --- /dev/null +++ b/addons/block_code/blocks/logic/and.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://d0g11cp3ff81i"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="2_lxlcw"] + +[resource] +script = ExtResource("2_lxlcw") +name = &"and" +description = "" +category = "Logic | Boolean" +type = 3 +variant_type = 1 +display_template = "{bool1: BOOL} and {bool2: BOOL}" +code_template = "{bool1} and {bool2}" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/logic/compare.tres b/addons/block_code/blocks/logic/compare.tres new file mode 100644 index 00000000..d671d90e --- /dev/null +++ b/addons/block_code/blocks/logic/compare.tres @@ -0,0 +1,24 @@ +[gd_resource type="Resource" load_steps=4 format=3 uid="uid://pr5wnn3ltkbo"] + +[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="1_hcv2h"] +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_wp40r"] + +[sub_resource type="Resource" id="Resource_ie4sg"] +script = ExtResource("1_hcv2h") +selected = 0 +items = ["==", ">", "<", ">=", "<=", "!="] + +[resource] +script = ExtResource("1_wp40r") +name = &"compare" +description = "" +category = "Logic | Comparison" +type = 3 +variant_type = 1 +display_template = "{float1: FLOAT} {op: OPTION} {float2: FLOAT}" +code_template = "{float1} {op} {float2}" +defaults = { +"op": SubResource("Resource_ie4sg") +} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/logic/else.tres b/addons/block_code/blocks/logic/else.tres new file mode 100644 index 00000000..4877389d --- /dev/null +++ b/addons/block_code/blocks/logic/else.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://dpgx8j3veifgl"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_x816c"] + +[resource] +script = ExtResource("1_x816c") +name = &"else" +type = 4 +variant_type = 0 +display_template = "Else" +code_template = "else:" +description = "" +category = "Logic | Conditionals" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/logic/else_if.tres b/addons/block_code/blocks/logic/else_if.tres new file mode 100644 index 00000000..d3d4dae0 --- /dev/null +++ b/addons/block_code/blocks/logic/else_if.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://by53vmmn3wtny"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_kgjks"] + +[resource] +script = ExtResource("1_kgjks") +name = &"else_if" +type = 4 +variant_type = 0 +display_template = "Else if {condition: BOOL}" +code_template = "elif {condition}:" +description = "" +category = "Logic | Conditionals" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/logic/if.tres b/addons/block_code/blocks/logic/if.tres new file mode 100644 index 00000000..5ba37c37 --- /dev/null +++ b/addons/block_code/blocks/logic/if.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://cxvoo3jassq8c"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_c6ly3"] + +[resource] +script = ExtResource("1_c6ly3") +name = &"if" +type = 4 +variant_type = 0 +display_template = "If {condition: BOOL}" +code_template = "if {condition}:" +description = "" +category = "Logic | Conditionals" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/logic/not.tres b/addons/block_code/blocks/logic/not.tres new file mode 100644 index 00000000..5839cabb --- /dev/null +++ b/addons/block_code/blocks/logic/not.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://d6asv53q6ok8"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_6igv6"] + +[resource] +script = ExtResource("1_6igv6") +name = &"not" +description = "" +category = "Logic | Boolean" +type = 3 +variant_type = 1 +display_template = "Not {bool: BOOL}" +code_template = "not {bool}" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/logic/or.tres b/addons/block_code/blocks/logic/or.tres new file mode 100644 index 00000000..c7b0f909 --- /dev/null +++ b/addons/block_code/blocks/logic/or.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://cyu2tntoqf85m"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_oets3"] + +[resource] +script = ExtResource("1_oets3") +name = &"or" +description = "" +category = "Logic | Boolean" +type = 3 +variant_type = 1 +display_template = "{bool1: BOOL} or {bool2: BOOL}" +code_template = "{bool1} or {bool2}" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/loops/break.tres b/addons/block_code/blocks/loops/break.tres new file mode 100644 index 00000000..afcbb27d --- /dev/null +++ b/addons/block_code/blocks/loops/break.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://dwteydig4c6hi"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_4rhsl"] + +[resource] +script = ExtResource("1_4rhsl") +name = &"break" +type = 2 +variant_type = 0 +display_template = "Break" +code_template = "break" +description = "" +category = "Loops" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/loops/continue.tres b/addons/block_code/blocks/loops/continue.tres new file mode 100644 index 00000000..a2697831 --- /dev/null +++ b/addons/block_code/blocks/loops/continue.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://srm0bee85n0d"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_junev"] + +[resource] +script = ExtResource("1_junev") +name = &"continue" +type = 2 +variant_type = 0 +display_template = "Continue" +code_template = "continue" +description = "" +category = "Loops" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/loops/for.tres b/addons/block_code/blocks/loops/for.tres new file mode 100644 index 00000000..6491c063 --- /dev/null +++ b/addons/block_code/blocks/loops/for.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://0g4njflvemaa"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_u01bi"] + +[resource] +script = ExtResource("1_u01bi") +name = &"for" +type = 4 +variant_type = 0 +display_template = "Repeat {n: INT}" +code_template = "for __i in {n}:" +description = "Run the connected blocks [i]n[/i] times" +category = "Loops" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/loops/while.tres b/addons/block_code/blocks/loops/while.tres new file mode 100644 index 00000000..3c3404a0 --- /dev/null +++ b/addons/block_code/blocks/loops/while.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://ccnjk5s5qb2xe"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_fxxh0"] + +[resource] +script = ExtResource("1_fxxh0") +name = &"while" +type = 4 +variant_type = 0 +display_template = "While {condition: BOOL}" +code_template = "while {condition}:" +description = "Run the connected blocks as long as [i]condition[/i] is true.\\nHint: snap a [b]Comparison[/b] block into the condition." +category = "Loops" +defaults = {} +signal_name = "" diff --git a/addons/block_code/blocks/math/add.tres b/addons/block_code/blocks/math/add.tres new file mode 100644 index 00000000..8a8621d3 --- /dev/null +++ b/addons/block_code/blocks/math/add.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://coy3o7q0x0y60"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_rks7c"] + +[resource] +script = ExtResource("1_rks7c") +name = &"add" +description = "" +category = "Math" +type = 3 +variant_type = 3 +display_template = "{a: FLOAT} + {b: FLOAT}" +code_template = "{a} + {b}" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/math/divide.tres b/addons/block_code/blocks/math/divide.tres new file mode 100644 index 00000000..1c5de6e1 --- /dev/null +++ b/addons/block_code/blocks/math/divide.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://dwk6c70c4ta0"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_rhh7v"] + +[resource] +script = ExtResource("1_rhh7v") +name = &"divide" +description = "" +category = "Math" +type = 3 +variant_type = 3 +display_template = "{a: FLOAT} / {b: FLOAT}" +code_template = "{a} / {b}" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/math/multiply.tres b/addons/block_code/blocks/math/multiply.tres new file mode 100644 index 00000000..19ec90e0 --- /dev/null +++ b/addons/block_code/blocks/math/multiply.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://yipjitb3p66q"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_c5vny"] + +[resource] +script = ExtResource("1_c5vny") +name = &"multiply" +description = "" +category = "Math" +type = 3 +variant_type = 3 +display_template = "{a: FLOAT} * {b: FLOAT}" +code_template = "{a} * {b}" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/math/pow.tres b/addons/block_code/blocks/math/pow.tres new file mode 100644 index 00000000..50a5b375 --- /dev/null +++ b/addons/block_code/blocks/math/pow.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://bib11ow5t44to"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_cx5g5"] + +[resource] +script = ExtResource("1_cx5g5") +name = &"pow" +description = "" +category = "Math" +type = 3 +variant_type = 3 +display_template = "{base: FLOAT} ^ {exp: FLOAT}" +code_template = "pow({base}, {exp})" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/math/subtract.tres b/addons/block_code/blocks/math/subtract.tres new file mode 100644 index 00000000..371ccc0c --- /dev/null +++ b/addons/block_code/blocks/math/subtract.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://dkt135xfcklya"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_n0dmm"] + +[resource] +script = ExtResource("1_n0dmm") +name = &"subtract" +description = "" +category = "Math" +type = 3 +variant_type = 3 +display_template = "{a: FLOAT} - {b: FLOAT}" +code_template = "{a} - {b}" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/variables/vector2.tres b/addons/block_code/blocks/variables/vector2.tres new file mode 100644 index 00000000..0da6e806 --- /dev/null +++ b/addons/block_code/blocks/variables/vector2.tres @@ -0,0 +1,19 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://ddj24k1fp0s82"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_ilw3v"] + +[resource] +script = ExtResource("1_ilw3v") +name = &"vector2" +description = "" +category = "Variables" +type = 3 +variant_type = 5 +display_template = "Vector2 x: {x: FLOAT} y: {y: FLOAT}" +code_template = "Vector2({x}, {y})" +defaults = { +"x": 0.0, +"y": 0.0 +} +signal_name = "" +scope = "" From dbdaca861f748164e9b7800af074ed92e2537e20 Mon Sep 17 00:00:00 2001 From: Jian-Hong Pan Date: Tue, 30 Jul 2024 11:27:19 +0800 Subject: [PATCH 140/423] category_factory: Add another Sounds blocks for GDScript flavor According to the discussion [1], add the sound blocks into function get_built_in_blocks()'s class matching. It generates blocks belonging to AudioStreamPlayer node, including setting the property's value. Therfore, we have sound blocks in both types of general script and GDScript flavor. [1]: https://github.com/endlessm/godot-block-coding/pull/161#discussion_r1692961580 https://phabricator.endlessm.com/T35609 --- .../ui/picker/categories/category_factory.gd | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index d5e06b4e..14cb896d 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -564,6 +564,7 @@ static func property_to_blocklist(property: Dictionary) -> Array[Block]: var variant_type = property.type const FALLBACK_SET_FOR_TYPE = { + TYPE_BOOL: false, TYPE_INT: "0", TYPE_FLOAT: "0", TYPE_VECTOR2: "0,0", @@ -571,6 +572,7 @@ static func property_to_blocklist(property: Dictionary) -> Array[Block]: } const FALLBACK_CHANGE_FOR_TYPE = { + TYPE_BOOL: true, TYPE_INT: "1", TYPE_FLOAT: "1", TYPE_VECTOR2: "1,1", @@ -724,6 +726,31 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: "angular_velocity": {"category": "Physics | Velocity"}, } + "AudioStreamPlayer": + var b = BLOCKS["statement_block"].instantiate() + b.block_name = "audiostreamplayer_play" + b.block_format = "Play" + b.statement = "play()" + b.tooltip_text = "Play the audio stream" + b.category = "Sounds" + block_list.append(b) + + b = BLOCKS["statement_block"].instantiate() + b.block_name = "audiostreamplayer_stop" + b.block_format = "Stop" + b.statement = "stop()" + b.tooltip_text = "Stop the audio stream" + b.category = "Sounds" + block_list.append(b) + + props = { + "stream_paused": + { + "category": "Sounds", + "has_change": false, + }, + } + "AnimationPlayer": var b = BLOCKS["statement_block"].instantiate() b.block_name = "animationplayer_play" From 6f6a1c84e2d5ca1f7a94978b6c94fe52cdf1ba34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 12 Aug 2024 17:29:17 -0300 Subject: [PATCH 141/423] Block definition: Make description and code multiline This way the editor shows a text box for editing these fields allowing multiple lines. Previously the newlines appeared encoded as `\\n`. --- addons/block_code/code_generation/block_definition.gd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/block_code/code_generation/block_definition.gd b/addons/block_code/code_generation/block_definition.gd index 6ae6ce68..1daca6e0 100644 --- a/addons/block_code/code_generation/block_definition.gd +++ b/addons/block_code/code_generation/block_definition.gd @@ -5,14 +5,14 @@ extends Resource const Types = preload("res://addons/block_code/types/types.gd") @export var name: StringName -@export var description: String +@export_multiline var description: String @export var category: String @export var type: Types.BlockType @export var variant_type: Variant.Type @export var display_template: String -@export var code_template: String +@export_multiline var code_template: String @export var defaults: Dictionary ## Only for blocks of type Types.ENTRY. If non-empty, this block defines a From 6daedf76e7b1579b175407c4e7bdbe3bd069754e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 12 Aug 2024 17:43:30 -0300 Subject: [PATCH 142/423] UI util: Add quick workaround for Control blocks So they can be instantiated for now from block definitions. Note that this won't work for control blocks with multiple bodies like if/else. --- addons/block_code/ui/util.gd | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index 5184726b..2b6eeb18 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -7,6 +7,7 @@ const Types = preload("res://addons/block_code/types/types.gd") const SCENE_PER_TYPE = { Types.BlockType.ENTRY: preload("res://addons/block_code/ui/blocks/entry_block/entry_block.tscn"), Types.BlockType.STATEMENT: preload("res://addons/block_code/ui/blocks/statement_block/statement_block.tscn"), + Types.BlockType.CONTROL: preload("res://addons/block_code/ui/blocks/control_block/control_block.tscn"), } @@ -20,8 +21,12 @@ static func instantiate_block(block_name: StringName) -> Block: var scene = SCENE_PER_TYPE[block_definition.type] var b = scene.instantiate() b.block_name = block_definition.name - b.block_format = block_definition.display_template - b.statement = block_definition.code_template + if block_definition.type == Types.BlockType.CONTROL: + b.block_formats = [block_definition.display_template] + b.statements = [block_definition.code_template] + else: + b.block_format = block_definition.display_template + b.statement = block_definition.code_template b.defaults = block_definition.defaults b.tooltip_text = block_definition.description b.category = block_definition.category From 0322101f8e6fbb5596178f02ac49834445a4a903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 12 Aug 2024 16:51:53 -0300 Subject: [PATCH 143/423] Add utility to get files matching pattern Given a directory path, the function will return all files whose file name matches the given pattern. Co-authored-by: Will Baumgartner --- addons/block_code/code_generation/util.gd | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 addons/block_code/code_generation/util.gd diff --git a/addons/block_code/code_generation/util.gd b/addons/block_code/code_generation/util.gd new file mode 100644 index 00000000..875f70f3 --- /dev/null +++ b/addons/block_code/code_generation/util.gd @@ -0,0 +1,24 @@ +extends Object + + +static func get_files_in_dir_recursive(path: String, pattern: String) -> Array: + var files = [] + var dir := DirAccess.open(path) + + if not dir: + return files + + dir.list_dir_begin() + + var file_name = dir.get_next() + + while file_name != "": + var file_path = path + "/" + file_name + if dir.current_is_dir(): + files.append_array(get_files_in_dir_recursive(file_path, pattern)) + elif file_name.matchn(pattern): + files.append(file_path) + + file_name = dir.get_next() + + return files From fd3e3ac1a30d6131ae5f1d7d2c158b55fd523740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 12 Aug 2024 16:55:17 -0300 Subject: [PATCH 144/423] Update ready and print definitions To the current ones. Done using the editor Inspector dock. --- addons/block_code/blocks/lifecycle/ready.tres | 5 +++-- addons/block_code/blocks/log/print.tres | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/addons/block_code/blocks/lifecycle/ready.tres b/addons/block_code/blocks/lifecycle/ready.tres index 1455b0ae..664fba2f 100644 --- a/addons/block_code/blocks/lifecycle/ready.tres +++ b/addons/block_code/blocks/lifecycle/ready.tres @@ -5,11 +5,12 @@ [resource] script = ExtResource("1_vk0xk") name = &"ready" +description = "Attached blocks will be executed once when the node is \"ready\"" +category = "Lifecycle" type = 1 variant_type = 0 display_template = "On Ready" code_template = "func _ready():" -description = "The following will be executed when the node is \"ready\"" -category = "Lifecycle" defaults = {} signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/log/print.tres b/addons/block_code/blocks/log/print.tres index b0e85240..e6b9b89d 100644 --- a/addons/block_code/blocks/log/print.tres +++ b/addons/block_code/blocks/log/print.tres @@ -11,6 +11,8 @@ type = 2 variant_type = 0 display_template = "Print {text: STRING}" code_template = "print({text})" -defaults = {} +defaults = { +"text": "Hello" +} signal_name = "" scope = "" From 724969706dc048b1a169eee1497e86ab2fae344a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 12 Aug 2024 16:56:30 -0300 Subject: [PATCH 145/423] Blocks catalog: Read definitions from resource files And remove the 2 definitions from code. Please note the name of the On Ready block has changed. This will be addressed in the next commit. --- .../code_generation/blocks_catalog.gd | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/addons/block_code/code_generation/blocks_catalog.gd b/addons/block_code/code_generation/blocks_catalog.gd index 8ceda199..104c3df2 100644 --- a/addons/block_code/code_generation/blocks_catalog.gd +++ b/addons/block_code/code_generation/blocks_catalog.gd @@ -2,6 +2,9 @@ extends Object const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") const Types = preload("res://addons/block_code/types/types.gd") +const Util = preload("res://addons/block_code/code_generation/util.gd") + +const _BLOCKS_PATH = "res://addons/block_code/blocks/" static var _catalog: Dictionary @@ -11,24 +14,11 @@ static func setup(): return _catalog = {} - var block_definition: BlockDefinition = BlockDefinition.new() - block_definition.name = &"ready_block" - block_definition.type = Types.BlockType.ENTRY - block_definition.display_template = "On Ready" - block_definition.code_template = "func _ready():" - block_definition.description = 'Attached blocks will be executed once when the node is "ready"' - block_definition.category = "Lifecycle" - _catalog[&"ready_block"] = block_definition - - block_definition = BlockDefinition.new() - block_definition.name = &"print" - block_definition.type = Types.BlockType.STATEMENT - block_definition.display_template = "print {text: STRING}" - block_definition.code_template = "print({text})" - block_definition.defaults = {"text": "Hello"} - block_definition.description = "Print the text to output" - block_definition.category = "Log" - _catalog[&"print"] = block_definition + + var definition_files = Util.get_files_in_dir_recursive(_BLOCKS_PATH, "*.tres") + for file in definition_files: + var block_definition = load(file) + _catalog[block_definition.name] = block_definition static func get_block(block_name: StringName): From feab669333a7696e192b2efb10560cb3aa105d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 12 Aug 2024 17:01:34 -0300 Subject: [PATCH 146/423] Rename block "ready_block" to "ready" This is how it's now named in the resource files. --- addons/block_code/examples/pong_game/pong_game.tscn | 8 ++++---- addons/block_code/serialization/default_block_script.tres | 2 +- .../block_code/ui/picker/categories/category_factory.gd | 2 +- tests/test_instruction_tree.gd | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index 17654396..bb282ed8 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -35,7 +35,7 @@ serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", " [sub_resource type="Resource" id="Resource_yiq7s"] script = ExtResource("4_qtggh") -name = &"ready_block" +name = &"ready" position = Vector2(75, 175) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_q65fe")]] block_serialized_properties = SubResource("Resource_q1vhx") @@ -130,7 +130,7 @@ serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", " [sub_resource type="Resource" id="Resource_hrubs"] script = ExtResource("4_qtggh") -name = &"ready_block" +name = &"ready" position = Vector2(50, 175) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ttkrd")]] block_serialized_properties = SubResource("Resource_06s7w") @@ -269,7 +269,7 @@ serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", " [sub_resource type="Resource" id="Resource_1h6wi"] script = ExtResource("4_qtggh") -name = &"ready_block" +name = &"ready" position = Vector2(54, 47) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_gywyt")]] block_serialized_properties = SubResource("Resource_b0aen") @@ -862,7 +862,7 @@ serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", " [sub_resource type="Resource" id="Resource_njwj4"] script = ExtResource("4_qtggh") -name = &"ready_block" +name = &"ready" position = Vector2(54, 47) path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_8xxm3")]] block_serialized_properties = SubResource("Resource_g3mty") diff --git a/addons/block_code/serialization/default_block_script.tres b/addons/block_code/serialization/default_block_script.tres index ca5ee151..bb6cc2ce 100644 --- a/addons/block_code/serialization/default_block_script.tres +++ b/addons/block_code/serialization/default_block_script.tres @@ -11,7 +11,7 @@ serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", " [sub_resource type="Resource" id="Resource_1h6wi"] script = ExtResource("1_barc5") -name = &"ready_block" +name = &"ready" position = Vector2(54, 47) path_child_pairs = [] block_serialized_properties = SubResource("Resource_b0aen") diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 14cb896d..62f84dfe 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -172,7 +172,7 @@ static func get_general_blocks() -> Array[Block]: #region Lifecycle - b = Util.instantiate_block(&"ready_block") + b = Util.instantiate_block(&"ready") block_list.append(b) b = BLOCKS["entry_block"].instantiate() diff --git a/tests/test_instruction_tree.gd b/tests/test_instruction_tree.gd index 680b127d..d7f90981 100644 --- a/tests/test_instruction_tree.gd +++ b/tests/test_instruction_tree.gd @@ -123,7 +123,7 @@ func test_script_no_entry_blocks(): func test_basic_script(): - var ready_block: Block = dup_node(general_blocks["ready_block"]) + var ready_block: Block = dup_node(general_blocks[&"ready"]) var print_block: Block = dup_node(general_blocks["print"]) # XXX: It seems like this should substitute {text} in the statement, @@ -158,8 +158,8 @@ func test_basic_script(): func test_multiple_entry_script(): - var ready_block: Block = dup_node(general_blocks["ready_block"]) - var print_block: Block = dup_node(general_blocks["print"]) + var ready_block: Block = dup_node(general_blocks[&"ready"]) + var print_block: Block = dup_node(general_blocks[&"print"]) ready_block.bottom_snap.insert_snapped_block(print_block) ready_block.bottom_snap.snapped_block = print_block From 3971f4792b7a651e45feb07881827a1e3da8d769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 12 Aug 2024 17:27:38 -0300 Subject: [PATCH 147/423] Port lifecycle and loops blocks To the new block definitions. Update the resource files to match the current values when needed. --- .../blocks/lifecycle/physics_process.tres | 5 +- .../block_code/blocks/lifecycle/process.tres | 5 +- addons/block_code/blocks/loops/for.tres | 9 ++- addons/block_code/blocks/loops/while.tres | 7 +- .../ui/picker/categories/category_factory.gd | 80 +++---------------- 5 files changed, 25 insertions(+), 81 deletions(-) diff --git a/addons/block_code/blocks/lifecycle/physics_process.tres b/addons/block_code/blocks/lifecycle/physics_process.tres index 9042e139..a797f4b6 100644 --- a/addons/block_code/blocks/lifecycle/physics_process.tres +++ b/addons/block_code/blocks/lifecycle/physics_process.tres @@ -5,11 +5,12 @@ [resource] script = ExtResource("1_s0hq0") name = &"physics_process" +description = "Attached blocks will be executed during the \"physics\" processing step of the main loop" +category = "Lifecycle" type = 1 variant_type = 0 display_template = "On Physics Process" code_template = "func _physics_process(delta):" -description = "The following will be executed during the \"physics\" processing step of the main loop" -category = "Lifecycle" defaults = {} signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/lifecycle/process.tres b/addons/block_code/blocks/lifecycle/process.tres index 7bb2ee83..7a43cea3 100644 --- a/addons/block_code/blocks/lifecycle/process.tres +++ b/addons/block_code/blocks/lifecycle/process.tres @@ -5,11 +5,12 @@ [resource] script = ExtResource("1_pmina") name = &"process" +description = "Attached blocks will be executed during the processing step of the main loop" +category = "Lifecycle" type = 1 variant_type = 0 display_template = "On Process" code_template = "func _process(delta):" -description = "The following will be executed during the processing step of the main loop" -category = "Lifecycle" defaults = {} signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/loops/for.tres b/addons/block_code/blocks/loops/for.tres index 6491c063..1505118d 100644 --- a/addons/block_code/blocks/loops/for.tres +++ b/addons/block_code/blocks/loops/for.tres @@ -5,11 +5,12 @@ [resource] script = ExtResource("1_u01bi") name = &"for" +description = "Run the connected blocks [i]number[/i] times" +category = "Loops" type = 4 variant_type = 0 -display_template = "Repeat {n: INT}" -code_template = "for __i in {n}:" -description = "Run the connected blocks [i]n[/i] times" -category = "Loops" +display_template = "Repeat {number: INT}" +code_template = "for __i in {number}:" defaults = {} signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/loops/while.tres b/addons/block_code/blocks/loops/while.tres index 3c3404a0..91e2d4fa 100644 --- a/addons/block_code/blocks/loops/while.tres +++ b/addons/block_code/blocks/loops/while.tres @@ -5,11 +5,14 @@ [resource] script = ExtResource("1_fxxh0") name = &"while" +description = "Run the connected blocks as long as [i]condition[/i] is true. + +Hint: snap a [b]Comparison[/b] block into the condition." +category = "Loops" type = 4 variant_type = 0 display_template = "While {condition: BOOL}" code_template = "while {condition}:" -description = "Run the connected blocks as long as [i]condition[/i] is true.\\nHint: snap a [b]Comparison[/b] block into the condition." -category = "Loops" defaults = {} signal_name = "" +scope = "" diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 62f84dfe..31952ba3 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -170,60 +170,15 @@ static func get_general_blocks() -> Array[Block]: var b: Block var block_list: Array[Block] = [] -#region Lifecycle - - b = Util.instantiate_block(&"ready") - block_list.append(b) - - b = BLOCKS["entry_block"].instantiate() - b.block_name = "process_block" - b.block_format = "On Process" - b.statement = "func _process(delta):" - b.tooltip_text = "Attached blocks will be executed during the processing step of the main loop" - b.category = "Lifecycle" - block_list.append(b) - - b = BLOCKS["entry_block"].instantiate() - b.block_name = "physics_process_block" - b.block_format = "On Physics Process" - b.statement = "func _physics_process(delta):" - b.tooltip_text = 'Attached blocks will be executed during the "physics" processing step of the main loop' - b.category = "Lifecycle" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "queue_free" - b.block_format = "Queue Free" - b.statement = "queue_free()" - b.tooltip_text = "Queues this node to be deleted at the end of the current frame" - b.category = "Lifecycle" - block_list.append(b) - -#endregion -#region Loops - - b = BLOCKS["control_block"].instantiate() - b.block_name = "for_loop" - b.block_formats = ["repeat {number: INT}"] - b.statements = ["for __i in {number}:"] - b.category = "Loops" - b.tooltip_text = "Run the connected blocks [i]number[/i] times" - block_list.append(b) - - b = BLOCKS["control_block"].instantiate() - b.block_name = "while_loop" - b.block_formats = ["while {condition: BOOL}"] - b.statements = ["while {condition}:"] - b.category = "Loops" - b.tooltip_text = ( - """ - Run the connected blocks as long as [i]condition[/i] is true. + # Lifecycle + for block_name in [&"ready", &"process", &"physics_process", &"queue_free"]: + b = Util.instantiate_block(block_name) + block_list.append(b) - Hint: snap a [b]Comparison[/b] block into the condition. - """ - . dedent() - ) - block_list.append(b) + # Loops + for block_name in [&"for", &"while", &"break", &"continue"]: + b = Util.instantiate_block(block_name) + block_list.append(b) b = BLOCKS["statement_block"].instantiate() b.block_name = "await_scene_ready" @@ -238,27 +193,10 @@ static func get_general_blocks() -> Array[Block]: b.category = "Loops" block_list.append(b) - b = BLOCKS["statement_block"].instantiate() - b.block_name = "break" - b.block_format = "Break" - b.statement = "break" - b.category = "Loops" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "continue" - b.block_format = "Continue" - b.statement = "continue" - b.category = "Loops" - block_list.append(b) - -#endregion -#region Logs - + # Logs b = Util.instantiate_block(&"print") block_list.append(b) -#endregion #region Communication b = BLOCKS["entry_block"].instantiate() From 01ad14ed734aa15dcc0e0d67d6af718e22be5a92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 14 Aug 2024 07:15:12 -0300 Subject: [PATCH 148/423] UI util: Support value blocks These have variant type that it must be passed to the scene. --- addons/block_code/ui/util.gd | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index 2b6eeb18..13d602eb 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -7,6 +7,7 @@ const Types = preload("res://addons/block_code/types/types.gd") const SCENE_PER_TYPE = { Types.BlockType.ENTRY: preload("res://addons/block_code/ui/blocks/entry_block/entry_block.tscn"), Types.BlockType.STATEMENT: preload("res://addons/block_code/ui/blocks/statement_block/statement_block.tscn"), + Types.BlockType.VALUE: preload("res://addons/block_code/ui/blocks/parameter_block/parameter_block.tscn"), Types.BlockType.CONTROL: preload("res://addons/block_code/ui/blocks/control_block/control_block.tscn"), } @@ -27,11 +28,14 @@ static func instantiate_block(block_name: StringName) -> Block: else: b.block_format = block_definition.display_template b.statement = block_definition.code_template + if block_definition.type == Types.BlockType.VALUE: + b.variant_type = block_definition.variant_type + elif block_definition.type == Types.BlockType.ENTRY: + if block_definition.signal_name != "": + b.signal_name = block_definition.signal_name b.defaults = block_definition.defaults b.tooltip_text = block_definition.description b.category = block_definition.category - if block_definition.type == Types.BlockType.ENTRY and block_definition.signal_name != "": - b.signal_name = block_definition.signal_name return b From 2bdd938ed5d576724b322ec9007d8172fd71384c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 14 Aug 2024 10:06:44 -0300 Subject: [PATCH 149/423] Stop serializing properties for control and value blocks Like previously done for entry and statement blocks in 13e57004. --- addons/block_code/ui/blocks/control_block/control_block.gd | 3 ++- addons/block_code/ui/blocks/parameter_block/parameter_block.gd | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/block_code/ui/blocks/control_block/control_block.gd b/addons/block_code/ui/blocks/control_block/control_block.gd index 7d72e751..0e40f101 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.gd +++ b/addons/block_code/ui/blocks/control_block/control_block.gd @@ -69,7 +69,8 @@ func get_instruction_node() -> InstructionTree.TreeNode: func get_serialized_props() -> Array: var props := super() - props.append_array(serialize_props(["block_formats", "statements", "defaults"])) + if not BlocksCatalog.has_block(block_name): + props.append_array(serialize_props(["block_formats", "statements", "defaults"])) var _param_input_strings_array = [] for param_name_input_pairs in param_name_input_pairs_array: diff --git a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd index 247e3051..cd6bb599 100644 --- a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd +++ b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd @@ -49,7 +49,8 @@ func _on_drag_drop_area_mouse_down(): func get_serialized_props() -> Array: var props := super() - props.append_array(serialize_props(["block_format", "statement", "defaults", "variant_type"])) + if not BlocksCatalog.has_block(block_name): + props.append_array(serialize_props(["block_format", "statement", "defaults", "variant_type"])) var _param_input_strings: Dictionary = {} for pair in param_name_input_pairs: From 886177497f705c6a2f3b6285fa85685ffb7bf170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 13 Aug 2024 13:55:15 -0300 Subject: [PATCH 150/423] Port "await_scene_ready" block The resource file was missing. --- .../blocks/loops/await_scene_ready.tres | 17 +++++++++++++++++ .../ui/picker/categories/category_factory.gd | 15 +-------------- 2 files changed, 18 insertions(+), 14 deletions(-) create mode 100644 addons/block_code/blocks/loops/await_scene_ready.tres diff --git a/addons/block_code/blocks/loops/await_scene_ready.tres b/addons/block_code/blocks/loops/await_scene_ready.tres new file mode 100644 index 00000000..18f7e085 --- /dev/null +++ b/addons/block_code/blocks/loops/await_scene_ready.tres @@ -0,0 +1,17 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://bkdmiqavhqrph"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_qy2t4"] + +[resource] +script = ExtResource("1_qy2t4") +name = &"await_scene_ready" +description = "" +category = "Loops" +type = 2 +variant_type = 0 +display_template = "Await scene ready" +code_template = "if not get_tree().root.is_node_ready(): + await get_tree().root.ready" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 31952ba3..f7752a33 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -176,23 +176,10 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) # Loops - for block_name in [&"for", &"while", &"break", &"continue"]: + for block_name in [&"for", &"while", &"break", &"continue", &"await_scene_ready"]: b = Util.instantiate_block(block_name) block_list.append(b) - b = BLOCKS["statement_block"].instantiate() - b.block_name = "await_scene_ready" - b.block_format = "Await scene ready" - b.statement = ( - """ - if not get_tree().root.is_node_ready(): - await get_tree().root.ready - """ - . dedent() - ) - b.category = "Loops" - block_list.append(b) - # Logs b = Util.instantiate_block(&"print") block_list.append(b) From c2e77ae98640def571c5f013afd30eae3f7420f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 13 Aug 2024 14:09:24 -0300 Subject: [PATCH 151/423] Port communication blocks Please note that the block name has changed slightly for the call methods. They are now: "call_method_group" and "call_method_node". But we are not considering this ABI yet. Also the node parameters have changed from NODE_PATH to OBJECT and the code templates have been simplified. They still work as before, passing node references like %UniqueName to the input field. Co-authored-by: Will Baumgartner --- .../communication/call_method_node.tres | 7 +- .../blocks/communication/define_method.tres | 2 +- .../ui/picker/categories/category_factory.gd | 91 ++----------------- 3 files changed, 12 insertions(+), 88 deletions(-) diff --git a/addons/block_code/blocks/communication/call_method_node.tres b/addons/block_code/blocks/communication/call_method_node.tres index 5ed916df..ba78855c 100644 --- a/addons/block_code/blocks/communication/call_method_node.tres +++ b/addons/block_code/blocks/communication/call_method_node.tres @@ -5,11 +5,12 @@ [resource] script = ExtResource("1_pg363") name = &"call_method_node" +description = "Calls the method/function of the given node" +category = "Communication | Methods" type = 2 variant_type = 0 -display_template = "Call method {method_name: STRING} on node {node: OBJECT}" +display_template = "Call method {method_name: STRING} in node {node: OBJECT}" code_template = "{node}.call({method_name})" -description = "Calls the method/function of the given node" -category = "Communication | Methods" defaults = {} signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/communication/define_method.tres b/addons/block_code/blocks/communication/define_method.tres index 5679c761..4278151d 100644 --- a/addons/block_code/blocks/communication/define_method.tres +++ b/addons/block_code/blocks/communication/define_method.tres @@ -5,7 +5,7 @@ [resource] script = ExtResource("1_6e473") name = &"define_method" -description = "Define a method/function with following code_templates" +description = "Define a method/function with following statements" category = "Communication | Methods" type = 1 variant_type = 0 diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index f7752a33..b29d058e 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -184,92 +184,15 @@ static func get_general_blocks() -> Array[Block]: b = Util.instantiate_block(&"print") block_list.append(b) -#region Communication - - b = BLOCKS["entry_block"].instantiate() - b.block_name = "define_method" - # HACK: make signals work with new entry nodes. NIL instead of STRING type allows - # plain text input for function name. Should revamp signals later - b.block_format = "Define method {method_name: NIL}" - b.statement = "func {method_name}():" - b.category = "Communication | Methods" - b.tooltip_text = "Define a method/function with following statements" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "call_group_method" - b.block_format = "Call method {method_name: STRING} in group {group: STRING}" - b.statement = "get_tree().call_group({group}, {method_name})" - b.category = "Communication | Methods" - b.tooltip_text = "Calls the method/function on each member of the given group" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "call_node_method" - b.block_format = "Call method {method_name: STRING} in node {node_path: NODE_PATH}" - b.statement = ( - """ - var node = get_node({node_path}) - if node: - node.call({method_name}) - """ - . dedent() - ) - b.tooltip_text = "Calls the method/function of the given node" - b.category = "Communication | Methods" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "add_to_group" - b.block_format = "Add to group {group: STRING}" - b.statement = "add_to_group({group})" - b.category = "Communication | Groups" - b.tooltip_text = "Add this node into the group" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "add_node_to_group" - b.block_format = "Add {node: NODE_PATH} to group {group: STRING}" - b.statement = "get_node({node}).add_to_group({group})" - b.category = "Communication | Groups" - b.tooltip_text = "Add the node into the group" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "remove_from_group" - b.block_format = "Remove from group {group: STRING}" - b.statement = "remove_from_group({group})" - b.tooltip_text = "Remove this node from the group" - b.category = "Communication | Groups" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "remove_node_from_group" - b.block_format = "Remove {node: NODE_PATH} from group {group: STRING}" - b.statement = "get_node({node}).remove_from_group({group})" - b.tooltip_text = "Remove the node from the group" - b.category = "Communication | Groups" - block_list.append(b) - - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "is_in_group" - b.variant_type = TYPE_BOOL - b.block_format = "Is in group {group: STRING}" - b.statement = "is_in_group({group})" - b.tooltip_text = "Is this node in the group" - b.category = "Communication | Groups" - block_list.append(b) + # Communication + for block_name in [&"define_method", &"call_method_group", &"call_method_node"]: + b = Util.instantiate_block(block_name) + block_list.append(b) - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "is_node_in_group" - b.variant_type = TYPE_BOOL - b.block_format = "Is {node: NODE_PATH} in group {group: STRING}" - b.statement = "get_node({node}).is_in_group({group})" - b.tooltip_text = "Is the node in the group" - b.category = "Communication | Groups" - block_list.append(b) + for block_name in [&"add_to_group", &"add_node_to_group", &"remove_from_group", &"remove_node_from_group", &"is_in_group", &"is_node_in_group"]: + b = Util.instantiate_block(block_name) + block_list.append(b) -#endregion #region Variables b = BLOCKS["parameter_block"].instantiate() From a9ac0bb1dd28ac55a589ab5a89debe7e8729d28d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 13 Aug 2024 14:28:22 -0300 Subject: [PATCH 152/423] Port vector2 block Co-authored-by: Will Baumgartner --- .../ui/picker/categories/category_factory.gd | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index b29d058e..17c4b4ce 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -193,18 +193,10 @@ static func get_general_blocks() -> Array[Block]: b = Util.instantiate_block(block_name) block_list.append(b) -#region Variables - - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "vector2" - b.variant_type = TYPE_VECTOR2 - b.block_format = "Vector2 x: {x: FLOAT} y: {y: FLOAT}" - b.statement = "Vector2({x}, {y})" - b.defaults = {"x": "0", "y": "0"} - b.category = "Variables" + # Variables + b = Util.instantiate_block(&"vector2") block_list.append(b) -#endregion #region Math b = BLOCKS["parameter_block"].instantiate() From df5ff192366e10713bb2e7e498a8f8faf2e7cf83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 14 Aug 2024 10:23:44 -0300 Subject: [PATCH 153/423] Port math blocks And add missing defaults to the resource files. Please note that the type for arguments and return value have changed from integer to floating point. Co-authored-by: Will Baumgartner --- addons/block_code/blocks/math/add.tres | 5 +- addons/block_code/blocks/math/divide.tres | 5 +- addons/block_code/blocks/math/multiply.tres | 5 +- addons/block_code/blocks/math/pow.tres | 5 +- addons/block_code/blocks/math/subtract.tres | 5 +- .../ui/picker/categories/category_factory.gd | 51 ++----------------- 6 files changed, 24 insertions(+), 52 deletions(-) diff --git a/addons/block_code/blocks/math/add.tres b/addons/block_code/blocks/math/add.tres index 8a8621d3..6ffb4155 100644 --- a/addons/block_code/blocks/math/add.tres +++ b/addons/block_code/blocks/math/add.tres @@ -11,6 +11,9 @@ type = 3 variant_type = 3 display_template = "{a: FLOAT} + {b: FLOAT}" code_template = "{a} + {b}" -defaults = {} +defaults = { +"a": 1.0, +"b": 1.0 +} signal_name = "" scope = "" diff --git a/addons/block_code/blocks/math/divide.tres b/addons/block_code/blocks/math/divide.tres index 1c5de6e1..5d4dae46 100644 --- a/addons/block_code/blocks/math/divide.tres +++ b/addons/block_code/blocks/math/divide.tres @@ -11,6 +11,9 @@ type = 3 variant_type = 3 display_template = "{a: FLOAT} / {b: FLOAT}" code_template = "{a} / {b}" -defaults = {} +defaults = { +"a": 1.0, +"b": 1.0 +} signal_name = "" scope = "" diff --git a/addons/block_code/blocks/math/multiply.tres b/addons/block_code/blocks/math/multiply.tres index 19ec90e0..285c592d 100644 --- a/addons/block_code/blocks/math/multiply.tres +++ b/addons/block_code/blocks/math/multiply.tres @@ -11,6 +11,9 @@ type = 3 variant_type = 3 display_template = "{a: FLOAT} * {b: FLOAT}" code_template = "{a} * {b}" -defaults = {} +defaults = { +"a": 1.0, +"b": 1.0 +} signal_name = "" scope = "" diff --git a/addons/block_code/blocks/math/pow.tres b/addons/block_code/blocks/math/pow.tres index 50a5b375..654d741a 100644 --- a/addons/block_code/blocks/math/pow.tres +++ b/addons/block_code/blocks/math/pow.tres @@ -11,6 +11,9 @@ type = 3 variant_type = 3 display_template = "{base: FLOAT} ^ {exp: FLOAT}" code_template = "pow({base}, {exp})" -defaults = {} +defaults = { +"base": 1.0, +"exp": 1.0 +} signal_name = "" scope = "" diff --git a/addons/block_code/blocks/math/subtract.tres b/addons/block_code/blocks/math/subtract.tres index 371ccc0c..a23bc765 100644 --- a/addons/block_code/blocks/math/subtract.tres +++ b/addons/block_code/blocks/math/subtract.tres @@ -11,6 +11,9 @@ type = 3 variant_type = 3 display_template = "{a: FLOAT} - {b: FLOAT}" code_template = "{a} - {b}" -defaults = {} +defaults = { +"a": 1.0, +"b": 1.0 +} signal_name = "" scope = "" diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 17c4b4ce..ec325a7e 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -197,54 +197,11 @@ static func get_general_blocks() -> Array[Block]: b = Util.instantiate_block(&"vector2") block_list.append(b) -#region Math - - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "add_int" - b.variant_type = TYPE_INT - b.block_format = "{a: INT} + {b: INT}" - b.statement = "({a} + {b})" - b.defaults = {"a": "1", "b": "1"} - b.category = "Math" - block_list.append(b) - - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "subtract_int" - b.variant_type = TYPE_INT - b.block_format = "{a: INT} - {b: INT}" - b.statement = "({a} - {b})" - b.defaults = {"a": "1", "b": "1"} - b.category = "Math" - block_list.append(b) - - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "multiply_int" - b.variant_type = TYPE_INT - b.block_format = "{a: INT} * {b: INT}" - b.statement = "({a} * {b})" - b.defaults = {"a": "1", "b": "1"} - b.category = "Math" - block_list.append(b) - - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "divide_int" - b.variant_type = TYPE_INT - b.block_format = "{a: INT} / {b: INT}" - b.statement = "({a} / {b})" - b.defaults = {"a": "1", "b": "1"} - b.category = "Math" - block_list.append(b) - - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "pow_int" - b.variant_type = TYPE_INT - b.block_format = "{base: INT} ^ {exp: INT}" - b.statement = "(pow({base}, {exp}))" - b.defaults = {"base": "1", "exp": "1"} - b.category = "Math" - block_list.append(b) + # Math + for block_name in [&"add", &"subtract", &"multiply", &"divide", &"pow"]: + b = Util.instantiate_block(block_name) + block_list.append(b) -#endregion #region Logic b = BLOCKS["control_block"].instantiate() From db6ac46ed94d95f5f5d54c1ef20e6be39cf2ee54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 14 Aug 2024 10:39:38 -0300 Subject: [PATCH 154/423] Port logic blocks And add missing defaults to the compare resource file. Co-authored-by: Will Baumgartner --- addons/block_code/blocks/logic/compare.tres | 2 + .../ui/picker/categories/category_factory.gd | 48 ++----------------- 2 files changed, 5 insertions(+), 45 deletions(-) diff --git a/addons/block_code/blocks/logic/compare.tres b/addons/block_code/blocks/logic/compare.tres index d671d90e..6556645b 100644 --- a/addons/block_code/blocks/logic/compare.tres +++ b/addons/block_code/blocks/logic/compare.tres @@ -18,6 +18,8 @@ variant_type = 1 display_template = "{float1: FLOAT} {op: OPTION} {float2: FLOAT}" code_template = "{float1} {op} {float2}" defaults = { +"float1": 1.0, +"float2": 1.0, "op": SubResource("Resource_ie4sg") } signal_name = "" diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index ec325a7e..affa0bba 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -202,53 +202,11 @@ static func get_general_blocks() -> Array[Block]: b = Util.instantiate_block(block_name) block_list.append(b) -#region Logic - - b = BLOCKS["control_block"].instantiate() - b.block_name = "if" - b.block_formats = ["if {condition: BOOL}"] - b.statements = ["if {condition}:"] - b.category = "Logic | Conditionals" - block_list.append(b) - - b = BLOCKS["control_block"].instantiate() - b.block_name = "if_else" - b.block_formats = ["if {condition: BOOL}", "else"] - b.statements = ["if {condition}:", "else:"] - b.category = "Logic | Conditionals" - block_list.append(b) - - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "compare_int" - b.variant_type = TYPE_BOOL - b.block_format = "{int1: INT} {op: OPTION} {int2: INT}" - b.statement = "({int1} {op} {int2})" - b.defaults = { - "op": OptionData.new(["==", ">", "<", ">=", "<=", "!="]), - "int1": "1", - "int2": "1", - } - b.category = "Logic | Comparison" - block_list.append(b) - - for op in ["and", "or"]: - b = BLOCKS["parameter_block"].instantiate() - b.block_name = op - b.variant_type = TYPE_BOOL - b.block_format = "{bool1: BOOL} %s {bool2: BOOL}" % op - b.statement = "({bool1} %s {bool2})" % op - b.category = "Logic | Boolean" + # Logic + for block_name in [&"if", &"else_if", &"else", &"compare", &"and", &"or", &"not"]: + b = Util.instantiate_block(block_name) block_list.append(b) - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "not" - b.variant_type = TYPE_BOOL - b.block_format = "Not {bool: BOOL}" - b.statement = "(not {bool})" - b.category = "Logic | Boolean" - block_list.append(b) - -#endregion #region Input block_list.append_array(_get_input_blocks()) From 54edc3316ca35dd28e6fe4b4f09bf0a69b476220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 14 Aug 2024 11:35:58 -0300 Subject: [PATCH 155/423] Port general sound blocks And add the resource files for the block definitions. --- .../block_code/blocks/sounds/load_sound.tres | 20 +++++ .../blocks/sounds/pause_continue_sound.tres | 29 +++++++ .../block_code/blocks/sounds/play_sound.tres | 23 ++++++ .../block_code/blocks/sounds/stop_sound.tres | 21 +++++ .../ui/picker/categories/category_factory.gd | 77 ++----------------- 5 files changed, 98 insertions(+), 72 deletions(-) create mode 100644 addons/block_code/blocks/sounds/load_sound.tres create mode 100644 addons/block_code/blocks/sounds/pause_continue_sound.tres create mode 100644 addons/block_code/blocks/sounds/play_sound.tres create mode 100644 addons/block_code/blocks/sounds/stop_sound.tres diff --git a/addons/block_code/blocks/sounds/load_sound.tres b/addons/block_code/blocks/sounds/load_sound.tres new file mode 100644 index 00000000..ddbe4fac --- /dev/null +++ b/addons/block_code/blocks/sounds/load_sound.tres @@ -0,0 +1,20 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://coefocdmytg0j"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_4w4si"] + +[resource] +script = ExtResource("1_4w4si") +name = &"load_sound" +description = "Load a resource file as the audio stream" +category = "Sounds" +type = 2 +variant_type = 0 +display_template = "Load file {file_path: STRING} as sound {name: STRING}" +code_template = "var __sound = AudioStreamPlayer.new() +__sound.name = {name} +__sound.set_stream(load({file_path})) +add_child(__sound) +" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/sounds/pause_continue_sound.tres b/addons/block_code/blocks/sounds/pause_continue_sound.tres new file mode 100644 index 00000000..acac9de4 --- /dev/null +++ b/addons/block_code/blocks/sounds/pause_continue_sound.tres @@ -0,0 +1,29 @@ +[gd_resource type="Resource" load_steps=4 format=3 uid="uid://wpdspamg3f6g"] + +[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="1_ilhdq"] +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_q04gm"] + +[sub_resource type="Resource" id="Resource_lalgp"] +script = ExtResource("1_ilhdq") +selected = 0 +items = ["Pause", "Continue"] + +[resource] +script = ExtResource("1_q04gm") +name = &"pause_continue_sound" +description = "Pause/Continue the audio stream" +category = "Sounds" +type = 2 +variant_type = 0 +display_template = "{pause: OPTION} the sound {name: STRING}" +code_template = "var __sound_node = get_node({name}) +if \"{pause}\" == \"pause\": + __sound_node.stream_paused = true +else: + __sound_node.stream_paused = false +" +defaults = { +"pause": SubResource("Resource_lalgp") +} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/sounds/play_sound.tres b/addons/block_code/blocks/sounds/play_sound.tres new file mode 100644 index 00000000..128c5701 --- /dev/null +++ b/addons/block_code/blocks/sounds/play_sound.tres @@ -0,0 +1,23 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://dt022ilveapt5"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_llfp1"] + +[resource] +script = ExtResource("1_llfp1") +name = &"play_sound" +description = "Play the audio stream with volume and pitch" +category = "Sounds" +type = 2 +variant_type = 0 +display_template = "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}" +code_template = "var __sound_node = get_node({name}) +__sound_node.volume_db = {db} +__sound_node.pitch_scale = {pitch} +__sound_node.play() +" +defaults = { +"db": 0.0, +"pitch": 1.0 +} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/sounds/stop_sound.tres b/addons/block_code/blocks/sounds/stop_sound.tres new file mode 100644 index 00000000..e9c1a4a2 --- /dev/null +++ b/addons/block_code/blocks/sounds/stop_sound.tres @@ -0,0 +1,21 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://csg40u5awp1sy"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_rfujh"] + +[resource] +script = ExtResource("1_rfujh") +name = &"stop_sound" +description = "Stop the audio stream" +category = "Sounds" +type = 2 +variant_type = 0 +display_template = "Stop the sound {name: STRING}" +code_template = "var __sound_node = get_node({name}) +__sound_node.stop() +" +defaults = { +"db": 0.0, +"pitch": 1.0 +} +signal_name = "" +scope = "" diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index affa0bba..3064c72c 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -207,81 +207,14 @@ static func get_general_blocks() -> Array[Block]: b = Util.instantiate_block(block_name) block_list.append(b) -#region Input - + # Input block_list.append_array(_get_input_blocks()) -#endregion -#region Sounds - b = BLOCKS["statement_block"].instantiate() - b.block_name = "load_sound" - b.block_type = Types.BlockType.STATEMENT - b.block_format = "Load file {file_path: STRING} as sound {name: STRING}" - b.statement = ( - """ - var __sound = AudioStreamPlayer.new() - __sound.name = {name} - __sound.set_stream(load({file_path})) - add_child(__sound) - """ - . dedent() - ) - b.tooltip_text = "Load a resource file as the audio stream" - b.category = "Sounds" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "play_sound" - b.block_type = Types.BlockType.STATEMENT - b.block_format = "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}" - b.statement = ( - """ - var __sound_node = get_node({name}) - __sound_node.volume_db = {db} - __sound_node.pitch_scale = {pitch} - __sound_node.play() - """ - . dedent() - ) - b.defaults = {"db": "0.0", "pitch": "1.0"} - b.tooltip_text = "Play the audio stream with volume and pitch" - b.category = "Sounds" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "pause_continue_sound" - b.block_type = Types.BlockType.STATEMENT - b.block_format = "{pause: OPTION} the sound {name: STRING}" - b.statement = ( - """ - var __sound_node = get_node({name}) - if "{pause}" == "pause": - __sound_node.stream_paused = true - else: - __sound_node.stream_paused = false - """ - . dedent() - ) - b.defaults = {"pause": OptionData.new(["Pause", "Continue"])} - b.tooltip_text = "Pause/Continue the audio stream" - b.category = "Sounds" - block_list.append(b) + # Sounds + for block_name in [&"load_sound", &"play_sound", &"pause_continue_sound", &"stop_sound"]: + b = Util.instantiate_block(block_name) + block_list.append(b) - b = BLOCKS["statement_block"].instantiate() - b.block_name = "stop_sound" - b.block_type = Types.BlockType.STATEMENT - b.block_format = "Stop the sound {name: STRING}" - b.statement = ( - """ - var __sound_node = get_node({name}) - __sound_node.stop() - """ - . dedent() - ) - b.tooltip_text = "Stop the audio stream" - b.category = "Sounds" - block_list.append(b) -#endregion #region Graphics b = BLOCKS["parameter_block"].instantiate() From 5fa8e9dbfe2278e355f3d1632fd2ea24cb2cb0a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 14 Aug 2024 11:49:05 -0300 Subject: [PATCH 156/423] Port general graphics blocks And add the resource files for the block definitions. --- .../blocks/graphics/viewport_center.tres | 16 ++++++++++ .../blocks/graphics/viewport_height.tres | 16 ++++++++++ .../blocks/graphics/viewport_width.tres | 16 ++++++++++ .../ui/picker/categories/category_factory.gd | 31 +++---------------- 4 files changed, 52 insertions(+), 27 deletions(-) create mode 100644 addons/block_code/blocks/graphics/viewport_center.tres create mode 100644 addons/block_code/blocks/graphics/viewport_height.tres create mode 100644 addons/block_code/blocks/graphics/viewport_width.tres diff --git a/addons/block_code/blocks/graphics/viewport_center.tres b/addons/block_code/blocks/graphics/viewport_center.tres new file mode 100644 index 00000000..3779ce21 --- /dev/null +++ b/addons/block_code/blocks/graphics/viewport_center.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://1536itmdu8yo"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_rc1so"] + +[resource] +script = ExtResource("1_rc1so") +name = &"viewport_center" +description = "" +category = "Graphics | Viewport" +type = 3 +variant_type = 5 +display_template = "Viewport Center" +code_template = "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/graphics/viewport_height.tres b/addons/block_code/blocks/graphics/viewport_height.tres new file mode 100644 index 00000000..789de6d6 --- /dev/null +++ b/addons/block_code/blocks/graphics/viewport_height.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://bdm4yr68mdf4d"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_1debb"] + +[resource] +script = ExtResource("1_1debb") +name = &"viewport_height" +description = "" +category = "Graphics | Viewport" +type = 3 +variant_type = 3 +display_template = "Viewport Height" +code_template = "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin.y / scale.y + get_viewport_rect().size.y / scale.y).call()" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/graphics/viewport_width.tres b/addons/block_code/blocks/graphics/viewport_width.tres new file mode 100644 index 00000000..ceb30730 --- /dev/null +++ b/addons/block_code/blocks/graphics/viewport_width.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://bt78ajp56ga24"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_ll4rh"] + +[resource] +script = ExtResource("1_ll4rh") +name = &"viewport_width" +description = "" +category = "Graphics | Viewport" +type = 3 +variant_type = 3 +display_template = "Viewport Width" +code_template = "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin.x / scale.x + get_viewport_rect().size.x / scale.x).call()" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 3064c72c..b95e4255 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -215,33 +215,10 @@ static func get_general_blocks() -> Array[Block]: b = Util.instantiate_block(block_name) block_list.append(b) -#region Graphics - - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "viewport_width" - b.variant_type = TYPE_FLOAT - b.block_format = "Viewport Width" - b.statement = "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin.x / scale.x + get_viewport_rect().size.x / scale.x).call()" - b.category = "Graphics | Viewport" - block_list.append(b) - - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "viewport_height" - b.variant_type = TYPE_FLOAT - b.block_format = "Viewport Height" - b.statement = "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin.y / scale.y + get_viewport_rect().size.y / scale.y).call()" - b.category = "Graphics | Viewport" - block_list.append(b) - - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "viewport_center" - b.variant_type = TYPE_VECTOR2 - b.block_format = "Viewport Center" - b.statement = "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()" - b.category = "Graphics | Viewport" - block_list.append(b) - -#endregion + # Graphics + for block_name in [&"viewport_width", &"viewport_height", &"viewport_center"]: + b = Util.instantiate_block(block_name) + block_list.append(b) return block_list From 937bf213cbe4d91a544a44119c6fd3a4a6d61771 Mon Sep 17 00:00:00 2001 From: jfcharron Date: Thu, 15 Aug 2024 09:18:45 -0300 Subject: [PATCH 157/423] Add random number generation blocks --- .../block_code/blocks/math/randf_range.tres | 19 +++++++++++++++++++ .../block_code/blocks/math/randi_range.tres | 19 +++++++++++++++++++ .../ui/picker/categories/category_factory.gd | 2 +- 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 addons/block_code/blocks/math/randf_range.tres create mode 100644 addons/block_code/blocks/math/randi_range.tres diff --git a/addons/block_code/blocks/math/randf_range.tres b/addons/block_code/blocks/math/randf_range.tres new file mode 100644 index 00000000..641e8b34 --- /dev/null +++ b/addons/block_code/blocks/math/randf_range.tres @@ -0,0 +1,19 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://u35glf576fue"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_03jps"] + +[resource] +script = ExtResource("1_03jps") +name = &"randf_range" +description = "Generate a random floating point number between [i]from[/i] and [i]to[/i] inclusively" +category = "Math" +type = 3 +variant_type = 3 +display_template = "Random floating point number between {from: FLOAT} and {to: FLOAT}" +code_template = "randf_range({from}, {to})" +defaults = { +"from": -1.0, +"to": 1.0 +} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/math/randi_range.tres b/addons/block_code/blocks/math/randi_range.tres new file mode 100644 index 00000000..2d00f194 --- /dev/null +++ b/addons/block_code/blocks/math/randi_range.tres @@ -0,0 +1,19 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://b3b1dyarh2hmo"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_hk574"] + +[resource] +script = ExtResource("1_hk574") +name = &"randi_range" +description = "Generate a random signed 32-bits integer number between [i]from[/i] and [i]to[/i] inclusively. [i]from[/i] and [i]to[/i] can be a negative or positive number" +category = "Math" +type = 3 +variant_type = 2 +display_template = "Random integer number between {from: INT} and {to: INT}" +code_template = "randi_range({from}, {to})" +defaults = { +"from": 0, +"to": 100 +} +signal_name = "" +scope = "" diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index b95e4255..3257c054 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -198,7 +198,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) # Math - for block_name in [&"add", &"subtract", &"multiply", &"divide", &"pow"]: + for block_name in [&"add", &"subtract", &"multiply", &"divide", &"pow", &"randf_range", &"randi_range"]: b = Util.instantiate_block(block_name) block_list.append(b) From b9500518664d54051135e6545b379a4fa6bf002e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Thu, 15 Aug 2024 13:43:37 -0300 Subject: [PATCH 158/423] Move development project to Godot 4.3 https://phabricator.endlessm.com/T35494 --- project.godot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.godot b/project.godot index 4be7b9c3..4e23f05a 100644 --- a/project.godot +++ b/project.godot @@ -12,7 +12,7 @@ config_version=5 config/name="Block Coding Plugin" run/main_scene="res://addons/block_code/examples/pong_game/pong_game.tscn" -config/features=PackedStringArray("4.2", "GL Compatibility") +config/features=PackedStringArray("4.3", "GL Compatibility") config/icon="res://icon.svg" [editor_plugins] From 68522f84053451aec49edeed537a66dcf8c2a938 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Thu, 15 Aug 2024 15:04:11 -0700 Subject: [PATCH 159/423] Update import files for Godot 4.3 Godot 4.3 adds `disable_embedded_bitmaps=true` in font file imports. https://phabricator.endlessm.com/T35494 --- addons/gut/fonts/AnonymousPro-Bold.ttf.import | 1 + addons/gut/fonts/AnonymousPro-BoldItalic.ttf.import | 1 + addons/gut/fonts/AnonymousPro-Italic.ttf.import | 1 + addons/gut/fonts/AnonymousPro-Regular.ttf.import | 1 + addons/gut/fonts/CourierPrime-Bold.ttf.import | 1 + addons/gut/fonts/CourierPrime-BoldItalic.ttf.import | 1 + addons/gut/fonts/CourierPrime-Italic.ttf.import | 1 + addons/gut/fonts/CourierPrime-Regular.ttf.import | 1 + addons/gut/fonts/LobsterTwo-Bold.ttf.import | 1 + addons/gut/fonts/LobsterTwo-BoldItalic.ttf.import | 1 + addons/gut/fonts/LobsterTwo-Italic.ttf.import | 1 + addons/gut/fonts/LobsterTwo-Regular.ttf.import | 1 + 12 files changed, 12 insertions(+) diff --git a/addons/gut/fonts/AnonymousPro-Bold.ttf.import b/addons/gut/fonts/AnonymousPro-Bold.ttf.import index a3eb4791..de1351f6 100644 --- a/addons/gut/fonts/AnonymousPro-Bold.ttf.import +++ b/addons/gut/fonts/AnonymousPro-Bold.ttf.import @@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/AnonymousPro-Bold.ttf-9d8fef4d357af5b52cd60af Rendering=null antialiasing=1 generate_mipmaps=false +disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/addons/gut/fonts/AnonymousPro-BoldItalic.ttf.import b/addons/gut/fonts/AnonymousPro-BoldItalic.ttf.import index ef28dd80..bdde2072 100644 --- a/addons/gut/fonts/AnonymousPro-BoldItalic.ttf.import +++ b/addons/gut/fonts/AnonymousPro-BoldItalic.ttf.import @@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/AnonymousPro-BoldItalic.ttf-4274bf704d3d6b9cd Rendering=null antialiasing=1 generate_mipmaps=false +disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/addons/gut/fonts/AnonymousPro-Italic.ttf.import b/addons/gut/fonts/AnonymousPro-Italic.ttf.import index 1779af17..ce3e5b91 100644 --- a/addons/gut/fonts/AnonymousPro-Italic.ttf.import +++ b/addons/gut/fonts/AnonymousPro-Italic.ttf.import @@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/AnonymousPro-Italic.ttf-9989590b02137b799e13d Rendering=null antialiasing=1 generate_mipmaps=false +disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/addons/gut/fonts/AnonymousPro-Regular.ttf.import b/addons/gut/fonts/AnonymousPro-Regular.ttf.import index 1e2975b1..a567498c 100644 --- a/addons/gut/fonts/AnonymousPro-Regular.ttf.import +++ b/addons/gut/fonts/AnonymousPro-Regular.ttf.import @@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/AnonymousPro-Regular.ttf-856c843fd6f89964d2ca Rendering=null antialiasing=1 generate_mipmaps=false +disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/addons/gut/fonts/CourierPrime-Bold.ttf.import b/addons/gut/fonts/CourierPrime-Bold.ttf.import index 7d60fb0a..cb05171d 100644 --- a/addons/gut/fonts/CourierPrime-Bold.ttf.import +++ b/addons/gut/fonts/CourierPrime-Bold.ttf.import @@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/CourierPrime-Bold.ttf-1f003c66d63ebed70964e77 Rendering=null antialiasing=1 generate_mipmaps=false +disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/addons/gut/fonts/CourierPrime-BoldItalic.ttf.import b/addons/gut/fonts/CourierPrime-BoldItalic.ttf.import index 4678c9eb..0a9a7b77 100644 --- a/addons/gut/fonts/CourierPrime-BoldItalic.ttf.import +++ b/addons/gut/fonts/CourierPrime-BoldItalic.ttf.import @@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/CourierPrime-BoldItalic.ttf-65ebcc61dd5e1dfa8 Rendering=null antialiasing=1 generate_mipmaps=false +disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/addons/gut/fonts/CourierPrime-Italic.ttf.import b/addons/gut/fonts/CourierPrime-Italic.ttf.import index 522e2950..89412fc9 100644 --- a/addons/gut/fonts/CourierPrime-Italic.ttf.import +++ b/addons/gut/fonts/CourierPrime-Italic.ttf.import @@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/CourierPrime-Italic.ttf-baa9156a73770735a0f72 Rendering=null antialiasing=1 generate_mipmaps=false +disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/addons/gut/fonts/CourierPrime-Regular.ttf.import b/addons/gut/fonts/CourierPrime-Regular.ttf.import index 38174660..9fde40b1 100644 --- a/addons/gut/fonts/CourierPrime-Regular.ttf.import +++ b/addons/gut/fonts/CourierPrime-Regular.ttf.import @@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/CourierPrime-Regular.ttf-3babe7e4a7a588dfc9a8 Rendering=null antialiasing=1 generate_mipmaps=false +disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/addons/gut/fonts/LobsterTwo-Bold.ttf.import b/addons/gut/fonts/LobsterTwo-Bold.ttf.import index 7548ad04..673d1515 100644 --- a/addons/gut/fonts/LobsterTwo-Bold.ttf.import +++ b/addons/gut/fonts/LobsterTwo-Bold.ttf.import @@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/LobsterTwo-Bold.ttf-7c7f734103b58a32491a47881 Rendering=null antialiasing=1 generate_mipmaps=false +disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/addons/gut/fonts/LobsterTwo-BoldItalic.ttf.import b/addons/gut/fonts/LobsterTwo-BoldItalic.ttf.import index 4b609e80..62048b0e 100644 --- a/addons/gut/fonts/LobsterTwo-BoldItalic.ttf.import +++ b/addons/gut/fonts/LobsterTwo-BoldItalic.ttf.import @@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/LobsterTwo-BoldItalic.ttf-227406a33e84448e6aa Rendering=null antialiasing=1 generate_mipmaps=false +disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/addons/gut/fonts/LobsterTwo-Italic.ttf.import b/addons/gut/fonts/LobsterTwo-Italic.ttf.import index 5899b797..d3ca2728 100644 --- a/addons/gut/fonts/LobsterTwo-Italic.ttf.import +++ b/addons/gut/fonts/LobsterTwo-Italic.ttf.import @@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/LobsterTwo-Italic.ttf-f93abf6c25390c85ad5fb6c Rendering=null antialiasing=1 generate_mipmaps=false +disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/addons/gut/fonts/LobsterTwo-Regular.ttf.import b/addons/gut/fonts/LobsterTwo-Regular.ttf.import index 45a12c8a..9cc75421 100644 --- a/addons/gut/fonts/LobsterTwo-Regular.ttf.import +++ b/addons/gut/fonts/LobsterTwo-Regular.ttf.import @@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/LobsterTwo-Regular.ttf-f3fcfa01cd671c8da433dd Rendering=null antialiasing=1 generate_mipmaps=false +disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 From 9991c2a5532d0f44d54dbfa4834afb33e13fb165 Mon Sep 17 00:00:00 2001 From: jfcharron Date: Thu, 15 Aug 2024 20:11:51 -0400 Subject: [PATCH 160/423] Adds sin, cos and tan trigonometry function --- addons/block_code/blocks/math/cos.tres | 18 ++++++++++++++++++ addons/block_code/blocks/math/sin.tres | 18 ++++++++++++++++++ addons/block_code/blocks/math/tan.tres | 18 ++++++++++++++++++ .../ui/picker/categories/category_factory.gd | 2 +- 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 addons/block_code/blocks/math/cos.tres create mode 100644 addons/block_code/blocks/math/sin.tres create mode 100644 addons/block_code/blocks/math/tan.tres diff --git a/addons/block_code/blocks/math/cos.tres b/addons/block_code/blocks/math/cos.tres new file mode 100644 index 00000000..1f0bb4a8 --- /dev/null +++ b/addons/block_code/blocks/math/cos.tres @@ -0,0 +1,18 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://c6g6ljp46lfrj"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_lxbvo"] + +[resource] +script = ExtResource("1_lxbvo") +name = &"cos" +description = "Calculate the cosine of [i]angle[/i]" +category = "Math" +type = 3 +variant_type = 3 +display_template = "cos {angle: FLOAT}" +code_template = "cos(deg_to_rad({angle}))" +defaults = { +"angle": 0.0 +} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/math/sin.tres b/addons/block_code/blocks/math/sin.tres new file mode 100644 index 00000000..fca5fca4 --- /dev/null +++ b/addons/block_code/blocks/math/sin.tres @@ -0,0 +1,18 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://b1r7f06rfci6o"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_dlr47"] + +[resource] +script = ExtResource("1_dlr47") +name = &"sin" +description = "Calculate the sine of [i]angle[/i]" +category = "Math" +type = 3 +variant_type = 3 +display_template = "sin {angle: FLOAT}" +code_template = "sin(deg_to_rad({angle}))" +defaults = { +"angle": 0.0 +} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/math/tan.tres b/addons/block_code/blocks/math/tan.tres new file mode 100644 index 00000000..2c6b5cd6 --- /dev/null +++ b/addons/block_code/blocks/math/tan.tres @@ -0,0 +1,18 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://blpo01pjjheqb"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_e2566"] + +[resource] +script = ExtResource("1_e2566") +name = &"tan" +description = "Calculate the tangent of [i]angle[/i]" +category = "Math" +type = 3 +variant_type = 3 +display_template = "tan {angle: FLOAT}" +code_template = "tan(deg_to_rad({angle}))" +defaults = { +"angle": 0.0 +} +signal_name = "" +scope = "" diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 3257c054..9ae41db1 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -198,7 +198,7 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) # Math - for block_name in [&"add", &"subtract", &"multiply", &"divide", &"pow", &"randf_range", &"randi_range"]: + for block_name in [&"add", &"subtract", &"multiply", &"divide", &"pow", &"randf_range", &"randi_range", &"sin", &"cos", &"tan"]: b = Util.instantiate_block(block_name) block_list.append(b) From 2594c269f893b2da535e71207e0185fddaace1be Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Thu, 15 Aug 2024 17:28:55 -0700 Subject: [PATCH 161/423] Run tests with Godot 4.3 in addition to 4.2.2 https://phabricator.endlessm.com/T35494 --- .github/workflows/checks.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 5ed986b8..f8057221 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -25,6 +25,9 @@ jobs: tests: name: Tests + strategy: + matrix: + godot-version: [4.2.2, 4.3.0] runs-on: ubuntu-latest steps: - name: Checkout @@ -32,7 +35,7 @@ jobs: - name: Setup Godot uses: chickensoft-games/setup-godot@v2.1.1 with: - version: 4.2.2 + version: ${{ matrix.godot-version }} use-dotnet: false - name: Initialize Godot run: | From 6c14f0d5372fd86736e630f2c3a131543cf58f8d Mon Sep 17 00:00:00 2001 From: Jian-Hong Pan Date: Fri, 16 Aug 2024 16:44:48 +0800 Subject: [PATCH 162/423] Generate real nodes in test_multiple_entry_script() Duplicating the ready_block as ready_block_2 works with Godot 4.2, but fails with Godot 4.3. Looks like ready_block_2 does not have the following print_block properly. So, generate ready_block_2 and its print_block_2 from duplicated general_blocks: "ready" and "print" directly to avoid the issue with Godot 4.3. https://phabricator.endlessm.com/T35494 --- tests/test_instruction_tree.gd | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_instruction_tree.gd b/tests/test_instruction_tree.gd index d7f90981..8f83a9be 100644 --- a/tests/test_instruction_tree.gd +++ b/tests/test_instruction_tree.gd @@ -163,7 +163,10 @@ func test_multiple_entry_script(): ready_block.bottom_snap.insert_snapped_block(print_block) ready_block.bottom_snap.snapped_block = print_block - var ready_block_2: Block = dup_node(ready_block) + var ready_block_2: Block = dup_node(general_blocks[&"ready"]) + var print_block_2: Block = dup_node(general_blocks[&"print"]) + ready_block_2.bottom_snap.insert_snapped_block(print_block_2) + ready_block_2.bottom_snap.snapped_block = print_block_2 var block_script := BlockScriptSerialization.new("Node2D") var text_script := BlockTreeUtil.generate_script_from_nodes([ready_block, ready_block_2], block_script) From ec266e491a99dca8552e963afa53c7a1640ae903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 16 Aug 2024 11:14:01 -0300 Subject: [PATCH 163/423] Block definition: Add target node class Add target node class to the definition for class-specific blocks. For example, "On body entered / exited" block is specific to a node that inherits RigidBody2D. https://phabricator.endlessm.com/T35591 --- addons/block_code/blocks/communication/add_to_group.tres | 6 ++++-- addons/block_code/blocks/log/print.tres | 1 + addons/block_code/blocks/logic/compare.tres | 1 + addons/block_code/blocks/math/add.tres | 1 + addons/block_code/blocks/math/divide.tres | 1 + addons/block_code/blocks/math/multiply.tres | 1 + addons/block_code/blocks/math/pow.tres | 1 + addons/block_code/blocks/math/randf_range.tres | 1 + addons/block_code/blocks/math/randi_range.tres | 1 + addons/block_code/blocks/math/subtract.tres | 1 + addons/block_code/blocks/sounds/load_sound.tres | 1 + addons/block_code/blocks/sounds/pause_continue_sound.tres | 1 + addons/block_code/blocks/sounds/play_sound.tres | 1 + addons/block_code/blocks/sounds/stop_sound.tres | 1 + addons/block_code/blocks/variables/vector2.tres | 1 + addons/block_code/code_generation/block_definition.gd | 7 +++++++ 16 files changed, 25 insertions(+), 2 deletions(-) diff --git a/addons/block_code/blocks/communication/add_to_group.tres b/addons/block_code/blocks/communication/add_to_group.tres index a7dcb889..d4ccb2bc 100644 --- a/addons/block_code/blocks/communication/add_to_group.tres +++ b/addons/block_code/blocks/communication/add_to_group.tres @@ -5,11 +5,13 @@ [resource] script = ExtResource("1_bcm71") name = &"add_to_group" +target_node_class = "" +description = "Add this node into the group" +category = "Communication | Groups" type = 2 variant_type = 0 display_template = "Add to group {group: STRING}" code_template = "add_to_group({group})" -description = "Add this node into the group" -category = "Communication | Groups" defaults = {} signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/log/print.tres b/addons/block_code/blocks/log/print.tres index e6b9b89d..128c491a 100644 --- a/addons/block_code/blocks/log/print.tres +++ b/addons/block_code/blocks/log/print.tres @@ -5,6 +5,7 @@ [resource] script = ExtResource("1_0lih2") name = &"print" +target_node_class = "" description = "Print the text to output" category = "Log" type = 2 diff --git a/addons/block_code/blocks/logic/compare.tres b/addons/block_code/blocks/logic/compare.tres index 6556645b..8e124cf7 100644 --- a/addons/block_code/blocks/logic/compare.tres +++ b/addons/block_code/blocks/logic/compare.tres @@ -11,6 +11,7 @@ items = ["==", ">", "<", ">=", "<=", "!="] [resource] script = ExtResource("1_wp40r") name = &"compare" +target_node_class = "" description = "" category = "Logic | Comparison" type = 3 diff --git a/addons/block_code/blocks/math/add.tres b/addons/block_code/blocks/math/add.tres index 6ffb4155..336e1afc 100644 --- a/addons/block_code/blocks/math/add.tres +++ b/addons/block_code/blocks/math/add.tres @@ -5,6 +5,7 @@ [resource] script = ExtResource("1_rks7c") name = &"add" +target_node_class = "" description = "" category = "Math" type = 3 diff --git a/addons/block_code/blocks/math/divide.tres b/addons/block_code/blocks/math/divide.tres index 5d4dae46..0d6f00a5 100644 --- a/addons/block_code/blocks/math/divide.tres +++ b/addons/block_code/blocks/math/divide.tres @@ -5,6 +5,7 @@ [resource] script = ExtResource("1_rhh7v") name = &"divide" +target_node_class = "" description = "" category = "Math" type = 3 diff --git a/addons/block_code/blocks/math/multiply.tres b/addons/block_code/blocks/math/multiply.tres index 285c592d..1e29b3bb 100644 --- a/addons/block_code/blocks/math/multiply.tres +++ b/addons/block_code/blocks/math/multiply.tres @@ -5,6 +5,7 @@ [resource] script = ExtResource("1_c5vny") name = &"multiply" +target_node_class = "" description = "" category = "Math" type = 3 diff --git a/addons/block_code/blocks/math/pow.tres b/addons/block_code/blocks/math/pow.tres index 654d741a..a21f3eff 100644 --- a/addons/block_code/blocks/math/pow.tres +++ b/addons/block_code/blocks/math/pow.tres @@ -5,6 +5,7 @@ [resource] script = ExtResource("1_cx5g5") name = &"pow" +target_node_class = "" description = "" category = "Math" type = 3 diff --git a/addons/block_code/blocks/math/randf_range.tres b/addons/block_code/blocks/math/randf_range.tres index 641e8b34..ea47e98e 100644 --- a/addons/block_code/blocks/math/randf_range.tres +++ b/addons/block_code/blocks/math/randf_range.tres @@ -5,6 +5,7 @@ [resource] script = ExtResource("1_03jps") name = &"randf_range" +target_node_class = "" description = "Generate a random floating point number between [i]from[/i] and [i]to[/i] inclusively" category = "Math" type = 3 diff --git a/addons/block_code/blocks/math/randi_range.tres b/addons/block_code/blocks/math/randi_range.tres index 2d00f194..6636b4d4 100644 --- a/addons/block_code/blocks/math/randi_range.tres +++ b/addons/block_code/blocks/math/randi_range.tres @@ -5,6 +5,7 @@ [resource] script = ExtResource("1_hk574") name = &"randi_range" +target_node_class = "" description = "Generate a random signed 32-bits integer number between [i]from[/i] and [i]to[/i] inclusively. [i]from[/i] and [i]to[/i] can be a negative or positive number" category = "Math" type = 3 diff --git a/addons/block_code/blocks/math/subtract.tres b/addons/block_code/blocks/math/subtract.tres index a23bc765..1284f408 100644 --- a/addons/block_code/blocks/math/subtract.tres +++ b/addons/block_code/blocks/math/subtract.tres @@ -5,6 +5,7 @@ [resource] script = ExtResource("1_n0dmm") name = &"subtract" +target_node_class = "" description = "" category = "Math" type = 3 diff --git a/addons/block_code/blocks/sounds/load_sound.tres b/addons/block_code/blocks/sounds/load_sound.tres index ddbe4fac..918ba273 100644 --- a/addons/block_code/blocks/sounds/load_sound.tres +++ b/addons/block_code/blocks/sounds/load_sound.tres @@ -5,6 +5,7 @@ [resource] script = ExtResource("1_4w4si") name = &"load_sound" +target_node_class = "" description = "Load a resource file as the audio stream" category = "Sounds" type = 2 diff --git a/addons/block_code/blocks/sounds/pause_continue_sound.tres b/addons/block_code/blocks/sounds/pause_continue_sound.tres index acac9de4..074e0352 100644 --- a/addons/block_code/blocks/sounds/pause_continue_sound.tres +++ b/addons/block_code/blocks/sounds/pause_continue_sound.tres @@ -11,6 +11,7 @@ items = ["Pause", "Continue"] [resource] script = ExtResource("1_q04gm") name = &"pause_continue_sound" +target_node_class = "" description = "Pause/Continue the audio stream" category = "Sounds" type = 2 diff --git a/addons/block_code/blocks/sounds/play_sound.tres b/addons/block_code/blocks/sounds/play_sound.tres index 128c5701..ac910d95 100644 --- a/addons/block_code/blocks/sounds/play_sound.tres +++ b/addons/block_code/blocks/sounds/play_sound.tres @@ -5,6 +5,7 @@ [resource] script = ExtResource("1_llfp1") name = &"play_sound" +target_node_class = "" description = "Play the audio stream with volume and pitch" category = "Sounds" type = 2 diff --git a/addons/block_code/blocks/sounds/stop_sound.tres b/addons/block_code/blocks/sounds/stop_sound.tres index e9c1a4a2..8233b734 100644 --- a/addons/block_code/blocks/sounds/stop_sound.tres +++ b/addons/block_code/blocks/sounds/stop_sound.tres @@ -5,6 +5,7 @@ [resource] script = ExtResource("1_rfujh") name = &"stop_sound" +target_node_class = "" description = "Stop the audio stream" category = "Sounds" type = 2 diff --git a/addons/block_code/blocks/variables/vector2.tres b/addons/block_code/blocks/variables/vector2.tres index 0da6e806..cbdcf2eb 100644 --- a/addons/block_code/blocks/variables/vector2.tres +++ b/addons/block_code/blocks/variables/vector2.tres @@ -5,6 +5,7 @@ [resource] script = ExtResource("1_ilw3v") name = &"vector2" +target_node_class = "" description = "" category = "Variables" type = 3 diff --git a/addons/block_code/code_generation/block_definition.gd b/addons/block_code/code_generation/block_definition.gd index 1daca6e0..defbf9aa 100644 --- a/addons/block_code/code_generation/block_definition.gd +++ b/addons/block_code/code_generation/block_definition.gd @@ -5,6 +5,11 @@ extends Resource const Types = preload("res://addons/block_code/types/types.gd") @export var name: StringName + +## The target node. Leaving this empty the block is considered a general block +## (for any node). +@export var target_node_class: String + @export_multiline var description: String @export var category: String @@ -25,6 +30,7 @@ const Types = preload("res://addons/block_code/types/types.gd") func _init( p_name: StringName = &"", + p_target_node_class = "", p_description: String = "", p_category: String = "", p_type: Types.BlockType = Types.BlockType.STATEMENT, @@ -36,6 +42,7 @@ func _init( p_scope: String = "", ): name = p_name + target_node_class = p_target_node_class description = p_description category = p_category type = p_type From 4349a7a3b7285bf269a2fc90c0c3730738d29424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 16 Aug 2024 11:45:31 -0300 Subject: [PATCH 164/423] Block catalog: Add getter for blocks by class As defined by the target class in the resource file. --- .../block_code/code_generation/blocks_catalog.gd | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/addons/block_code/code_generation/blocks_catalog.gd b/addons/block_code/code_generation/blocks_catalog.gd index 104c3df2..124073f5 100644 --- a/addons/block_code/code_generation/blocks_catalog.gd +++ b/addons/block_code/code_generation/blocks_catalog.gd @@ -7,6 +7,7 @@ const Util = preload("res://addons/block_code/code_generation/util.gd") const _BLOCKS_PATH = "res://addons/block_code/blocks/" static var _catalog: Dictionary +static var _by_class_name: Dictionary static func setup(): @@ -17,8 +18,14 @@ static func setup(): var definition_files = Util.get_files_in_dir_recursive(_BLOCKS_PATH, "*.tres") for file in definition_files: - var block_definition = load(file) + var block_definition: BlockDefinition = load(file) _catalog[block_definition.name] = block_definition + var target = block_definition.target_node_class + if not target: + continue + if not target in _by_class_name: + _by_class_name[target] = {} + _by_class_name[target][block_definition.name] = block_definition static func get_block(block_name: StringName): @@ -27,3 +34,10 @@ static func get_block(block_name: StringName): static func has_block(block_name: StringName): return block_name in _catalog + + +static func get_blocks_by_class(_class_name: String): + if not _class_name in _by_class_name: + return [] + var block_definitions = _by_class_name[_class_name] as Dictionary + return block_definitions.values() From 855c3dd84974eef8bec22aa4f00adb166b836f34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 16 Aug 2024 11:47:55 -0300 Subject: [PATCH 165/423] UI util: Instantiate all blocks by class For this, the previous instantiate_block is renamed to instantiate_block_by_name. --- .../ui/block_canvas/block_canvas.gd | 2 +- .../ui/picker/categories/category_factory.gd | 22 +++---- addons/block_code/ui/util.gd | 59 ++++++++++++++++--- 3 files changed, 65 insertions(+), 18 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 8fe07107..ffcc4b86 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -154,7 +154,7 @@ func clear_canvas(): func load_tree(parent: Node, node: BlockSerialization): - var scene: Block = Util.instantiate_block(node.name) + var scene: Block = Util.instantiate_block_by_name(node.name) # TODO: Remove once the data/UI decouple is done. if scene == null: diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 9ae41db1..13dc4671 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -172,39 +172,39 @@ static func get_general_blocks() -> Array[Block]: # Lifecycle for block_name in [&"ready", &"process", &"physics_process", &"queue_free"]: - b = Util.instantiate_block(block_name) + b = Util.instantiate_block_by_name(block_name) block_list.append(b) # Loops for block_name in [&"for", &"while", &"break", &"continue", &"await_scene_ready"]: - b = Util.instantiate_block(block_name) + b = Util.instantiate_block_by_name(block_name) block_list.append(b) # Logs - b = Util.instantiate_block(&"print") + b = Util.instantiate_block_by_name(&"print") block_list.append(b) # Communication for block_name in [&"define_method", &"call_method_group", &"call_method_node"]: - b = Util.instantiate_block(block_name) + b = Util.instantiate_block_by_name(block_name) block_list.append(b) for block_name in [&"add_to_group", &"add_node_to_group", &"remove_from_group", &"remove_node_from_group", &"is_in_group", &"is_node_in_group"]: - b = Util.instantiate_block(block_name) + b = Util.instantiate_block_by_name(block_name) block_list.append(b) # Variables - b = Util.instantiate_block(&"vector2") + b = Util.instantiate_block_by_name(&"vector2") block_list.append(b) # Math for block_name in [&"add", &"subtract", &"multiply", &"divide", &"pow", &"randf_range", &"randi_range", &"sin", &"cos", &"tan"]: - b = Util.instantiate_block(block_name) + b = Util.instantiate_block_by_name(block_name) block_list.append(b) # Logic for block_name in [&"if", &"else_if", &"else", &"compare", &"and", &"or", &"not"]: - b = Util.instantiate_block(block_name) + b = Util.instantiate_block_by_name(block_name) block_list.append(b) # Input @@ -212,12 +212,12 @@ static func get_general_blocks() -> Array[Block]: # Sounds for block_name in [&"load_sound", &"play_sound", &"pause_continue_sound", &"stop_sound"]: - b = Util.instantiate_block(block_name) + b = Util.instantiate_block_by_name(block_name) block_list.append(b) # Graphics for block_name in [&"viewport_width", &"viewport_height", &"viewport_center"]: - b = Util.instantiate_block(block_name) + b = Util.instantiate_block_by_name(block_name) block_list.append(b) return block_list @@ -298,6 +298,8 @@ static func blocks_from_property_list(property_list: Array, selected_props: Dict static func get_inherited_blocks(_class_name: String) -> Array[Block]: var blocks: Array[Block] = [] + blocks.append_array(Util.instantiate_blocks_for_class(_class_name)) + var current: String = _class_name while current != "": diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index 13d602eb..d6fb72a0 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -12,13 +12,7 @@ const SCENE_PER_TYPE = { } -static func instantiate_block(block_name: StringName) -> Block: - BlocksCatalog.setup() - var block_definition: BlockDefinition = BlocksCatalog.get_block(block_name) - if block_definition == null: - push_error("The block %s is not in the catalog yet!" % block_name) - return - +static func instantiate_block(block_definition: BlockDefinition) -> Block: var scene = SCENE_PER_TYPE[block_definition.type] var b = scene.instantiate() b.block_name = block_definition.name @@ -39,6 +33,57 @@ static func instantiate_block(block_name: StringName) -> Block: return b +static func instantiate_block_by_name(block_name: StringName) -> Block: + BlocksCatalog.setup() + var block_definition: BlockDefinition = BlocksCatalog.get_block(block_name) + if block_definition == null: + push_error("The block %s is not in the catalog yet!" % block_name) + return + return instantiate_block(block_definition) + + +static func _get_builtin_parents(_class_name: String) -> Array[String]: + var parents: Array[String] = [] + var current = _class_name + + while current != "": + parents.append(current) + current = ClassDB.get_parent_class(current) + + return parents + + +static func _get_custom_parent_class_name(_custom_class_name: String) -> String: + for class_dict in ProjectSettings.get_global_class_list(): + if class_dict.class != _custom_class_name: + continue + var script = load(class_dict.path) + var builtin_class = script.get_instance_base_type() + return builtin_class + return "Node" + + +static func _get_parents(_class_name: String) -> Array[String]: + if ClassDB.class_exists(_class_name): + return _get_builtin_parents(_class_name) + var parents: Array[String] = [_class_name] + var _parent_class_name = _get_custom_parent_class_name(_class_name) + parents.append_array(_get_builtin_parents(_parent_class_name)) + return parents + + +static func instantiate_blocks_for_class(_class_name: String) -> Array[Block]: + BlocksCatalog.setup() + + var blocks: Array[Block] = [] + for subclass in _get_parents(_class_name): + for block_definition in BlocksCatalog.get_blocks_by_class(subclass): + var b = instantiate_block(block_definition) + blocks.append(b) + + return blocks + + ## Polyfill of Node.is_part_of_edited_scene(), available to GDScript in Godot 4.3+. static func node_is_part_of_edited_scene(node: Node) -> bool: if not Engine.is_editor_hint(): From 203b1de021a8ab2afb0ca440321e51f110e047ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 16 Aug 2024 11:17:54 -0300 Subject: [PATCH 166/423] Add CharacterBody2D block definitions And remove them from the category factory. Also add a default value for speed in the characterbody2d_move block. https://phabricator.endlessm.com/T35591 --- .../blocks/input/characterbody2d_move.tres | 31 +++++++++++++++++++ .../characterbody2d_move_and_slide.tres | 17 ++++++++++ .../ui/picker/categories/category_factory.gd | 31 ------------------- 3 files changed, 48 insertions(+), 31 deletions(-) create mode 100644 addons/block_code/blocks/input/characterbody2d_move.tres create mode 100644 addons/block_code/blocks/physics/characterbody2d_move_and_slide.tres diff --git a/addons/block_code/blocks/input/characterbody2d_move.tres b/addons/block_code/blocks/input/characterbody2d_move.tres new file mode 100644 index 00000000..07614611 --- /dev/null +++ b/addons/block_code/blocks/input/characterbody2d_move.tres @@ -0,0 +1,31 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://cu3ru61vg6bx5"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_btxic"] + +[resource] +script = ExtResource("1_btxic") +name = &"characterbody2d_move" +target_node_class = "CharacterBody2D" +description = "" +category = "Input" +type = 2 +variant_type = 0 +display_template = "Move with keys {up: STRING} {down: STRING} {left: STRING} {right: STRING} with speed {speed: VECTOR2}" +code_template = "var dir = Vector2() +dir.x += float(Input.is_key_pressed(OS.find_keycode_from_string({right}))) +dir.x -= float(Input.is_key_pressed(OS.find_keycode_from_string({left}))) +dir.y += float(Input.is_key_pressed(OS.find_keycode_from_string({down}))) +dir.y -= float(Input.is_key_pressed(OS.find_keycode_from_string({up}))) +dir = dir.normalized() +velocity = dir*{speed} +move_and_slide() +" +defaults = { +"down": "S", +"left": "A", +"right": "D", +"speed": Vector2(100, 100), +"up": "W" +} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/physics/characterbody2d_move_and_slide.tres b/addons/block_code/blocks/physics/characterbody2d_move_and_slide.tres new file mode 100644 index 00000000..89448e21 --- /dev/null +++ b/addons/block_code/blocks/physics/characterbody2d_move_and_slide.tres @@ -0,0 +1,17 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://cp6ak6wea8ogh"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_e3r2r"] + +[resource] +script = ExtResource("1_e3r2r") +name = &"characterbody2d_move_and_slide" +target_node_class = "CharacterBody2D" +description = "" +category = "Physics | Velocity" +type = 2 +variant_type = 0 +display_template = "Move and slide" +code_template = "move_and_slide()" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 13dc4671..9549012d 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -485,37 +485,6 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: block_list.append(b) "CharacterBody2D": - var b = BLOCKS["statement_block"].instantiate() - b.block_name = "characterbody2d_move" - b.block_type = Types.BlockType.STATEMENT - b.block_format = "Move with keys {up: STRING} {down: STRING} {left: STRING} {right: STRING} with speed {speed: VECTOR2}" - b.statement = ( - "var dir = Vector2()\n" - + "dir.x += float(Input.is_key_pressed(OS.find_keycode_from_string({right})))\n" - + "dir.x -= float(Input.is_key_pressed(OS.find_keycode_from_string({left})))\n" - + "dir.y += float(Input.is_key_pressed(OS.find_keycode_from_string({down})))\n" - + "dir.y -= float(Input.is_key_pressed(OS.find_keycode_from_string({up})))\n" - + "dir = dir.normalized()\n" - + "velocity = dir*{speed}\n" - + "move_and_slide()" - ) - b.defaults = { - "up": "W", - "down": "S", - "left": "A", - "right": "D", - } - b.category = "Input" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "characterbody2d_move_and_slide" - b.block_type = Types.BlockType.STATEMENT - b.block_format = "Move and slide" - b.statement = "move_and_slide()" - b.category = "Physics | Velocity" - block_list.append(b) - props = { "velocity": {"category": "Physics | Velocity"}, } From 4a1e52a70db944b911a6e483d9dcfb4fa4002e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 16 Aug 2024 14:29:51 -0300 Subject: [PATCH 167/423] Add Area2D block definitions And change the body type from NODE_PATH to OBJECT, as in previous definitions. https://phabricator.endlessm.com/T35591 --- .../communication/area2d_on_entered.tres | 18 ++++++++++++++++ .../communication/area2d_on_exited.tres | 18 ++++++++++++++++ .../ui/picker/categories/category_factory.gd | 21 ------------------- tests/test_instruction_tree.gd | 4 +--- 4 files changed, 37 insertions(+), 24 deletions(-) create mode 100644 addons/block_code/blocks/communication/area2d_on_entered.tres create mode 100644 addons/block_code/blocks/communication/area2d_on_exited.tres diff --git a/addons/block_code/blocks/communication/area2d_on_entered.tres b/addons/block_code/blocks/communication/area2d_on_entered.tres new file mode 100644 index 00000000..370331e6 --- /dev/null +++ b/addons/block_code/blocks/communication/area2d_on_entered.tres @@ -0,0 +1,18 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://de4k7t7uqws1j"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_xotf5"] + +[resource] +script = ExtResource("1_xotf5") +name = &"area2d_on_entered" +target_node_class = "Area2D" +description = "" +category = "Communication | Methods" +type = 1 +variant_type = 0 +display_template = "On [body: OBJECT] entered" +code_template = "func _on_body_entered(body: Node2D): +" +defaults = {} +signal_name = "body_entered" +scope = "" diff --git a/addons/block_code/blocks/communication/area2d_on_exited.tres b/addons/block_code/blocks/communication/area2d_on_exited.tres new file mode 100644 index 00000000..3236546f --- /dev/null +++ b/addons/block_code/blocks/communication/area2d_on_exited.tres @@ -0,0 +1,18 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://b36nq4mau6lu6"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_21qth"] + +[resource] +script = ExtResource("1_21qth") +name = &"area2d_on_exited" +target_node_class = "Area2D" +description = "" +category = "Communication | Methods" +type = 1 +variant_type = 0 +display_template = "On [body: OBJECT] exited" +code_template = "func _on_body_exited(body: Node2D): +" +defaults = {} +signal_name = "body_entered" +scope = "" diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 9549012d..4d7a3f3e 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -463,27 +463,6 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: b.category = "Graphics | Animation" block_list.append(b) - "Area2D": - for verb in ["entered", "exited"]: - var b = BLOCKS["entry_block"].instantiate() - b.block_name = "area2d_on_%s" % verb - b.block_format = "On [body: NODE_PATH] %s" % [verb] - # HACK: Blocks refer to nodes by path but the callback receives the node itself; - # convert to path - b.statement = ( - ( - """ - func _on_body_%s(_body: Node2D): - var body: NodePath = _body.get_path() - """ - . dedent() - ) - % [verb] - ) - b.signal_name = "body_%s" % [verb] - b.category = "Communication | Methods" - block_list.append(b) - "CharacterBody2D": props = { "velocity": {"category": "Physics | Velocity"}, diff --git a/tests/test_instruction_tree.gd b/tests/test_instruction_tree.gd index 8f83a9be..81e17fab 100644 --- a/tests/test_instruction_tree.gd +++ b/tests/test_instruction_tree.gd @@ -208,9 +208,7 @@ func test_signal_script(): extends Area2D - - func _on_body_entered(_body: Node2D): - var body: NodePath = _body.get_path() + func _on_body_entered(body: Node2D): print({text}) From 2fbb3cb9a345a7f0c071213ede1f119983c72a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 16 Aug 2024 14:42:49 -0300 Subject: [PATCH 168/423] Add AnimationPlayer block definitions https://phabricator.endlessm.com/T35591 --- .../graphics/animationplayer_is_playing.tres | 17 +++++++ .../graphics/animationplayer_pause.tres | 17 +++++++ .../blocks/graphics/animationplayer_play.tres | 29 ++++++++++++ .../blocks/graphics/animationplayer_stop.tres | 17 +++++++ .../ui/picker/categories/category_factory.gd | 45 ------------------- 5 files changed, 80 insertions(+), 45 deletions(-) create mode 100644 addons/block_code/blocks/graphics/animationplayer_is_playing.tres create mode 100644 addons/block_code/blocks/graphics/animationplayer_pause.tres create mode 100644 addons/block_code/blocks/graphics/animationplayer_play.tres create mode 100644 addons/block_code/blocks/graphics/animationplayer_stop.tres diff --git a/addons/block_code/blocks/graphics/animationplayer_is_playing.tres b/addons/block_code/blocks/graphics/animationplayer_is_playing.tres new file mode 100644 index 00000000..1e3f6578 --- /dev/null +++ b/addons/block_code/blocks/graphics/animationplayer_is_playing.tres @@ -0,0 +1,17 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://mg4y3o0rsqd5"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_xr50b"] + +[resource] +script = ExtResource("1_xr50b") +name = &"animationplayer_is_playing" +target_node_class = "AnimationPlayer" +description = "Check if an animation is currently playing." +category = "Graphics | Animation" +type = 3 +variant_type = 1 +display_template = "Is playing" +code_template = "is_playing()" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/graphics/animationplayer_pause.tres b/addons/block_code/blocks/graphics/animationplayer_pause.tres new file mode 100644 index 00000000..15f80903 --- /dev/null +++ b/addons/block_code/blocks/graphics/animationplayer_pause.tres @@ -0,0 +1,17 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://clopo7gmje5a"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_2enqv"] + +[resource] +script = ExtResource("1_2enqv") +name = &"animationplayer_pause" +target_node_class = "AnimationPlayer" +description = "Pause the currently playing animation." +category = "Graphics | Animation" +type = 2 +variant_type = 0 +display_template = "Pause" +code_template = "pause()" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/graphics/animationplayer_play.tres b/addons/block_code/blocks/graphics/animationplayer_play.tres new file mode 100644 index 00000000..43bbce1e --- /dev/null +++ b/addons/block_code/blocks/graphics/animationplayer_play.tres @@ -0,0 +1,29 @@ +[gd_resource type="Resource" load_steps=4 format=3 uid="uid://c5e1byehtxwc0"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_emeuv"] +[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="1_xu43h"] + +[sub_resource type="Resource" id="Resource_vnp2w"] +script = ExtResource("1_xu43h") +selected = 0 +items = ["ahead", "backwards"] + +[resource] +script = ExtResource("1_emeuv") +name = &"animationplayer_play" +target_node_class = "AnimationPlayer" +description = "Play the animation." +category = "Graphics | Animation" +type = 2 +variant_type = 0 +display_template = "Play {animation: STRING} {direction: OPTION}" +code_template = "if \"{direction}\" == \"ahead\": + play({animation}) +else: + play_backwards({animation}) +" +defaults = { +"direction": SubResource("Resource_vnp2w") +} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/graphics/animationplayer_stop.tres b/addons/block_code/blocks/graphics/animationplayer_stop.tres new file mode 100644 index 00000000..35369a87 --- /dev/null +++ b/addons/block_code/blocks/graphics/animationplayer_stop.tres @@ -0,0 +1,17 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://b4v00oxoxbfet"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_wp8gr"] + +[resource] +script = ExtResource("1_wp8gr") +name = &"animationplayer_stop" +target_node_class = "AnimationPlayer" +description = "Stop the currently playing animation." +category = "Graphics | Animation" +type = 2 +variant_type = 0 +display_template = "Stop" +code_template = "stop()" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 4d7a3f3e..94e877d6 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -418,51 +418,6 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: }, } - "AnimationPlayer": - var b = BLOCKS["statement_block"].instantiate() - b.block_name = "animationplayer_play" - b.block_format = "Play {animation: STRING} {direction: OPTION}" - b.statement = ( - """ - if "{direction}" == "ahead": - play({animation}) - else: - play_backwards({animation}) - """ - . dedent() - ) - b.defaults = { - "direction": OptionData.new(["ahead", "backwards"]), - } - b.tooltip_text = "Play the animation." - b.category = "Graphics | Animation" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "animationplayer_pause" - b.block_format = "Pause" - b.statement = "pause()" - b.tooltip_text = "Pause the currently playing animation." - b.category = "Graphics | Animation" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "animationplayer_stop" - b.block_format = "Stop" - b.statement = "stop()" - b.tooltip_text = "Stop the currently playing animation." - b.category = "Graphics | Animation" - block_list.append(b) - - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "animationplayer_is_playing" - b.variant_type = TYPE_BOOL - b.block_format = "Is playing" - b.statement = "is_playing()" - b.tooltip_text = "Check if an animation is currently playing." - b.category = "Graphics | Animation" - block_list.append(b) - "CharacterBody2D": props = { "velocity": {"category": "Physics | Velocity"}, From 9514bbbf0f0719f34c3b65ee512460e691bc8c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 16 Aug 2024 14:48:18 -0300 Subject: [PATCH 169/423] Add AudioStreamPlayer block definitions https://phabricator.endlessm.com/T35591 --- .../blocks/sounds/audiostreamplayer_play.tres | 17 +++++++++++++++++ .../blocks/sounds/audiostreamplayer_stop.tres | 17 +++++++++++++++++ .../ui/picker/categories/category_factory.gd | 16 ---------------- 3 files changed, 34 insertions(+), 16 deletions(-) create mode 100644 addons/block_code/blocks/sounds/audiostreamplayer_play.tres create mode 100644 addons/block_code/blocks/sounds/audiostreamplayer_stop.tres diff --git a/addons/block_code/blocks/sounds/audiostreamplayer_play.tres b/addons/block_code/blocks/sounds/audiostreamplayer_play.tres new file mode 100644 index 00000000..1e574832 --- /dev/null +++ b/addons/block_code/blocks/sounds/audiostreamplayer_play.tres @@ -0,0 +1,17 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://bxjjml7u3rokv"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_vyl5w"] + +[resource] +script = ExtResource("1_vyl5w") +name = &"audiostreamplayer_play" +target_node_class = "AudioStreamPlayer" +description = "Play the audio stream" +category = "Sounds" +type = 2 +variant_type = 0 +display_template = "Play" +code_template = "play()" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/blocks/sounds/audiostreamplayer_stop.tres b/addons/block_code/blocks/sounds/audiostreamplayer_stop.tres new file mode 100644 index 00000000..d95f6a31 --- /dev/null +++ b/addons/block_code/blocks/sounds/audiostreamplayer_stop.tres @@ -0,0 +1,17 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://ib16grbtduab"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_db4g2"] + +[resource] +script = ExtResource("1_db4g2") +name = &"audiostreamplayer_stop" +target_node_class = "AudioStreamPlayer" +description = "Stop the audio stream" +category = "Sounds" +type = 2 +variant_type = 0 +display_template = "Stop" +code_template = "stop()" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 94e877d6..a10afce2 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -394,22 +394,6 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: } "AudioStreamPlayer": - var b = BLOCKS["statement_block"].instantiate() - b.block_name = "audiostreamplayer_play" - b.block_format = "Play" - b.statement = "play()" - b.tooltip_text = "Play the audio stream" - b.category = "Sounds" - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "audiostreamplayer_stop" - b.block_format = "Stop" - b.statement = "stop()" - b.tooltip_text = "Stop the audio stream" - b.category = "Sounds" - block_list.append(b) - props = { "stream_paused": { From 575e7c80226ddac23ccd6838c236de02c6937ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 16 Aug 2024 14:58:20 -0300 Subject: [PATCH 170/423] Add RigidBody2D block definitions https://phabricator.endlessm.com/T35591 --- .../communication/rigidbody2d_on_entered.tres | 18 ++++++++++ .../communication/rigidbody2d_on_exited.tres | 18 ++++++++++ .../rigidbody2d_physics_position.tres | 22 ++++++++++++ .../ui/picker/categories/category_factory.gd | 36 ------------------- 4 files changed, 58 insertions(+), 36 deletions(-) create mode 100644 addons/block_code/blocks/communication/rigidbody2d_on_entered.tres create mode 100644 addons/block_code/blocks/communication/rigidbody2d_on_exited.tres create mode 100644 addons/block_code/blocks/transform/rigidbody2d_physics_position.tres diff --git a/addons/block_code/blocks/communication/rigidbody2d_on_entered.tres b/addons/block_code/blocks/communication/rigidbody2d_on_entered.tres new file mode 100644 index 00000000..5be0ca5c --- /dev/null +++ b/addons/block_code/blocks/communication/rigidbody2d_on_entered.tres @@ -0,0 +1,18 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://dl1xd1jit2mlp"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_v2421"] + +[resource] +script = ExtResource("1_v2421") +name = &"rigidbody2d_on_entered" +target_node_class = "RigidBody2D" +description = "" +category = "Communication | Methods" +type = 1 +variant_type = 0 +display_template = "On [body: OBJECT] entered" +code_template = "func _on_body_entered(body: Node2D): +" +defaults = {} +signal_name = "body_entered" +scope = "" diff --git a/addons/block_code/blocks/communication/rigidbody2d_on_exited.tres b/addons/block_code/blocks/communication/rigidbody2d_on_exited.tres new file mode 100644 index 00000000..f16eb085 --- /dev/null +++ b/addons/block_code/blocks/communication/rigidbody2d_on_exited.tres @@ -0,0 +1,18 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://c15ymi1kxb570"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_sahiu"] + +[resource] +script = ExtResource("1_sahiu") +name = &"rigidbody2d_on_exited" +target_node_class = "RigidBody2D" +description = "" +category = "Communication | Methods" +type = 1 +variant_type = 0 +display_template = "On [body: OBJECT] exited" +code_template = "func _on_body_exited(body: Node2D): +" +defaults = {} +signal_name = "body_exited" +scope = "" diff --git a/addons/block_code/blocks/transform/rigidbody2d_physics_position.tres b/addons/block_code/blocks/transform/rigidbody2d_physics_position.tres new file mode 100644 index 00000000..8059830d --- /dev/null +++ b/addons/block_code/blocks/transform/rigidbody2d_physics_position.tres @@ -0,0 +1,22 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://ses5486g56q"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_72i54"] + +[resource] +script = ExtResource("1_72i54") +name = &"rigidbody2d_physics_position" +target_node_class = "RigidBody2D" +description = "" +category = "Transform | Position" +type = 2 +variant_type = 0 +display_template = "Set Physics Position {position: VECTOR2}" +code_template = "PhysicsServer2D.body_set_state( + get_rid(), + PhysicsServer2D.BODY_STATE_TRANSFORM, + Transform2D.IDENTITY.translated({position}) +) +" +defaults = {} +signal_name = "" +scope = "" diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index a10afce2..7493963e 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -351,42 +351,6 @@ static func get_built_in_blocks(_class_name: String) -> Array[Block]: } "RigidBody2D": - for verb in ["entered", "exited"]: - var b = BLOCKS["entry_block"].instantiate() - b.block_name = "rigidbody2d_on_%s" % verb - b.block_format = "On [body: NODE_PATH] %s" % [verb] - # HACK: Blocks refer to nodes by path but the callback receives the node itself; - # convert to path - b.statement = ( - ( - """ - func _on_body_%s(_body: Node): - var body: NodePath = _body.get_path() - """ - . dedent() - ) - % [verb] - ) - b.signal_name = "body_%s" % [verb] - b.category = "Communication | Methods" - block_list.append(b) - - var b = BLOCKS["statement_block"].instantiate() - b.block_name = "rigidbody2d_physics_position" - b.block_format = "Set Physics Position {position: VECTOR2}" - b.statement = ( - """ - PhysicsServer2D.body_set_state( - get_rid(), - PhysicsServer2D.BODY_STATE_TRANSFORM, - Transform2D.IDENTITY.translated({position}) - ) - """ - . dedent() - ) - b.category = "Transform | Position" - block_list.append(b) - props = { "mass": {"category": "Physics | Mass"}, "linear_velocity": {"category": "Physics | Velocity"}, From dd1e0e9aca642dda48a741861f5e592b25b9d4ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 19 Aug 2024 17:25:03 -0300 Subject: [PATCH 171/423] Blocks catalog: Add property blocks Port the property setter/changer/getter blocks to the new block definition. These are not loaded from resource files, they are defined in code. https://phabricator.endlessm.com/T35591 --- .../code_generation/blocks_catalog.gd | 159 +++++++++++++++++- .../ui/picker/categories/category_factory.gd | 152 +---------------- 2 files changed, 154 insertions(+), 157 deletions(-) diff --git a/addons/block_code/code_generation/blocks_catalog.gd b/addons/block_code/code_generation/blocks_catalog.gd index 124073f5..c41e7a68 100644 --- a/addons/block_code/code_generation/blocks_catalog.gd +++ b/addons/block_code/code_generation/blocks_catalog.gd @@ -6,16 +6,82 @@ const Util = preload("res://addons/block_code/code_generation/util.gd") const _BLOCKS_PATH = "res://addons/block_code/blocks/" -static var _catalog: Dictionary -static var _by_class_name: Dictionary +const _FALLBACK_SET_FOR_TYPE = { + TYPE_BOOL: false, + TYPE_INT: 0, + TYPE_FLOAT: 0.0, + TYPE_VECTOR2: Vector2(0, 0), + TYPE_COLOR: Color.DARK_ORANGE, +} +const _FALLBACK_CHANGE_FOR_TYPE = { + TYPE_BOOL: true, + TYPE_INT: 1, + TYPE_FLOAT: 1.0, + TYPE_VECTOR2: Vector2(1, 1), + TYPE_COLOR: Color.DARK_ORANGE, +} -static func setup(): - if _catalog: - return +const _SETTINGS_FOR_CLASS_PROPERTY = { + "Node2D": + { + "position": + { + "category": "Transform | Position", + "default_set": Vector2(100, 100), + "default_change": Vector2(1, 1), + }, + "rotation_degrees": + { + "category": "Transform | Rotation", + "default_set": 45, + "default_change": 1, + }, + "scale": + { + "category": "Transform | Scale", + "default_set": Vector2(2, 2), + "default_change": Vector2(0.1, 0.1), + }, + }, + "CanvasItem": + { + "modulate": + { + "category": "Graphics | Modulate", + "has_change": false, + }, + "visible": + { + "category": "Graphics | Visibility", + "has_change": false, + }, + }, + "RigidBody2D": + { + "mass": {"category": "Physics | Mass"}, + "linear_velocity": {"category": "Physics | Velocity"}, + "angular_velocity": {"category": "Physics | Velocity"}, + }, + "AudioStreamPlayer": + { + "stream_paused": + { + "category": "Sounds", + "has_change": false, + }, + }, + "CharacterBody2D": + { + "velocity": {"category": "Physics | Velocity"}, + }, +} + +static var _catalog: Dictionary +static var _by_class_name: Dictionary - _catalog = {} +static func _setup_definitions_from_files(): var definition_files = Util.get_files_in_dir_recursive(_BLOCKS_PATH, "*.tres") for file in definition_files: var block_definition: BlockDefinition = load(file) @@ -28,6 +94,87 @@ static func setup(): _by_class_name[target][block_definition.name] = block_definition +static func _add_property_definitions(_class_name: String, property_list: Array[Dictionary], property_settings: Dictionary): + for property in property_list: + if not property.name in property_settings: + continue + var block_settings = property_settings[property.name] + var type_string: String = Types.VARIANT_TYPE_TO_STRING[property.type] + + if not _class_name in _by_class_name: + _by_class_name[_class_name] = {} + + # Setter + var block_definition: BlockDefinition = ( + BlockDefinition + . new( + &"%s_set_%s" % [_class_name, property.name], + _class_name, + "Set the %s property" % property.name, + block_settings.category, + Types.BlockType.STATEMENT, + TYPE_NIL, + "Set %s to {value: %s}" % [property.name.capitalize(), type_string], + "%s = {value}" % property.name, + {"value": block_settings.get("default_set", _FALLBACK_SET_FOR_TYPE[property.type])}, + ) + ) + _catalog[block_definition.name] = block_definition + _by_class_name[_class_name][block_definition.name] = block_definition + + # Changer + if block_settings.get("has_change", true): + block_definition = ( + BlockDefinition + . new( + &"%s_change_%s" % [_class_name, property.name], + _class_name, + "Change the %s property" % property.name, + block_settings.category, + Types.BlockType.STATEMENT, + TYPE_NIL, + "Change %s by {value: %s}" % [property.name.capitalize(), type_string], + "%s += {value}" % property.name, + {"value": block_settings.get("default_change", _FALLBACK_CHANGE_FOR_TYPE[property.type])}, + ) + ) + _catalog[block_definition.name] = block_definition + _by_class_name[_class_name][block_definition.name] = block_definition + + # Getter + block_definition = ( + BlockDefinition + . new( + &"%s_get_%s" % [_class_name, property.name], + _class_name, + "The %s property" % property.name, + block_settings.category, + Types.BlockType.VALUE, + property.type, + "%s" % property.name.capitalize(), + "%s" % property.name, + ) + ) + _catalog[block_definition.name] = block_definition + _by_class_name[_class_name][block_definition.name] = block_definition + + +static func _setup_properties_for_class(): + for _class_name in _SETTINGS_FOR_CLASS_PROPERTY: + var property_list = ClassDB.class_get_property_list(_class_name, true) + var property_settings = _SETTINGS_FOR_CLASS_PROPERTY[_class_name] + _add_property_definitions(_class_name, property_list, property_settings) + + +static func setup(): + if _catalog: + return + + _catalog = {} + _setup_definitions_from_files() + _setup_properties_for_class() + + static func get_block(block_name: StringName): return _catalog.get(block_name) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 7493963e..3315e6f6 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -223,158 +223,8 @@ static func get_general_blocks() -> Array[Block]: return block_list -static func property_to_blocklist(property: Dictionary) -> Array[Block]: - var block_list: Array[Block] = [] - - var variant_type = property.type - - const FALLBACK_SET_FOR_TYPE = { - TYPE_BOOL: false, - TYPE_INT: "0", - TYPE_FLOAT: "0", - TYPE_VECTOR2: "0,0", - TYPE_COLOR: "DARK_ORANGE", - } - - const FALLBACK_CHANGE_FOR_TYPE = { - TYPE_BOOL: true, - TYPE_INT: "1", - TYPE_FLOAT: "1", - TYPE_VECTOR2: "1,1", - TYPE_COLOR: "DARK_ORANGE", - } - - if variant_type: - var type_string: String = Types.VARIANT_TYPE_TO_STRING[variant_type] - - var b = BLOCKS["statement_block"].instantiate() - b.block_name = "set_prop_%s" % property.name - b.block_format = "Set %s to {value: %s}" % [property.name.capitalize(), type_string] - b.statement = "%s = {value}" % property.name - var default_set = property.get("default_set", FALLBACK_SET_FOR_TYPE.get(variant_type, "")) - b.defaults = {"value": default_set} - b.category = property.category - block_list.append(b) - - if property.get("has_change", true): - b = BLOCKS["statement_block"].instantiate() - b.block_name = "change_prop_%s" % property.name - b.block_format = "Change %s by {value: %s}" % [property.name.capitalize(), type_string] - b.statement = "%s += {value}" % property.name - var default_change = property.get("default_change", FALLBACK_CHANGE_FOR_TYPE[variant_type]) - b.defaults = {"value": default_change} - b.category = property.category - block_list.append(b) - - b = BLOCKS["parameter_block"].instantiate() - b.block_name = "get_prop_%s" % property.name - b.variant_type = variant_type - b.block_format = "%s" % property.name.capitalize() - b.statement = "%s" % property.name - b.category = property.category - block_list.append(b) - - return block_list - - -static func blocks_from_property_list(property_list: Array, selected_props: Dictionary) -> Array[Block]: - var block_list: Array[Block] - - for selected_property in selected_props: - var found_prop - for prop in property_list: - if selected_property == prop.name: - found_prop = prop - found_prop.merge(selected_props[selected_property]) - break - if found_prop: - block_list.append_array(property_to_blocklist(found_prop)) - else: - push_warning("No property matching %s found in %s" % [selected_property, property_list]) - - return block_list - - static func get_inherited_blocks(_class_name: String) -> Array[Block]: - var blocks: Array[Block] = [] - - blocks.append_array(Util.instantiate_blocks_for_class(_class_name)) - - var current: String = _class_name - - while current != "": - blocks.append_array(get_built_in_blocks(current)) - current = ClassDB.get_parent_class(current) - - return blocks - - -static func get_built_in_blocks(_class_name: String) -> Array[Block]: - var props: Dictionary = {} - var block_list: Array[Block] = [] - - match _class_name: - "Node2D": - props = { - "position": - { - "category": "Transform | Position", - "default_set": "100,100", - "default_change": "1,1", - }, - "rotation_degrees": - { - "category": "Transform | Rotation", - "default_set": "45", - "default_change": "1", - }, - "scale": - { - "category": "Transform | Scale", - "default_set": "2,2", - "default_change": "0.1,0.1", - }, - } - - "CanvasItem": - props = { - "modulate": - { - "category": "Graphics | Modulate", - "has_change": false, - }, - "visible": - { - "category": "Graphics | Visibility", - "has_change": false, - }, - } - - "RigidBody2D": - props = { - "mass": {"category": "Physics | Mass"}, - "linear_velocity": {"category": "Physics | Velocity"}, - "angular_velocity": {"category": "Physics | Velocity"}, - } - - "AudioStreamPlayer": - props = { - "stream_paused": - { - "category": "Sounds", - "has_change": false, - }, - } - - "CharacterBody2D": - props = { - "velocity": {"category": "Physics | Velocity"}, - } - - var prop_list = ClassDB.class_get_property_list(_class_name, true) - block_list.append_array(blocks_from_property_list(prop_list, props)) - - return block_list + return Util.instantiate_blocks_for_class(_class_name) static func _get_input_blocks() -> Array[Block]: From 768de50eeb9fbd6899228a8093a9a0ab5ac19ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 19 Aug 2024 17:28:48 -0300 Subject: [PATCH 172/423] Simple nodes: Port custom blocks Add a way in the blocks catalog to add custom blocks. Port SimpleScoring and SimpleCharacter to the new block definitions. Change the picker logic to instantiate these blocks. https://phabricator.endlessm.com/T35591 --- .../code_generation/blocks_catalog.gd | 18 ++++++ .../simple_character/simple_character.gd | 56 ++++++++++--------- .../simple_scoring/simple_scoring.gd | 45 ++++++++------- addons/block_code/ui/picker/picker.gd | 11 ++-- 4 files changed, 76 insertions(+), 54 deletions(-) diff --git a/addons/block_code/code_generation/blocks_catalog.gd b/addons/block_code/code_generation/blocks_catalog.gd index c41e7a68..233f5508 100644 --- a/addons/block_code/code_generation/blocks_catalog.gd +++ b/addons/block_code/code_generation/blocks_catalog.gd @@ -188,3 +188,21 @@ static func get_blocks_by_class(_class_name: String): return [] var block_definitions = _by_class_name[_class_name] as Dictionary return block_definitions.values() + + +static func add_custom_blocks( + _class_name, + block_definitions: Array[BlockDefinition] = [], + property_list: Array[Dictionary] = [], + property_settings: Dictionary = {}, +): + setup() + + if not _class_name in _by_class_name: + _by_class_name[_class_name] = {} + + for block_definition in block_definitions: + _catalog[block_definition.name] = block_definition + _by_class_name[_class_name][block_definition.name] = block_definition + + _add_property_definitions(_class_name, property_list, property_settings) diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index 3eb8fcee..dffaff35 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -2,7 +2,8 @@ class_name SimpleCharacter extends CharacterBody2D -const CategoryFactory = preload("res://addons/block_code/ui/picker/categories/category_factory.gd") +const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") +const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") const Types = preload("res://addons/block_code/types/types.gd") @export var texture: Texture2D: @@ -117,35 +118,38 @@ func move_with_player_buttons(player: String, kind: String, delta: float): move_and_slide() -static func get_custom_blocks() -> Array[Block]: - var b: Block - var block_list: Array[Block] = [] +static func setup_custom_blocks(): + var _class_name = "SimpleCharacter" + var block_list: Array[BlockDefinition] = [] # Movement - b = CategoryFactory.BLOCKS["statement_block"].instantiate() - b.block_name = "simplecharacter_move" - b.block_type = Types.BlockType.STATEMENT - b.block_format = "Move with {player: OPTION} buttons as {kind: OPTION}" + var block_definition: BlockDefinition = BlockDefinition.new() + block_definition.name = &"simplecharacter_move" + block_definition.target_node_class = _class_name + block_definition.category = "Input" + block_definition.type = Types.BlockType.STATEMENT + block_definition.display_template = "Move with {player: OPTION} buttons as {kind: OPTION}" # TODO: delta here is assumed to be the parameter name of # the _process or _physics_process method: - b.statement = 'move_with_player_buttons("{player}", "{kind}", delta)' - b.defaults = { + block_definition.code_template = 'move_with_player_buttons("{player}", "{kind}", delta)' + block_definition.defaults = { "player": OptionData.new(["player_1", "player_2"]), "kind": OptionData.new(["top-down", "platformer", "spaceship"]), } - b.category = "Input" - block_list.append(b) - - var property_blocks = ( - CategoryFactory - . property_to_blocklist( - { - "name": "speed", - "type": TYPE_VECTOR2, - "category": "Physics | Velocity", - } - ) - ) - block_list.append_array(property_blocks) - - return block_list + block_list.append(block_definition) + + var property_list: Array[Dictionary] = [ + { + "name": "speed", + "type": TYPE_VECTOR2, + }, + ] + + var property_settings = { + "speed": + { + "category": "Physics | Velocity", + }, + } + + BlocksCatalog.add_custom_blocks(_class_name, block_list, property_list, property_settings) diff --git a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd index dcb2114a..185fcba9 100644 --- a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd +++ b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd @@ -2,7 +2,8 @@ class_name SimpleScoring extends CanvasLayer -const CategoryFactory = preload("res://addons/block_code/ui/picker/categories/category_factory.gd") +const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") +const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") const Types = preload("res://addons/block_code/types/types.gd") @export var score_left: int: @@ -95,25 +96,27 @@ func set_player_score(player: String, score: int): _score_labels[player].text = str(score) -static func get_custom_blocks() -> Array[Block]: - var b: Block - var block_list: Array[Block] = [] +static func setup_custom_blocks(): + var _class_name = "SimpleScoring" + var block_list: Array[BlockDefinition] = [] for player in _POSITIONS_FOR_PLAYER: - b = CategoryFactory.BLOCKS["statement_block"].instantiate() - b.block_name = "simplescoring_set_score" - b.block_type = Types.BlockType.STATEMENT - b.block_format = "Set player %s score to {score: INT}" % player - b.statement = "score_%s = {score}" % _POSITIONS_FOR_PLAYER[player] - b.category = "Info | Score" - block_list.append(b) - - b = CategoryFactory.BLOCKS["statement_block"].instantiate() - b.block_name = "simplescoring_change_score" - b.block_type = Types.BlockType.STATEMENT - b.block_format = "Change player %s score by {score: INT}" % player - b.statement = "score_%s += {score}" % _POSITIONS_FOR_PLAYER[player] - b.category = "Info | Score" - block_list.append(b) - - return block_list + var block_definition: BlockDefinition = BlockDefinition.new() + block_definition.name = &"simplescoring_set_score_player_%s" % player + block_definition.target_node_class = _class_name + block_definition.category = "Info | Score" + block_definition.type = Types.BlockType.STATEMENT + block_definition.display_template = "Set player %s score to {score: INT}" % player + block_definition.code_template = "score_%s = {score}" % _POSITIONS_FOR_PLAYER[player] + block_list.append(block_definition) + + block_definition = BlockDefinition.new() + block_definition.name = &"simplescoring_change_score_player_%s" % player + block_definition.target_node_class = _class_name + block_definition.category = "Info | Score" + block_definition.type = Types.BlockType.STATEMENT + block_definition.display_template = "Change player %s score by {score: INT}" % player + block_definition.code_template = "score_%s += {score}" % _POSITIONS_FOR_PLAYER[player] + block_list.append(block_definition) + + BlocksCatalog.add_custom_blocks(_class_name, block_list) diff --git a/addons/block_code/ui/picker/picker.gd b/addons/block_code/ui/picker/picker.gd index 490956e3..7d7b9648 100644 --- a/addons/block_code/ui/picker/picker.gd +++ b/addons/block_code/ui/picker/picker.gd @@ -25,22 +25,19 @@ func block_script_selected(block_script: BlockScriptSerialization): reset_picker() return - var blocks_to_add: Array[Block] = [] var categories_to_add: Array[BlockCategory] = [] - # By default, assume the class is built-in. - var parent_class: String = block_script.script_inherits for class_dict in ProjectSettings.get_global_class_list(): if class_dict.class == block_script.script_inherits: var script = load(class_dict.path) if script.has_method("get_custom_categories"): categories_to_add = script.get_custom_categories() - if script.has_method("get_custom_blocks"): - blocks_to_add = script.get_custom_blocks() - parent_class = str(script.get_instance_base_type()) + if script.has_method("setup_custom_blocks"): + script.setup_custom_blocks() break - blocks_to_add.append_array(CategoryFactory.get_inherited_blocks(parent_class)) + var blocks_to_add: Array[Block] = [] + blocks_to_add.append_array(CategoryFactory.get_inherited_blocks(block_script.script_inherits)) init_picker(blocks_to_add, categories_to_add) reload_variables(block_script.variables) From 4c6acb1e9c18fddbf960e3f89e8f5ecf13d84a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 19 Aug 2024 17:30:56 -0300 Subject: [PATCH 173/423] Block definition: Add _to_string() method For easier debugging. --- addons/block_code/code_generation/block_definition.gd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addons/block_code/code_generation/block_definition.gd b/addons/block_code/code_generation/block_definition.gd index defbf9aa..9f3bbb90 100644 --- a/addons/block_code/code_generation/block_definition.gd +++ b/addons/block_code/code_generation/block_definition.gd @@ -52,3 +52,7 @@ func _init( defaults = p_defaults signal_name = p_signal_name scope = p_scope + + +func _to_string(): + return "%s - %s" % [name, target_node_class] From e70ac87d94d32c18f4ace3fcc45c72d01c5349b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 20 Aug 2024 12:42:53 -0300 Subject: [PATCH 174/423] Blocks catalog: Port "is action pressed / released" block And split obtaining the inputmap action names to a inner function. https://phabricator.endlessm.com/T35591 --- .../code_generation/blocks_catalog.gd | 47 +++++++++++++++++++ .../ui/picker/categories/category_factory.gd | 36 +------------- 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/addons/block_code/code_generation/blocks_catalog.gd b/addons/block_code/code_generation/blocks_catalog.gd index 233f5508..18ec616b 100644 --- a/addons/block_code/code_generation/blocks_catalog.gd +++ b/addons/block_code/code_generation/blocks_catalog.gd @@ -159,6 +159,32 @@ static func _add_property_definitions(_class_name: String, property_list: Array[ _by_class_name[_class_name][block_definition.name] = block_definition +static func _get_inputmap_actions() -> Array[StringName]: + var inputmap_actions: Array[StringName] + + var editor_input_actions: Dictionary = {} + var editor_input_action_deadzones: Dictionary = {} + if Engine.is_editor_hint(): + var actions := InputMap.get_actions() + for action in actions: + if action.begins_with("spatial_editor"): + var events := InputMap.action_get_events(action) + editor_input_actions[action] = events + editor_input_action_deadzones[action] = InputMap.action_get_deadzone(action) + + InputMap.load_from_project_settings() + + inputmap_actions = InputMap.get_actions() + + if Engine.is_editor_hint(): + for action in editor_input_actions.keys(): + InputMap.add_action(action, editor_input_action_deadzones[action]) + for event in editor_input_actions[action]: + InputMap.action_add_event(action, event) + + return inputmap_actions + + static func _setup_properties_for_class(): for _class_name in _SETTINGS_FOR_CLASS_PROPERTY: var property_list = ClassDB.class_get_property_list(_class_name, true) @@ -166,6 +192,26 @@ static func _setup_properties_for_class(): _add_property_definitions(_class_name, property_list, property_settings) +static func _setup_input_block(): + var inputmap_actions = _get_inputmap_actions() + + var block_definition: BlockDefinition = ( + BlockDefinition + . new( + &"is_input_actioned", + "", + "", + "Input", + Types.BlockType.VALUE, + TYPE_BOOL, + "Is action {action_name: OPTION} {action: OPTION}", + 'Input.is_action_{action}("{action_name}")', + {"action_name": OptionData.new(inputmap_actions), "action": OptionData.new(["pressed", "just_pressed", "just_released"])}, + ) + ) + _catalog[block_definition.name] = block_definition + + static func setup(): if _catalog: return @@ -173,6 +219,7 @@ static func setup(): _catalog = {} _setup_definitions_from_files() _setup_properties_for_class() + _setup_input_block() static func get_block(block_name: StringName): diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 3315e6f6..2f82fa62 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -208,7 +208,8 @@ static func get_general_blocks() -> Array[Block]: block_list.append(b) # Input - block_list.append_array(_get_input_blocks()) + b = Util.instantiate_block_by_name(&"is_input_actioned") + block_list.append(b) # Sounds for block_name in [&"load_sound", &"play_sound", &"pause_continue_sound", &"stop_sound"]: @@ -227,39 +228,6 @@ static func get_inherited_blocks(_class_name: String) -> Array[Block]: return Util.instantiate_blocks_for_class(_class_name) -static func _get_input_blocks() -> Array[Block]: - var block_list: Array[Block] - - var editor_input_actions: Dictionary = {} - var editor_input_action_deadzones: Dictionary = {} - if Engine.is_editor_hint(): - var actions := InputMap.get_actions() - for action in actions: - if action.begins_with("spatial_editor"): - var events := InputMap.action_get_events(action) - editor_input_actions[action] = events - editor_input_action_deadzones[action] = InputMap.action_get_deadzone(action) - - InputMap.load_from_project_settings() - - var block: Block = BLOCKS["parameter_block"].instantiate() - block.block_name = "is_action" - block.variant_type = TYPE_BOOL - block.block_format = "Is action {action_name: OPTION} {action: OPTION}" - block.statement = 'Input.is_action_{action}("{action_name}")' - block.defaults = {"action_name": OptionData.new(InputMap.get_actions()), "action": OptionData.new(["pressed", "just_pressed", "just_released"])} - block.category = "Input" - block_list.append(block) - - if Engine.is_editor_hint(): - for action in editor_input_actions.keys(): - InputMap.add_action(action, editor_input_action_deadzones[action]) - for event in editor_input_actions[action]: - InputMap.action_add_event(action, event) - - return block_list - - static func get_variable_blocks(variables: Array[VariableResource]): var block_list: Array[Block] From 2a03d079caf04f2dc80717f95049016a6c0dccd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 20 Aug 2024 14:13:09 -0300 Subject: [PATCH 175/423] Dynamically add blocks for variables Using the new block definition. These are the only blocks that are not stored in the catalog. Instead, they are dynamically generated when the BlockScriptSerialization changes. Also: Move constant for the builtin category properties to the constants.gd script. Also: Finally remove the preloaded scene blocks from the category_factory.gd script. The single place where those scenes are now instantiated is the ui/util.gd script. https://phabricator.endlessm.com/T35591 --- addons/block_code/ui/constants.gd | 116 ++++++++++++++ .../ui/picker/categories/category_factory.gd | 150 +----------------- addons/block_code/ui/util.gd | 35 ++++ 3 files changed, 154 insertions(+), 147 deletions(-) diff --git a/addons/block_code/ui/constants.gd b/addons/block_code/ui/constants.gd index dcb65e23..b0830952 100644 --- a/addons/block_code/ui/constants.gd +++ b/addons/block_code/ui/constants.gd @@ -11,3 +11,119 @@ const OUTLINE_WIDTH = 3.0 const MINIMUM_SNAP_DISTANCE = 80.0 const FOCUS_BORDER_COLOR = Color(225, 242, 0) + +## Properties for builtin categories. Order starts at 10 for the first +## category and then are separated by 10 to allow custom categories to +## be easily placed between builtin categories. +const BUILTIN_CATEGORIES_PROPS: Dictionary = { + "Lifecycle": + { + "color": Color("ec3b59"), + "order": 10, + }, + "Transform | Position": + { + "color": Color("4b6584"), + "order": 20, + }, + "Transform | Rotation": + { + "color": Color("4b6584"), + "order": 30, + }, + "Transform | Scale": + { + "color": Color("4b6584"), + "order": 40, + }, + "Graphics | Modulate": + { + "color": Color("03aa74"), + "order": 50, + }, + "Graphics | Visibility": + { + "color": Color("03aa74"), + "order": 60, + }, + "Graphics | Viewport": + { + "color": Color("03aa74"), + "order": 61, + }, + "Graphics | Animation": + { + "color": Color("03aa74"), + "order": 62, + }, + "Sounds": + { + "color": Color("e30fc0"), + "order": 70, + }, + "Physics | Mass": + { + "color": Color("a5b1c2"), + "order": 80, + }, + "Physics | Velocity": + { + "color": Color("a5b1c2"), + "order": 90, + }, + "Input": + { + "color": Color("d54322"), + "order": 100, + }, + "Communication | Methods": + { + "color": Color("4b7bec"), + "order": 110, + }, + "Communication | Groups": + { + "color": Color("4b7bec"), + "order": 120, + }, + "Info | Score": + { + "color": Color("cf6a87"), + "order": 130, + }, + "Loops": + { + "color": Color("20bf6b"), + "order": 140, + }, + "Logic | Conditionals": + { + "color": Color("45aaf2"), + "order": 150, + }, + "Logic | Comparison": + { + "color": Color("45aaf2"), + "order": 160, + }, + "Logic | Boolean": + { + "color": Color("45aaf2"), + "order": 170, + }, + "Variables": + { + "color": Color("ff8f08"), + "order": 180, + }, + "Math": + { + "color": Color("a55eea"), + "order": 190, + }, + "Log": + { + "color": Color("002050"), + "order": 200, + }, +} diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 2f82fa62..358d3809 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -4,129 +4,7 @@ extends Object const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") const Types = preload("res://addons/block_code/types/types.gd") const Util = preload("res://addons/block_code/ui/util.gd") - -const BLOCKS: Dictionary = { - "control_block": preload("res://addons/block_code/ui/blocks/control_block/control_block.tscn"), - "parameter_block": preload("res://addons/block_code/ui/blocks/parameter_block/parameter_block.tscn"), - "statement_block": preload("res://addons/block_code/ui/blocks/statement_block/statement_block.tscn"), - "entry_block": preload("res://addons/block_code/ui/blocks/entry_block/entry_block.tscn"), -} - -## Properties for builtin categories. Order starts at 10 for the first -## category and then are separated by 10 to allow custom categories to -## be easily placed between builtin categories. -const BUILTIN_PROPS: Dictionary = { - "Lifecycle": - { - "color": Color("ec3b59"), - "order": 10, - }, - "Transform | Position": - { - "color": Color("4b6584"), - "order": 20, - }, - "Transform | Rotation": - { - "color": Color("4b6584"), - "order": 30, - }, - "Transform | Scale": - { - "color": Color("4b6584"), - "order": 40, - }, - "Graphics | Modulate": - { - "color": Color("03aa74"), - "order": 50, - }, - "Graphics | Visibility": - { - "color": Color("03aa74"), - "order": 60, - }, - "Graphics | Viewport": - { - "color": Color("03aa74"), - "order": 61, - }, - "Graphics | Animation": - { - "color": Color("03aa74"), - "order": 62, - }, - "Sounds": - { - "color": Color("e30fc0"), - "order": 70, - }, - "Physics | Mass": - { - "color": Color("a5b1c2"), - "order": 80, - }, - "Physics | Velocity": - { - "color": Color("a5b1c2"), - "order": 90, - }, - "Input": - { - "color": Color("d54322"), - "order": 100, - }, - "Communication | Methods": - { - "color": Color("4b7bec"), - "order": 110, - }, - "Communication | Groups": - { - "color": Color("4b7bec"), - "order": 120, - }, - "Info | Score": - { - "color": Color("cf6a87"), - "order": 130, - }, - "Loops": - { - "color": Color("20bf6b"), - "order": 140, - }, - "Logic | Conditionals": - { - "color": Color("45aaf2"), - "order": 150, - }, - "Logic | Comparison": - { - "color": Color("45aaf2"), - "order": 160, - }, - "Logic | Boolean": - { - "color": Color("45aaf2"), - "order": 170, - }, - "Variables": - { - "color": Color("ff8f08"), - "order": 180, - }, - "Math": - { - "color": Color("a55eea"), - "order": 190, - }, - "Log": - { - "color": Color("002050"), - "order": 200, - }, -} +const Constants = preload("res://addons/block_code/ui/constants.gd") ## Compare block categories for sorting. Compare by order then name. @@ -148,7 +26,7 @@ static func get_categories(blocks: Array[Block], extra_categories: Array[BlockCa if cat == null: cat = extra_cat_map.get(block.category) if cat == null: - var props: Dictionary = BUILTIN_PROPS.get(block.category, {}) + var props: Dictionary = Constants.BUILTIN_CATEGORIES_PROPS.get(block.category, {}) var color: Color = props.get("color", Color.SLATE_GRAY) var order: int = props.get("order", 0) cat = BlockCategory.new(block.category, color, order) @@ -229,26 +107,4 @@ static func get_inherited_blocks(_class_name: String) -> Array[Block]: static func get_variable_blocks(variables: Array[VariableResource]): - var block_list: Array[Block] - - for variable in variables: - var type_string: String = Types.VARIANT_TYPE_TO_STRING[variable.var_type] - - var b = BLOCKS["parameter_block"].instantiate() - b.block_name = "get_var_%s" % variable.var_name - b.variant_type = variable.var_type - b.block_format = variable.var_name - b.statement = variable.var_name - # HACK: Color the blocks since they are outside of the normal picker system - b.color = BUILTIN_PROPS["Variables"].color - block_list.append(b) - - b = BLOCKS["statement_block"].instantiate() - b.block_name = "set_var_%s" % variable.var_name - b.block_type = Types.BlockType.STATEMENT - b.block_format = "Set %s to {value: %s}" % [variable.var_name, type_string] - b.statement = "%s = {value}" % [variable.var_name] - b.color = BUILTIN_PROPS["Variables"].color - block_list.append(b) - - return block_list + return Util.instantiate_variable_blocks(variables) diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index d6fb72a0..b6d8beb7 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -3,6 +3,7 @@ extends Object const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") const Types = preload("res://addons/block_code/types/types.gd") +const Constants = preload("res://addons/block_code/ui/constants.gd") const SCENE_PER_TYPE = { Types.BlockType.ENTRY: preload("res://addons/block_code/ui/blocks/entry_block/entry_block.tscn"), @@ -84,6 +85,40 @@ static func instantiate_blocks_for_class(_class_name: String) -> Array[Block]: return blocks +static func get_variable_block_definitions(variables: Array[VariableResource]) -> Array[BlockDefinition]: + var block_definitions: Array[BlockDefinition] = [] + for variable: VariableResource in variables: + var type_string: String = Types.VARIANT_TYPE_TO_STRING[variable.var_type] + + var b = BlockDefinition.new() + b.name = "get_var_%s" % variable.var_name + b.type = Types.BlockType.VALUE + b.variant_type = variable.var_type + b.display_template = variable.var_name + b.code_template = variable.var_name + block_definitions.append(b) + + b = BlockDefinition.new() + b.name = "set_var_%s" % variable.var_name + b.type = Types.BlockType.STATEMENT + b.display_template = "Set %s to {value: %s}" % [variable.var_name, type_string] + b.code_template = "%s = {value}" % [variable.var_name] + block_definitions.append(b) + + return block_definitions + + +static func instantiate_variable_blocks(variables: Array[VariableResource]) -> Array[Block]: + var blocks: Array[Block] = [] + for block_definition in get_variable_block_definitions(variables): + var b = instantiate_block(block_definition) + # HACK: Color the blocks since they are outside of the normal picker system + b.color = Constants.BUILTIN_CATEGORIES_PROPS["Variables"].color + blocks.append(b) + + return blocks + + ## Polyfill of Node.is_part_of_edited_scene(), available to GDScript in Godot 4.3+. static func node_is_part_of_edited_scene(node: Node) -> bool: if not Engine.is_editor_hint(): From 9a0da761cdd9961ad23c594a3c6c875a137e6cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 20 Aug 2024 16:10:01 -0300 Subject: [PATCH 176/423] Derive block color from category Stop persisting the color in the serialization. https://phabricator.endlessm.com/T35591 --- addons/block_code/ui/blocks/block/block.gd | 3 +-- .../ui/picker/categories/block_category_display.gd | 6 +----- addons/block_code/ui/util.gd | 7 +++++++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 6d97c605..3a4e056a 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -138,9 +138,8 @@ func get_serialized_props() -> Array: return serialize_props(["block_name", "label", "color", "block_type", "position", "scope"]) # TODO: Remove remaining serialization: - # - Derive color from category. # - Handle scope in a different way? - return serialize_props(["color", "scope"]) + return serialize_props(["scope"]) func _to_string(): diff --git a/addons/block_code/ui/picker/categories/block_category_display.gd b/addons/block_code/ui/picker/categories/block_category_display.gd index ce85f620..b4c536e3 100644 --- a/addons/block_code/ui/picker/categories/block_category_display.gd +++ b/addons/block_code/ui/picker/categories/block_category_display.gd @@ -12,9 +12,5 @@ var category: BlockCategory func _ready(): _label.text = category.name - for _block in category.block_list: - var block: Block = _block as Block - - block.color = category.color - + for block: Block in category.block_list: _blocks.add_child(block) diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index b6d8beb7..5371b4e8 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -13,6 +13,11 @@ const SCENE_PER_TYPE = { } +static func get_category_color(category: String) -> Color: + var category_props: Dictionary = Constants.BUILTIN_CATEGORIES_PROPS.get(category, {}) + return category_props.get("color", Color.SLATE_GRAY) + + static func instantiate_block(block_definition: BlockDefinition) -> Block: var scene = SCENE_PER_TYPE[block_definition.type] var b = scene.instantiate() @@ -31,6 +36,8 @@ static func instantiate_block(block_definition: BlockDefinition) -> Block: b.defaults = block_definition.defaults b.tooltip_text = block_definition.description b.category = block_definition.category + b.color = get_category_color(block_definition.category) + return b From c037bfd8647948f4d9a35539ee785abd9cf26544 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Tue, 20 Aug 2024 22:50:03 -0300 Subject: [PATCH 177/423] Serialize user input as Variants instead of Strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Manuel Quiñones --- .../parameter_input/parameter_input.gd | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd index 95073a0e..96abece8 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd +++ b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd @@ -56,13 +56,15 @@ func set_raw_input(raw_input): _color_input.color = raw_input _update_panel_bg_color(raw_input) TYPE_VECTOR2: - var split = raw_input.split(",") - _x_line_edit.text = split[0] - _y_line_edit.text = split[1] + # Rounding because floats are doubles by default but Vector2s have single components + _x_line_edit.text = ("%.4f" % raw_input.x).rstrip("0").rstrip(".") + _y_line_edit.text = ("%.4f" % raw_input.y).rstrip("0").rstrip(".") TYPE_BOOL: _bool_input_option.select(raw_input) - _: + TYPE_NIL: _line_edit.text = raw_input + _: + _line_edit.text = "" if raw_input == null else str(raw_input) func get_raw_input(): @@ -76,9 +78,15 @@ func get_raw_input(): TYPE_COLOR: return _color_input.color TYPE_VECTOR2: - return _x_line_edit.text + "," + _y_line_edit.text + return Vector2(float(_x_line_edit.text), float(_y_line_edit.text)) TYPE_BOOL: return bool(_bool_input_option.selected) + TYPE_INT: + return null if _line_edit.text == "" else int(_line_edit.text) + TYPE_FLOAT: + return null if _line_edit.text == "" else float(_line_edit.text) + TYPE_NIL: + return _line_edit.text _: return _line_edit.text @@ -127,11 +135,16 @@ func get_string() -> String: TYPE_STRING: return "'%s'" % input.replace("\\", "\\\\").replace("'", "\\'") TYPE_VECTOR2: - return "Vector2(%s)" % input + return "Vector2%s" % str(input) TYPE_COLOR: return "Color%s" % str(input) + TYPE_OBJECT: + if input is OptionData: + var option_data := input as OptionData + return option_data.items[option_data.selected] _: return "%s" % input + return "" func _validate_and_submit_edit_text(line_edit: Node, type: Variant.Type): From 2d13c92a283142e2310691de5093309d9eecad7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 20 Aug 2024 23:24:13 -0300 Subject: [PATCH 178/423] Category factory: rename variable "b" to "block" To avoid single character names. --- .../ui/picker/categories/category_factory.gd | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 358d3809..934a333b 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -45,59 +45,59 @@ static func get_categories(blocks: Array[Block], extra_categories: Array[BlockCa static func get_general_blocks() -> Array[Block]: - var b: Block + var block: Block var block_list: Array[Block] = [] # Lifecycle for block_name in [&"ready", &"process", &"physics_process", &"queue_free"]: - b = Util.instantiate_block_by_name(block_name) - block_list.append(b) + block = Util.instantiate_block_by_name(block_name) + block_list.append(block) # Loops for block_name in [&"for", &"while", &"break", &"continue", &"await_scene_ready"]: - b = Util.instantiate_block_by_name(block_name) - block_list.append(b) + block = Util.instantiate_block_by_name(block_name) + block_list.append(block) # Logs - b = Util.instantiate_block_by_name(&"print") - block_list.append(b) + block = Util.instantiate_block_by_name(&"print") + block_list.append(block) # Communication for block_name in [&"define_method", &"call_method_group", &"call_method_node"]: - b = Util.instantiate_block_by_name(block_name) - block_list.append(b) + block = Util.instantiate_block_by_name(block_name) + block_list.append(block) for block_name in [&"add_to_group", &"add_node_to_group", &"remove_from_group", &"remove_node_from_group", &"is_in_group", &"is_node_in_group"]: - b = Util.instantiate_block_by_name(block_name) - block_list.append(b) + block = Util.instantiate_block_by_name(block_name) + block_list.append(block) # Variables - b = Util.instantiate_block_by_name(&"vector2") - block_list.append(b) + block = Util.instantiate_block_by_name(&"vector2") + block_list.append(block) # Math for block_name in [&"add", &"subtract", &"multiply", &"divide", &"pow", &"randf_range", &"randi_range", &"sin", &"cos", &"tan"]: - b = Util.instantiate_block_by_name(block_name) - block_list.append(b) + block = Util.instantiate_block_by_name(block_name) + block_list.append(block) # Logic for block_name in [&"if", &"else_if", &"else", &"compare", &"and", &"or", &"not"]: - b = Util.instantiate_block_by_name(block_name) - block_list.append(b) + block = Util.instantiate_block_by_name(block_name) + block_list.append(block) # Input - b = Util.instantiate_block_by_name(&"is_input_actioned") - block_list.append(b) + block = Util.instantiate_block_by_name(&"is_input_actioned") + block_list.append(block) # Sounds for block_name in [&"load_sound", &"play_sound", &"pause_continue_sound", &"stop_sound"]: - b = Util.instantiate_block_by_name(block_name) - block_list.append(b) + block = Util.instantiate_block_by_name(block_name) + block_list.append(block) # Graphics for block_name in [&"viewport_width", &"viewport_height", &"viewport_center"]: - b = Util.instantiate_block_by_name(block_name) - block_list.append(b) + block = Util.instantiate_block_by_name(block_name) + block_list.append(block) return block_list From 9dec121223591f2b8e17017f89f6e517ecdee954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 21 Aug 2024 10:27:30 -0300 Subject: [PATCH 179/423] Redo the Pong example --- .../examples/pong_game/pong_game.tscn | 937 ++++++++---------- 1 file changed, 417 insertions(+), 520 deletions(-) diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index 6cad69bd..ec3ab35c 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=122 format=3 uid="uid://tf7b8c64ecc0"] +[gd_scene load_steps=119 format=3 uid="uid://tf7b8c64ecc0"] [ext_resource type="PackedScene" uid="uid://cg8ibi18um3vg" path="res://addons/block_code/examples/pong_game/space.tscn" id="1_y56ac"] [ext_resource type="Script" path="res://addons/block_code/block_code_node/block_code.gd" id="3_6jaq8"] @@ -8,98 +8,84 @@ [ext_resource type="Script" path="res://addons/block_code/serialization/block_serialized_properties.gd" id="5_wr38c"] [ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="7_3q6bj"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_script_serialization.gd" id="7_uuuue"] +[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/variable_resource.gd" id="9_lo3p1"] [ext_resource type="PackedScene" uid="uid://c7l70grmkauij" path="res://addons/block_code/examples/pong_game/ball.tscn" id="9_xrqll"] [ext_resource type="PackedScene" uid="uid://fhoapg3anjsu" path="res://addons/block_code/examples/pong_game/goal_area.tscn" id="12_nqmxu"] [ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd" id="13_tg3yk"] -[sub_resource type="Resource" id="Resource_860cl"] +[sub_resource type="Resource" id="Resource_iegsu"] +script = ExtResource("5_wr38c") +block_class = &"EntryBlock" +serialized_props = [["scope", ""], ["param_input_strings", {}]] + +[sub_resource type="Resource" id="Resource_6fwti"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"set_prop_speed"], ["label", "StatementBlock"], ["color", Color(0.647059, 0.694118, 0.760784, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Speed to {value: VECTOR2}"], ["statement", "speed = {value}"], ["defaults", { -"value": "0, 0" -}], ["param_input_strings", { -"value": "0,1000" +serialized_props = [["scope", ""], ["param_input_strings", { +"value": Vector2(0, 1000) }]] -[sub_resource type="Resource" id="Resource_q65fe"] +[sub_resource type="Resource" id="Resource_bxt7h"] script = ExtResource("4_qtggh") -name = &"set_prop_speed" +name = &"SimpleCharacter_set_speed" position = Vector2(0, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_860cl") +block_serialized_properties = SubResource("Resource_6fwti") -[sub_resource type="Resource" id="Resource_q1vhx"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", ""], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_yiq7s"] +[sub_resource type="Resource" id="Resource_xsn6l"] script = ExtResource("4_qtggh") name = &"ready" position = Vector2(75, 175) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_q65fe")]] -block_serialized_properties = SubResource("Resource_q1vhx") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_bxt7h")]] +block_serialized_properties = SubResource("Resource_iegsu") -[sub_resource type="Resource" id="Resource_a45un"] -script = ExtResource("7_3q6bj") -selected = 0 -items = ["top-down", "platformer", "spaceship"] - -[sub_resource type="Resource" id="Resource_ldmk0"] -script = ExtResource("7_3q6bj") -selected = 0 -items = ["player_1", "player_2"] +[sub_resource type="Resource" id="Resource_41mcx"] +script = ExtResource("5_wr38c") +block_class = &"EntryBlock" +serialized_props = [["scope", ""], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_604n7"] +[sub_resource type="Resource" id="Resource_rwx76"] script = ExtResource("7_3q6bj") selected = 0 items = ["top-down", "platformer", "spaceship"] -[sub_resource type="Resource" id="Resource_h8b8o"] +[sub_resource type="Resource" id="Resource_ksb0o"] script = ExtResource("7_3q6bj") selected = 0 items = ["player_1", "player_2"] -[sub_resource type="Resource" id="Resource_d3xtc"] +[sub_resource type="Resource" id="Resource_82o3l"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"simplecharacter_move"], ["label", "StatementBlock"], ["color", Color(0.835294, 0.262745, 0.133333, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Move with {player: OPTION} buttons as {kind: OPTION}"], ["statement", "move_with_player_buttons(\"{player}\", \"{kind}\", delta)"], ["defaults", { -"kind": SubResource("Resource_a45un"), -"player": SubResource("Resource_ldmk0") -}], ["param_input_strings", { -"kind": SubResource("Resource_604n7"), -"player": SubResource("Resource_h8b8o") +serialized_props = [["scope", ""], ["param_input_strings", { +"kind": SubResource("Resource_rwx76"), +"player": SubResource("Resource_ksb0o") }]] -[sub_resource type="Resource" id="Resource_7x3sw"] +[sub_resource type="Resource" id="Resource_4vl0d"] script = ExtResource("4_qtggh") name = &"simplecharacter_move" position = Vector2(0, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_d3xtc") +block_serialized_properties = SubResource("Resource_82o3l") -[sub_resource type="Resource" id="Resource_x6ddv"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["block_name", &"process_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(75, 300)], ["scope", ""], ["block_format", "On Process"], ["statement", "func _process(delta):"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] - -[sub_resource type="Resource" id="Resource_0m462"] +[sub_resource type="Resource" id="Resource_wntwg"] script = ExtResource("4_qtggh") -name = &"process_block" +name = &"process" position = Vector2(75, 300) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_7x3sw")]] -block_serialized_properties = SubResource("Resource_x6ddv") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_4vl0d")]] +block_serialized_properties = SubResource("Resource_41mcx") [sub_resource type="Resource" id="Resource_m2svk"] script = ExtResource("7_uuuue") script_inherits = "SimpleCharacter" -block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_yiq7s"), SubResource("Resource_0m462")]) -variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) +block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_xsn6l"), SubResource("Resource_wntwg")]) +variables = Array[ExtResource("9_lo3p1")]([]) generated_script = "extends SimpleCharacter func _ready(): - speed = Vector2(0,1000) + speed = Vector2(0, 1000) func _process(delta): move_with_player_buttons(\"player_1\", \"top-down\", delta) @@ -107,94 +93,79 @@ func _process(delta): " version = 0 -[sub_resource type="Resource" id="Resource_isc56"] +[sub_resource type="Resource" id="Resource_lhobc"] +script = ExtResource("5_wr38c") +block_class = &"EntryBlock" +serialized_props = [["scope", ""], ["param_input_strings", {}]] + +[sub_resource type="Resource" id="Resource_1ycg8"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"set_prop_speed"], ["label", "StatementBlock"], ["color", Color(0.647059, 0.694118, 0.760784, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Speed to {value: VECTOR2}"], ["statement", "speed = {value}"], ["defaults", { -"value": "0, 0" -}], ["param_input_strings", { -"value": "0,1000" +serialized_props = [["scope", ""], ["param_input_strings", { +"value": Vector2(0, 1000) }]] -[sub_resource type="Resource" id="Resource_ttkrd"] +[sub_resource type="Resource" id="Resource_nkjuo"] script = ExtResource("4_qtggh") -name = &"set_prop_speed" +name = &"SimpleCharacter_set_speed" position = Vector2(0, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_isc56") +block_serialized_properties = SubResource("Resource_1ycg8") -[sub_resource type="Resource" id="Resource_06s7w"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", ""], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_hrubs"] +[sub_resource type="Resource" id="Resource_t1m7j"] script = ExtResource("4_qtggh") name = &"ready" position = Vector2(50, 175) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ttkrd")]] -block_serialized_properties = SubResource("Resource_06s7w") - -[sub_resource type="Resource" id="Resource_y2msu"] -script = ExtResource("7_3q6bj") -selected = 0 -items = ["top-down", "platformer", "spaceship"] +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_nkjuo")]] +block_serialized_properties = SubResource("Resource_lhobc") -[sub_resource type="Resource" id="Resource_wq8lu"] -script = ExtResource("7_3q6bj") -selected = 0 -items = ["player_1", "player_2"] +[sub_resource type="Resource" id="Resource_ud032"] +script = ExtResource("5_wr38c") +block_class = &"EntryBlock" +serialized_props = [["scope", ""], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_cqi0p"] +[sub_resource type="Resource" id="Resource_ixcua"] script = ExtResource("7_3q6bj") selected = 0 items = ["top-down", "platformer", "spaceship"] -[sub_resource type="Resource" id="Resource_1apud"] +[sub_resource type="Resource" id="Resource_728pr"] script = ExtResource("7_3q6bj") selected = 1 items = ["player_1", "player_2"] -[sub_resource type="Resource" id="Resource_bl8w1"] +[sub_resource type="Resource" id="Resource_7aw38"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"simplecharacter_move"], ["label", "StatementBlock"], ["color", Color(0.835294, 0.262745, 0.133333, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Move with {player: OPTION} buttons as {kind: OPTION}"], ["statement", "move_with_player_buttons(\"{player}\", \"{kind}\", delta)"], ["defaults", { -"kind": SubResource("Resource_y2msu"), -"player": SubResource("Resource_wq8lu") -}], ["param_input_strings", { -"kind": SubResource("Resource_cqi0p"), -"player": SubResource("Resource_1apud") +serialized_props = [["scope", ""], ["param_input_strings", { +"kind": SubResource("Resource_ixcua"), +"player": SubResource("Resource_728pr") }]] -[sub_resource type="Resource" id="Resource_enqe8"] +[sub_resource type="Resource" id="Resource_gtejw"] script = ExtResource("4_qtggh") name = &"simplecharacter_move" position = Vector2(0, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_bl8w1") +block_serialized_properties = SubResource("Resource_7aw38") -[sub_resource type="Resource" id="Resource_3wgnl"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["block_name", &"process_block"], ["label", "EntryBlock"], ["color", Color(0.92549, 0.231373, 0.34902, 1)], ["block_type", 1], ["position", Vector2(50, 300)], ["scope", ""], ["block_format", "On Process"], ["statement", "func _process(delta):"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", ""]] - -[sub_resource type="Resource" id="Resource_s8vl4"] +[sub_resource type="Resource" id="Resource_03rje"] script = ExtResource("4_qtggh") -name = &"process_block" +name = &"process" position = Vector2(50, 300) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_enqe8")]] -block_serialized_properties = SubResource("Resource_3wgnl") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_gtejw")]] +block_serialized_properties = SubResource("Resource_ud032") [sub_resource type="Resource" id="Resource_ysbi4"] script = ExtResource("7_uuuue") script_inherits = "SimpleCharacter" -block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_hrubs"), SubResource("Resource_s8vl4")]) -variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) +block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_t1m7j"), SubResource("Resource_03rje")]) +variables = Array[ExtResource("9_lo3p1")]([]) generated_script = "extends SimpleCharacter func _ready(): - speed = Vector2(0,1000) + speed = Vector2(0, 1000) func _process(delta): move_with_player_buttons(\"player_2\", \"top-down\", delta) @@ -202,319 +173,265 @@ func _process(delta): " version = 0 -[sub_resource type="Resource" id="Resource_rf047"] +[sub_resource type="Resource" id="Resource_d8f3t"] +script = ExtResource("5_wr38c") +block_class = &"EntryBlock" +serialized_props = [["scope", ""], ["param_input_strings", {}]] + +[sub_resource type="Resource" id="Resource_wtbtc"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"load_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " -var __sound = AudioStreamPlayer.new() -__sound.name = {name} -__sound.set_stream(load({file_path})) -add_child(__sound) -"], ["defaults", {}], ["param_input_strings", { -"file_path": "res://addons/block_code/examples/pong_game/assets/score.ogg", -"name": "score_sound" +serialized_props = [["scope", ""], ["param_input_strings", { +"file_path": "res://addons/block_code/examples/pong_game/assets/paddle_hit.ogg", +"name": "paddle_hit" }]] -[sub_resource type="Resource" id="Resource_d34ke"] -script = ExtResource("4_qtggh") -name = &"load_sound" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_rf047") - -[sub_resource type="Resource" id="Resource_md4i5"] +[sub_resource type="Resource" id="Resource_st0iw"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"load_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " -var __sound = AudioStreamPlayer.new() -__sound.name = {name} -__sound.set_stream(load({file_path})) -add_child(__sound) -"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["scope", ""], ["param_input_strings", { "file_path": "res://addons/block_code/examples/pong_game/assets/wall_hit.ogg", "name": "wall_hit" }]] -[sub_resource type="Resource" id="Resource_roxh4"] +[sub_resource type="Resource" id="Resource_jp6b8"] +script = ExtResource("5_wr38c") +block_class = &"StatementBlock" +serialized_props = [["scope", ""], ["param_input_strings", { +"file_path": "res://addons/block_code/examples/pong_game/assets/score.ogg", +"name": "score_sound" +}]] + +[sub_resource type="Resource" id="Resource_xs0e6"] script = ExtResource("4_qtggh") name = &"load_sound" position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_d34ke")]] -block_serialized_properties = SubResource("Resource_md4i5") +path_child_pairs = [] +block_serialized_properties = SubResource("Resource_jp6b8") -[sub_resource type="Resource" id="Resource_4luvu"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["block_name", &"load_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Load file {file_path: STRING} as sound {name: STRING}"], ["statement", " -var __sound = AudioStreamPlayer.new() -__sound.name = {name} -__sound.set_stream(load({file_path})) -add_child(__sound) -"], ["defaults", {}], ["param_input_strings", { -"file_path": "res://addons/block_code/examples/pong_game/assets/paddle_hit.ogg", -"name": "paddle_hit" -}]] +[sub_resource type="Resource" id="Resource_spen4"] +script = ExtResource("4_qtggh") +name = &"load_sound" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_xs0e6")]] +block_serialized_properties = SubResource("Resource_st0iw") -[sub_resource type="Resource" id="Resource_gywyt"] +[sub_resource type="Resource" id="Resource_r5331"] script = ExtResource("4_qtggh") name = &"load_sound" position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_roxh4")]] -block_serialized_properties = SubResource("Resource_4luvu") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_spen4")]] +block_serialized_properties = SubResource("Resource_wtbtc") + +[sub_resource type="Resource" id="Resource_phaw7"] +script = ExtResource("4_qtggh") +name = &"ready" +position = Vector2(50, 50) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_r5331")]] +block_serialized_properties = SubResource("Resource_d8f3t") -[sub_resource type="Resource" id="Resource_b0aen"] +[sub_resource type="Resource" id="Resource_47jf7"] script = ExtResource("5_wr38c") block_class = &"EntryBlock" -serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", ""], ["param_input_strings", {}]] +serialized_props = [["scope", ""], ["param_input_strings", { +"method_name": "reset" +}]] -[sub_resource type="Resource" id="Resource_1h6wi"] -script = ExtResource("4_qtggh") -name = &"ready" -position = Vector2(54, 47) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_gywyt")]] -block_serialized_properties = SubResource("Resource_b0aen") +[sub_resource type="Resource" id="Resource_obbdk"] +script = ExtResource("5_wr38c") +block_class = &"StatementBlock" +serialized_props = [["scope", ""], ["param_input_strings", { +"position": Vector2(0, 0) +}]] -[sub_resource type="Resource" id="Resource_05cdj"] +[sub_resource type="Resource" id="Resource_qae7k"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", &"viewport_center"], ["label", "Param"], ["color", Color(0.0117647, 0.666667, 0.454902, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Viewport Center"], ["statement", "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()"], ["defaults", {}], ["variant_type", 5], ["param_input_strings", {}]] +serialized_props = [["scope", ""], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_kt3qw"] +[sub_resource type="Resource" id="Resource_1sea1"] script = ExtResource("4_qtggh") name = &"viewport_center" position = Vector2(0, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_05cdj") +block_serialized_properties = SubResource("Resource_qae7k") -[sub_resource type="Resource" id="Resource_uob83"] +[sub_resource type="Resource" id="Resource_3b4ka"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"play_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " -var __sound_node = get_node({name}) -__sound_node.volume_db = {db} -__sound_node.pitch_scale = {pitch} -__sound_node.play() -"], ["defaults", { -"db": "0.0", -"pitch": "1.0" -}], ["param_input_strings", { -"db": "0.0", +serialized_props = [["scope", ""], ["param_input_strings", { +"db": 0.0, "name": "score_sound", -"pitch": "1.0" +"pitch": 1.0 }]] -[sub_resource type="Resource" id="Resource_oawyp"] +[sub_resource type="Resource" id="Resource_16pmr"] script = ExtResource("4_qtggh") name = &"play_sound" position = Vector2(0, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_uob83") +block_serialized_properties = SubResource("Resource_3b4ka") -[sub_resource type="Resource" id="Resource_5x1be"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["block_name", &"rigidbody2d_physics_position"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.396078, 0.517647, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set Physics Position {position: VECTOR2}"], ["statement", " -PhysicsServer2D.body_set_state( - get_rid(), - PhysicsServer2D.BODY_STATE_TRANSFORM, - Transform2D.IDENTITY.translated({position}) -) -"], ["defaults", {}], ["param_input_strings", { -"position": "," -}]] - -[sub_resource type="Resource" id="Resource_ftveg"] +[sub_resource type="Resource" id="Resource_ugq5m"] script = ExtResource("4_qtggh") name = &"rigidbody2d_physics_position" position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_kt3qw")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_oawyp")]] -block_serialized_properties = SubResource("Resource_5x1be") - -[sub_resource type="Resource" id="Resource_sp3a4"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["block_name", &"define_method"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(50, 275)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { -"method_name": "reset" -}], ["signal_name", ""]] +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_1sea1")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_16pmr")]] +block_serialized_properties = SubResource("Resource_obbdk") -[sub_resource type="Resource" id="Resource_gmlt0"] +[sub_resource type="Resource" id="Resource_ane3b"] script = ExtResource("4_qtggh") name = &"define_method" position = Vector2(50, 275) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ftveg")]] -block_serialized_properties = SubResource("Resource_sp3a4") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ugq5m")]] +block_serialized_properties = SubResource("Resource_47jf7") -[sub_resource type="Resource" id="Resource_r1gqk"] +[sub_resource type="Resource" id="Resource_7kl7g"] script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " -func _on_body_entered(_body: Node): - var body: NodePath = _body.get_path() -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_gj1nu"] -script = ExtResource("4_qtggh") -name = &"parameter_block" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_r1gqk") +block_class = &"EntryBlock" +serialized_props = [["scope", ""], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_ri33r"] +[sub_resource type="Resource" id="Resource_vqtp0"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " -func _on_body_entered(_body: Node): - var body: NodePath = _body.get_path() -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): +"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_7qpii"] +[sub_resource type="Resource" id="Resource_bgppn"] script = ExtResource("4_qtggh") name = &"parameter_block" position = Vector2(0, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_ri33r") +block_serialized_properties = SubResource("Resource_vqtp0") + +[sub_resource type="Resource" id="Resource_dnsl7"] +script = ExtResource("5_wr38c") +block_class = &"ControlBlock" +serialized_props = [["scope", ""], ["param_input_strings_array", [{ +"condition": false +}]]] -[sub_resource type="Resource" id="Resource_s7b4y"] +[sub_resource type="Resource" id="Resource_kvrwg"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", &"is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { +serialized_props = [["scope", ""], ["param_input_strings", { "group": "paddles", "node": "" }]] -[sub_resource type="Resource" id="Resource_xsgv2"] +[sub_resource type="Resource" id="Resource_et4ib"] +script = ExtResource("5_wr38c") +block_class = &"ParameterBlock" +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): +"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] + +[sub_resource type="Resource" id="Resource_707bn"] +script = ExtResource("4_qtggh") +name = &"parameter_block" +position = Vector2(0, 0) +path_child_pairs = [] +block_serialized_properties = SubResource("Resource_et4ib") + +[sub_resource type="Resource" id="Resource_dj7fd"] script = ExtResource("4_qtggh") name = &"is_node_in_group" position = Vector2(0, 0) -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_7qpii")]] -block_serialized_properties = SubResource("Resource_s7b4y") +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_707bn")]] +block_serialized_properties = SubResource("Resource_kvrwg") -[sub_resource type="Resource" id="Resource_bh5jo"] +[sub_resource type="Resource" id="Resource_t4jty"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"play_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " -var __sound_node = get_node({name}) -__sound_node.volume_db = {db} -__sound_node.pitch_scale = {pitch} -__sound_node.play() -"], ["defaults", { -"db": "0.0", -"pitch": "1.0" -}], ["param_input_strings", { -"db": "0.0", +serialized_props = [["scope", ""], ["param_input_strings", { +"db": 0.0, "name": "paddle_hit", -"pitch": "1.0" +"pitch": 1.0 }]] -[sub_resource type="Resource" id="Resource_ic2jq"] +[sub_resource type="Resource" id="Resource_2lgdm"] script = ExtResource("4_qtggh") name = &"play_sound" -position = Vector2(0, 0) +position = Vector2(20, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_bh5jo") +block_serialized_properties = SubResource("Resource_t4jty") -[sub_resource type="Resource" id="Resource_mgvpf"] +[sub_resource type="Resource" id="Resource_e1awu"] script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " -func _on_body_entered(_body: Node): - var body: NodePath = _body.get_path() -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_mbuv7"] -script = ExtResource("4_qtggh") -name = &"parameter_block" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_mgvpf") +block_class = &"ControlBlock" +serialized_props = [["scope", ""], ["param_input_strings_array", [{ +"condition": false +}]]] -[sub_resource type="Resource" id="Resource_rc730"] +[sub_resource type="Resource" id="Resource_1en27"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", &"is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { +serialized_props = [["scope", ""], ["param_input_strings", { "group": "walls", "node": "" }]] -[sub_resource type="Resource" id="Resource_fgryt"] +[sub_resource type="Resource" id="Resource_mur5c"] +script = ExtResource("5_wr38c") +block_class = &"ParameterBlock" +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): +"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] + +[sub_resource type="Resource" id="Resource_wo7ob"] +script = ExtResource("4_qtggh") +name = &"parameter_block" +position = Vector2(0, 0) +path_child_pairs = [] +block_serialized_properties = SubResource("Resource_mur5c") + +[sub_resource type="Resource" id="Resource_jb4li"] script = ExtResource("4_qtggh") name = &"is_node_in_group" position = Vector2(0, 0) -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_mbuv7")]] -block_serialized_properties = SubResource("Resource_rc730") +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_wo7ob")]] +block_serialized_properties = SubResource("Resource_1en27") -[sub_resource type="Resource" id="Resource_71yrt"] +[sub_resource type="Resource" id="Resource_s6roe"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"play_sound"], ["label", "StatementBlock"], ["color", Color(0.890196, 0.0588235, 0.752941, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"], ["statement", " -var __sound_node = get_node({name}) -__sound_node.volume_db = {db} -__sound_node.pitch_scale = {pitch} -__sound_node.play() -"], ["defaults", { -"db": "0.0", -"pitch": "1.0" -}], ["param_input_strings", { -"db": "0.0", +serialized_props = [["scope", ""], ["param_input_strings", { +"db": 0.0, "name": "wall_hit", -"pitch": "1.0" +"pitch": 1.0 }]] -[sub_resource type="Resource" id="Resource_f3xwp"] +[sub_resource type="Resource" id="Resource_kd52t"] script = ExtResource("4_qtggh") name = &"play_sound" -position = Vector2(0, 0) +position = Vector2(20, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_71yrt") - -[sub_resource type="Resource" id="Resource_wkj8h"] -script = ExtResource("5_wr38c") -block_class = &"ControlBlock" -serialized_props = [["block_name", &"if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ -"condition": false -}]]] +block_serialized_properties = SubResource("Resource_s6roe") -[sub_resource type="Resource" id="Resource_qmdbv"] +[sub_resource type="Resource" id="Resource_ky5ld"] script = ExtResource("4_qtggh") name = &"if" position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_fgryt")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_f3xwp")]] -block_serialized_properties = SubResource("Resource_wkj8h") - -[sub_resource type="Resource" id="Resource_dwd2k"] -script = ExtResource("5_wr38c") -block_class = &"ControlBlock" -serialized_props = [["block_name", &"if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ -"condition": false -}]]] +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_jb4li")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_kd52t")]] +block_serialized_properties = SubResource("Resource_e1awu") -[sub_resource type="Resource" id="Resource_rs6a0"] +[sub_resource type="Resource" id="Resource_ef7x8"] script = ExtResource("4_qtggh") name = &"if" position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_xsgv2")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_ic2jq")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_qmdbv")]] -block_serialized_properties = SubResource("Resource_dwd2k") +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_dj7fd")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_2lgdm")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ky5ld")]] +block_serialized_properties = SubResource("Resource_dnsl7") -[sub_resource type="Resource" id="Resource_7mdg3"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["block_name", &"rigidbody2d_on_entered"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(50, 475)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " -func _on_body_entered(_body: Node): - var body: NodePath = _body.get_path() -"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", "body_entered"]] - -[sub_resource type="Resource" id="Resource_tyrtu"] +[sub_resource type="Resource" id="Resource_1bd3d"] script = ExtResource("4_qtggh") name = &"rigidbody2d_on_entered" position = Vector2(50, 475) -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_gj1nu")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_rs6a0")]] -block_serialized_properties = SubResource("Resource_7mdg3") +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_bgppn")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ef7x8")]] +block_serialized_properties = SubResource("Resource_7kl7g") [sub_resource type="Resource" id="Resource_6m2mk"] script = ExtResource("7_uuuue") script_inherits = "RigidBody2D" -block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_1h6wi"), SubResource("Resource_gmlt0"), SubResource("Resource_tyrtu")]) -variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) +block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_phaw7"), SubResource("Resource_ane3b"), SubResource("Resource_1bd3d")]) +variables = Array[ExtResource("9_lo3p1")]([]) generated_script = "extends RigidBody2D @@ -539,23 +456,21 @@ func reset(): Transform2D.IDENTITY.translated((func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()) ) var __sound_node_1 = get_node('score_sound') - __sound_node_1.volume_db = 0.0 - __sound_node_1.pitch_scale = 1.0 + __sound_node_1.volume_db = 0 + __sound_node_1.pitch_scale = 1 __sound_node_1.play() +func _on_body_entered(body: Node2D): -func _on_body_entered(_body: Node): - var body: NodePath = _body.get_path() - - if get_node(body).is_in_group('paddles'): + if body.is_in_group('paddles'): var __sound_node_1 = get_node('paddle_hit') - __sound_node_1.volume_db = 0.0 - __sound_node_1.pitch_scale = 1.0 + __sound_node_1.volume_db = 0 + __sound_node_1.pitch_scale = 1 __sound_node_1.play() - if get_node(body).is_in_group('walls'): + if body.is_in_group('walls'): var __sound_node_2 = get_node('wall_hit') - __sound_node_2.volume_db = 0.0 - __sound_node_2.pitch_scale = 1.0 + __sound_node_2.volume_db = 0 + __sound_node_2.pitch_scale = 1 __sound_node_2.play() func _init(): @@ -563,123 +478,114 @@ func _init(): " version = 0 -[sub_resource type="Resource" id="Resource_itmch"] +[sub_resource type="Resource" id="Resource_xxj4u"] script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " -func _on_body_entered(_body: Node2D): - var body: NodePath = _body.get_path() -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_3wodo"] -script = ExtResource("4_qtggh") -name = &"parameter_block" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_itmch") +block_class = &"EntryBlock" +serialized_props = [["scope", ""], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_wo02o"] +[sub_resource type="Resource" id="Resource_lnfkn"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " -func _on_body_entered(_body: Node2D): - var body: NodePath = _body.get_path() -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): +"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_dcwek"] +[sub_resource type="Resource" id="Resource_r1q4l"] script = ExtResource("4_qtggh") name = &"parameter_block" position = Vector2(0, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_wo02o") +block_serialized_properties = SubResource("Resource_lnfkn") + +[sub_resource type="Resource" id="Resource_ft8ne"] +script = ExtResource("5_wr38c") +block_class = &"ControlBlock" +serialized_props = [["scope", ""], ["param_input_strings_array", [{ +"condition": false +}]]] -[sub_resource type="Resource" id="Resource_ma3m2"] +[sub_resource type="Resource" id="Resource_s06y5"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", &"is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { +serialized_props = [["scope", ""], ["param_input_strings", { "group": "balls", "node": "" }]] -[sub_resource type="Resource" id="Resource_bny5u"] -script = ExtResource("4_qtggh") -name = &"is_node_in_group" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_dcwek")]] -block_serialized_properties = SubResource("Resource_ma3m2") - -[sub_resource type="Resource" id="Resource_dkm1h"] +[sub_resource type="Resource" id="Resource_5itae"] script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["block_name", &"call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { -"group": "balls", -"method_name": "reset" -}]] +block_class = &"ParameterBlock" +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): +"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_57tvt"] +[sub_resource type="Resource" id="Resource_ht2bw"] script = ExtResource("4_qtggh") -name = &"call_group_method" +name = &"parameter_block" position = Vector2(0, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_dkm1h") +block_serialized_properties = SubResource("Resource_5itae") + +[sub_resource type="Resource" id="Resource_iyvmc"] +script = ExtResource("4_qtggh") +name = &"is_node_in_group" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_ht2bw")]] +block_serialized_properties = SubResource("Resource_s06y5") -[sub_resource type="Resource" id="Resource_lm5iy"] +[sub_resource type="Resource" id="Resource_eyu21"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["scope", ""], ["param_input_strings", { "group": "scoring", "method_name": "goal_left" }]] -[sub_resource type="Resource" id="Resource_26pqe"] +[sub_resource type="Resource" id="Resource_5hog4"] +script = ExtResource("5_wr38c") +block_class = &"StatementBlock" +serialized_props = [["scope", ""], ["param_input_strings", { +"group": "balls", +"method_name": "reset" +}]] + +[sub_resource type="Resource" id="Resource_x6rc5"] script = ExtResource("4_qtggh") -name = &"call_group_method" +name = &"call_method_group" position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_57tvt")]] -block_serialized_properties = SubResource("Resource_lm5iy") +path_child_pairs = [] +block_serialized_properties = SubResource("Resource_5hog4") -[sub_resource type="Resource" id="Resource_yd7xk"] -script = ExtResource("5_wr38c") -block_class = &"ControlBlock" -serialized_props = [["block_name", &"if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ -"condition": false -}]]] +[sub_resource type="Resource" id="Resource_s8f8n"] +script = ExtResource("4_qtggh") +name = &"call_method_group" +position = Vector2(20, 0) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_x6rc5")]] +block_serialized_properties = SubResource("Resource_eyu21") -[sub_resource type="Resource" id="Resource_wva5q"] +[sub_resource type="Resource" id="Resource_fs8jx"] script = ExtResource("4_qtggh") name = &"if" position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_bny5u")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_26pqe")]] -block_serialized_properties = SubResource("Resource_yd7xk") - -[sub_resource type="Resource" id="Resource_fufky"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["block_name", &"area2d_on_entered"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(100, 50)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " -func _on_body_entered(_body: Node2D): - var body: NodePath = _body.get_path() -"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", "body_entered"]] +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_iyvmc")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_s8f8n")]] +block_serialized_properties = SubResource("Resource_ft8ne") -[sub_resource type="Resource" id="Resource_fkj3e"] +[sub_resource type="Resource" id="Resource_m4esq"] script = ExtResource("4_qtggh") name = &"area2d_on_entered" -position = Vector2(100, 50) -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_3wodo")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_wva5q")]] -block_serialized_properties = SubResource("Resource_fufky") +position = Vector2(100, 350) +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_r1q4l")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_fs8jx")]] +block_serialized_properties = SubResource("Resource_xxj4u") [sub_resource type="Resource" id="Resource_4xylj"] script = ExtResource("7_uuuue") script_inherits = "Area2D" -block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_fkj3e")]) -variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) +block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_m4esq")]) +variables = Array[ExtResource("9_lo3p1")]([]) generated_script = "extends Area2D +func _on_body_entered(body: Node2D): -func _on_body_entered(_body: Node2D): - var body: NodePath = _body.get_path() - - if get_node(body).is_in_group('balls'): + if body.is_in_group('balls'): get_tree().call_group('scoring', 'goal_left') get_tree().call_group('balls', 'reset') @@ -688,123 +594,114 @@ func _init(): " version = 0 -[sub_resource type="Resource" id="Resource_8h48s"] +[sub_resource type="Resource" id="Resource_tfqiy"] script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " -func _on_body_entered(_body: Node2D): - var body: NodePath = _body.get_path() -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_0x61c"] -script = ExtResource("4_qtggh") -name = &"parameter_block" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_8h48s") +block_class = &"EntryBlock" +serialized_props = [["scope", ""], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_n8f73"] +[sub_resource type="Resource" id="Resource_5i6ga"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", " -func _on_body_entered(_body: Node2D): - var body: NodePath = _body.get_path() -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 22], ["param_input_strings", {}]] +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): +"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_tnwiy"] +[sub_resource type="Resource" id="Resource_oyktt"] script = ExtResource("4_qtggh") name = &"parameter_block" position = Vector2(0, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_n8f73") +block_serialized_properties = SubResource("Resource_5i6ga") + +[sub_resource type="Resource" id="Resource_pssgx"] +script = ExtResource("5_wr38c") +block_class = &"ControlBlock" +serialized_props = [["scope", ""], ["param_input_strings_array", [{ +"condition": false +}]]] -[sub_resource type="Resource" id="Resource_lurjo"] +[sub_resource type="Resource" id="Resource_2w0n0"] script = ExtResource("5_wr38c") block_class = &"ParameterBlock" -serialized_props = [["block_name", &"is_node_in_group"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Is {node: NODE_PATH} in group {group: STRING}"], ["statement", "get_node({node}).is_in_group({group})"], ["defaults", {}], ["variant_type", 1], ["param_input_strings", { +serialized_props = [["scope", ""], ["param_input_strings", { "group": "balls", "node": "" }]] -[sub_resource type="Resource" id="Resource_j6idn"] -script = ExtResource("4_qtggh") -name = &"is_node_in_group" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_tnwiy")]] -block_serialized_properties = SubResource("Resource_lurjo") - -[sub_resource type="Resource" id="Resource_y2wc6"] +[sub_resource type="Resource" id="Resource_q1iue"] script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["block_name", &"call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { -"group": "balls", -"method_name": "reset" -}]] +block_class = &"ParameterBlock" +serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): +"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] -[sub_resource type="Resource" id="Resource_krykp"] +[sub_resource type="Resource" id="Resource_aaxrr"] script = ExtResource("4_qtggh") -name = &"call_group_method" +name = &"parameter_block" position = Vector2(0, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_y2wc6") +block_serialized_properties = SubResource("Resource_q1iue") -[sub_resource type="Resource" id="Resource_daagb"] +[sub_resource type="Resource" id="Resource_005bn"] +script = ExtResource("4_qtggh") +name = &"is_node_in_group" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_aaxrr")]] +block_serialized_properties = SubResource("Resource_2w0n0") + +[sub_resource type="Resource" id="Resource_1n3fn"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"call_group_method"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Call method {method_name: STRING} in group {group: STRING}"], ["statement", "get_tree().call_group({group}, {method_name})"], ["defaults", {}], ["param_input_strings", { +serialized_props = [["scope", ""], ["param_input_strings", { "group": "scoring", "method_name": "goal_right" }]] -[sub_resource type="Resource" id="Resource_klxbs"] +[sub_resource type="Resource" id="Resource_jr3es"] +script = ExtResource("5_wr38c") +block_class = &"StatementBlock" +serialized_props = [["scope", ""], ["param_input_strings", { +"group": "balls", +"method_name": "reset" +}]] + +[sub_resource type="Resource" id="Resource_6moia"] script = ExtResource("4_qtggh") -name = &"call_group_method" +name = &"call_method_group" position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_krykp")]] -block_serialized_properties = SubResource("Resource_daagb") +path_child_pairs = [] +block_serialized_properties = SubResource("Resource_jr3es") -[sub_resource type="Resource" id="Resource_twkoi"] -script = ExtResource("5_wr38c") -block_class = &"ControlBlock" -serialized_props = [["block_name", &"if"], ["label", "Control Block"], ["color", Color(0.270588, 0.666667, 0.94902, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_formats", ["if {condition: BOOL}"]], ["statements", ["if {condition}:"]], ["defaults", {}], ["param_input_strings_array", [{ -"condition": false -}]]] +[sub_resource type="Resource" id="Resource_gy7s5"] +script = ExtResource("4_qtggh") +name = &"call_method_group" +position = Vector2(20, 0) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_6moia")]] +block_serialized_properties = SubResource("Resource_1n3fn") -[sub_resource type="Resource" id="Resource_1a3km"] +[sub_resource type="Resource" id="Resource_2ys4x"] script = ExtResource("4_qtggh") name = &"if" position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_j6idn")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_klxbs")]] -block_serialized_properties = SubResource("Resource_twkoi") - -[sub_resource type="Resource" id="Resource_c4had"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["block_name", &"area2d_on_entered"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(75, 50)], ["scope", ""], ["block_format", "On [body: NODE_PATH] entered"], ["statement", " -func _on_body_entered(_body: Node2D): - var body: NodePath = _body.get_path() -"], ["defaults", {}], ["param_input_strings", {}], ["signal_name", "body_entered"]] +path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_005bn")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_gy7s5")]] +block_serialized_properties = SubResource("Resource_pssgx") -[sub_resource type="Resource" id="Resource_qtw4n"] +[sub_resource type="Resource" id="Resource_mi6hv"] script = ExtResource("4_qtggh") name = &"area2d_on_entered" -position = Vector2(75, 50) -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_0x61c")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_1a3km")]] -block_serialized_properties = SubResource("Resource_c4had") +position = Vector2(75, 350) +path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_oyktt")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_2ys4x")]] +block_serialized_properties = SubResource("Resource_tfqiy") [sub_resource type="Resource" id="Resource_xoc8a"] script = ExtResource("7_uuuue") script_inherits = "Area2D" -block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_qtw4n")]) -variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) +block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_mi6hv")]) +variables = Array[ExtResource("9_lo3p1")]([]) generated_script = "extends Area2D +func _on_body_entered(body: Node2D): -func _on_body_entered(_body: Node2D): - var body: NodePath = _body.get_path() - - if get_node(body).is_in_group('balls'): + if body.is_in_group('balls'): get_tree().call_group('scoring', 'goal_right') get_tree().call_group('balls', 'reset') @@ -813,121 +710,121 @@ func _init(): " version = 0 -[sub_resource type="Resource" id="Resource_tqdqf"] +[sub_resource type="Resource" id="Resource_n6aol"] +script = ExtResource("5_wr38c") +block_class = &"EntryBlock" +serialized_props = [["scope", ""], ["param_input_strings", {}]] + +[sub_resource type="Resource" id="Resource_76s7d"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"add_to_group"], ["label", "StatementBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Add to group {group: STRING}"], ["statement", "add_to_group({group})"], ["defaults", {}], ["param_input_strings", { -"group": "scoring" +serialized_props = [["scope", ""], ["param_input_strings", { +"score": 0 }]] -[sub_resource type="Resource" id="Resource_uxpim"] -script = ExtResource("4_qtggh") -name = &"add_to_group" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_tqdqf") - -[sub_resource type="Resource" id="Resource_yuj6e"] +[sub_resource type="Resource" id="Resource_clf6h"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"simplescoring_set_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set player 2 score to {score: INT}"], ["statement", "score_right = {score}"], ["defaults", {}], ["param_input_strings", { -"score": "0" +serialized_props = [["scope", ""], ["param_input_strings", { +"score": 0 }]] -[sub_resource type="Resource" id="Resource_oar78"] -script = ExtResource("4_qtggh") -name = &"simplescoring_set_score" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_uxpim")]] -block_serialized_properties = SubResource("Resource_yuj6e") - -[sub_resource type="Resource" id="Resource_gkoq3"] +[sub_resource type="Resource" id="Resource_rpicc"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"simplescoring_set_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Set player 1 score to {score: INT}"], ["statement", "score_left = {score}"], ["defaults", {}], ["param_input_strings", { -"score": "0" +serialized_props = [["scope", ""], ["param_input_strings", { +"group": "scoring" }]] -[sub_resource type="Resource" id="Resource_8xxm3"] +[sub_resource type="Resource" id="Resource_hxlka"] script = ExtResource("4_qtggh") -name = &"simplescoring_set_score" +name = &"add_to_group" position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_oar78")]] -block_serialized_properties = SubResource("Resource_gkoq3") +path_child_pairs = [] +block_serialized_properties = SubResource("Resource_rpicc") -[sub_resource type="Resource" id="Resource_g3mty"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", ""], ["param_input_strings", {}]] +[sub_resource type="Resource" id="Resource_os82j"] +script = ExtResource("4_qtggh") +name = &"simplescoring_set_score_player_2" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_hxlka")]] +block_serialized_properties = SubResource("Resource_clf6h") + +[sub_resource type="Resource" id="Resource_2cci1"] +script = ExtResource("4_qtggh") +name = &"simplescoring_set_score_player_1" +position = Vector2(0, 0) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_os82j")]] +block_serialized_properties = SubResource("Resource_76s7d") -[sub_resource type="Resource" id="Resource_njwj4"] +[sub_resource type="Resource" id="Resource_e0qr3"] script = ExtResource("4_qtggh") name = &"ready" -position = Vector2(54, 47) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_8xxm3")]] -block_serialized_properties = SubResource("Resource_g3mty") +position = Vector2(50, 25) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_2cci1")]] +block_serialized_properties = SubResource("Resource_n6aol") + +[sub_resource type="Resource" id="Resource_mhqvs"] +script = ExtResource("5_wr38c") +block_class = &"EntryBlock" +serialized_props = [["scope", ""], ["param_input_strings", { +"method_name": "goal_right" +}]] -[sub_resource type="Resource" id="Resource_3j7i4"] +[sub_resource type="Resource" id="Resource_nd6ab"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"simplescoring_change_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Change player 1 score by {score: INT}"], ["statement", "score_left += {score}"], ["defaults", {}], ["param_input_strings", { -"score": "1" +serialized_props = [["scope", ""], ["param_input_strings", { +"score": 1 }]] -[sub_resource type="Resource" id="Resource_ntjp0"] +[sub_resource type="Resource" id="Resource_m8e8y"] script = ExtResource("4_qtggh") -name = &"simplescoring_change_score" +name = &"simplescoring_change_score_player_1" position = Vector2(0, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_3j7i4") - -[sub_resource type="Resource" id="Resource_2e0ed"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["block_name", &"define_method"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(50, 300)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { -"method_name": "goal_right" -}], ["signal_name", ""]] +block_serialized_properties = SubResource("Resource_nd6ab") -[sub_resource type="Resource" id="Resource_t8g7r"] +[sub_resource type="Resource" id="Resource_kr7eg"] script = ExtResource("4_qtggh") name = &"define_method" -position = Vector2(50, 300) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ntjp0")]] -block_serialized_properties = SubResource("Resource_2e0ed") +position = Vector2(50, 275) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_m8e8y")]] +block_serialized_properties = SubResource("Resource_mhqvs") + +[sub_resource type="Resource" id="Resource_3fbnf"] +script = ExtResource("5_wr38c") +block_class = &"EntryBlock" +serialized_props = [["scope", ""], ["param_input_strings", { +"method_name": "goal_left" +}]] -[sub_resource type="Resource" id="Resource_cxj82"] +[sub_resource type="Resource" id="Resource_7rc07"] script = ExtResource("5_wr38c") block_class = &"StatementBlock" -serialized_props = [["block_name", &"simplescoring_change_score"], ["label", "StatementBlock"], ["color", Color(0.811765, 0.415686, 0.529412, 1)], ["block_type", 2], ["position", Vector2(0, 0)], ["scope", ""], ["block_format", "Change player 2 score by {score: INT}"], ["statement", "score_right += {score}"], ["defaults", {}], ["param_input_strings", { -"score": "1" +serialized_props = [["scope", ""], ["param_input_strings", { +"score": 1 }]] -[sub_resource type="Resource" id="Resource_c17ry"] +[sub_resource type="Resource" id="Resource_7dmgm"] script = ExtResource("4_qtggh") -name = &"simplescoring_change_score" +name = &"simplescoring_change_score_player_2" position = Vector2(0, 0) path_child_pairs = [] -block_serialized_properties = SubResource("Resource_cxj82") - -[sub_resource type="Resource" id="Resource_udc68"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["block_name", &"define_method"], ["label", "EntryBlock"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 1], ["position", Vector2(50, 450)], ["scope", ""], ["block_format", "Define method {method_name: NIL}"], ["statement", "func {method_name}():"], ["defaults", {}], ["param_input_strings", { -"method_name": "goal_left" -}], ["signal_name", ""]] +block_serialized_properties = SubResource("Resource_7rc07") -[sub_resource type="Resource" id="Resource_v2aur"] +[sub_resource type="Resource" id="Resource_cnona"] script = ExtResource("4_qtggh") name = &"define_method" -position = Vector2(50, 450) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_c17ry")]] -block_serialized_properties = SubResource("Resource_udc68") +position = Vector2(50, 425) +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_7dmgm")]] +block_serialized_properties = SubResource("Resource_3fbnf") [sub_resource type="Resource" id="Resource_q418f"] script = ExtResource("7_uuuue") script_inherits = "SimpleScoring" -block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_njwj4"), SubResource("Resource_t8g7r"), SubResource("Resource_v2aur")]) -variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) +block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_e0qr3"), SubResource("Resource_kr7eg"), SubResource("Resource_cnona")]) +variables = Array[ExtResource("9_lo3p1")]([]) generated_script = "extends SimpleScoring From 83267f1a73d0a36bee7ee165d00784ce36a889ef Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Thu, 29 Aug 2024 10:02:37 -0700 Subject: [PATCH 180/423] Check _selected_block_code is still valid before disconnecting Previously, it was possible for _selected_block_code to refer to an object which had been freed, which resulted in an error when calling disconnect for its signals. --- addons/block_code/block_code_plugin.gd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index f7e0ac8a..7b865235 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -145,7 +145,7 @@ func select_block_code_node(block_code: BlockCode): if not is_block_code_editable(block_code): block_code = null - if _selected_block_code: + if is_instance_valid(_selected_block_code): _selected_block_code.tree_entered.disconnect(_on_selected_block_code_changed) _selected_block_code.tree_exited.disconnect(_on_selected_block_code_changed) _selected_block_code.property_list_changed.disconnect(_on_selected_block_code_changed) @@ -153,7 +153,7 @@ func select_block_code_node(block_code: BlockCode): _selected_block_code = block_code - if _selected_block_code: + if is_instance_valid(_selected_block_code): _selected_block_code.tree_entered.connect(_on_selected_block_code_changed) _selected_block_code.tree_exited.connect(_on_selected_block_code_changed) _selected_block_code.property_list_changed.connect(_on_selected_block_code_changed) From 9e996fe6022f63b8669dbae04dc511d58c968d33 Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Thu, 29 Aug 2024 16:02:50 -0600 Subject: [PATCH 181/423] blocks: Add descriptions for Viewport blocks These were missing, and it's better to have something than nothing at all! https://phabricator.endlessm.com/T35563 --- addons/block_code/blocks/graphics/viewport_center.tres | 2 +- addons/block_code/blocks/graphics/viewport_height.tres | 2 +- addons/block_code/blocks/graphics/viewport_width.tres | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/block_code/blocks/graphics/viewport_center.tres b/addons/block_code/blocks/graphics/viewport_center.tres index 3779ce21..e3b65041 100644 --- a/addons/block_code/blocks/graphics/viewport_center.tres +++ b/addons/block_code/blocks/graphics/viewport_center.tres @@ -5,7 +5,7 @@ [resource] script = ExtResource("1_rc1so") name = &"viewport_center" -description = "" +description = "Coordinates of the middle of the viewable screen when playing." category = "Graphics | Viewport" type = 3 variant_type = 5 diff --git a/addons/block_code/blocks/graphics/viewport_height.tres b/addons/block_code/blocks/graphics/viewport_height.tres index 789de6d6..50dcf640 100644 --- a/addons/block_code/blocks/graphics/viewport_height.tres +++ b/addons/block_code/blocks/graphics/viewport_height.tres @@ -5,7 +5,7 @@ [resource] script = ExtResource("1_1debb") name = &"viewport_height" -description = "" +description = "How tall the viewable screen is when playing." category = "Graphics | Viewport" type = 3 variant_type = 3 diff --git a/addons/block_code/blocks/graphics/viewport_width.tres b/addons/block_code/blocks/graphics/viewport_width.tres index ceb30730..39ba35aa 100644 --- a/addons/block_code/blocks/graphics/viewport_width.tres +++ b/addons/block_code/blocks/graphics/viewport_width.tres @@ -5,7 +5,7 @@ [resource] script = ExtResource("1_ll4rh") name = &"viewport_width" -description = "" +description = "How wide the viewable screen is when playing." category = "Graphics | Viewport" type = 3 variant_type = 3 From edfbe8d72ee5f736d02c05c994b3332936afe82f Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Thu, 29 Aug 2024 16:04:07 -0600 Subject: [PATCH 182/423] characterbody2d_move: add description Hopefully this makes sense? It documents the order of the inputs as well which I think is important. https://phabricator.endlessm.com/T35563 --- addons/block_code/blocks/input/characterbody2d_move.tres | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/block_code/blocks/input/characterbody2d_move.tres b/addons/block_code/blocks/input/characterbody2d_move.tres index 07614611..89e20a9a 100644 --- a/addons/block_code/blocks/input/characterbody2d_move.tres +++ b/addons/block_code/blocks/input/characterbody2d_move.tres @@ -6,7 +6,7 @@ script = ExtResource("1_btxic") name = &"characterbody2d_move" target_node_class = "CharacterBody2D" -description = "" +description = "Move the node up, down, left, and right with the keyboard. Speed is in the format x, y (left/right, up/down)." category = "Input" type = 2 variant_type = 0 From ea8a90f9865852734577615c801ad99ee5e7afcb Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Thu, 29 Aug 2024 16:38:12 -0600 Subject: [PATCH 183/423] characterbody2d_move: improve description --- addons/block_code/blocks/input/characterbody2d_move.tres | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/block_code/blocks/input/characterbody2d_move.tres b/addons/block_code/blocks/input/characterbody2d_move.tres index 89e20a9a..688ff5af 100644 --- a/addons/block_code/blocks/input/characterbody2d_move.tres +++ b/addons/block_code/blocks/input/characterbody2d_move.tres @@ -6,7 +6,7 @@ script = ExtResource("1_btxic") name = &"characterbody2d_move" target_node_class = "CharacterBody2D" -description = "Move the node up, down, left, and right with the keyboard. Speed is in the format x, y (left/right, up/down)." +description = "Move the character up, down, left, and right with the keyboard using the given keys. The speed of movement can be adjusted separately for x (left and right) and y (up and down)." category = "Input" type = 2 variant_type = 0 From 34f9beee5936b5ad4c53bf1cc3564158e4fdde65 Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Thu, 29 Aug 2024 17:11:33 -0600 Subject: [PATCH 184/423] simple_character: Add description for tooltip The multi-line formatting is a little weird in the code, but it looks nice as a tooltip! https://phabricator.endlessm.com/T35563 --- .../simple_nodes/simple_character/simple_character.gd | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index dffaff35..90987be1 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -129,6 +129,13 @@ static func setup_custom_blocks(): block_definition.category = "Input" block_definition.type = Types.BlockType.STATEMENT block_definition.display_template = "Move with {player: OPTION} buttons as {kind: OPTION}" + block_definition.description = """Move the character using the “Player 1” or “Player 2” controls as configured in Godot. + +“Top-down” enables the character to move in both x (vertical) and y (horizontal) dimensions, as if the camera is above the character, looking down. No gravity is added. + +“Platformer” enables the character to move as if the camera is looking from the side, like a side-scroller. Gravity is applied on the x (vertical) axis, making the character fall down until they collide. + +“Spaceship” uses the left/right controls to turn the character and up/down controls to go forward or backward.""" # TODO: delta here is assumed to be the parameter name of # the _process or _physics_process method: block_definition.code_template = 'move_with_player_buttons("{player}", "{kind}", delta)' From e08d44861d0c1bda3b462dc0b9245f2b5ab7738e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Wed, 4 Sep 2024 13:43:29 -0300 Subject: [PATCH 185/423] Fix signal name for area2d_on_exited block The signal needs to be body_exited. --- addons/block_code/blocks/communication/area2d_on_exited.tres | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/block_code/blocks/communication/area2d_on_exited.tres b/addons/block_code/blocks/communication/area2d_on_exited.tres index 3236546f..ba3d0e53 100644 --- a/addons/block_code/blocks/communication/area2d_on_exited.tres +++ b/addons/block_code/blocks/communication/area2d_on_exited.tres @@ -14,5 +14,5 @@ display_template = "On [body: OBJECT] exited" code_template = "func _on_body_exited(body: Node2D): " defaults = {} -signal_name = "body_entered" +signal_name = "body_exited" scope = "" From ec063a7d67587b7827f4a57820ff1b58df554c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Thu, 5 Sep 2024 10:38:00 -0300 Subject: [PATCH 186/423] Remove _exit_tree methods from Simple nodes There is no need for this cleanup because from docs: [1] > If the node has children, its _exit_tree callback will be called last, > after all its children have left the tree. Also because: [2] > when a node is freed with Object.free or queue_free, it will also free > all its children. Further, this removes the sprite and collision while in the editor when the user switches to another scene tab #213. [1] https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-private-method-exit-tree [2] https://docs.godotengine.org/en/stable/classes/class_node.html#description Fixes #213 --- .../simple_nodes/simple_character/simple_character.gd | 10 ---------- .../simple_nodes/simple_scoring/simple_scoring.gd | 6 ------ 2 files changed, 16 deletions(-) diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index 90987be1..4a934b1e 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -72,16 +72,6 @@ func simple_setup(): _texture_updated() -func _exit_tree(): - if collision: - collision.queue_free() - collision = null - - if sprite: - sprite.queue_free() - sprite = null - - func get_custom_class(): return "SimpleCharacter" diff --git a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd index 185fcba9..c1b2104b 100644 --- a/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd +++ b/addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd @@ -63,12 +63,6 @@ func simple_setup(): add_child(right_label) -func _exit_tree(): - for label in _score_labels.values(): - label.queue_free() - _score_labels.clear() - - func get_custom_class(): return "SimpleScoring" From b3c4890e49d31678ead8ccb3dd07061c7bebed3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Thu, 5 Sep 2024 11:15:53 -0300 Subject: [PATCH 187/423] SimpleCharacter: Don't impose a collision shape Change the logic so there is no fallback 100x100 collision shape if a texture is not provided. This way the user can customize their character by adding their own sprites and collision shapes as node children. The simple setup of passing a texture is still maintained. Although it has been found to be inflexible (can't resize the texture from the canvas, can't change the shape of the collision). Addresses #215 --- .../simple_character/simple_character.gd | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index 4a934b1e..d1fd0ac1 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -6,6 +6,8 @@ const BlockDefinition = preload("res://addons/block_code/code_generation/block_d const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") const Types = preload("res://addons/block_code/types/types.gd") +## A texture can be provided for simple setup. If provided, the character will have a collision box +## that matches the size of the texture. @export var texture: Texture2D: set = _set_texture @@ -44,8 +46,28 @@ func _set_texture(new_texture): func _texture_updated(): + if not texture: + if sprite: + sprite.queue_free() + sprite = null + if collision: + collision.queue_free() + collision = null + return + + if not sprite: + sprite = Sprite2D.new() + sprite.name = &"Sprite2D" + add_child(sprite) + + if not collision: + collision = CollisionShape2D.new() + collision.name = &"CollisionShape2D" + collision.shape = RectangleShape2D.new() + add_child(collision) + sprite.texture = texture - collision.shape.size = Vector2(100, 100) if texture == null else texture.get_size() + collision.shape.size = texture.get_size() ## Nodes in the "affected_by_gravity" group will receive gravity changes: @@ -59,16 +81,6 @@ func _ready(): func simple_setup(): add_to_group("affected_by_gravity", true) - - sprite = Sprite2D.new() - sprite.name = &"Sprite2D" - add_child(sprite) - - collision = CollisionShape2D.new() - collision.name = &"CollisionShape2D" - collision.shape = RectangleShape2D.new() - add_child(collision) - _texture_updated() From c4901cef62ade3230edfeb5f41d84577dd3f1c76 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Wed, 4 Sep 2024 16:07:41 -0600 Subject: [PATCH 188/423] Use StringName variant for unquoted strings Normally a Variant of type String is quoted for code generation. That breaks in some scenarios such as defining a method where the string needs to be inserted verbatim. For that, use StringName under the assumption that we won't use interned strings to represent quoted strings later. --- addons/block_code/blocks/communication/define_method.tres | 3 ++- addons/block_code/types/types.gd | 2 ++ .../ui/blocks/utilities/parameter_input/parameter_input.gd | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/block_code/blocks/communication/define_method.tres b/addons/block_code/blocks/communication/define_method.tres index 4278151d..f3bd8926 100644 --- a/addons/block_code/blocks/communication/define_method.tres +++ b/addons/block_code/blocks/communication/define_method.tres @@ -5,11 +5,12 @@ [resource] script = ExtResource("1_6e473") name = &"define_method" +target_node_class = "" description = "Define a method/function with following statements" category = "Communication | Methods" type = 1 variant_type = 0 -display_template = "Define method {method_name: NIL}" +display_template = "Define method {method_name: STRING_NAME}" code_template = "func {method_name}():" defaults = {} signal_name = "" diff --git a/addons/block_code/types/types.gd b/addons/block_code/types/types.gd index aab4bf79..99f64c36 100644 --- a/addons/block_code/types/types.gd +++ b/addons/block_code/types/types.gd @@ -18,6 +18,7 @@ const VARIANT_TYPE_TO_STRING: Dictionary = { TYPE_NODE_PATH: "NODE_PATH", TYPE_OBJECT: "OBJECT", TYPE_NIL: "NIL", + TYPE_STRING_NAME: "STRING_NAME", } const STRING_TO_VARIANT_TYPE: Dictionary = { @@ -30,6 +31,7 @@ const STRING_TO_VARIANT_TYPE: Dictionary = { "NODE_PATH": TYPE_NODE_PATH, "OBJECT": TYPE_OBJECT, "NIL": TYPE_NIL, + "STRING_NAME": TYPE_STRING_NAME, } const cast_relationships = [ diff --git a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd index 96abece8..104bf792 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd +++ b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd @@ -85,6 +85,8 @@ func get_raw_input(): return null if _line_edit.text == "" else int(_line_edit.text) TYPE_FLOAT: return null if _line_edit.text == "" else float(_line_edit.text) + TYPE_STRING_NAME: + return StringName(_line_edit.text) TYPE_NIL: return _line_edit.text _: From e2a158c67723d2a15f0d91393ad0578f09c582bf Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Wed, 4 Sep 2024 16:23:48 -0600 Subject: [PATCH 189/423] BlocksCatalog: Create parameter output definitions Automatically create parameter output block definitions based on any entry blocks that use the `[param: TYPE]` bracket template. These will be used later when converting UI blocks to be based on BlockDefinition. --- .../code_generation/blocks_catalog.gd | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/addons/block_code/code_generation/blocks_catalog.gd b/addons/block_code/code_generation/blocks_catalog.gd index 18ec616b..a6b6b615 100644 --- a/addons/block_code/code_generation/blocks_catalog.gd +++ b/addons/block_code/code_generation/blocks_catalog.gd @@ -94,6 +94,40 @@ static func _setup_definitions_from_files(): _by_class_name[target][block_definition.name] = block_definition +static func _add_output_definitions(definitions: Array[BlockDefinition]): + # Capture things of format [test] + var _output_regex := RegEx.create_from_string("\\[([^\\]]+)\\]") + + for definition in definitions: + if definition.type != Types.BlockType.ENTRY: + continue + + for reg_match in _output_regex.search_all(definition.display_template): + var parts := reg_match.get_string(1).split(": ") + var param_name := parts[0] + var param_type: Variant.Type = Types.STRING_TO_VARIANT_TYPE[parts[1]] + + var output_def := BlockDefinition.new() + output_def.name = &"%s_%s" % [definition.name, param_name] + output_def.target_node_class = definition.target_node_class + output_def.category = definition.category + output_def.type = Types.BlockType.VALUE + output_def.variant_type = param_type + output_def.display_template = param_name + output_def.code_template = param_name + output_def.scope = definition.code_template + + # Note that these are not added to the _by_class_name dict + # because they only make sense within the entry block scope. + _catalog[output_def.name] = output_def + + +static func _setup_output_definitions(): + var definitions: Array[BlockDefinition] + definitions.assign(_catalog.values()) + _add_output_definitions(definitions) + + static func _add_property_definitions(_class_name: String, property_list: Array[Dictionary], property_settings: Dictionary): for property in property_list: if not property.name in property_settings: @@ -218,6 +252,7 @@ static func setup(): _catalog = {} _setup_definitions_from_files() + _setup_output_definitions() _setup_properties_for_class() _setup_input_block() @@ -252,4 +287,5 @@ static func add_custom_blocks( _catalog[block_definition.name] = block_definition _by_class_name[_class_name][block_definition.name] = block_definition + _add_output_definitions(block_definitions) _add_property_definitions(_class_name, property_list, property_settings) From bd4028e19c84c488fd828f52a52cfe9d39631450 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Wed, 4 Sep 2024 23:06:55 -0600 Subject: [PATCH 190/423] Move OptionData and VariableResource to code_generation These are being used in all states, and the common location is code generation. While here, rename VariableResource to VariableDefinition to better match BlockDefinition. Similarly, remove both from the global class registry. --- .../block_code/blocks/graphics/animationplayer_play.tres | 2 +- addons/block_code/blocks/logic/compare.tres | 2 +- addons/block_code/blocks/sounds/pause_continue_sound.tres | 2 +- addons/block_code/code_generation/blocks_catalog.gd | 1 + .../{ui/block_canvas => code_generation}/option_data.gd | 1 - .../variable_definition.gd} | 1 - addons/block_code/examples/pong_game/pong_game.tscn | 4 ++-- .../block_code/serialization/block_script_serialization.gd | 6 ++++-- addons/block_code/serialization/default_block_script.tres | 3 ++- .../simple_nodes/simple_character/simple_character.gd | 1 + .../ui/blocks/utilities/parameter_input/parameter_input.gd | 1 + addons/block_code/ui/main_panel.gd | 3 ++- addons/block_code/ui/picker/categories/category_factory.gd | 3 ++- .../variable_category/variable_category_display.gd | 5 +++-- addons/block_code/ui/picker/picker.gd | 5 +++-- addons/block_code/ui/util.gd | 7 ++++--- 16 files changed, 28 insertions(+), 19 deletions(-) rename addons/block_code/{ui/block_canvas => code_generation}/option_data.gd (88%) rename addons/block_code/{ui/block_canvas/variable_resource.gd => code_generation/variable_definition.gd} (87%) diff --git a/addons/block_code/blocks/graphics/animationplayer_play.tres b/addons/block_code/blocks/graphics/animationplayer_play.tres index 43bbce1e..2a2f373f 100644 --- a/addons/block_code/blocks/graphics/animationplayer_play.tres +++ b/addons/block_code/blocks/graphics/animationplayer_play.tres @@ -1,7 +1,7 @@ [gd_resource type="Resource" load_steps=4 format=3 uid="uid://c5e1byehtxwc0"] [ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_emeuv"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="1_xu43h"] +[ext_resource type="Script" path="res://addons/block_code/code_generation/option_data.gd" id="1_xu43h"] [sub_resource type="Resource" id="Resource_vnp2w"] script = ExtResource("1_xu43h") diff --git a/addons/block_code/blocks/logic/compare.tres b/addons/block_code/blocks/logic/compare.tres index 8e124cf7..f657ba44 100644 --- a/addons/block_code/blocks/logic/compare.tres +++ b/addons/block_code/blocks/logic/compare.tres @@ -1,6 +1,6 @@ [gd_resource type="Resource" load_steps=4 format=3 uid="uid://pr5wnn3ltkbo"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="1_hcv2h"] +[ext_resource type="Script" path="res://addons/block_code/code_generation/option_data.gd" id="1_hcv2h"] [ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_wp40r"] [sub_resource type="Resource" id="Resource_ie4sg"] diff --git a/addons/block_code/blocks/sounds/pause_continue_sound.tres b/addons/block_code/blocks/sounds/pause_continue_sound.tres index 074e0352..3cbfab88 100644 --- a/addons/block_code/blocks/sounds/pause_continue_sound.tres +++ b/addons/block_code/blocks/sounds/pause_continue_sound.tres @@ -1,6 +1,6 @@ [gd_resource type="Resource" load_steps=4 format=3 uid="uid://wpdspamg3f6g"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="1_ilhdq"] +[ext_resource type="Script" path="res://addons/block_code/code_generation/option_data.gd" id="1_ilhdq"] [ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_q04gm"] [sub_resource type="Resource" id="Resource_lalgp"] diff --git a/addons/block_code/code_generation/blocks_catalog.gd b/addons/block_code/code_generation/blocks_catalog.gd index a6b6b615..8c8fda12 100644 --- a/addons/block_code/code_generation/blocks_catalog.gd +++ b/addons/block_code/code_generation/blocks_catalog.gd @@ -1,6 +1,7 @@ extends Object const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") +const OptionData = preload("res://addons/block_code/code_generation/option_data.gd") const Types = preload("res://addons/block_code/types/types.gd") const Util = preload("res://addons/block_code/code_generation/util.gd") diff --git a/addons/block_code/ui/block_canvas/option_data.gd b/addons/block_code/code_generation/option_data.gd similarity index 88% rename from addons/block_code/ui/block_canvas/option_data.gd rename to addons/block_code/code_generation/option_data.gd index d233c819..20364c04 100644 --- a/addons/block_code/ui/block_canvas/option_data.gd +++ b/addons/block_code/code_generation/option_data.gd @@ -1,4 +1,3 @@ -class_name OptionData extends Resource @export var selected: int diff --git a/addons/block_code/ui/block_canvas/variable_resource.gd b/addons/block_code/code_generation/variable_definition.gd similarity index 87% rename from addons/block_code/ui/block_canvas/variable_resource.gd rename to addons/block_code/code_generation/variable_definition.gd index 119d4371..680de228 100644 --- a/addons/block_code/ui/block_canvas/variable_resource.gd +++ b/addons/block_code/code_generation/variable_definition.gd @@ -1,4 +1,3 @@ -class_name VariableResource extends Resource @export var var_name: String diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index ec3ab35c..4aaa9329 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -6,9 +6,9 @@ [ext_resource type="Script" path="res://addons/block_code/serialization/block_serialization.gd" id="4_qtggh"] [ext_resource type="Texture2D" uid="uid://tplpgtnfeda0" path="res://addons/block_code/examples/pong_game/assets/paddle.png" id="4_ra7bh"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_serialized_properties.gd" id="5_wr38c"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/option_data.gd" id="7_3q6bj"] +[ext_resource type="Script" path="res://addons/block_code/code_generation/option_data.gd" id="7_3q6bj"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_script_serialization.gd" id="7_uuuue"] -[ext_resource type="Script" path="res://addons/block_code/ui/block_canvas/variable_resource.gd" id="9_lo3p1"] +[ext_resource type="Script" path="res://addons/block_code/code_generation/variable_definition.gd" id="9_lo3p1"] [ext_resource type="PackedScene" uid="uid://c7l70grmkauij" path="res://addons/block_code/examples/pong_game/ball.tscn" id="9_xrqll"] [ext_resource type="PackedScene" uid="uid://fhoapg3anjsu" path="res://addons/block_code/examples/pong_game/goal_area.tscn" id="12_nqmxu"] [ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd" id="13_tg3yk"] diff --git a/addons/block_code/serialization/block_script_serialization.gd b/addons/block_code/serialization/block_script_serialization.gd index 74be0856..4015fd68 100644 --- a/addons/block_code/serialization/block_script_serialization.gd +++ b/addons/block_code/serialization/block_script_serialization.gd @@ -1,14 +1,16 @@ class_name BlockScriptSerialization extends Resource +const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") + @export var script_inherits: String @export var block_trees: Array[BlockSerialization] -@export var variables: Array[VariableResource] +@export var variables: Array[VariableDefinition] @export var generated_script: String @export var version: int -func _init(p_script_inherits: String = "", p_block_trees: Array[BlockSerialization] = [], p_variables: Array[VariableResource] = [], p_generated_script: String = "", p_version = 0): +func _init(p_script_inherits: String = "", p_block_trees: Array[BlockSerialization] = [], p_variables: Array[VariableDefinition] = [], p_generated_script: String = "", p_version = 0): script_inherits = p_script_inherits block_trees = p_block_trees generated_script = p_generated_script diff --git a/addons/block_code/serialization/default_block_script.tres b/addons/block_code/serialization/default_block_script.tres index bb6cc2ce..5c3459d9 100644 --- a/addons/block_code/serialization/default_block_script.tres +++ b/addons/block_code/serialization/default_block_script.tres @@ -3,6 +3,7 @@ [ext_resource type="Script" path="res://addons/block_code/serialization/block_serialization.gd" id="1_barc5"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_serialized_properties.gd" id="2_cgfpx"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_script_serialization.gd" id="4_cqq7x"] +[ext_resource type="Script" path="res://addons/block_code/code_generation/variable_definition.gd" id="3_wb2fg"] [sub_resource type="Resource" id="Resource_b0aen"] script = ExtResource("2_cgfpx") @@ -20,6 +21,6 @@ block_serialized_properties = SubResource("Resource_b0aen") script = ExtResource("4_cqq7x") script_inherits = "INHERIT_DEFAULT" block_trees = Array[ExtResource("1_barc5")]([SubResource("Resource_1h6wi")]) -variables = Array[Resource("res://addons/block_code/ui/block_canvas/variable_resource.gd")]([]) +variables = Array[ExtResource("3_wb2fg")]([]) generated_script = "extends INHERIT_DEFAULT" version = 0 diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index dffaff35..9e2012e4 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -4,6 +4,7 @@ extends CharacterBody2D const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") +const OptionData = preload("res://addons/block_code/code_generation/option_data.gd") const Types = preload("res://addons/block_code/types/types.gd") @export var texture: Texture2D: diff --git a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd index 104bf792..d64d380b 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd +++ b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd @@ -1,6 +1,7 @@ @tool extends MarginContainer +const OptionData = preload("res://addons/block_code/code_generation/option_data.gd") const Types = preload("res://addons/block_code/types/types.gd") signal modified diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index 810f378e..96a100aa 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -8,6 +8,7 @@ const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd") const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") const Picker = preload("res://addons/block_code/ui/picker/picker.gd") const TitleBar = preload("res://addons/block_code/ui/title_bar/title_bar.gd") +const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") @onready var _picker: Picker = %Picker @onready var _block_canvas: BlockCanvas = %BlockCanvas @@ -261,7 +262,7 @@ func _set_selection(nodes: Array[Node]): EditorInterface.get_selection().add_node(node) -func _create_variable(variable: VariableResource): +func _create_variable(variable: VariableDefinition): if _current_block_code_node == null: print("No script loaded to add variable to.") return diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 934a333b..c7949e84 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -5,6 +5,7 @@ const BlockCategory = preload("res://addons/block_code/ui/picker/categories/bloc const Types = preload("res://addons/block_code/types/types.gd") const Util = preload("res://addons/block_code/ui/util.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") +const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") ## Compare block categories for sorting. Compare by order then name. @@ -106,5 +107,5 @@ static func get_inherited_blocks(_class_name: String) -> Array[Block]: return Util.instantiate_blocks_for_class(_class_name) -static func get_variable_blocks(variables: Array[VariableResource]): +static func get_variable_blocks(variables: Array[VariableDefinition]): return Util.instantiate_variable_blocks(variables) diff --git a/addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd b/addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd index 6f27bf3b..6e049dc1 100644 --- a/addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd +++ b/addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd @@ -2,8 +2,9 @@ extends "res://addons/block_code/ui/picker/categories/block_category_display.gd" const Types = preload("res://addons/block_code/types/types.gd") +const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") -signal variable_created(variable: VariableResource) +signal variable_created(variable: VariableDefinition) @onready var variable_blocks := %VariableBlocks @@ -13,4 +14,4 @@ func _ready(): func _on_create_variable(var_name, var_type): - variable_created.emit(VariableResource.new(var_name, Types.STRING_TO_VARIANT_TYPE[var_type])) + variable_created.emit(VariableDefinition.new(var_name, Types.STRING_TO_VARIANT_TYPE[var_type])) diff --git a/addons/block_code/ui/picker/picker.gd b/addons/block_code/ui/picker/picker.gd index 7d7b9648..8f90b15d 100644 --- a/addons/block_code/ui/picker/picker.gd +++ b/addons/block_code/ui/picker/picker.gd @@ -7,9 +7,10 @@ const BlockCategoryButton = preload("res://addons/block_code/ui/picker/categorie const BlockCategoryDisplay = preload("res://addons/block_code/ui/picker/categories/block_category_display.gd") const CategoryFactory = preload("res://addons/block_code/ui/picker/categories/category_factory.gd") const VariableCategoryDisplay = preload("res://addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd") +const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") signal block_picked(block: Block) -signal variable_created(variable: VariableResource) +signal variable_created(variable: VariableDefinition) @onready var _block_list := %BlockList @onready var _block_scroll := %BlockScroll @@ -110,7 +111,7 @@ func set_collapsed(collapsed: bool): _widget_container.visible = not collapsed -func reload_variables(variables: Array[VariableResource]): +func reload_variables(variables: Array[VariableDefinition]): if _variable_category_display: for c in _variable_category_display.variable_blocks.get_children(): c.queue_free() diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index 5371b4e8..050ccc04 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -4,6 +4,7 @@ const BlockDefinition = preload("res://addons/block_code/code_generation/block_d const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") const Types = preload("res://addons/block_code/types/types.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") +const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") const SCENE_PER_TYPE = { Types.BlockType.ENTRY: preload("res://addons/block_code/ui/blocks/entry_block/entry_block.tscn"), @@ -92,9 +93,9 @@ static func instantiate_blocks_for_class(_class_name: String) -> Array[Block]: return blocks -static func get_variable_block_definitions(variables: Array[VariableResource]) -> Array[BlockDefinition]: +static func get_variable_block_definitions(variables: Array[VariableDefinition]) -> Array[BlockDefinition]: var block_definitions: Array[BlockDefinition] = [] - for variable: VariableResource in variables: + for variable: VariableDefinition in variables: var type_string: String = Types.VARIANT_TYPE_TO_STRING[variable.var_type] var b = BlockDefinition.new() @@ -115,7 +116,7 @@ static func get_variable_block_definitions(variables: Array[VariableResource]) - return block_definitions -static func instantiate_variable_blocks(variables: Array[VariableResource]) -> Array[Block]: +static func instantiate_variable_blocks(variables: Array[VariableDefinition]) -> Array[Block]: var blocks: Array[Block] = [] for block_definition in get_variable_block_definitions(variables): var b = instantiate_block(block_definition) From b1aef2afddae19466954d9d1df4f3c07a529a3e4 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Fri, 9 Aug 2024 14:58:04 -0400 Subject: [PATCH 191/423] Refactor serialization classes --- addons/block_code/block_code_plugin.gd | 2 - .../examples/pong_game/pong_game.tscn | 877 +++++++----------- .../block_script_serialization.gd | 9 +- .../serialization/block_serialization.gd | 17 +- .../serialization/block_serialization_tree.gd | 24 + .../block_serialized_properties.gd | 12 - .../serialization/default_block_script.tres | 31 +- .../value_block_serialization.gd | 9 + .../ui/block_canvas/block_canvas.gd | 1 + addons/block_code/ui/blocks/block/block.gd | 1 + 10 files changed, 376 insertions(+), 607 deletions(-) create mode 100644 addons/block_code/serialization/block_serialization_tree.gd delete mode 100644 addons/block_code/serialization/block_serialized_properties.gd create mode 100644 addons/block_code/serialization/value_block_serialization.gd diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index f7e0ac8a..f1cc1a0a 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -24,8 +24,6 @@ const DISABLED_CLASSES := [ "ParameterBlock", "StatementBlock", "SnapPoint", - "BlockSerialization", - "BlockSerializedProperties", "BlockScriptSerialization", "CategoryFactory", ] diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index 4aaa9329..57cd062a 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -1,85 +1,72 @@ -[gd_scene load_steps=119 format=3 uid="uid://tf7b8c64ecc0"] +[gd_scene load_steps=81 format=3 uid="uid://tf7b8c64ecc0"] [ext_resource type="PackedScene" uid="uid://cg8ibi18um3vg" path="res://addons/block_code/examples/pong_game/space.tscn" id="1_y56ac"] [ext_resource type="Script" path="res://addons/block_code/block_code_node/block_code.gd" id="3_6jaq8"] [ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_character/simple_character.gd" id="3_mdrcv"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_serialization.gd" id="4_qtggh"] [ext_resource type="Texture2D" uid="uid://tplpgtnfeda0" path="res://addons/block_code/examples/pong_game/assets/paddle.png" id="4_ra7bh"] -[ext_resource type="Script" path="res://addons/block_code/serialization/block_serialized_properties.gd" id="5_wr38c"] +[ext_resource type="Script" path="res://addons/block_code/serialization/block_serialization_tree.gd" id="5_omlge"] [ext_resource type="Script" path="res://addons/block_code/code_generation/option_data.gd" id="7_3q6bj"] [ext_resource type="Script" path="res://addons/block_code/serialization/block_script_serialization.gd" id="7_uuuue"] [ext_resource type="Script" path="res://addons/block_code/code_generation/variable_definition.gd" id="9_lo3p1"] [ext_resource type="PackedScene" uid="uid://c7l70grmkauij" path="res://addons/block_code/examples/pong_game/ball.tscn" id="9_xrqll"] +[ext_resource type="Script" path="res://addons/block_code/serialization/value_block_serialization.gd" id="11_yafka"] [ext_resource type="PackedScene" uid="uid://fhoapg3anjsu" path="res://addons/block_code/examples/pong_game/goal_area.tscn" id="12_nqmxu"] [ext_resource type="Script" path="res://addons/block_code/simple_nodes/simple_scoring/simple_scoring.gd" id="13_tg3yk"] -[sub_resource type="Resource" id="Resource_iegsu"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["scope", ""], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_6fwti"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"value": Vector2(0, 1000) -}]] - -[sub_resource type="Resource" id="Resource_bxt7h"] +[sub_resource type="Resource" id="Resource_7e5rp"] script = ExtResource("4_qtggh") name = &"SimpleCharacter_set_speed" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_6fwti") +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"value": Vector2(0, 1000) +} -[sub_resource type="Resource" id="Resource_xsn6l"] +[sub_resource type="Resource" id="Resource_inqps"] script = ExtResource("4_qtggh") name = &"ready" -position = Vector2(75, 175) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_bxt7h")]] -block_serialized_properties = SubResource("Resource_iegsu") +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_7e5rp")]) +arguments = {} -[sub_resource type="Resource" id="Resource_41mcx"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["scope", ""], ["param_input_strings", {}]] +[sub_resource type="Resource" id="Resource_yjwqr"] +script = ExtResource("5_omlge") +root = SubResource("Resource_inqps") +canvas_position = Vector2(50, 25) -[sub_resource type="Resource" id="Resource_rwx76"] +[sub_resource type="Resource" id="Resource_ytth5"] script = ExtResource("7_3q6bj") selected = 0 items = ["top-down", "platformer", "spaceship"] -[sub_resource type="Resource" id="Resource_ksb0o"] +[sub_resource type="Resource" id="Resource_ujg3k"] script = ExtResource("7_3q6bj") selected = 0 items = ["player_1", "player_2"] -[sub_resource type="Resource" id="Resource_82o3l"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"kind": SubResource("Resource_rwx76"), -"player": SubResource("Resource_ksb0o") -}]] - -[sub_resource type="Resource" id="Resource_4vl0d"] +[sub_resource type="Resource" id="Resource_ocowr"] script = ExtResource("4_qtggh") name = &"simplecharacter_move" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_82o3l") +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"kind": SubResource("Resource_ytth5"), +"player": SubResource("Resource_ujg3k") +} -[sub_resource type="Resource" id="Resource_wntwg"] +[sub_resource type="Resource" id="Resource_at2ah"] script = ExtResource("4_qtggh") name = &"process" -position = Vector2(75, 300) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_4vl0d")]] -block_serialized_properties = SubResource("Resource_41mcx") +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_ocowr")]) +arguments = {} + +[sub_resource type="Resource" id="Resource_1w7mq"] +script = ExtResource("5_omlge") +root = SubResource("Resource_at2ah") +canvas_position = Vector2(50, 175) [sub_resource type="Resource" id="Resource_m2svk"] script = ExtResource("7_uuuue") script_inherits = "SimpleCharacter" -block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_xsn6l"), SubResource("Resource_wntwg")]) +block_serialization_trees = Array[ExtResource("5_omlge")]([SubResource("Resource_yjwqr"), SubResource("Resource_1w7mq")]) variables = Array[ExtResource("9_lo3p1")]([]) generated_script = "extends SimpleCharacter @@ -93,73 +80,59 @@ func _process(delta): " version = 0 -[sub_resource type="Resource" id="Resource_lhobc"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["scope", ""], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_1ycg8"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"value": Vector2(0, 1000) -}]] - -[sub_resource type="Resource" id="Resource_nkjuo"] +[sub_resource type="Resource" id="Resource_qmwe2"] script = ExtResource("4_qtggh") name = &"SimpleCharacter_set_speed" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_1ycg8") +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"value": Vector2(0, 1000) +} -[sub_resource type="Resource" id="Resource_t1m7j"] +[sub_resource type="Resource" id="Resource_ehp62"] script = ExtResource("4_qtggh") name = &"ready" -position = Vector2(50, 175) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_nkjuo")]] -block_serialized_properties = SubResource("Resource_lhobc") +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_qmwe2")]) +arguments = {} -[sub_resource type="Resource" id="Resource_ud032"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["scope", ""], ["param_input_strings", {}]] +[sub_resource type="Resource" id="Resource_sgmlh"] +script = ExtResource("5_omlge") +root = SubResource("Resource_ehp62") +canvas_position = Vector2(25, 0) -[sub_resource type="Resource" id="Resource_ixcua"] +[sub_resource type="Resource" id="Resource_6cn1w"] script = ExtResource("7_3q6bj") selected = 0 items = ["top-down", "platformer", "spaceship"] -[sub_resource type="Resource" id="Resource_728pr"] +[sub_resource type="Resource" id="Resource_i3nv8"] script = ExtResource("7_3q6bj") selected = 1 items = ["player_1", "player_2"] -[sub_resource type="Resource" id="Resource_7aw38"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"kind": SubResource("Resource_ixcua"), -"player": SubResource("Resource_728pr") -}]] - -[sub_resource type="Resource" id="Resource_gtejw"] +[sub_resource type="Resource" id="Resource_im4n0"] script = ExtResource("4_qtggh") name = &"simplecharacter_move" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_7aw38") +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"kind": SubResource("Resource_6cn1w"), +"player": SubResource("Resource_i3nv8") +} -[sub_resource type="Resource" id="Resource_03rje"] +[sub_resource type="Resource" id="Resource_plb5i"] script = ExtResource("4_qtggh") name = &"process" -position = Vector2(50, 300) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_gtejw")]] -block_serialized_properties = SubResource("Resource_ud032") +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_im4n0")]) +arguments = {} + +[sub_resource type="Resource" id="Resource_xbg8g"] +script = ExtResource("5_omlge") +root = SubResource("Resource_plb5i") +canvas_position = Vector2(25, 175) [sub_resource type="Resource" id="Resource_ysbi4"] script = ExtResource("7_uuuue") script_inherits = "SimpleCharacter" -block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_t1m7j"), SubResource("Resource_03rje")]) +block_serialization_trees = Array[ExtResource("5_omlge")]([SubResource("Resource_sgmlh"), SubResource("Resource_xbg8g")]) variables = Array[ExtResource("9_lo3p1")]([]) generated_script = "extends SimpleCharacter @@ -173,657 +146,433 @@ func _process(delta): " version = 0 -[sub_resource type="Resource" id="Resource_d8f3t"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["scope", ""], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_wtbtc"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { +[sub_resource type="Resource" id="Resource_olii0"] +script = ExtResource("4_qtggh") +name = &"load_sound" +children = Array[ExtResource("4_qtggh")]([]) +arguments = { "file_path": "res://addons/block_code/examples/pong_game/assets/paddle_hit.ogg", "name": "paddle_hit" -}]] +} -[sub_resource type="Resource" id="Resource_st0iw"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { +[sub_resource type="Resource" id="Resource_31ax8"] +script = ExtResource("4_qtggh") +name = &"load_sound" +children = Array[ExtResource("4_qtggh")]([]) +arguments = { "file_path": "res://addons/block_code/examples/pong_game/assets/wall_hit.ogg", "name": "wall_hit" -}]] +} -[sub_resource type="Resource" id="Resource_jp6b8"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { +[sub_resource type="Resource" id="Resource_2duo7"] +script = ExtResource("4_qtggh") +name = &"load_sound" +children = Array[ExtResource("4_qtggh")]([]) +arguments = { "file_path": "res://addons/block_code/examples/pong_game/assets/score.ogg", "name": "score_sound" -}]] +} -[sub_resource type="Resource" id="Resource_xs0e6"] +[sub_resource type="Resource" id="Resource_04bql"] script = ExtResource("4_qtggh") -name = &"load_sound" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_jp6b8") +name = &"ready" +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_olii0"), SubResource("Resource_31ax8"), SubResource("Resource_2duo7")]) +arguments = {} -[sub_resource type="Resource" id="Resource_spen4"] -script = ExtResource("4_qtggh") -name = &"load_sound" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_xs0e6")]] -block_serialized_properties = SubResource("Resource_st0iw") +[sub_resource type="Resource" id="Resource_t5jjg"] +script = ExtResource("5_omlge") +root = SubResource("Resource_04bql") +canvas_position = Vector2(25, 0) -[sub_resource type="Resource" id="Resource_r5331"] -script = ExtResource("4_qtggh") -name = &"load_sound" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_spen4")]] -block_serialized_properties = SubResource("Resource_wtbtc") +[sub_resource type="Resource" id="Resource_trtrd"] +script = ExtResource("11_yafka") +name = &"viewport_center" +arguments = {} -[sub_resource type="Resource" id="Resource_phaw7"] +[sub_resource type="Resource" id="Resource_nc43w"] script = ExtResource("4_qtggh") -name = &"ready" -position = Vector2(50, 50) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_r5331")]] -block_serialized_properties = SubResource("Resource_d8f3t") - -[sub_resource type="Resource" id="Resource_47jf7"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"method_name": "reset" -}]] - -[sub_resource type="Resource" id="Resource_obbdk"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"position": Vector2(0, 0) -}]] - -[sub_resource type="Resource" id="Resource_qae7k"] -script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["scope", ""], ["param_input_strings", {}]] +name = &"rigidbody2d_physics_position" +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"position": SubResource("Resource_trtrd") +} -[sub_resource type="Resource" id="Resource_1sea1"] +[sub_resource type="Resource" id="Resource_1dd5f"] script = ExtResource("4_qtggh") -name = &"viewport_center" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_qae7k") - -[sub_resource type="Resource" id="Resource_3b4ka"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { +name = &"play_sound" +children = Array[ExtResource("4_qtggh")]([]) +arguments = { "db": 0.0, "name": "score_sound", "pitch": 1.0 -}]] +} -[sub_resource type="Resource" id="Resource_16pmr"] -script = ExtResource("4_qtggh") -name = &"play_sound" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_3b4ka") - -[sub_resource type="Resource" id="Resource_ugq5m"] -script = ExtResource("4_qtggh") -name = &"rigidbody2d_physics_position" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_1sea1")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_16pmr")]] -block_serialized_properties = SubResource("Resource_obbdk") - -[sub_resource type="Resource" id="Resource_ane3b"] +[sub_resource type="Resource" id="Resource_klc3o"] script = ExtResource("4_qtggh") name = &"define_method" -position = Vector2(50, 275) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ugq5m")]] -block_serialized_properties = SubResource("Resource_47jf7") - -[sub_resource type="Resource" id="Resource_7kl7g"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["scope", ""], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_vqtp0"] -script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_bgppn"] -script = ExtResource("4_qtggh") -name = &"parameter_block" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_vqtp0") - -[sub_resource type="Resource" id="Resource_dnsl7"] -script = ExtResource("5_wr38c") -block_class = &"ControlBlock" -serialized_props = [["scope", ""], ["param_input_strings_array", [{ -"condition": false -}]]] - -[sub_resource type="Resource" id="Resource_kvrwg"] -script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["scope", ""], ["param_input_strings", { +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_nc43w"), SubResource("Resource_1dd5f")]) +arguments = { +"method_name": &"reset" +} + +[sub_resource type="Resource" id="Resource_2q6mf"] +script = ExtResource("5_omlge") +root = SubResource("Resource_klc3o") +canvas_position = Vector2(25, 250) + +[sub_resource type="Resource" id="Resource_hmv46"] +script = ExtResource("11_yafka") +name = &"rigidbody2d_on_entered_body" +arguments = {} + +[sub_resource type="Resource" id="Resource_l16xj"] +script = ExtResource("11_yafka") +name = &"is_node_in_group" +arguments = { "group": "paddles", -"node": "" -}]] - -[sub_resource type="Resource" id="Resource_et4ib"] -script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_707bn"] -script = ExtResource("4_qtggh") -name = &"parameter_block" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_et4ib") +"node": SubResource("Resource_hmv46") +} -[sub_resource type="Resource" id="Resource_dj7fd"] +[sub_resource type="Resource" id="Resource_0ltlg"] script = ExtResource("4_qtggh") -name = &"is_node_in_group" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_707bn")]] -block_serialized_properties = SubResource("Resource_kvrwg") - -[sub_resource type="Resource" id="Resource_t4jty"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { +name = &"play_sound" +children = Array[ExtResource("4_qtggh")]([]) +arguments = { "db": 0.0, "name": "paddle_hit", "pitch": 1.0 -}]] +} -[sub_resource type="Resource" id="Resource_2lgdm"] +[sub_resource type="Resource" id="Resource_pgmj0"] script = ExtResource("4_qtggh") -name = &"play_sound" -position = Vector2(20, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_t4jty") - -[sub_resource type="Resource" id="Resource_e1awu"] -script = ExtResource("5_wr38c") -block_class = &"ControlBlock" -serialized_props = [["scope", ""], ["param_input_strings_array", [{ -"condition": false -}]]] - -[sub_resource type="Resource" id="Resource_1en27"] -script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["scope", ""], ["param_input_strings", { +name = &"if" +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_0ltlg")]) +arguments = { +"condition": SubResource("Resource_l16xj") +} + +[sub_resource type="Resource" id="Resource_1d2v5"] +script = ExtResource("11_yafka") +name = &"rigidbody2d_on_entered_body" +arguments = {} + +[sub_resource type="Resource" id="Resource_cikin"] +script = ExtResource("11_yafka") +name = &"is_node_in_group" +arguments = { "group": "walls", -"node": "" -}]] - -[sub_resource type="Resource" id="Resource_mur5c"] -script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_wo7ob"] -script = ExtResource("4_qtggh") -name = &"parameter_block" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_mur5c") +"node": SubResource("Resource_1d2v5") +} -[sub_resource type="Resource" id="Resource_jb4li"] +[sub_resource type="Resource" id="Resource_iue1k"] script = ExtResource("4_qtggh") -name = &"is_node_in_group" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_wo7ob")]] -block_serialized_properties = SubResource("Resource_1en27") - -[sub_resource type="Resource" id="Resource_s6roe"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { +name = &"play_sound" +children = Array[ExtResource("4_qtggh")]([]) +arguments = { "db": 0.0, "name": "wall_hit", "pitch": 1.0 -}]] - -[sub_resource type="Resource" id="Resource_kd52t"] -script = ExtResource("4_qtggh") -name = &"play_sound" -position = Vector2(20, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_s6roe") - -[sub_resource type="Resource" id="Resource_ky5ld"] -script = ExtResource("4_qtggh") -name = &"if" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_jb4li")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_kd52t")]] -block_serialized_properties = SubResource("Resource_e1awu") +} -[sub_resource type="Resource" id="Resource_ef7x8"] +[sub_resource type="Resource" id="Resource_bk4nw"] script = ExtResource("4_qtggh") name = &"if" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_dj7fd")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_2lgdm")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ky5ld")]] -block_serialized_properties = SubResource("Resource_dnsl7") +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_iue1k")]) +arguments = { +"condition": SubResource("Resource_cikin") +} -[sub_resource type="Resource" id="Resource_1bd3d"] +[sub_resource type="Resource" id="Resource_u4qvk"] script = ExtResource("4_qtggh") name = &"rigidbody2d_on_entered" -position = Vector2(50, 475) -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_bgppn")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_ef7x8")]] -block_serialized_properties = SubResource("Resource_7kl7g") +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_pgmj0"), SubResource("Resource_bk4nw")]) +arguments = {} + +[sub_resource type="Resource" id="Resource_88olk"] +script = ExtResource("5_omlge") +root = SubResource("Resource_u4qvk") +canvas_position = Vector2(25, 450) [sub_resource type="Resource" id="Resource_6m2mk"] script = ExtResource("7_uuuue") script_inherits = "RigidBody2D" -block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_phaw7"), SubResource("Resource_ane3b"), SubResource("Resource_1bd3d")]) +block_serialization_trees = Array[ExtResource("5_omlge")]([SubResource("Resource_t5jjg"), SubResource("Resource_2q6mf"), SubResource("Resource_88olk")]) variables = Array[ExtResource("9_lo3p1")]([]) generated_script = "extends RigidBody2D +func _init(): + body_entered.connect(_on_body_entered) + func _ready(): var __sound_1 = AudioStreamPlayer.new() __sound_1.name = 'paddle_hit' __sound_1.set_stream(load('res://addons/block_code/examples/pong_game/assets/paddle_hit.ogg')) add_child(__sound_1) + var __sound_2 = AudioStreamPlayer.new() __sound_2.name = 'wall_hit' __sound_2.set_stream(load('res://addons/block_code/examples/pong_game/assets/wall_hit.ogg')) add_child(__sound_2) + var __sound_3 = AudioStreamPlayer.new() __sound_3.name = 'score_sound' __sound_3.set_stream(load('res://addons/block_code/examples/pong_game/assets/score.ogg')) add_child(__sound_3) + func reset(): PhysicsServer2D.body_set_state( get_rid(), PhysicsServer2D.BODY_STATE_TRANSFORM, - Transform2D.IDENTITY.translated((func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()) + Transform2D.IDENTITY.translated(((func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call())) ) + var __sound_node_1 = get_node('score_sound') __sound_node_1.volume_db = 0 __sound_node_1.pitch_scale = 1 __sound_node_1.play() + func _on_body_entered(body: Node2D): - if body.is_in_group('paddles'): + if ((body).is_in_group('paddles')): var __sound_node_1 = get_node('paddle_hit') __sound_node_1.volume_db = 0 __sound_node_1.pitch_scale = 1 __sound_node_1.play() - if body.is_in_group('walls'): + + if ((body).is_in_group('walls')): var __sound_node_2 = get_node('wall_hit') __sound_node_2.volume_db = 0 __sound_node_2.pitch_scale = 1 __sound_node_2.play() -func _init(): - body_entered.connect(_on_body_entered) + " version = 0 -[sub_resource type="Resource" id="Resource_xxj4u"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["scope", ""], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_lnfkn"] -script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_r1q4l"] -script = ExtResource("4_qtggh") -name = &"parameter_block" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_lnfkn") - -[sub_resource type="Resource" id="Resource_ft8ne"] -script = ExtResource("5_wr38c") -block_class = &"ControlBlock" -serialized_props = [["scope", ""], ["param_input_strings_array", [{ -"condition": false -}]]] - -[sub_resource type="Resource" id="Resource_s06y5"] -script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"group": "balls", -"node": "" -}]] - -[sub_resource type="Resource" id="Resource_5itae"] -script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_ht2bw"] -script = ExtResource("4_qtggh") -name = &"parameter_block" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_5itae") +[sub_resource type="Resource" id="Resource_v1wmj"] +script = ExtResource("11_yafka") +name = &"area2d_on_entered_body" +arguments = {} -[sub_resource type="Resource" id="Resource_iyvmc"] -script = ExtResource("4_qtggh") +[sub_resource type="Resource" id="Resource_vfj0r"] +script = ExtResource("11_yafka") name = &"is_node_in_group" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_ht2bw")]] -block_serialized_properties = SubResource("Resource_s06y5") - -[sub_resource type="Resource" id="Resource_eyu21"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"group": "scoring", -"method_name": "goal_left" -}]] - -[sub_resource type="Resource" id="Resource_5hog4"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { +arguments = { "group": "balls", -"method_name": "reset" -}]] +"node": SubResource("Resource_v1wmj") +} -[sub_resource type="Resource" id="Resource_x6rc5"] +[sub_resource type="Resource" id="Resource_n8gnx"] script = ExtResource("4_qtggh") name = &"call_method_group" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_5hog4") +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"group": "scoring", +"method_name": "goal_left" +} -[sub_resource type="Resource" id="Resource_s8f8n"] +[sub_resource type="Resource" id="Resource_bt4xb"] script = ExtResource("4_qtggh") name = &"call_method_group" -position = Vector2(20, 0) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_x6rc5")]] -block_serialized_properties = SubResource("Resource_eyu21") +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"group": "balls", +"method_name": "reset" +} -[sub_resource type="Resource" id="Resource_fs8jx"] +[sub_resource type="Resource" id="Resource_ckhru"] script = ExtResource("4_qtggh") name = &"if" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_iyvmc")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_s8f8n")]] -block_serialized_properties = SubResource("Resource_ft8ne") +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_n8gnx"), SubResource("Resource_bt4xb")]) +arguments = { +"condition": SubResource("Resource_vfj0r") +} -[sub_resource type="Resource" id="Resource_m4esq"] +[sub_resource type="Resource" id="Resource_0wq4q"] script = ExtResource("4_qtggh") name = &"area2d_on_entered" -position = Vector2(100, 350) -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_r1q4l")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_fs8jx")]] -block_serialized_properties = SubResource("Resource_xxj4u") +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_ckhru")]) +arguments = {} + +[sub_resource type="Resource" id="Resource_5xtxj"] +script = ExtResource("5_omlge") +root = SubResource("Resource_0wq4q") +canvas_position = Vector2(0, 25) [sub_resource type="Resource" id="Resource_4xylj"] script = ExtResource("7_uuuue") script_inherits = "Area2D" -block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_m4esq")]) +block_serialization_trees = Array[ExtResource("5_omlge")]([SubResource("Resource_5xtxj")]) variables = Array[ExtResource("9_lo3p1")]([]) generated_script = "extends Area2D +func _init(): + body_entered.connect(_on_body_entered) + func _on_body_entered(body: Node2D): - if body.is_in_group('balls'): + if ((body).is_in_group('balls')): get_tree().call_group('scoring', 'goal_left') get_tree().call_group('balls', 'reset') -func _init(): - body_entered.connect(_on_body_entered) " version = 0 -[sub_resource type="Resource" id="Resource_tfqiy"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["scope", ""], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_5i6ga"] -script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_oyktt"] -script = ExtResource("4_qtggh") -name = &"parameter_block" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_5i6ga") - -[sub_resource type="Resource" id="Resource_pssgx"] -script = ExtResource("5_wr38c") -block_class = &"ControlBlock" -serialized_props = [["scope", ""], ["param_input_strings_array", [{ -"condition": false -}]]] - -[sub_resource type="Resource" id="Resource_2w0n0"] -script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"group": "balls", -"node": "" -}]] - -[sub_resource type="Resource" id="Resource_q1iue"] -script = ExtResource("5_wr38c") -block_class = &"ParameterBlock" -serialized_props = [["block_name", &"parameter_block"], ["label", "Param"], ["color", Color(0.294118, 0.482353, 0.92549, 1)], ["block_type", 3], ["position", Vector2(0, 0)], ["scope", "func _on_body_entered(body: Node2D): -"], ["block_format", "body"], ["statement", "body"], ["defaults", {}], ["variant_type", 24], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_aaxrr"] -script = ExtResource("4_qtggh") -name = &"parameter_block" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_q1iue") +[sub_resource type="Resource" id="Resource_iwaix"] +script = ExtResource("11_yafka") +name = &"area2d_on_entered_body" +arguments = {} -[sub_resource type="Resource" id="Resource_005bn"] -script = ExtResource("4_qtggh") +[sub_resource type="Resource" id="Resource_imoq7"] +script = ExtResource("11_yafka") name = &"is_node_in_group" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("MarginContainer/HBoxContainer/ParameterInput0/SnapPoint"), SubResource("Resource_aaxrr")]] -block_serialized_properties = SubResource("Resource_2w0n0") - -[sub_resource type="Resource" id="Resource_1n3fn"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"group": "scoring", -"method_name": "goal_right" -}]] - -[sub_resource type="Resource" id="Resource_jr3es"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { +arguments = { "group": "balls", -"method_name": "reset" -}]] +"node": SubResource("Resource_iwaix") +} -[sub_resource type="Resource" id="Resource_6moia"] +[sub_resource type="Resource" id="Resource_uqjge"] script = ExtResource("4_qtggh") name = &"call_method_group" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_jr3es") +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"group": "scoring", +"method_name": "goal_right" +} -[sub_resource type="Resource" id="Resource_gy7s5"] +[sub_resource type="Resource" id="Resource_s5k8u"] script = ExtResource("4_qtggh") name = &"call_method_group" -position = Vector2(20, 0) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_6moia")]] -block_serialized_properties = SubResource("Resource_1n3fn") +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"group": "balls", +"method_name": "reset" +} -[sub_resource type="Resource" id="Resource_2ys4x"] +[sub_resource type="Resource" id="Resource_utwdq"] script = ExtResource("4_qtggh") name = &"if" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/MarginContainer/Rows/Row0/RowHBoxContainer/RowHBox/ParameterInput0/SnapPoint"), SubResource("Resource_005bn")], [NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer0/SnapPoint"), SubResource("Resource_gy7s5")]] -block_serialized_properties = SubResource("Resource_pssgx") +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_uqjge"), SubResource("Resource_s5k8u")]) +arguments = { +"condition": SubResource("Resource_imoq7") +} -[sub_resource type="Resource" id="Resource_mi6hv"] +[sub_resource type="Resource" id="Resource_bm8bv"] script = ExtResource("4_qtggh") name = &"area2d_on_entered" -position = Vector2(75, 350) -path_child_pairs = [[NodePath("VBoxContainer/TopMarginContainer/MarginContainer/HBoxContainer/ParameterOutput0/SnapPoint"), SubResource("Resource_oyktt")], [NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_2ys4x")]] -block_serialized_properties = SubResource("Resource_tfqiy") +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_utwdq")]) +arguments = {} + +[sub_resource type="Resource" id="Resource_pnsgy"] +script = ExtResource("5_omlge") +root = SubResource("Resource_bm8bv") +canvas_position = Vector2(50, 25) [sub_resource type="Resource" id="Resource_xoc8a"] script = ExtResource("7_uuuue") script_inherits = "Area2D" -block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_mi6hv")]) +block_serialization_trees = Array[ExtResource("5_omlge")]([SubResource("Resource_pnsgy")]) variables = Array[ExtResource("9_lo3p1")]([]) generated_script = "extends Area2D +func _init(): + body_entered.connect(_on_body_entered) + func _on_body_entered(body: Node2D): - if body.is_in_group('balls'): + if ((body).is_in_group('balls')): get_tree().call_group('scoring', 'goal_right') get_tree().call_group('balls', 'reset') -func _init(): - body_entered.connect(_on_body_entered) " version = 0 -[sub_resource type="Resource" id="Resource_n6aol"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["scope", ""], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_76s7d"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"score": 0 -}]] - -[sub_resource type="Resource" id="Resource_clf6h"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"score": 0 -}]] - -[sub_resource type="Resource" id="Resource_rpicc"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"group": "scoring" -}]] - -[sub_resource type="Resource" id="Resource_hxlka"] +[sub_resource type="Resource" id="Resource_hyh0v"] script = ExtResource("4_qtggh") -name = &"add_to_group" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_rpicc") +name = &"simplescoring_set_score_player_1" +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"score": 0 +} -[sub_resource type="Resource" id="Resource_os82j"] +[sub_resource type="Resource" id="Resource_nnat8"] script = ExtResource("4_qtggh") name = &"simplescoring_set_score_player_2" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_hxlka")]] -block_serialized_properties = SubResource("Resource_clf6h") +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"score": 0 +} -[sub_resource type="Resource" id="Resource_2cci1"] +[sub_resource type="Resource" id="Resource_qf8bl"] script = ExtResource("4_qtggh") -name = &"simplescoring_set_score_player_1" -position = Vector2(0, 0) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_os82j")]] -block_serialized_properties = SubResource("Resource_76s7d") +name = &"add_to_group" +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"group": "scoring" +} -[sub_resource type="Resource" id="Resource_e0qr3"] +[sub_resource type="Resource" id="Resource_7dyjv"] script = ExtResource("4_qtggh") name = &"ready" -position = Vector2(50, 25) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_2cci1")]] -block_serialized_properties = SubResource("Resource_n6aol") - -[sub_resource type="Resource" id="Resource_mhqvs"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"method_name": "goal_right" -}]] +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_hyh0v"), SubResource("Resource_nnat8"), SubResource("Resource_qf8bl")]) +arguments = {} -[sub_resource type="Resource" id="Resource_nd6ab"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"score": 1 -}]] +[sub_resource type="Resource" id="Resource_g0f0k"] +script = ExtResource("5_omlge") +root = SubResource("Resource_7dyjv") +canvas_position = Vector2(25, 0) -[sub_resource type="Resource" id="Resource_m8e8y"] +[sub_resource type="Resource" id="Resource_0ak1s"] script = ExtResource("4_qtggh") name = &"simplescoring_change_score_player_1" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_nd6ab") +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"score": 1 +} -[sub_resource type="Resource" id="Resource_kr7eg"] +[sub_resource type="Resource" id="Resource_7rjjw"] script = ExtResource("4_qtggh") name = &"define_method" -position = Vector2(50, 275) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_m8e8y")]] -block_serialized_properties = SubResource("Resource_mhqvs") - -[sub_resource type="Resource" id="Resource_3fbnf"] -script = ExtResource("5_wr38c") -block_class = &"EntryBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"method_name": "goal_left" -}]] +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_0ak1s")]) +arguments = { +"method_name": "goal_right" +} -[sub_resource type="Resource" id="Resource_7rc07"] -script = ExtResource("5_wr38c") -block_class = &"StatementBlock" -serialized_props = [["scope", ""], ["param_input_strings", { -"score": 1 -}]] +[sub_resource type="Resource" id="Resource_hiqld"] +script = ExtResource("5_omlge") +root = SubResource("Resource_7rjjw") +canvas_position = Vector2(25, 250) -[sub_resource type="Resource" id="Resource_7dmgm"] +[sub_resource type="Resource" id="Resource_e7bsf"] script = ExtResource("4_qtggh") name = &"simplescoring_change_score_player_2" -position = Vector2(0, 0) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_7rc07") +children = Array[ExtResource("4_qtggh")]([]) +arguments = { +"score": 1 +} -[sub_resource type="Resource" id="Resource_cnona"] +[sub_resource type="Resource" id="Resource_8gvgu"] script = ExtResource("4_qtggh") name = &"define_method" -position = Vector2(50, 425) -path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_7dmgm")]] -block_serialized_properties = SubResource("Resource_3fbnf") +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_e7bsf")]) +arguments = { +"method_name": "goal_left" +} + +[sub_resource type="Resource" id="Resource_3kxo7"] +script = ExtResource("5_omlge") +root = SubResource("Resource_8gvgu") +canvas_position = Vector2(25, 400) [sub_resource type="Resource" id="Resource_q418f"] script = ExtResource("7_uuuue") script_inherits = "SimpleScoring" -block_trees = Array[ExtResource("4_qtggh")]([SubResource("Resource_e0qr3"), SubResource("Resource_kr7eg"), SubResource("Resource_cnona")]) +block_serialization_trees = Array[ExtResource("5_omlge")]([SubResource("Resource_g0f0k"), SubResource("Resource_hiqld"), SubResource("Resource_3kxo7")]) variables = Array[ExtResource("9_lo3p1")]([]) generated_script = "extends SimpleScoring @@ -833,10 +582,10 @@ func _ready(): score_right = 0 add_to_group('scoring') -func goal_right(): +func 'goal_right'(): score_left += 1 -func goal_left(): +func 'goal_left'(): score_right += 1 " diff --git a/addons/block_code/serialization/block_script_serialization.gd b/addons/block_code/serialization/block_script_serialization.gd index 4015fd68..896bf0ce 100644 --- a/addons/block_code/serialization/block_script_serialization.gd +++ b/addons/block_code/serialization/block_script_serialization.gd @@ -1,18 +1,21 @@ class_name BlockScriptSerialization extends Resource +const BlockSerializationTree = preload("res://addons/block_code/serialization/block_serialization_tree.gd") const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") @export var script_inherits: String -@export var block_trees: Array[BlockSerialization] +@export var block_serialization_trees: Array[BlockSerializationTree] @export var variables: Array[VariableDefinition] @export var generated_script: String @export var version: int -func _init(p_script_inherits: String = "", p_block_trees: Array[BlockSerialization] = [], p_variables: Array[VariableDefinition] = [], p_generated_script: String = "", p_version = 0): +func _init( + p_script_inherits: String = "", p_block_serialization_trees: Array[BlockSerializationTree] = [], p_variables: Array[VariableDefinition] = [], p_generated_script: String = "", p_version = 0 +): script_inherits = p_script_inherits - block_trees = p_block_trees + block_serialization_trees = p_block_serialization_trees generated_script = p_generated_script variables = p_variables version = p_version diff --git a/addons/block_code/serialization/block_serialization.gd b/addons/block_code/serialization/block_serialization.gd index 433ca567..5a62b008 100644 --- a/addons/block_code/serialization/block_serialization.gd +++ b/addons/block_code/serialization/block_serialization.gd @@ -1,16 +1,13 @@ -class_name BlockSerialization extends Resource -@export var name: StringName -@export var position: Vector2 -@export var path_child_pairs: Array +const BlockSerialization = preload("res://addons/block_code/serialization/block_serialization.gd") -# TODO: Remove once the data/UI decouple is done. -@export var block_serialized_properties: BlockSerializedProperties +@export var name: StringName +@export var children: Array[BlockSerialization] +@export var arguments: Dictionary # String, ValueBlockSerialization -func _init(p_name: StringName, p_position: Vector2 = Vector2.ZERO, p_block_serialized_properties: BlockSerializedProperties = null, p_path_child_pairs: Array = []): +func _init(p_name: StringName = &"", p_children: Array[BlockSerialization] = [], p_arguments: Dictionary = {}): name = p_name - position = p_position - block_serialized_properties = p_block_serialized_properties - path_child_pairs = p_path_child_pairs + children = p_children + arguments = p_arguments diff --git a/addons/block_code/serialization/block_serialization_tree.gd b/addons/block_code/serialization/block_serialization_tree.gd new file mode 100644 index 00000000..1da2babe --- /dev/null +++ b/addons/block_code/serialization/block_serialization_tree.gd @@ -0,0 +1,24 @@ +extends Resource + +const BlockSerialization = preload("res://addons/block_code/serialization/block_serialization.gd") + +@export var root: BlockSerialization +@export var canvas_position: Vector2 + + +func _init(p_root: BlockSerialization = null, p_canvas_position: Vector2 = Vector2(0, 0)): + root = p_root + canvas_position = p_canvas_position + + +func _to_string(): + return to_string_recursive(root, 0) + + +func to_string_recursive(node: BlockSerialization, depth: int) -> String: + var string: String = "%s %s\n" % ["-".repeat(depth), node.block_name] + + for c in node.children: + string += to_string_recursive(c, depth + 1) + + return string diff --git a/addons/block_code/serialization/block_serialized_properties.gd b/addons/block_code/serialization/block_serialized_properties.gd deleted file mode 100644 index 2841c6ca..00000000 --- a/addons/block_code/serialization/block_serialized_properties.gd +++ /dev/null @@ -1,12 +0,0 @@ -class_name BlockSerializedProperties -extends Resource - -# TODO: Remove this class after removing the remaining serialization. - -@export var block_class: StringName -@export var serialized_props: Array - - -func _init(p_block_class: StringName = "", p_serialized_props: Array = []): - block_class = p_block_class - serialized_props = p_serialized_props diff --git a/addons/block_code/serialization/default_block_script.tres b/addons/block_code/serialization/default_block_script.tres index 5c3459d9..438e3fd5 100644 --- a/addons/block_code/serialization/default_block_script.tres +++ b/addons/block_code/serialization/default_block_script.tres @@ -1,26 +1,25 @@ -[gd_resource type="Resource" script_class="BlockScriptSerialization" load_steps=6 format=3 uid="uid://dit7fykhl3h48"] +[gd_resource type="Resource" script_class="BlockScriptSerialization" load_steps=7 format=3 uid="uid://i7adsp6x51ml"] -[ext_resource type="Script" path="res://addons/block_code/serialization/block_serialization.gd" id="1_barc5"] -[ext_resource type="Script" path="res://addons/block_code/serialization/block_serialized_properties.gd" id="2_cgfpx"] -[ext_resource type="Script" path="res://addons/block_code/serialization/block_script_serialization.gd" id="4_cqq7x"] +[ext_resource type="Script" path="res://addons/block_code/serialization/block_serialization_tree.gd" id="1_opywe"] +[ext_resource type="Script" path="res://addons/block_code/serialization/block_serialization.gd" id="2_h8ehk"] +[ext_resource type="Script" path="res://addons/block_code/serialization/block_script_serialization.gd" id="2_yjlcv"] [ext_resource type="Script" path="res://addons/block_code/code_generation/variable_definition.gd" id="3_wb2fg"] -[sub_resource type="Resource" id="Resource_b0aen"] -script = ExtResource("2_cgfpx") -block_class = &"EntryBlock" -serialized_props = [["color", Color(0.92549, 0.231373, 0.34902, 1)], ["scope", ""], ["param_input_strings", {}]] - -[sub_resource type="Resource" id="Resource_1h6wi"] -script = ExtResource("1_barc5") +[sub_resource type="Resource" id="Resource_oalom"] +script = ExtResource("2_h8ehk") name = &"ready" -position = Vector2(54, 47) -path_child_pairs = [] -block_serialized_properties = SubResource("Resource_b0aen") +children = Array[ExtResource("2_h8ehk")]([]) +arguments = {} + +[sub_resource type="Resource" id="Resource_8sqy5"] +script = ExtResource("1_opywe") +root = SubResource("Resource_oalom") +canvas_position = Vector2(54, 47) [resource] -script = ExtResource("4_cqq7x") +script = ExtResource("2_yjlcv") script_inherits = "INHERIT_DEFAULT" -block_trees = Array[ExtResource("1_barc5")]([SubResource("Resource_1h6wi")]) +block_serialization_trees = Array[ExtResource("1_opywe")]([SubResource("Resource_8sqy5")]) variables = Array[ExtResource("3_wb2fg")]([]) generated_script = "extends INHERIT_DEFAULT" version = 0 diff --git a/addons/block_code/serialization/value_block_serialization.gd b/addons/block_code/serialization/value_block_serialization.gd new file mode 100644 index 00000000..6aea5a77 --- /dev/null +++ b/addons/block_code/serialization/value_block_serialization.gd @@ -0,0 +1,9 @@ +extends Resource + +@export var name: StringName +@export var arguments: Dictionary # String, ValueBlockSerialization + + +func _init(p_name: StringName = &"", p_arguments: Dictionary = {}): + name = p_name + arguments = p_arguments diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index ffcc4b86..70638c3c 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -2,6 +2,7 @@ extends MarginContainer const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd") +const BlockSerialization = preload("res://addons/block_code/serialization/block_serialization.gd") const BlockTreeUtil = preload("res://addons/block_code/ui/block_tree_util.gd") const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 3a4e056a..91cbcf21 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -3,6 +3,7 @@ class_name Block extends MarginContainer const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") +const BlockSerialization = preload("res://addons/block_code/serialization/block_serialization.gd") const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") const Types = preload("res://addons/block_code/types/types.gd") From 79288788a69014d0ed66028d43495bd469434ad2 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Wed, 7 Aug 2024 16:17:55 -0400 Subject: [PATCH 192/423] Add new code generation infrastructure These classes will be used as standalone structures to generate code. They will be used as an intermediate state between the UI and serialization states. --- addons/block_code/code_generation/ast_list.gd | 37 +++++ .../block_code/code_generation/block_ast.gd | 145 ++++++++++++++++++ .../instruction_tree/instruction_tree.gd | 58 ------- 3 files changed, 182 insertions(+), 58 deletions(-) create mode 100644 addons/block_code/code_generation/ast_list.gd create mode 100644 addons/block_code/code_generation/block_ast.gd delete mode 100644 addons/block_code/instruction_tree/instruction_tree.gd diff --git a/addons/block_code/code_generation/ast_list.gd b/addons/block_code/code_generation/ast_list.gd new file mode 100644 index 00000000..aafb6caa --- /dev/null +++ b/addons/block_code/code_generation/ast_list.gd @@ -0,0 +1,37 @@ +extends RefCounted + +const Types = preload("res://addons/block_code/types/types.gd") +const BlockAST = preload("res://addons/block_code/code_generation/block_ast.gd") + +var array: Array[ASTPair] + + +class ASTPair: + var ast: BlockAST + var canvas_position: Vector2 + + func _init(p_ast: BlockAST, p_canvas_position: Vector2): + ast = p_ast + canvas_position = p_canvas_position + + +func _init(): + array = [] + + +func append(ast: BlockAST, canvas_position: Vector2): + array.append(ASTPair.new(ast, canvas_position)) + + +func clear(): + array.clear() + + +func get_top_level_nodes_of_type(block_type: Types.BlockType) -> Array[BlockAST]: + var asts: Array[BlockAST] = [] + + for ast_pair in array: + if ast_pair.ast.root.data.type == block_type: + asts.append(ast_pair.ast) + + return asts diff --git a/addons/block_code/code_generation/block_ast.gd b/addons/block_code/code_generation/block_ast.gd new file mode 100644 index 00000000..df35e354 --- /dev/null +++ b/addons/block_code/code_generation/block_ast.gd @@ -0,0 +1,145 @@ +extends RefCounted + +const BlockAST = preload("res://addons/block_code/code_generation/block_ast.gd") +const OptionData = preload("res://addons/block_code/code_generation/option_data.gd") +const Types = preload("res://addons/block_code/types/types.gd") + +var root: ASTNode + + +class IDHandler: + static var counts: Dictionary = {} + + static func reset(): + counts = {} + + static func get_unique_id(str: String) -> int: + if not counts.has(str): + counts[str] = 0 + + counts[str] += 1 + + return counts[str] + + static func make_unique(formatted_string: String) -> String: + var unique_string = formatted_string + var regex = RegEx.new() + regex.compile("\\b__[^\\s]+") + var ids: Dictionary = {} + for result in regex.search_all(formatted_string): + var result_string = result.get_string() + if not ids.has(result_string): + ids[result_string] = get_unique_id(result_string) + unique_string = unique_string.replace(result_string, result_string + "_%d" % ids[result_string]) + + return unique_string + + +class ASTNode: + var data #: BlockDefinition + var children: Array[ASTNode] + var arguments: Dictionary # String, ASTValueNode + + func _init(): + children = [] + arguments = {} + + func get_code_block() -> String: + var code_block: String = data.code_template # get multiline code_template from block definition + + # insert args + + # check if args match an overload in the resource + + for arg_name in arguments: + # Use parentheses to be safe + var argument = arguments[arg_name] + var code_string: String + if argument is ASTValueNode: + code_string = argument.get_code() + else: + code_string = BlockAST.raw_input_to_code_string(argument) + + code_block = code_block.replace("{%s}" % arg_name, code_string) + + return IDHandler.make_unique(code_block) + + func get_code(depth: int) -> String: + var code: String = "" + + # append code block + var code_block := get_code_block() + code_block = code_block.indent("\t".repeat(depth)) + + code += code_block + "\n" + + # fill empty entry and control blocks with pass + if children.is_empty() and (data.type == Types.BlockType.ENTRY || data.type == Types.BlockType.CONTROL): + code += "pass\n".indent("\t".repeat(depth + 1)) + + for child in children: + code += child.get_code(depth + 1) + + return code + + +class ASTValueNode: + var data #: BlockDefinition + var arguments: Dictionary # String, ASTValueNode + + func _init(): + arguments = {} + + func get_code() -> String: + var code: String = data.code_template # get code_template from block definition + + # check if args match an overload in the resource + + for arg_name in arguments: + # Use parentheses to be safe + var argument = arguments[arg_name] + var code_string: String + if argument is ASTValueNode: + code_string = argument.get_code() + else: + code_string = BlockAST.raw_input_to_code_string(argument) + + code = code.replace("{%s}" % arg_name, code_string) + + return IDHandler.make_unique("(%s)" % code) + + +func get_code() -> String: + IDHandler.reset() + return root.get_code(0) + + +func _to_string(): + return to_string_recursive(root, 0) + + +func to_string_recursive(node: ASTNode, depth: int) -> String: + var string: String = "%s %s\n" % ["-".repeat(depth), node.data.display_template] + + for c in node.children: + string += to_string_recursive(c, depth + 1) + + return string + + +static func raw_input_to_code_string(input) -> String: + match typeof(input): + TYPE_STRING: + return "'%s'" % input.replace("\\", "\\\\").replace("'", "\\'") + TYPE_VECTOR2: + return "Vector2%s" % str(input) + TYPE_COLOR: + return "Color%s" % str(input) + TYPE_OBJECT: + if input is OptionData: + var option_data := input as OptionData + return option_data.items[option_data.selected] + _: + return "%s" % input + + return "" diff --git a/addons/block_code/instruction_tree/instruction_tree.gd b/addons/block_code/instruction_tree/instruction_tree.gd deleted file mode 100644 index 0b6d5011..00000000 --- a/addons/block_code/instruction_tree/instruction_tree.gd +++ /dev/null @@ -1,58 +0,0 @@ -extends Object - - -class TreeNode: - var data: String - var children: Array[TreeNode] - var next: TreeNode - - func _init(_data: String): - data = _data - - func add_child(node: TreeNode): - children.append(node) - - -class IDHandler: - static var counts: Dictionary = {} - - static func reset(): - counts = {} - - static func get_unique_id(str: String) -> int: - if not counts.has(str): - counts[str] = 0 - - counts[str] += 1 - - return counts[str] - - static func make_unique(formatted_string: String) -> String: - var unique_string = formatted_string - var regex = RegEx.new() - regex.compile("\\b__[^\\s]+") - var ids: Dictionary = {} - for result in regex.search_all(formatted_string): - var result_string = result.get_string() - if not ids.has(result_string): - ids[result_string] = get_unique_id(result_string) - unique_string = unique_string.replace(result_string, result_string + "_%d" % ids[result_string]) - - return unique_string - - -static func generate_text(root_node: TreeNode, start_depth: int = 0) -> String: - var out = PackedStringArray() - generate_text_recursive(root_node, start_depth, out) - return "".join(out) - - -static func generate_text_recursive(node: TreeNode, depth: int, out: PackedStringArray): - if node.data != "": - out.append("\t".repeat(depth) + node.data + "\n") - - for c in node.children: - generate_text_recursive(c, depth + 1, out) - - if node.next: - generate_text_recursive(node.next, depth, out) From b79aef5f09463ccfc2941ee7c07fb68fd73eeb20 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Thu, 5 Sep 2024 15:51:44 -0600 Subject: [PATCH 193/423] serialization: Add methods for getting script block definitions These will be used to populate the picker rather than doing it in the UI layer. --- .../block_script_serialization.gd | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/addons/block_code/serialization/block_script_serialization.gd b/addons/block_code/serialization/block_script_serialization.gd index 896bf0ce..ba1590d7 100644 --- a/addons/block_code/serialization/block_script_serialization.gd +++ b/addons/block_code/serialization/block_script_serialization.gd @@ -1,6 +1,10 @@ +@tool class_name BlockScriptSerialization extends Resource +const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") +const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") +const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") const BlockSerializationTree = preload("res://addons/block_code/serialization/block_serialization_tree.gd") const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") @@ -19,3 +23,24 @@ func _init( generated_script = p_generated_script variables = p_variables version = p_version + + +func get_definitions() -> Array[BlockDefinition]: + for class_dict in ProjectSettings.get_global_class_list(): + if class_dict.class == script_inherits: + var script = load(class_dict.path) + if script.has_method("setup_custom_blocks"): + script.setup_custom_blocks() + break + + return BlocksCatalog.get_inherited_blocks(script_inherits) + + +func get_categories() -> Array[BlockCategory]: + for class_dict in ProjectSettings.get_global_class_list(): + if class_dict.class == script_inherits: + var script = load(class_dict.path) + if script.has_method("get_custom_categories"): + return script.get_custom_categories() + + return [] From 8fdd57c11435c4b9fa3d0e2a2c07ce43078c2571 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Wed, 7 Aug 2024 16:20:15 -0400 Subject: [PATCH 194/423] Generate script from ScriptGenerator class --- .../code_generation/script_generator.gd | 63 +++++++++++++++++ addons/block_code/ui/block_tree_util.gd | 70 +------------------ 2 files changed, 65 insertions(+), 68 deletions(-) create mode 100644 addons/block_code/code_generation/script_generator.gd diff --git a/addons/block_code/code_generation/script_generator.gd b/addons/block_code/code_generation/script_generator.gd new file mode 100644 index 00000000..264b73f4 --- /dev/null +++ b/addons/block_code/code_generation/script_generator.gd @@ -0,0 +1,63 @@ +extends Object + +const Types = preload("res://addons/block_code/types/types.gd") +const ASTList = preload("res://addons/block_code/code_generation/ast_list.gd") +const BlockAST = preload("res://addons/block_code/code_generation/block_ast.gd") +const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") + + +static func generate_script(ast_list: ASTList, block_script: BlockScriptSerialization) -> String: + var entry_asts: Array[BlockAST] = ast_list.get_top_level_nodes_of_type(Types.BlockType.ENTRY) + + var init_ast := BlockAST.new() + init_ast.root = BlockAST.ASTNode.new() + init_ast.root.data = BlockDefinition.new() + init_ast.root.data.type = Types.BlockType.ENTRY + init_ast.root.data.code_template = "func _init():" + + var combined_entry_asts = {} + + # Combine entry asts with same root statement + for entry_ast in entry_asts: + var statement = entry_ast.root.get_code(0) + if not statement in combined_entry_asts: + var new_ast := BlockAST.new() + var root = BlockAST.ASTNode.new() + root.data = entry_ast.root.data + root.arguments = entry_ast.root.arguments + root.children = entry_ast.root.children.duplicate() + new_ast.root = root + combined_entry_asts[statement] = new_ast + else: + combined_entry_asts[statement].root.children.append_array(entry_ast.root.children) + + # Connect signals on _init + for entry_statement in combined_entry_asts: + var entry_ast: BlockAST = combined_entry_asts[entry_statement] + var signal_name = entry_ast.root.data.signal_name + if signal_name != "": + var signal_node := BlockAST.ASTNode.new() + signal_node.data = BlockDefinition.new() + signal_node.data.code_template = "{0}.connect(_on_{0})".format([signal_name]) + init_ast.root.children.append(signal_node) + + # Generate script extends statement + var script := "extends %s\n\n" % block_script.script_inherits + + # Generate variables + for variable in block_script.variables: + script += "var %s: %s\n\n" % [variable.var_name, type_string(variable.var_type)] + + script += "\n" + + # Generate _init + if not init_ast.root.children.is_empty(): + script += init_ast.get_code() + "\n" + + # Generate other entry methods + for entry_statement in combined_entry_asts: + var entry_ast: BlockAST = combined_entry_asts[entry_statement] + script += entry_ast.get_code() + script += "\n" + + return script diff --git a/addons/block_code/ui/block_tree_util.gd b/addons/block_code/ui/block_tree_util.gd index d5ebf718..4cc49898 100644 --- a/addons/block_code/ui/block_tree_util.gd +++ b/addons/block_code/ui/block_tree_util.gd @@ -1,77 +1,11 @@ extends Object -const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") - - -static func generate_script_from_nodes(nodes: Array[Node], block_script: BlockScriptSerialization) -> String: - var entry_blocks_by_entry_statement: Dictionary = {} - - for block in nodes: - if !(block is Block): - continue - - if block is EntryBlock: - var entry_statement = block.get_entry_statement() - if not entry_blocks_by_entry_statement.has(entry_statement): - entry_blocks_by_entry_statement[entry_statement] = [] - entry_blocks_by_entry_statement[entry_statement].append(block) - - var script: String = "" - - script += "extends %s\n\n" % block_script.script_inherits - - for variable in block_script.variables: - script += "var %s: %s\n\n" % [variable.var_name, type_string(variable.var_type)] - - script += "\n" - - var init_func = InstructionTree.TreeNode.new("func _init():") - - for entry_statement in entry_blocks_by_entry_statement: - var entry_blocks: Array[EntryBlock] - entry_blocks.assign(entry_blocks_by_entry_statement[entry_statement]) - script += _generate_script_from_entry_blocks(entry_statement, entry_blocks, init_func) - - if init_func.children: - script += InstructionTree.generate_text(init_func) - - return script - - -static func _generate_script_from_entry_blocks(entry_statement: String, entry_blocks: Array[EntryBlock], init_func: InstructionTree.TreeNode) -> String: - var script = entry_statement + "\n" - var signal_node: InstructionTree.TreeNode - var is_empty = true - - InstructionTree.IDHandler.reset() - - for entry_block in entry_blocks: - var next_block := entry_block.bottom_snap.get_snapped_block() - - if next_block != null: - var instruction_node: InstructionTree.TreeNode = next_block.get_instruction_node() - var to_append := InstructionTree.generate_text(instruction_node, 1) - script += to_append - script += "\n" - is_empty = false - - if signal_node == null and entry_block.signal_name: - signal_node = InstructionTree.TreeNode.new("{0}.connect(_on_{0})".format([entry_block.signal_name])) - - if signal_node: - init_func.add_child(signal_node) - - if is_empty: - script += "\tpass\n\n" - - return script - ## Returns the scope of the first non-empty scope child block static func get_tree_scope(node: Node) -> String: if node is Block: - if node.scope != "": - return node.scope + if node.definition.scope != "": + return node.definition.scope for c in node.get_children(): var scope := get_tree_scope(c) From ff9df9152dcab9066c53e51cc1662992e5368745 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Wed, 7 Aug 2024 17:09:25 -0400 Subject: [PATCH 195/423] Remove code generation from UI blocks --- addons/block_code/ui/blocks/block/block.gd | 13 ------- .../ui/blocks/control_block/control_block.gd | 36 ------------------- .../blocks/parameter_block/parameter_block.gd | 12 ------- .../blocks/statement_block/statement_block.gd | 26 -------------- 4 files changed, 87 deletions(-) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 91cbcf21..f541774d 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -4,7 +4,6 @@ extends MarginContainer const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") const BlockSerialization = preload("res://addons/block_code/serialization/block_serialization.gd") -const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") const Types = preload("res://addons/block_code/types/types.gd") signal drag_started(block: Block) @@ -104,18 +103,6 @@ func disconnect_signals(): drag_started.disconnect(c.callable) -# Override this method to create custom block functionality -func get_instruction_node() -> InstructionTree.TreeNode: - var node: InstructionTree.TreeNode = InstructionTree.TreeNode.new("") - - if bottom_snap: - var snapped_block: Block = bottom_snap.get_snapped_block() - if snapped_block: - node.next = snapped_block.get_instruction_node() - - return node - - func update_resources(undo_redo: EditorUndoRedoManager): if resource == null: var block_serialized_properties = BlockSerializedProperties.new(get_block_class(), get_serialized_props()) diff --git a/addons/block_code/ui/blocks/control_block/control_block.gd b/addons/block_code/ui/blocks/control_block/control_block.gd index 0e40f101..715cb35b 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.gd +++ b/addons/block_code/ui/blocks/control_block/control_block.gd @@ -31,42 +31,6 @@ func _on_drag_drop_area_mouse_down(): _drag_started() -# Override this method to create custom block functionality -func get_instruction_node() -> InstructionTree.TreeNode: - var root: InstructionTree.TreeNode = InstructionTree.TreeNode.new("") - var node: InstructionTree.TreeNode - - for i in snaps.size(): - var snap: SnapPoint = snaps[i] - var formatted_statement: String = statements[i] - - for pair in param_name_input_pairs_array[i]: - formatted_statement = formatted_statement.replace("{%s}" % pair[0], pair[1].get_string()) - - formatted_statement = InstructionTree.IDHandler.make_unique(formatted_statement) - - var new_node := InstructionTree.TreeNode.new(formatted_statement) - if i == 0: - node = new_node - root = node - else: - node.next = new_node - node = node.next - - var snapped_block: Block = snap.get_snapped_block() - if snapped_block: - node.add_child(snapped_block.get_instruction_node()) - else: - node.add_child(InstructionTree.TreeNode.new("pass")) -# - if bottom_snap: - var snapped_block: Block = bottom_snap.get_snapped_block() - if snapped_block: - node.next = snapped_block.get_instruction_node() - - return root - - func get_serialized_props() -> Array: var props := super() if not BlocksCatalog.has_block(block_name): diff --git a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd index cd6bb599..e630e2fd 100644 --- a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd +++ b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd @@ -61,18 +61,6 @@ func get_serialized_props() -> Array: return props -# Override this method to create custom parameter functionality -func get_parameter_string() -> String: - var formatted_statement := statement - - for pair in param_name_input_pairs: - formatted_statement = formatted_statement.replace("{%s}" % pair[0], pair[1].get_string()) - - formatted_statement = InstructionTree.IDHandler.make_unique(formatted_statement) - - return formatted_statement - - static func get_block_class(): return "ParameterBlock" diff --git a/addons/block_code/ui/blocks/statement_block/statement_block.gd b/addons/block_code/ui/blocks/statement_block/statement_block.gd index a39ce705..190476be 100644 --- a/addons/block_code/ui/blocks/statement_block/statement_block.gd +++ b/addons/block_code/ui/blocks/statement_block/statement_block.gd @@ -55,32 +55,6 @@ static func get_scene_path(): return "res://addons/block_code/ui/blocks/statement_block/statement_block.tscn" -# Override this method to create custom block functionality -func get_instruction_node() -> InstructionTree.TreeNode: - var formatted_statement := statement - - for pair in param_name_input_pairs: - formatted_statement = formatted_statement.replace("{%s}" % pair[0], pair[1].get_string()) - - formatted_statement = InstructionTree.IDHandler.make_unique(formatted_statement) - - var statement_lines := formatted_statement.split("\n") - - var root: InstructionTree.TreeNode = InstructionTree.TreeNode.new(statement_lines[0]) - var node := root - - for i in range(1, statement_lines.size()): - node.next = InstructionTree.TreeNode.new(statement_lines[i]) - node = node.next - - if bottom_snap: - var snapped_block: Block = bottom_snap.get_snapped_block() - if snapped_block: - node.next = snapped_block.get_instruction_node() - - return root - - func format(): param_name_input_pairs = format_string(self, %HBoxContainer, block_format, defaults) From 7a6fe1329cb2d2b746a08fedb3fb6288cc0e6bba Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Wed, 7 Aug 2024 17:10:22 -0400 Subject: [PATCH 196/423] Refactor UI block classes to depend on BlockDefinition --- addons/block_code/ui/blocks/block/block.gd | 75 ++--------- .../ui/blocks/control_block/control_block.gd | 125 +++--------------- .../blocks/control_block/control_block.tscn | 77 +++++++++-- .../ui/blocks/entry_block/entry_block.gd | 18 +-- .../ui/blocks/entry_block/entry_block.tscn | 60 +++++++-- .../blocks/parameter_block/parameter_block.gd | 36 ++--- .../parameter_block/parameter_block.tscn | 3 - .../blocks/statement_block/statement_block.gd | 67 +++++----- .../statement_block/statement_block.tscn | 6 +- .../parameter_input/parameter_input.gd | 32 +---- addons/block_code/ui/util.gd | 32 ++--- 11 files changed, 206 insertions(+), 325 deletions(-) diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index f541774d..741d31c4 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -2,55 +2,38 @@ class_name Block extends MarginContainer -const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") -const BlockSerialization = preload("res://addons/block_code/serialization/block_serialization.gd") -const Types = preload("res://addons/block_code/types/types.gd") +const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") signal drag_started(block: Block) signal modified -## Name of the block to be referenced by others in search -@export var block_name: StringName - -## Label of block (optionally used to draw block labels) -@export var label: String = "" - ## Color of block (optionally used to draw block color) @export var color: Color = Color(1., 1., 1.) -## Type of block to check if can be attached to snap point -@export var block_type: Types.BlockType = Types.BlockType.STATEMENT - ## Category to add the block to @export var category: String +# FIXME Note: This used to be a NodePath. There is a bug in Godot 4.2 that causes the +# reference to not be set properly when the node is duplicated. Since we don't +# use the Node duplicate function anymore, this is okay. +# https://github.com/godotengine/godot/issues/82670 ## The next block in the line of execution (can be null if end) -@export var bottom_snap_path: NodePath: - set = _set_bottom_snap_path +@export var bottom_snap: SnapPoint = null + +## Snap point that holds blocks that should be nested under this block +@export var child_snap: SnapPoint = null ## The scope of the block (statement of matching entry block) @export var scope: String = "" -## The resource containing the block properties and the snapped blocks -@export var resource: BlockSerialization - -# FIXME: Add export to this variable and remove bottom_snap_path above. -# There is a bug in Godot 4.2 that prevents using SnapPoint directly: -# https://github.com/godotengine/godot/issues/82670 -var bottom_snap: SnapPoint +## The resource containing the definition of the block +@export var definition: BlockDefinition ## Whether the block can be deleted by the Delete key. var can_delete: bool = true -func _set_bottom_snap_path(value: NodePath): - bottom_snap_path = value - bottom_snap = get_node_or_null(bottom_snap_path) - - func _ready(): - if bottom_snap == null: - _set_bottom_snap_path(bottom_snap_path) focus_mode = FocusMode.FOCUS_ALL mouse_filter = Control.MOUSE_FILTER_IGNORE @@ -103,42 +86,8 @@ func disconnect_signals(): drag_started.disconnect(c.callable) -func update_resources(undo_redo: EditorUndoRedoManager): - if resource == null: - var block_serialized_properties = BlockSerializedProperties.new(get_block_class(), get_serialized_props()) - resource = BlockSerialization.new(block_name, position, block_serialized_properties) - return - - if resource.position != position: - undo_redo.add_undo_property(resource, "position", resource.position) - undo_redo.add_do_property(resource, "position", position) - - var serialized_props = get_serialized_props() - - if serialized_props != resource.block_serialized_properties.serialized_props: - undo_redo.add_undo_property(resource.block_serialized_properties, "serialized_props", resource.block_serialized_properties.serialized_props) - undo_redo.add_do_property(resource.block_serialized_properties, "serialized_props", serialized_props) - - -# Override this method to add more serialized properties -func get_serialized_props() -> Array: - if not BlocksCatalog.has_block(block_name): - return serialize_props(["block_name", "label", "color", "block_type", "position", "scope"]) - - # TODO: Remove remaining serialization: - # - Handle scope in a different way? - return serialize_props(["scope"]) - - func _to_string(): - return "<{block_class}:{block_name}#{rid}>".format({"block_name": block_name, "block_class": get_block_class(), "rid": get_instance_id()}) - - -func serialize_props(prop_names: Array) -> Array: - var pairs := [] - for p in prop_names: - pairs.append([p, self.get(p)]) - return pairs + return "<{block_class}:{block_name}#{rid}>".format({"block_name": definition.name, "block_class": get_block_class(), "rid": get_instance_id()}) func _make_custom_tooltip(for_text) -> Control: diff --git a/addons/block_code/ui/blocks/control_block/control_block.gd b/addons/block_code/ui/blocks/control_block/control_block.gd index 715cb35b..c4d4590b 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.gd +++ b/addons/block_code/ui/blocks/control_block/control_block.gd @@ -2,53 +2,38 @@ class_name ControlBlock extends Block -const Background = preload("res://addons/block_code/ui/blocks/utilities/background/background.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") -const DragDropArea = preload("res://addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.gd") -const Gutter = preload("res://addons/block_code/ui/blocks/utilities/background/gutter.gd") -@export var block_formats: Array = [] -@export var statements: Array = [] -@export var defaults: Dictionary = {} - -var snaps: Array -var param_name_input_pairs_array: Array -var param_input_strings_array: Array # Only loaded from serialized +var arg_name_to_param_input_dict: Dictionary +var args_to_add_after_format: Dictionary # Only used when loading func _ready(): super() + %TopBackground.color = color + %TopBackground.shift_bottom = Constants.CONTROL_MARGIN + %BottomBackground.color = color + %BottomBackground.shift_top = Constants.CONTROL_MARGIN + %SnapPoint.add_theme_constant_override("margin_left", Constants.CONTROL_MARGIN) + %SnapGutter.color = color + %SnapGutter.custom_minimum_size.x = Constants.CONTROL_MARGIN + format() - if param_input_strings_array: - for i in param_name_input_pairs_array.size(): - for pair in param_name_input_pairs_array[i]: - pair[1].set_raw_input(param_input_strings_array[i][pair[0]]) + for arg_name in arg_name_to_param_input_dict: + if arg_name in args_to_add_after_format: + var argument = args_to_add_after_format[arg_name] + if argument is Block: + arg_name_to_param_input_dict[arg_name].snap_point.add_child(argument) + else: + arg_name_to_param_input_dict[arg_name].set_raw_input(argument) func _on_drag_drop_area_mouse_down(): _drag_started() -func get_serialized_props() -> Array: - var props := super() - if not BlocksCatalog.has_block(block_name): - props.append_array(serialize_props(["block_formats", "statements", "defaults"])) - - var _param_input_strings_array = [] - for param_name_input_pairs in param_name_input_pairs_array: - var _param_input_strings: Dictionary = {} - - for pair in param_name_input_pairs: - _param_input_strings[pair[0]] = pair[1].get_raw_input() - - _param_input_strings_array.append(_param_input_strings) - - props.append(["param_input_strings_array", _param_input_strings_array]) - return props - - static func get_block_class(): return "ControlBlock" @@ -58,78 +43,4 @@ static func get_scene_path(): func format(): - snaps = [] - param_name_input_pairs_array = [] - - if block_formats.size() == 0: - return - - for i in block_formats.size(): - var row := MarginContainer.new() - row.name = "Row%d" % i - row.custom_minimum_size.x = 80 - row.custom_minimum_size.y = 30 - row.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN - - var bg := Background.new() - bg.name = "Background" - bg.color = color - if i != 0: - bg.shift_top = Constants.CONTROL_MARGIN - bg.shift_bottom = Constants.CONTROL_MARGIN - row.add_child(bg) - - if i == 0: - var drag_drop: DragDropArea = preload("res://addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.tscn").instantiate() - row.add_child(drag_drop) - drag_drop.mouse_down.connect(_drag_started) - - var row_hbox_container := MarginContainer.new() - row_hbox_container.name = "RowHBoxContainer" - row_hbox_container.add_theme_constant_override("margin_left", 10) - row_hbox_container.add_theme_constant_override("margin_right", 6) - row_hbox_container.add_theme_constant_override("margin_top", 12) - row_hbox_container.add_theme_constant_override("margin_bottom", 6) - row_hbox_container.mouse_filter = Control.MOUSE_FILTER_IGNORE - row.add_child(row_hbox_container) - - var row_hbox := HBoxContainer.new() - row_hbox.name = "RowHBox" - row_hbox.add_theme_constant_override("separation", 0) - row_hbox.mouse_filter = Control.MOUSE_FILTER_IGNORE - row_hbox_container.add_child(row_hbox) - - param_name_input_pairs_array.append(StatementBlock.format_string(self, row_hbox, block_formats[i], defaults)) - - %Rows.add_child(row) - - var snap_container := MarginContainer.new() - snap_container.name = "SnapContainer%d" % i - snap_container.mouse_filter = Control.MOUSE_FILTER_IGNORE - snap_container.custom_minimum_size.x = 30 - snap_container.custom_minimum_size.y = 30 - snap_container.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN - - var snap_gutter := Gutter.new() - snap_gutter.name = "Background" - snap_gutter.custom_minimum_size.x = Constants.CONTROL_MARGIN - snap_gutter.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN - snap_gutter.size_flags_vertical = Control.SIZE_EXPAND_FILL - snap_gutter.color = color - snap_container.add_child(snap_gutter) - - var snap_point: SnapPoint = preload("res://addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn").instantiate() - snap_point.add_theme_constant_override("margin_left", Constants.CONTROL_MARGIN) - snap_container.add_child(snap_point) - - snaps.append(snap_point) - - %Rows.add_child(snap_container) - - var bg := Background.new() - bg.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN - bg.custom_minimum_size.x = 100 - bg.custom_minimum_size.y = 30 - bg.color = color - bg.shift_top = Constants.CONTROL_MARGIN - %Rows.add_child(bg) + arg_name_to_param_input_dict = StatementBlock.format_string(self, %RowHBox, definition.display_template, definition.defaults) diff --git a/addons/block_code/ui/blocks/control_block/control_block.tscn b/addons/block_code/ui/blocks/control_block/control_block.tscn index e45c85d6..947b8d25 100644 --- a/addons/block_code/ui/blocks/control_block/control_block.tscn +++ b/addons/block_code/ui/blocks/control_block/control_block.tscn @@ -1,17 +1,18 @@ -[gd_scene load_steps=3 format=3 uid="uid://bk2argmujy0kk"] +[gd_scene load_steps=6 format=3 uid="uid://bk2argmujy0kk"] [ext_resource type="Script" path="res://addons/block_code/ui/blocks/control_block/control_block.gd" id="1_2hbir"] +[ext_resource type="Script" path="res://addons/block_code/ui/blocks/utilities/background/gutter.gd" id="2_6o8pf"] +[ext_resource type="PackedScene" uid="uid://c7puyxpqcq6xo" path="res://addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.tscn" id="2_lpu3c"] +[ext_resource type="Script" path="res://addons/block_code/ui/blocks/utilities/background/background.gd" id="2_tx0qr"] [ext_resource type="PackedScene" uid="uid://b1oge52xhjqnu" path="res://addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn" id="3_nhryi"] -[node name="ControlBlock" type="MarginContainer"] +[node name="ControlBlock" type="MarginContainer" node_paths=PackedStringArray("bottom_snap", "child_snap")] size_flags_horizontal = 0 focus_mode = 2 mouse_filter = 2 script = ExtResource("1_2hbir") -block_name = &"control_block" -label = "Control Block" -color = Color(0.59979, 0.536348, 0.876215, 1) -bottom_snap_path = NodePath("VBoxContainer/SnapPoint") +bottom_snap = NodePath("VBoxContainer/SnapPoint") +child_snap = NodePath("VBoxContainer/MarginContainer/Rows/SnapContainer/SnapPoint") [node name="VBoxContainer" type="VBoxContainer" parent="."] layout_mode = 2 @@ -24,9 +25,7 @@ mouse_filter = 2 [node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/MarginContainer"] layout_mode = 2 -mouse_filter = 2 -theme_override_constants/margin_top = 30 -theme_override_constants/margin_bottom = 30 +theme_override_constants/margin_top = 12 [node name="Rows" type="VBoxContainer" parent="VBoxContainer/MarginContainer"] unique_name_in_owner = true @@ -35,5 +34,65 @@ size_flags_horizontal = 0 mouse_filter = 2 theme_override_constants/separation = 0 +[node name="Row" type="MarginContainer" parent="VBoxContainer/MarginContainer/Rows"] +custom_minimum_size = Vector2(80, 30) +layout_mode = 2 +size_flags_horizontal = 0 + +[node name="TopBackground" type="Control" parent="VBoxContainer/MarginContainer/Rows/Row"] +unique_name_in_owner = true +layout_mode = 2 +script = ExtResource("2_tx0qr") +color = Color(1, 1, 1, 1) +shift_bottom = 20.0 + +[node name="DragDropArea" parent="VBoxContainer/MarginContainer/Rows/Row" instance=ExtResource("2_lpu3c")] +layout_mode = 2 + +[node name="RowHBoxContainer" type="MarginContainer" parent="VBoxContainer/MarginContainer/Rows/Row"] +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 6 +theme_override_constants/margin_right = 12 +theme_override_constants/margin_bottom = 6 + +[node name="RowHBox" type="HBoxContainer" parent="VBoxContainer/MarginContainer/Rows/Row/RowHBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/separation = 0 + +[node name="SnapContainer" type="MarginContainer" parent="VBoxContainer/MarginContainer/Rows"] +unique_name_in_owner = true +custom_minimum_size = Vector2(30, 30) +layout_mode = 2 +size_flags_horizontal = 0 +mouse_filter = 2 + +[node name="SnapGutter" type="Control" parent="VBoxContainer/MarginContainer/Rows/SnapContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(20, 0) +layout_mode = 2 +size_flags_horizontal = 0 +script = ExtResource("2_6o8pf") +color = Color(1, 1, 1, 1) + +[node name="SnapPoint" parent="VBoxContainer/MarginContainer/Rows/SnapContainer" instance=ExtResource("3_nhryi")] +unique_name_in_owner = true +layout_mode = 2 +theme_override_constants/margin_left = 20 + +[node name="BottomBackground" type="Control" parent="VBoxContainer/MarginContainer/Rows"] +unique_name_in_owner = true +custom_minimum_size = Vector2(80, 30) +layout_mode = 2 +size_flags_horizontal = 0 +script = ExtResource("2_tx0qr") +color = Color(1, 1, 1, 1) +shift_top = 20.0 + [node name="SnapPoint" parent="VBoxContainer" instance=ExtResource("3_nhryi")] layout_mode = 2 + +[connection signal="mouse_down" from="VBoxContainer/MarginContainer/Rows/Row/DragDropArea" to="." method="_on_drag_drop_area_mouse_down"] diff --git a/addons/block_code/ui/blocks/entry_block/entry_block.gd b/addons/block_code/ui/blocks/entry_block/entry_block.gd index 0659d4bc..22a8b58d 100644 --- a/addons/block_code/ui/blocks/entry_block/entry_block.gd +++ b/addons/block_code/ui/blocks/entry_block/entry_block.gd @@ -7,8 +7,8 @@ extends StatementBlock func _ready(): - block_type = Types.BlockType.ENTRY super() + bottom_snap = null static func get_block_class(): @@ -17,19 +17,3 @@ static func get_block_class(): static func get_scene_path(): return "res://addons/block_code/ui/blocks/entry_block/entry_block.tscn" - - -func get_entry_statement() -> String: - var formatted_statement := statement - - for pair in param_name_input_pairs: - formatted_statement = formatted_statement.replace("{%s}" % pair[0], pair[1].get_string()) - - return formatted_statement - - -func get_serialized_props() -> Array: - var props := super() - if not BlocksCatalog.has_block(block_name): - props.append_array(serialize_props(["signal_name"])) - return props diff --git a/addons/block_code/ui/blocks/entry_block/entry_block.tscn b/addons/block_code/ui/blocks/entry_block/entry_block.tscn index 50c2f0b6..9318bf94 100644 --- a/addons/block_code/ui/blocks/entry_block/entry_block.tscn +++ b/addons/block_code/ui/blocks/entry_block/entry_block.tscn @@ -1,15 +1,59 @@ -[gd_scene load_steps=3 format=3 uid="uid://d2fibflv3ojys"] +[gd_scene load_steps=5 format=3 uid="uid://d2fibflv3ojys"] -[ext_resource type="PackedScene" uid="uid://c84vmg3odrtxt" path="res://addons/block_code/ui/blocks/statement_block/statement_block.tscn" id="1_byjbb"] [ext_resource type="Script" path="res://addons/block_code/ui/blocks/entry_block/entry_block.gd" id="2_3ik8h"] +[ext_resource type="Script" path="res://addons/block_code/ui/blocks/utilities/background/background.gd" id="2_yrw8l"] +[ext_resource type="PackedScene" uid="uid://c7puyxpqcq6xo" path="res://addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.tscn" id="3_v0qw8"] +[ext_resource type="PackedScene" uid="uid://b1oge52xhjqnu" path="res://addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn" id="4_yj206"] -[node name="EntryBlock" instance=ExtResource("1_byjbb")] +[node name="EntryBlock" type="MarginContainer" node_paths=PackedStringArray("child_snap")] +size_flags_horizontal = 0 focus_mode = 2 +mouse_filter = 2 script = ExtResource("2_3ik8h") -signal_name = "" -block_name = &"entry_block" -label = "EntryBlock" -block_type = 1 +child_snap = NodePath("VBoxContainer/SnapPoint") -[node name="Background" parent="VBoxContainer/TopMarginContainer" index="0"] +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/separation = 0 + +[node name="TopMarginContainer" type="MarginContainer" parent="VBoxContainer"] +custom_minimum_size = Vector2(0, 30) +layout_mode = 2 +size_flags_horizontal = 0 +mouse_filter = 2 +theme_override_constants/margin_left = 0 +theme_override_constants/margin_top = 0 +theme_override_constants/margin_right = 0 +theme_override_constants/margin_bottom = 0 + +[node name="Background" type="Control" parent="VBoxContainer/TopMarginContainer"] +unique_name_in_owner = true +layout_mode = 2 +mouse_filter = 1 +script = ExtResource("2_yrw8l") +color = Color(1, 1, 1, 1) show_top = false + +[node name="DragDropArea" parent="VBoxContainer/TopMarginContainer" instance=ExtResource("3_v0qw8")] +layout_mode = 2 + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/TopMarginContainer"] +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 6 +theme_override_constants/margin_right = 12 +theme_override_constants/margin_bottom = 6 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/TopMarginContainer/MarginContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(50, 0) +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/separation = 0 + +[node name="SnapPoint" parent="VBoxContainer" instance=ExtResource("4_yj206")] +layout_mode = 2 + +[connection signal="mouse_down" from="VBoxContainer/TopMarginContainer/DragDropArea" to="." method="_on_drag_drop_area_mouse_down"] diff --git a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd index e630e2fd..2ed56aca 100644 --- a/addons/block_code/ui/blocks/parameter_block/parameter_block.gd +++ b/addons/block_code/ui/blocks/parameter_block/parameter_block.gd @@ -5,16 +5,11 @@ extends Block const Constants = preload("res://addons/block_code/ui/constants.gd") const Util = preload("res://addons/block_code/ui/util.gd") -@export var block_format: String = "" -@export var statement: String = "" -@export var variant_type: Variant.Type -@export var defaults: Dictionary = {} - @onready var _panel := $Panel @onready var _hbox := %HBoxContainer -var param_name_input_pairs: Array -var param_input_strings: Dictionary # Only loaded from serialized +var arg_name_to_param_input_dict: Dictionary +var args_to_add_after_format: Dictionary # Only used when loading var spawned_by: ParameterOutput var _panel_normal: StyleBox @@ -32,35 +27,24 @@ func _ready(): _panel_focus.bg_color = color _panel_focus.border_color = Constants.FOCUS_BORDER_COLOR - block_type = Types.BlockType.VALUE if not Util.node_is_part_of_edited_scene(self): _panel.add_theme_stylebox_override("panel", _panel_normal) format() - if param_input_strings: - for pair in param_name_input_pairs: - pair[1].set_raw_input(param_input_strings[pair[0]]) + for arg_name in arg_name_to_param_input_dict: + if arg_name in args_to_add_after_format: + var argument = args_to_add_after_format[arg_name] + if argument is Block: + arg_name_to_param_input_dict[arg_name].snap_point.add_child(argument) + else: + arg_name_to_param_input_dict[arg_name].set_raw_input(argument) func _on_drag_drop_area_mouse_down(): _drag_started() -func get_serialized_props() -> Array: - var props := super() - if not BlocksCatalog.has_block(block_name): - props.append_array(serialize_props(["block_format", "statement", "defaults", "variant_type"])) - - var _param_input_strings: Dictionary = {} - for pair in param_name_input_pairs: - _param_input_strings[pair[0]] = pair[1].get_raw_input() - - props.append(["param_input_strings", _param_input_strings]) - - return props - - static func get_block_class(): return "ParameterBlock" @@ -70,7 +54,7 @@ static func get_scene_path(): func format(): - param_name_input_pairs = StatementBlock.format_string(self, %HBoxContainer, block_format, defaults) + arg_name_to_param_input_dict = StatementBlock.format_string(self, %HBoxContainer, definition.display_template, definition.defaults) func _on_focus_entered(): diff --git a/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn b/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn index 2e901cd9..ac46b80a 100644 --- a/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn +++ b/addons/block_code/ui/blocks/parameter_block/parameter_block.tscn @@ -21,9 +21,6 @@ size_flags_horizontal = 0 focus_mode = 2 mouse_filter = 2 script = ExtResource("1_0hajy") -block_name = &"parameter_block" -label = "Param" -block_type = 3 [node name="Panel" type="Panel" parent="."] unique_name_in_owner = true diff --git a/addons/block_code/ui/blocks/statement_block/statement_block.gd b/addons/block_code/ui/blocks/statement_block/statement_block.gd index 190476be..5340477d 100644 --- a/addons/block_code/ui/blocks/statement_block/statement_block.gd +++ b/addons/block_code/ui/blocks/statement_block/statement_block.gd @@ -2,51 +2,42 @@ class_name StatementBlock extends Block +const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") const ParameterInput = preload("res://addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd") const ParameterInputScene = preload("res://addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.tscn") - -@export var block_format: String = "" -@export var statement: String = "" -@export var defaults: Dictionary = {} +const ParameterOutput = preload("res://addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd") +const ParameterOutputScene = preload("res://addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.tscn") +const Types = preload("res://addons/block_code/types/types.gd") @onready var _background := %Background @onready var _hbox := %HBoxContainer -var param_name_input_pairs: Array -var param_input_strings: Dictionary # Only loaded from serialized +var arg_name_to_param_input_dict: Dictionary +var args_to_add_after_format: Dictionary # Only used when loading func _ready(): super() - if block_type != Types.BlockType.STATEMENT: + if definition.type != Types.BlockType.STATEMENT: _background.show_top = false _background.color = color format() - if param_input_strings: - for pair in param_name_input_pairs: - pair[1].set_raw_input(param_input_strings[pair[0]]) + for arg_name in arg_name_to_param_input_dict: + if arg_name in args_to_add_after_format: + var argument = args_to_add_after_format[arg_name] + if argument is Block: + arg_name_to_param_input_dict[arg_name].snap_point.add_child(argument) + else: + arg_name_to_param_input_dict[arg_name].set_raw_input(argument) func _on_drag_drop_area_mouse_down(): _drag_started() -func get_serialized_props() -> Array: - var props := super() - if not BlocksCatalog.has_block(block_name): - props.append_array(serialize_props(["block_format", "statement", "defaults"])) - - var _param_input_strings: Dictionary = {} - for pair in param_name_input_pairs: - _param_input_strings[pair[0]] = pair[1].get_raw_input() - - props.append(["param_input_strings", _param_input_strings]) - return props - - static func get_block_class(): return "StatementBlock" @@ -56,11 +47,12 @@ static func get_scene_path(): func format(): - param_name_input_pairs = format_string(self, %HBoxContainer, block_format, defaults) + arg_name_to_param_input_dict = format_string(self, %HBoxContainer, definition.display_template, definition.defaults) -static func format_string(parent_block: Block, attach_to: Node, string: String, _defaults: Dictionary) -> Array: - var _param_name_input_pairs = [] +static func format_string(parent_block: Block, attach_to: Node, string: String, _defaults: Dictionary) -> Dictionary: + BlocksCatalog.setup() + var _arg_name_to_param_input_dict = {} var regex = RegEx.new() regex.compile("\\[([^\\]]+)\\]|\\{([^}]+)\\}") # Capture things of format {test} or [test] var results := regex.search_all(string) @@ -96,15 +88,15 @@ static func format_string(parent_block: Block, attach_to: Node, string: String, var param_node: Node if copy_block: - var parameter_output: ParameterOutput = preload("res://addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.tscn").instantiate() + var parameter_output: ParameterOutput = ParameterOutputScene.instantiate() parameter_output.name = "ParameterOutput%d" % start # Unique path - parameter_output.block_params = { - "block_format": param_name, - "statement": param_name, - "variant_type": param_type, - "color": parent_block.color, - "scope": parent_block.get_entry_statement() if parent_block is EntryBlock else "" - } + + var block_name = &"%s_%s" % [parent_block.definition.name, param_name] + var block_definition = BlocksCatalog.get_block(block_name) + if block_definition == null: + push_error("Could not locate block definition %s" % block_name) + + parameter_output.block_params = {"definition": block_definition, "color": parent_block.color} parameter_output.block = parent_block attach_to.add_child(parameter_output) else: @@ -118,10 +110,11 @@ static func format_string(parent_block: Block, attach_to: Node, string: String, parameter_input.modified.connect(func(): parent_block.modified.emit()) attach_to.add_child(parameter_input) - if param_default: + + if param_default != null: parameter_input.set_raw_input(param_default) - _param_name_input_pairs.append([param_name, parameter_input]) + _arg_name_to_param_input_dict[param_name] = parameter_input start = result.get_end() @@ -132,4 +125,4 @@ static func format_string(parent_block: Block, attach_to: Node, string: String, label.text = label_text attach_to.add_child(label) - return _param_name_input_pairs + return _arg_name_to_param_input_dict diff --git a/addons/block_code/ui/blocks/statement_block/statement_block.tscn b/addons/block_code/ui/blocks/statement_block/statement_block.tscn index f5507555..90bbdd9c 100644 --- a/addons/block_code/ui/blocks/statement_block/statement_block.tscn +++ b/addons/block_code/ui/blocks/statement_block/statement_block.tscn @@ -5,14 +5,12 @@ [ext_resource type="PackedScene" uid="uid://c7puyxpqcq6xo" path="res://addons/block_code/ui/blocks/utilities/drag_drop_area/drag_drop_area.tscn" id="2_owgdx"] [ext_resource type="PackedScene" uid="uid://b1oge52xhjqnu" path="res://addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn" id="3_5vaov"] -[node name="StatementBlock" type="MarginContainer"] +[node name="StatementBlock" type="MarginContainer" node_paths=PackedStringArray("bottom_snap")] size_flags_horizontal = 0 focus_mode = 2 mouse_filter = 2 script = ExtResource("1_6wvlf") -block_name = &"statement_block" -label = "StatementBlock" -bottom_snap_path = NodePath("VBoxContainer/SnapPoint") +bottom_snap = NodePath("VBoxContainer/SnapPoint") [node name="VBoxContainer" type="VBoxContainer" parent="."] layout_mode = 2 diff --git a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd index d64d380b..fdf2cd66 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd +++ b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd @@ -119,37 +119,6 @@ func get_snapped_block() -> Block: return snap_point.get_snapped_block() -func get_string() -> String: - var snapped_block: ParameterBlock = get_snapped_block() as ParameterBlock - if snapped_block: - var generated_string = snapped_block.get_parameter_string() - if Types.can_cast(snapped_block.variant_type, variant_type): - return Types.cast(generated_string, snapped_block.variant_type, variant_type) - else: - push_warning("No cast from %s to %s; using '%s' verbatim" % [snapped_block, variant_type, generated_string]) - return generated_string - - var input = get_raw_input() - - if option: - return _option_input.get_item_text(_option_input.selected).to_snake_case() - - match variant_type: - TYPE_STRING: - return "'%s'" % input.replace("\\", "\\\\").replace("'", "\\'") - TYPE_VECTOR2: - return "Vector2%s" % str(input) - TYPE_COLOR: - return "Color%s" % str(input) - TYPE_OBJECT: - if input is OptionData: - var option_data := input as OptionData - return option_data.items[option_data.selected] - _: - return "%s" % input - return "" - - func _validate_and_submit_edit_text(line_edit: Node, type: Variant.Type): if _last_submitted_text[line_edit] == line_edit.text: return @@ -163,6 +132,7 @@ func _validate_and_submit_edit_text(line_edit: Node, type: Variant.Type): line_edit.text = _last_submitted_text[line_edit] return _last_submitted_text[line_edit] = line_edit.text + modified.emit() diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index 050ccc04..f102483c 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -20,26 +20,18 @@ static func get_category_color(category: String) -> Color: static func instantiate_block(block_definition: BlockDefinition) -> Block: - var scene = SCENE_PER_TYPE[block_definition.type] - var b = scene.instantiate() - b.block_name = block_definition.name - if block_definition.type == Types.BlockType.CONTROL: - b.block_formats = [block_definition.display_template] - b.statements = [block_definition.code_template] - else: - b.block_format = block_definition.display_template - b.statement = block_definition.code_template - if block_definition.type == Types.BlockType.VALUE: - b.variant_type = block_definition.variant_type - elif block_definition.type == Types.BlockType.ENTRY: - if block_definition.signal_name != "": - b.signal_name = block_definition.signal_name - b.defaults = block_definition.defaults - b.tooltip_text = block_definition.description - b.category = block_definition.category - b.color = get_category_color(block_definition.category) - - return b + if block_definition == null: + push_error("Cannot construct block from null block definition.") + return null + + var scene = SCENE_PER_TYPE.get(block_definition.type) + if scene == null: + push_error("Cannot instantiate Block from type %s" % block_definition.type) + return null + + var block = scene.instantiate() + block.definition = block_definition + return block static func instantiate_block_by_name(block_name: StringName) -> Block: From c8536f54517147ecc7449ff48f7d71f318802a99 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Wed, 7 Aug 2024 15:42:39 -0400 Subject: [PATCH 197/423] Refactor drag classes to use properties from UI block definitions --- addons/block_code/drag_manager/drag.gd | 12 ++++++------ addons/block_code/drag_manager/drag_manager.gd | 6 ++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/addons/block_code/drag_manager/drag.gd b/addons/block_code/drag_manager/drag.gd index 7017c8c4..76d41b2c 100644 --- a/addons/block_code/drag_manager/drag.gd +++ b/addons/block_code/drag_manager/drag.gd @@ -5,7 +5,6 @@ const Background = preload("res://addons/block_code/ui/blocks/utilities/backgrou const BlockCanvas = preload("res://addons/block_code/ui/block_canvas/block_canvas.gd") const BlockTreeUtil = preload("res://addons/block_code/ui/block_tree_util.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") -const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") const Types = preload("res://addons/block_code/types/types.gd") enum DragAction { NONE, PLACE, REMOVE } @@ -124,11 +123,12 @@ func _snaps_to(node: Node) -> bool: # We only snap to blocks on the canvas: return false - if _block.block_type != _snap_point.block_type: - # We only snap to the same block type: - return false + # We only snap to the same block type: (HACK: Control blocks can snap to statements) + if not (_block.definition.type == Types.BlockType.CONTROL and _snap_point.block_type == Types.BlockType.STATEMENT): + if _block.definition.type != _snap_point.block_type: + return false - if _block.block_type == Types.BlockType.VALUE and not Types.can_cast(_block.variant_type, _snap_point.variant_type): + if _block.definition.type == Types.BlockType.VALUE and not Types.can_cast(_block.definition.variant_type, _snap_point.variant_type): # We only snap Value blocks to snaps that can cast to same variant: return false @@ -141,7 +141,7 @@ func _snaps_to(node: Node) -> bool: # Check if scope is valid if _block_scope != "": if top_block is EntryBlock: - if _block_scope != top_block.get_entry_statement(): + if _block_scope != top_block.definition.code_template: return false elif top_block: var tree_scope := BlockTreeUtil.get_tree_scope(top_block) diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index c12dd984..033f1e8d 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -7,8 +7,8 @@ signal block_modified const BlockCanvas = preload("res://addons/block_code/ui/block_canvas/block_canvas.gd") const BlockTreeUtil = preload("res://addons/block_code/ui/block_tree_util.gd") const Drag = preload("res://addons/block_code/drag_manager/drag.gd") -const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") const Picker = preload("res://addons/block_code/ui/picker/picker.gd") +const Util = preload("res://addons/block_code/ui/util.gd") @export var picker_path: NodePath @export var block_canvas_path: NodePath @@ -64,7 +64,9 @@ func drag_block(block: Block, copied_from: Block = null): func copy_block(block: Block) -> Block: - return block.duplicate(DUPLICATE_USE_INSTANTIATION) # use instantiation + var new_block = Util.instantiate_block(block.definition) + new_block.color = block.color + return new_block func copy_picked_block_and_drag(block: Block): From 0b1c3f09469f315a6705f7e07f7fd1b7861bac43 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Wed, 7 Aug 2024 15:48:43 -0400 Subject: [PATCH 198/423] Use BlockDefinition in block category classes --- .../block_code/ui/picker/categories/block_category.gd | 6 ++++-- .../ui/picker/categories/block_category_display.gd | 11 ++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/addons/block_code/ui/picker/categories/block_category.gd b/addons/block_code/ui/picker/categories/block_category.gd index aee65cb7..e076865d 100644 --- a/addons/block_code/ui/picker/categories/block_category.gd +++ b/addons/block_code/ui/picker/categories/block_category.gd @@ -1,12 +1,14 @@ extends RefCounted +const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") + var name: String -var block_list: Array[Block] +var block_list: Array[BlockDefinition] var color: Color var order: int -func _init(p_name: String = "", p_color: Color = Color.WHITE, p_order: int = 0, p_block_list: Array[Block] = []): +func _init(p_name: String = "", p_color: Color = Color.WHITE, p_order: int = 0, p_block_list: Array[BlockDefinition] = []): name = p_name block_list = p_block_list color = p_color diff --git a/addons/block_code/ui/picker/categories/block_category_display.gd b/addons/block_code/ui/picker/categories/block_category_display.gd index b4c536e3..5145836a 100644 --- a/addons/block_code/ui/picker/categories/block_category_display.gd +++ b/addons/block_code/ui/picker/categories/block_category_display.gd @@ -1,7 +1,10 @@ @tool extends MarginContainer +signal block_picked(block: Block) + const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") +const Util = preload("res://addons/block_code/ui/util.gd") var category: BlockCategory @@ -12,5 +15,11 @@ var category: BlockCategory func _ready(): _label.text = category.name - for block: Block in category.block_list: + for block_definition in category.block_list: + var block: Block = Util.instantiate_block(block_definition) + + block.color = category.color + block.can_delete = false + block.drag_started.connect(func(block: Block): block_picked.emit(block)) + _blocks.add_child(block) From d81d8b995bb62e82a0ea65e70d21a41107f99fec Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Thu, 5 Sep 2024 16:06:29 -0600 Subject: [PATCH 199/423] BlocksCatalog: Add inherited and variable block definition helpers These will be used when the picker and category factory transition to BlockDefinitions. After that, all BlockDefinition creation will happen in code generation. --- .../code_generation/blocks_catalog.gd | 67 +++++++++++++++ addons/block_code/ui/util.gd | 83 +------------------ 2 files changed, 71 insertions(+), 79 deletions(-) diff --git a/addons/block_code/code_generation/blocks_catalog.gd b/addons/block_code/code_generation/blocks_catalog.gd index 8c8fda12..8ab6f73a 100644 --- a/addons/block_code/code_generation/blocks_catalog.gd +++ b/addons/block_code/code_generation/blocks_catalog.gd @@ -4,6 +4,7 @@ const BlockDefinition = preload("res://addons/block_code/code_generation/block_d const OptionData = preload("res://addons/block_code/code_generation/option_data.gd") const Types = preload("res://addons/block_code/types/types.gd") const Util = preload("res://addons/block_code/code_generation/util.gd") +const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") const _BLOCKS_PATH = "res://addons/block_code/blocks/" @@ -273,6 +274,45 @@ static func get_blocks_by_class(_class_name: String): return block_definitions.values() +static func _get_builtin_parents(_class_name: String) -> Array[String]: + var parents: Array[String] = [] + var current = _class_name + + while current != "": + parents.append(current) + current = ClassDB.get_parent_class(current) + + return parents + + +static func _get_custom_parent_class_name(_custom_class_name: String) -> String: + for class_dict in ProjectSettings.get_global_class_list(): + if class_dict.class != _custom_class_name: + continue + var script = load(class_dict.path) + var builtin_class = script.get_instance_base_type() + return builtin_class + return "Node" + + +static func _get_parents(_class_name: String) -> Array[String]: + if ClassDB.class_exists(_class_name): + return _get_builtin_parents(_class_name) + var parents: Array[String] = [_class_name] + var _parent_class_name = _get_custom_parent_class_name(_class_name) + parents.append_array(_get_builtin_parents(_parent_class_name)) + return parents + + +static func get_inherited_blocks(_class_name: String) -> Array[BlockDefinition]: + setup() + + var definitions: Array[BlockDefinition] = [] + for _parent_class_name in _get_parents(_class_name): + definitions.append_array(get_blocks_by_class(_parent_class_name)) + return definitions + + static func add_custom_blocks( _class_name, block_definitions: Array[BlockDefinition] = [], @@ -290,3 +330,30 @@ static func add_custom_blocks( _add_output_definitions(block_definitions) _add_property_definitions(_class_name, property_list, property_settings) + + +static func get_variable_block_definitions(variables: Array[VariableDefinition]) -> Array[BlockDefinition]: + var block_definitions: Array[BlockDefinition] = [] + for variable: VariableDefinition in variables: + var type_string: String = Types.VARIANT_TYPE_TO_STRING[variable.var_type] + + # Getter + var block_def = BlockDefinition.new() + block_def.name = "get_var_%s" % variable.var_name + block_def.category = "Variables" + block_def.type = Types.BlockType.VALUE + block_def.variant_type = variable.var_type + block_def.display_template = variable.var_name + block_def.code_template = variable.var_name + block_definitions.append(block_def) + + # Setter + block_def = BlockDefinition.new() + block_def.name = "set_var_%s" % variable.var_name + block_def.category = "Variables" + block_def.type = Types.BlockType.STATEMENT + block_def.display_template = "Set %s to {value: %s}" % [variable.var_name, type_string] + block_def.code_template = "%s = {value}" % [variable.var_name] + block_definitions.append(block_def) + + return block_definitions diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index f102483c..076d1f84 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -34,87 +34,12 @@ static func instantiate_block(block_definition: BlockDefinition) -> Block: return block -static func instantiate_block_by_name(block_name: StringName) -> Block: - BlocksCatalog.setup() - var block_definition: BlockDefinition = BlocksCatalog.get_block(block_name) - if block_definition == null: - push_error("The block %s is not in the catalog yet!" % block_name) - return - return instantiate_block(block_definition) - - -static func _get_builtin_parents(_class_name: String) -> Array[String]: - var parents: Array[String] = [] - var current = _class_name - - while current != "": - parents.append(current) - current = ClassDB.get_parent_class(current) - - return parents - - -static func _get_custom_parent_class_name(_custom_class_name: String) -> String: - for class_dict in ProjectSettings.get_global_class_list(): - if class_dict.class != _custom_class_name: - continue - var script = load(class_dict.path) - var builtin_class = script.get_instance_base_type() - return builtin_class - return "Node" - - -static func _get_parents(_class_name: String) -> Array[String]: - if ClassDB.class_exists(_class_name): - return _get_builtin_parents(_class_name) - var parents: Array[String] = [_class_name] - var _parent_class_name = _get_custom_parent_class_name(_class_name) - parents.append_array(_get_builtin_parents(_parent_class_name)) - return parents - - -static func instantiate_blocks_for_class(_class_name: String) -> Array[Block]: - BlocksCatalog.setup() - - var blocks: Array[Block] = [] - for subclass in _get_parents(_class_name): - for block_definition in BlocksCatalog.get_blocks_by_class(subclass): - var b = instantiate_block(block_definition) - blocks.append(b) - - return blocks - - -static func get_variable_block_definitions(variables: Array[VariableDefinition]) -> Array[BlockDefinition]: - var block_definitions: Array[BlockDefinition] = [] - for variable: VariableDefinition in variables: - var type_string: String = Types.VARIANT_TYPE_TO_STRING[variable.var_type] - - var b = BlockDefinition.new() - b.name = "get_var_%s" % variable.var_name - b.type = Types.BlockType.VALUE - b.variant_type = variable.var_type - b.display_template = variable.var_name - b.code_template = variable.var_name - block_definitions.append(b) - - b = BlockDefinition.new() - b.name = "set_var_%s" % variable.var_name - b.type = Types.BlockType.STATEMENT - b.display_template = "Set %s to {value: %s}" % [variable.var_name, type_string] - b.code_template = "%s = {value}" % [variable.var_name] - block_definitions.append(b) - - return block_definitions - - static func instantiate_variable_blocks(variables: Array[VariableDefinition]) -> Array[Block]: var blocks: Array[Block] = [] - for block_definition in get_variable_block_definitions(variables): - var b = instantiate_block(block_definition) - # HACK: Color the blocks since they are outside of the normal picker system - b.color = Constants.BUILTIN_CATEGORIES_PROPS["Variables"].color - blocks.append(b) + for block_definition in BlocksCatalog.get_variable_block_definitions(variables): + var block = instantiate_block(block_definition) + block.color = get_category_color(block_definition.category) + blocks.append(block) return blocks From 1b04ea633a71a711c51d7c9d3d36c48d12f3e950 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Wed, 7 Aug 2024 15:50:36 -0400 Subject: [PATCH 200/423] Refactor Picker and CategoryFactory to use block definitions --- .../ui/picker/categories/category_factory.gd | 43 ++++++++----------- addons/block_code/ui/picker/picker.gd | 35 ++++----------- 2 files changed, 27 insertions(+), 51 deletions(-) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index c7949e84..02eda12b 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -2,10 +2,11 @@ class_name CategoryFactory extends Object const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") +const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") +const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") const Types = preload("res://addons/block_code/types/types.gd") const Util = preload("res://addons/block_code/ui/util.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") -const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") ## Compare block categories for sorting. Compare by order then name. @@ -15,7 +16,7 @@ static func _category_cmp(a: BlockCategory, b: BlockCategory) -> bool: return a.name.naturalcasecmp_to(b.name) < 0 -static func get_categories(blocks: Array[Block], extra_categories: Array[BlockCategory] = []) -> Array[BlockCategory]: +static func get_categories(blocks: Array[BlockDefinition], extra_categories: Array[BlockCategory] = []) -> Array[BlockCategory]: var cat_map: Dictionary = {} var extra_cat_map: Dictionary = {} @@ -45,67 +46,61 @@ static func get_categories(blocks: Array[Block], extra_categories: Array[BlockCa return cats -static func get_general_blocks() -> Array[Block]: - var block: Block - var block_list: Array[Block] = [] +static func get_general_blocks() -> Array[BlockDefinition]: + var block: BlockDefinition + var block_list: Array[BlockDefinition] = [] + + BlocksCatalog.setup() # Lifecycle for block_name in [&"ready", &"process", &"physics_process", &"queue_free"]: - block = Util.instantiate_block_by_name(block_name) + block = BlocksCatalog.get_block(block_name) block_list.append(block) # Loops for block_name in [&"for", &"while", &"break", &"continue", &"await_scene_ready"]: - block = Util.instantiate_block_by_name(block_name) + block = BlocksCatalog.get_block(block_name) block_list.append(block) # Logs - block = Util.instantiate_block_by_name(&"print") + block = BlocksCatalog.get_block(&"print") block_list.append(block) # Communication for block_name in [&"define_method", &"call_method_group", &"call_method_node"]: - block = Util.instantiate_block_by_name(block_name) + block = BlocksCatalog.get_block(block_name) block_list.append(block) for block_name in [&"add_to_group", &"add_node_to_group", &"remove_from_group", &"remove_node_from_group", &"is_in_group", &"is_node_in_group"]: - block = Util.instantiate_block_by_name(block_name) + block = BlocksCatalog.get_block(block_name) block_list.append(block) # Variables - block = Util.instantiate_block_by_name(&"vector2") + block = BlocksCatalog.get_block(&"vector2") block_list.append(block) # Math for block_name in [&"add", &"subtract", &"multiply", &"divide", &"pow", &"randf_range", &"randi_range", &"sin", &"cos", &"tan"]: - block = Util.instantiate_block_by_name(block_name) + block = BlocksCatalog.get_block(block_name) block_list.append(block) # Logic for block_name in [&"if", &"else_if", &"else", &"compare", &"and", &"or", &"not"]: - block = Util.instantiate_block_by_name(block_name) + block = BlocksCatalog.get_block(block_name) block_list.append(block) # Input - block = Util.instantiate_block_by_name(&"is_input_actioned") + block = BlocksCatalog.get_block(&"is_input_actioned") block_list.append(block) # Sounds for block_name in [&"load_sound", &"play_sound", &"pause_continue_sound", &"stop_sound"]: - block = Util.instantiate_block_by_name(block_name) + block = BlocksCatalog.get_block(block_name) block_list.append(block) # Graphics for block_name in [&"viewport_width", &"viewport_height", &"viewport_center"]: - block = Util.instantiate_block_by_name(block_name) + block = BlocksCatalog.get_block(block_name) block_list.append(block) return block_list - - -static func get_inherited_blocks(_class_name: String) -> Array[Block]: - return Util.instantiate_blocks_for_class(_class_name) - - -static func get_variable_blocks(variables: Array[VariableDefinition]): - return Util.instantiate_variable_blocks(variables) diff --git a/addons/block_code/ui/picker/picker.gd b/addons/block_code/ui/picker/picker.gd index 8f90b15d..d2fbd4c2 100644 --- a/addons/block_code/ui/picker/picker.gd +++ b/addons/block_code/ui/picker/picker.gd @@ -1,11 +1,13 @@ @tool extends MarginContainer +const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") const BlockCategoryButtonScene = preload("res://addons/block_code/ui/picker/categories/block_category_button.tscn") const BlockCategoryButton = preload("res://addons/block_code/ui/picker/categories/block_category_button.gd") const BlockCategoryDisplay = preload("res://addons/block_code/ui/picker/categories/block_category_display.gd") const CategoryFactory = preload("res://addons/block_code/ui/picker/categories/category_factory.gd") +const Util = preload("res://addons/block_code/ui/util.gd") const VariableCategoryDisplay = preload("res://addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd") const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") @@ -26,19 +28,8 @@ func block_script_selected(block_script: BlockScriptSerialization): reset_picker() return - var categories_to_add: Array[BlockCategory] = [] - - for class_dict in ProjectSettings.get_global_class_list(): - if class_dict.class == block_script.script_inherits: - var script = load(class_dict.path) - if script.has_method("get_custom_categories"): - categories_to_add = script.get_custom_categories() - if script.has_method("setup_custom_blocks"): - script.setup_custom_blocks() - break - - var blocks_to_add: Array[Block] = [] - blocks_to_add.append_array(CategoryFactory.get_inherited_blocks(block_script.script_inherits)) + var blocks_to_add: Array[BlockDefinition] = block_script.get_definitions() + var categories_to_add: Array[BlockCategory] = block_script.get_categories() init_picker(blocks_to_add, categories_to_add) reload_variables(block_script.variables) @@ -52,7 +43,7 @@ func reset_picker(): c.queue_free() -func init_picker(extra_blocks: Array[Block] = [], extra_categories: Array[BlockCategory] = []): +func init_picker(extra_blocks: Array[BlockDefinition] = [], extra_categories: Array[BlockCategory] = []): reset_picker() var blocks := CategoryFactory.get_general_blocks() + extra_blocks @@ -76,23 +67,13 @@ func init_picker(extra_blocks: Array[Block] = [], extra_categories: Array[BlockC _variable_category_display = block_category_display block_category_display.category = category + block_category_display.block_picked.connect(func(block: Block): block_picked.emit(block)) _block_list.add_child(block_category_display) - for _block in category.block_list: - var block: Block = _block as Block - block.drag_started.connect(_block_picked) - - # Don't allow the block to be deleted while in the picker. - block.can_delete = false - _block_scroll.scroll_vertical = 0 -func _block_picked(block: Block): - block_picked.emit(block) - - func scroll_to(y: float): if scroll_tween: scroll_tween.kill() @@ -117,9 +98,9 @@ func reload_variables(variables: Array[VariableDefinition]): c.queue_free() var i := 1 - for block in CategoryFactory.get_variable_blocks(variables): + for block in Util.instantiate_variable_blocks(variables): _variable_category_display.variable_blocks.add_child(block) - block.drag_started.connect(_block_picked) + block.drag_started.connect(func(block: Block): block_picked.emit(block)) if i % 2 == 0: var spacer := Control.new() spacer.custom_minimum_size.y = 12 From 2f062160a72dda8137a03d945fd59ba5069e8533 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Thu, 5 Sep 2024 15:41:45 -0600 Subject: [PATCH 201/423] serialization: Add codegen converter helpers These will be used when converting to and from the code generation classes so that you can go directly from the serialization to code. --- .../block_script_serialization.gd | 110 +++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-) diff --git a/addons/block_code/serialization/block_script_serialization.gd b/addons/block_code/serialization/block_script_serialization.gd index ba1590d7..02d61d22 100644 --- a/addons/block_code/serialization/block_script_serialization.gd +++ b/addons/block_code/serialization/block_script_serialization.gd @@ -2,18 +2,25 @@ class_name BlockScriptSerialization extends Resource +const ASTList = preload("res://addons/block_code/code_generation/ast_list.gd") +const BlockAST = preload("res://addons/block_code/code_generation/block_ast.gd") const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") +const BlockSerialization = preload("res://addons/block_code/serialization/block_serialization.gd") const BlockSerializationTree = preload("res://addons/block_code/serialization/block_serialization_tree.gd") +const ValueBlockSerialization = preload("res://addons/block_code/serialization/value_block_serialization.gd") const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") @export var script_inherits: String @export var block_serialization_trees: Array[BlockSerializationTree] -@export var variables: Array[VariableDefinition] +@export var variables: Array[VariableDefinition]: + set = _set_variables @export var generated_script: String @export var version: int +var _var_block_definitions: Dictionary # String, BlockDefinition + func _init( p_script_inherits: String = "", p_block_serialization_trees: Array[BlockSerializationTree] = [], p_variables: Array[VariableDefinition] = [], p_generated_script: String = "", p_version = 0 @@ -25,6 +32,24 @@ func _init( version = p_version +func _set_variables(value): + variables = value + _refresh_var_block_definitions() + + +func _refresh_var_block_definitions(): + _var_block_definitions.clear() + for block_def in BlocksCatalog.get_variable_block_definitions(variables): + _var_block_definitions[block_def.name] = block_def + + +func _get_block(block_name: StringName) -> BlockDefinition: + var block_def: BlockDefinition = _var_block_definitions.get(block_name) + if block_def == null: + block_def = BlocksCatalog.get_block(block_name) + return block_def + + func get_definitions() -> Array[BlockDefinition]: for class_dict in ProjectSettings.get_global_class_list(): if class_dict.class == script_inherits: @@ -44,3 +69,86 @@ func get_categories() -> Array[BlockCategory]: return script.get_custom_categories() return [] + + +func generate_ast_list() -> ASTList: + var ast_list := ASTList.new() + for tree in block_serialization_trees: + var ast: BlockAST = _tree_to_ast(tree) + ast_list.append(ast, tree.canvas_position) + return ast_list + + +func _tree_to_ast(tree: BlockSerializationTree) -> BlockAST: + var ast: BlockAST = BlockAST.new() + ast.root = _block_to_ast_node(tree.root) + return ast + + +func _block_to_ast_node(node: BlockSerialization) -> BlockAST.ASTNode: + var ast_node := BlockAST.ASTNode.new() + ast_node.data = _get_block(node.name) + + for arg_name in node.arguments: + var argument = node.arguments[arg_name] + if argument is ValueBlockSerialization: + argument = _value_to_ast_value(argument) + ast_node.arguments[arg_name] = argument + + var children: Array[BlockAST.ASTNode] + for c in node.children: + children.append(_block_to_ast_node(c)) + ast_node.children = children + + return ast_node + + +func _value_to_ast_value(value_node: ValueBlockSerialization) -> BlockAST.ASTValueNode: + var ast_value_node := BlockAST.ASTValueNode.new() + ast_value_node.data = _get_block(value_node.name) + + for arg_name in value_node.arguments: + var argument = value_node.arguments[arg_name] + if argument is ValueBlockSerialization: + argument = _value_to_ast_value(argument) + ast_value_node.arguments[arg_name] = argument + + return ast_value_node + + +func update_from_ast_list(ast_list: ASTList): + var trees: Array[BlockSerializationTree] + for ast_pair in ast_list.array: + var root := _block_from_ast_node(ast_pair.ast.root) + var tree := BlockSerializationTree.new(root, ast_pair.canvas_position) + trees.append(tree) + block_serialization_trees = trees + + +func _block_from_ast_node(ast_node: BlockAST.ASTNode) -> BlockSerialization: + var block := BlockSerialization.new(ast_node.data.name) + + for arg_name in ast_node.arguments: + var argument = ast_node.arguments[arg_name] + if argument is BlockAST.ASTValueNode: + argument = _value_from_ast_value(argument) + block.arguments[arg_name] = argument + + var children: Array[BlockSerialization] + for c in ast_node.children: + children.append(_block_from_ast_node(c)) + block.children = children + + return block + + +func _value_from_ast_value(ast_node: BlockAST.ASTValueNode) -> ValueBlockSerialization: + var value := ValueBlockSerialization.new(ast_node.data.name) + + for arg_name in ast_node.arguments: + var argument = ast_node.arguments[arg_name] + if argument is BlockAST.ASTValueNode: + argument = _value_from_ast_value(argument) + value.arguments[arg_name] = argument + + return value From 3e970413895f8c800f44957f3aa36d33156bf6b0 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Fri, 9 Aug 2024 15:11:26 -0400 Subject: [PATCH 202/423] Refactor BlockCanvas for new architecture Load block scripts by creating BlockASTs from BlockNameTrees, and then generate UI Blocks from them. Save block scripts by getting the BlockASTs from the UI Blocks, and then saving them as BlockNameTrees. --- .../ui/block_canvas/block_canvas.gd | 167 ++++++++++++------ addons/block_code/ui/main_panel.gd | 17 +- 2 files changed, 123 insertions(+), 61 deletions(-) diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index 70638c3c..c3095170 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -1,11 +1,12 @@ @tool extends MarginContainer +const ASTList = preload("res://addons/block_code/code_generation/ast_list.gd") +const BlockAST = preload("res://addons/block_code/code_generation/block_ast.gd") const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd") -const BlockSerialization = preload("res://addons/block_code/serialization/block_serialization.gd") const BlockTreeUtil = preload("res://addons/block_code/ui/block_tree_util.gd") const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") -const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") +const ScriptGenerator = preload("res://addons/block_code/code_generation/script_generator.gd") const Util = preload("res://addons/block_code/ui/util.gd") const EXTEND_MARGIN: float = 800 @@ -35,7 +36,7 @@ const ZOOM_FACTOR: float = 1.1 @onready var _zoom_button: Button = %ZoomButton var _current_block_script: BlockScriptSerialization -var _block_scenes_by_class = {} +var _current_ast_list: ASTList var _panning := false var zoom: float: set(value): @@ -53,17 +54,6 @@ signal replace_block_code func _ready(): if not _open_scene_button.icon and not Util.node_is_part_of_edited_scene(self): _open_scene_button.icon = _open_scene_icon - _populate_block_scenes_by_class() - - -func _populate_block_scenes_by_class(): - for _class in ProjectSettings.get_global_class_list(): - if not _class.base.ends_with("Block"): - continue - var _script = load(_class.path) - if not _script.has_method("get_scene_path"): - continue - _block_scenes_by_class[_class.class] = _script.get_scene_path() func add_block(block: Block, position: Vector2 = Vector2.ZERO) -> void: @@ -144,8 +134,62 @@ func block_script_selected(block_script: BlockScriptSerialization): func _load_block_script(block_script: BlockScriptSerialization): - for tree in block_script.block_trees: - load_tree(_window, tree) + _current_ast_list = block_script.generate_ast_list() + reload_ui_from_ast_list() + + +func reload_ui_from_ast_list(): + for ast_pair in _current_ast_list.array: + var root_block = ui_tree_from_ast_node(ast_pair.ast.root) + root_block.position = ast_pair.canvas_position + _window.add_child(root_block) + + +func ui_tree_from_ast_node(ast_node: BlockAST.ASTNode) -> Block: + var block: Block = Util.instantiate_block(ast_node.data) + block.color = Util.get_category_color(ast_node.data.category) + # Args + for arg_name in ast_node.arguments: + var argument = ast_node.arguments[arg_name] + if argument is BlockAST.ASTValueNode: + var value_block = ui_tree_from_ast_value_node(argument) + block.args_to_add_after_format[arg_name] = value_block + else: # Argument is not a node, but a user input value + block.args_to_add_after_format[arg_name] = argument + + # Children + var current_block: Block = block + + var i: int = 0 + for c in ast_node.children: + var child_block: Block = ui_tree_from_ast_node(c) + + if i == 0: + current_block.child_snap.add_child(child_block) + else: + current_block.bottom_snap.add_child(child_block) + + current_block = child_block + i += 1 + + reconnect_block.emit(block) + return block + + +func ui_tree_from_ast_value_node(ast_value_node: BlockAST.ASTValueNode) -> Block: + var block: Block = Util.instantiate_block(ast_value_node.data) + block.color = Util.get_category_color(ast_value_node.data.category) + # Args + for arg_name in ast_value_node.arguments: + var argument = ast_value_node.arguments[arg_name] + if argument is BlockAST.ASTValueNode: + var value_block = ui_tree_from_ast_value_node(argument) + block.args_to_add_after_format[arg_name] = value_block + else: # Argument is not a node, but a user input value + block.args_to_add_after_format[arg_name] = argument + + reconnect_block.emit(block) + return block func clear_canvas(): @@ -154,50 +198,68 @@ func clear_canvas(): child.queue_free() -func load_tree(parent: Node, node: BlockSerialization): - var scene: Block = Util.instantiate_block_by_name(node.name) +func rebuild_ast_list(): + _current_ast_list.clear() - # TODO: Remove once the data/UI decouple is done. - if scene == null: - var _block_scene_path = _block_scenes_by_class[node.block_serialized_properties.block_class] - scene = load(_block_scene_path).instantiate() - for prop_pair in node.block_serialized_properties.serialized_props: - scene.set(prop_pair[0], prop_pair[1]) + for c in _window.get_children(): + if c is StatementBlock: + var root: BlockAST.ASTNode = build_ast(c) + var ast: BlockAST = BlockAST.new() + ast.root = root + _current_ast_list.append(ast, c.position) + + +func build_ast(block: Block) -> BlockAST.ASTNode: + var ast_node := BlockAST.ASTNode.new() + ast_node.data = block.definition + + for arg_name in block.arg_name_to_param_input_dict: + var param_input = block.arg_name_to_param_input_dict[arg_name] + var snap_point = param_input.snap_point + var snapped_block = snap_point.get_snapped_block() + if snapped_block: + ast_node.arguments[arg_name] = build_value_ast(snapped_block) + else: + ast_node.arguments[arg_name] = param_input.get_raw_input() - scene.position = node.position - scene.resource = node - parent.add_child(scene) + var children: Array[BlockAST.ASTNode] = [] - var scene_block: Block = scene as Block - reconnect_block.emit(scene_block) + if block.child_snap: + var child: Block = block.child_snap.get_snapped_block() - for c in node.path_child_pairs: - load_tree(scene.get_node(c[0]), c[1]) + while child != null: + var child_ast_node := build_ast(child) + child_ast_node.data = child.definition + children.append(child_ast_node) + if child.bottom_snap == null: + child = null + else: + child = child.bottom_snap.get_snapped_block() -func rebuild_block_trees(undo_redo): - var block_trees: Array[BlockSerialization] - for c in _window.get_children(): - block_trees.append(build_tree(c, undo_redo)) - undo_redo.add_undo_property(_current_block_script, "block_trees", _current_block_script.block_trees) - undo_redo.add_do_property(_current_block_script, "block_trees", block_trees) + ast_node.children = children + return ast_node -func build_tree(block: Block, undo_redo: EditorUndoRedoManager) -> BlockSerialization: - var path_child_pairs = [] - block.update_resources(undo_redo) - for snap in find_snaps(block): - var snapped_block = snap.get_snapped_block() - if snapped_block == null: - continue - path_child_pairs.append([block.get_path_to(snap), build_tree(snapped_block, undo_redo)]) +func build_value_ast(block: ParameterBlock) -> BlockAST.ASTValueNode: + var ast_node := BlockAST.ASTValueNode.new() + ast_node.data = block.definition + + for arg_name in block.arg_name_to_param_input_dict: + var param_input = block.arg_name_to_param_input_dict[arg_name] + var snap_point = param_input.snap_point + var snapped_block = snap_point.get_snapped_block() + if snapped_block: + ast_node.arguments[arg_name] = build_value_ast(snapped_block) + else: + ast_node.arguments[arg_name] = param_input.get_raw_input() + + return ast_node - if block.resource.path_child_pairs != path_child_pairs: - undo_redo.add_undo_property(block.resource, "path_child_pairs", block.resource.path_child_pairs) - undo_redo.add_do_property(block.resource, "path_child_pairs", path_child_pairs) - return block.resource +func rebuild_block_serialization_trees(): + _current_block_script.update_from_ast_list(_current_ast_list) func find_snaps(node: Node) -> Array[SnapPoint]: @@ -217,7 +279,7 @@ func set_scope(scope: String): var valid := false if block is EntryBlock: - if scope == block.get_entry_statement(): + if scope == block.definition.code_template: valid = true else: var tree_scope := BlockTreeUtil.get_tree_scope(block) @@ -320,9 +382,8 @@ func set_mouse_override(override: bool): _mouse_override.mouse_default_cursor_shape = Control.CURSOR_ARROW -func generate_script_from_current_window(block_script: BlockScriptSerialization) -> String: - # TODO: implement multiple windows - return BlockTreeUtil.generate_script_from_nodes(_window.get_children(), block_script) +func generate_script_from_current_window() -> String: + return ScriptGenerator.generate_script(_current_ast_list, _current_block_script) func _on_zoom_button_pressed(): diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index 96a100aa..64ea1f90 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -62,8 +62,7 @@ func _on_undo_redo_version_changed(): func _on_show_script_button_pressed(): - var block_script: BlockScriptSerialization = _current_block_code_node.block_script - var script: String = _block_canvas.generate_script_from_current_window(block_script) + var script: String = _block_canvas.generate_script_from_current_window() script_window_requested.emit(script) @@ -149,8 +148,12 @@ func save_script(): block_script = block_script.duplicate(true) undo_redo.add_do_property(_current_block_code_node, "block_script", block_script) - _block_canvas.rebuild_block_trees(undo_redo) - var generated_script = _block_canvas.generate_script_from_current_window(block_script) + undo_redo.add_undo_property(block_script, "block_serialization_trees", block_script.block_serialization_trees) + _block_canvas.rebuild_ast_list() + _block_canvas.rebuild_block_serialization_trees() + undo_redo.add_do_property(block_script, "block_serialization_trees", block_script.block_serialization_trees) + + var generated_script = _block_canvas.generate_script_from_current_window() if generated_script != block_script.generated_script: undo_redo.add_undo_property(block_script, "generated_script", block_script.generated_script) undo_redo.add_do_property(block_script, "generated_script", generated_script) @@ -179,10 +182,8 @@ func _input(event): func _print_generated_script(): - if _current_block_code_node == null: - return - var block_script: BlockScriptSerialization = _current_block_code_node.block_script - var script: String = _block_canvas.generate_script_from_current_window(block_script) + var script: String = _block_canvas.generate_script_from_current_window() + print(script) print("Debug script! (not saved)") From 08b8dd468e8b2f11664a52e202c9eda8f5607754 Mon Sep 17 00:00:00 2001 From: Will Baumgartner Date: Wed, 7 Aug 2024 16:47:58 -0400 Subject: [PATCH 203/423] Fix tests Move the instruction tree tests to code generation tests. --- tests/test_category_factory.gd | 22 +-- tests/test_code_generation.gd | 240 +++++++++++++++++++++++++++++++++ tests/test_instruction_tree.gd | 223 ------------------------------ 3 files changed, 247 insertions(+), 238 deletions(-) create mode 100644 tests/test_code_generation.gd delete mode 100644 tests/test_instruction_tree.gd diff --git a/tests/test_category_factory.gd b/tests/test_category_factory.gd index 186d97b4..99dbfd11 100644 --- a/tests/test_category_factory.gd +++ b/tests/test_category_factory.gd @@ -1,14 +1,9 @@ extends GutTest ## Tests for CategoryFactory +const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") - - -func free_block_list(blocks: Array[Block]): - var block: Block = blocks.pop_back() - while block != null: - block.free() - block = blocks.pop_back() +const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") func get_category_names(categories: Array[BlockCategory]) -> Array[String]: @@ -19,16 +14,14 @@ func get_category_names(categories: Array[BlockCategory]) -> Array[String]: func get_class_category_names(_class_name: String) -> Array[String]: - var blocks: Array[Block] = CategoryFactory.get_inherited_blocks(_class_name) + var blocks: Array[BlockDefinition] = BlocksCatalog.get_inherited_blocks(_class_name) var names: Array[String] = get_category_names(CategoryFactory.get_categories(blocks)) - free_block_list(blocks) return names func test_general_category_names(): - var blocks: Array[Block] = CategoryFactory.get_general_blocks() + var blocks: Array[BlockDefinition] = CategoryFactory.get_general_blocks() var names: Array[String] = get_category_names(CategoryFactory.get_categories(blocks)) - free_block_list(blocks) assert_eq( names, [ @@ -62,9 +55,8 @@ func test_inherited_category_names(params = use_parameters(class_category_names) func test_unique_block_names(): - var blocks: Array[Block] = CategoryFactory.get_general_blocks() + var blocks: Array[BlockDefinition] = CategoryFactory.get_general_blocks() var block_names: Dictionary for block in blocks: - assert_does_not_have(block_names, block.block_name, "Block name %s is duplicated" % block.block_name) - block_names[block.block_name] = block - free_block_list(blocks) + assert_does_not_have(block_names, block.name, "Block name %s is duplicated" % block.name) + block_names[block.name] = block diff --git a/tests/test_code_generation.gd b/tests/test_code_generation.gd new file mode 100644 index 00000000..7e61602e --- /dev/null +++ b/tests/test_code_generation.gd @@ -0,0 +1,240 @@ +extends GutTest +## Tests for Script Generation + +const Types = preload("res://addons/block_code/types/types.gd") +const ScriptGenerator = preload("res://addons/block_code/code_generation/script_generator.gd") +const ASTList = preload("res://addons/block_code/code_generation/ast_list.gd") +const BlockAST = preload("res://addons/block_code/code_generation/block_ast.gd") +const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") +const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") + +var general_blocks: Dictionary + + +func build_block_map(block_map: Dictionary, blocks: Array[BlockDefinition]): + assert_eq(block_map, {}) + for block in blocks: + assert_does_not_have(block_map, block.name, "Block name %s is duplicated" % block.name) + block_map[block.name] = block + + +func free_block_map(block_map: Dictionary): + block_map.clear() + assert_eq(block_map, {}) + + +func before_each(): + build_block_map(general_blocks, CategoryFactory.get_general_blocks()) + + +func after_each(): + free_block_map(general_blocks) + + +func block_resource_from_code_template(code_template: String) -> BlockDefinition: + var block_resource = BlockDefinition.new() + block_resource.code_template = code_template + return block_resource + + +func ast_node_from_code_template(code_template: String) -> BlockAST.ASTNode: + var node = BlockAST.ASTNode.new() + node.data = block_resource_from_code_template(code_template) + return node + + +func test_single_node_text(): + var node = ast_node_from_code_template("blah") + var text: String = node.get_code(0) + assert_eq(text, "blah\n") + + +func test_root_depth_text(): + var node = ast_node_from_code_template("blah") + var text: String + for depth in range(5): + text = node.get_code(depth) + assert_eq(text, "\t".repeat(depth) + "blah\n") + + +func test_child_node_text(): + var parent = ast_node_from_code_template("parent") + var child = ast_node_from_code_template("child") + var grandchild = ast_node_from_code_template("grandchild") + parent.children.append(child) + child.children.append(grandchild) + var text: String = parent.get_code(0) + assert_eq(text, "parent\n\tchild\n\t\tgrandchild\n") + + +func test_sibling_node_text(): + var parent = ast_node_from_code_template("parent") + var brother = ast_node_from_code_template("brother") + var sister = ast_node_from_code_template("sister") + parent.children.append(brother) + parent.children.append(sister) + var text: String = parent.get_code(0) + assert_eq(text, "parent\n\tbrother\n\tsister\n") + + +## Test recursive node first, depth first text generation. +func test_tree_node_text(): + var root = ast_node_from_code_template("root") + var parent = ast_node_from_code_template("parent") + var child1 = ast_node_from_code_template("child1") + var child2 = ast_node_from_code_template("child2") + var grandchild = ast_node_from_code_template("grandchild") + var sibling = ast_node_from_code_template("sibling") + var nephew = ast_node_from_code_template("nephew") + + root.children.append(parent) + parent.children.append(child1) + parent.children.append(child2) + child1.children.append(grandchild) + root.children.append(sibling) + sibling.children.append(nephew) + + var text: String = root.get_code(0) + assert_eq(text, "root\n\tparent\n\t\tchild1\n\t\t\tgrandchild\n\t\tchild2\n\tsibling\n\t\tnephew\n") + + +func test_script_no_nodes(): + var bsd := BlockScriptSerialization.new("Foo") + var script := ScriptGenerator.generate_script(ASTList.new(), bsd) + assert_eq( + script, + ( + """\ + extends Foo + + + """ + . dedent() + ) + ) + + +func test_script_no_entry_blocks(): + var bsd := BlockScriptSerialization.new("Foo") + var ast := BlockAST.new() + ast.root = BlockAST.ASTNode.new() + ast.root.data = BlockDefinition.new() + ast.root.data.type = Types.BlockType.STATEMENT + var ast_list = ASTList.new() + ast_list.append(ast, Vector2(0, 0)) + var script := ScriptGenerator.generate_script(ast_list, bsd) + assert_eq( + script, + ( + """\ + extends Foo + + + """ + . dedent() + ) + ) + + +func test_basic_script(): + var ready_block: BlockDefinition = general_blocks[&"ready"] + var print_block: BlockDefinition = general_blocks[&"print"] + + var ast := BlockAST.new() + ast.root = BlockAST.ASTNode.new() + ast.root.data = ready_block + ast.root.children.append(BlockAST.ASTNode.new()) + ast.root.children[0].data = print_block + ast.root.children[0].arguments["text"] = "Hello world!" + var ast_list = ASTList.new() + ast_list.append(ast, Vector2(0, 0)) + + var bsd := BlockScriptSerialization.new("Node2D") + var script := ScriptGenerator.generate_script(ast_list, bsd) + assert_eq( + script, + ( + """\ + extends Node2D + + + func _ready(): + print('Hello world!') + + """ + . dedent() + ) + ) + + +func test_multiple_entry_script(): + var ready_block: BlockDefinition = general_blocks[&"ready"] + var print_block: BlockDefinition = general_blocks[&"print"] + + var ast := BlockAST.new() + ast.root = BlockAST.ASTNode.new() + ast.root.data = ready_block + ast.root.children.append(BlockAST.ASTNode.new()) + ast.root.children[0].data = print_block + ast.root.children[0].arguments["text"] = "Hello world!" + var ast_list = ASTList.new() + ast_list.append(ast, Vector2(0, 0)) + ast_list.append(ast, Vector2(0, 0)) + + var bsd := BlockScriptSerialization.new("Node2D") + var script := ScriptGenerator.generate_script(ast_list, bsd) + assert_eq( + script, + ( + """\ + extends Node2D + + + func _ready(): + print('Hello world!') + print('Hello world!') + + """ + . dedent() + ) + ) + + +func test_signal_script(): + var area2d_blocks: Dictionary + build_block_map(area2d_blocks, BlocksCatalog.get_inherited_blocks("Area2D")) + + var entered_block: BlockDefinition = area2d_blocks[&"area2d_on_entered"] + var print_block: BlockDefinition = general_blocks[&"print"] + + var ast := BlockAST.new() + ast.root = BlockAST.ASTNode.new() + ast.root.data = entered_block + ast.root.children.append(BlockAST.ASTNode.new()) + ast.root.children[0].data = print_block + ast.root.children[0].arguments["text"] = "Body entered!" + var ast_list = ASTList.new() + ast_list.append(ast, Vector2(0, 0)) + + var bsd := BlockScriptSerialization.new("Area2D") + var script := ScriptGenerator.generate_script(ast_list, bsd) + assert_eq( + script, + ( + """\ + extends Area2D + + + func _init(): + body_entered.connect(_on_body_entered) + + func _on_body_entered(body: Node2D): + + print('Body entered!') + + """ + . dedent() + ) + ) + + free_block_map(area2d_blocks) diff --git a/tests/test_instruction_tree.gd b/tests/test_instruction_tree.gd deleted file mode 100644 index 81e17fab..00000000 --- a/tests/test_instruction_tree.gd +++ /dev/null @@ -1,223 +0,0 @@ -extends GutTest -## Tests for InstructionTree - -const BlockTreeUtil = preload("res://addons/block_code/ui/block_tree_util.gd") -const CategoryFactory = preload("res://addons/block_code/ui/picker/categories/category_factory.gd") -const InstructionTree = preload("res://addons/block_code/instruction_tree/instruction_tree.gd") - -var general_blocks: Dictionary - - -func build_block_map(block_map: Dictionary, blocks: Array[Block]): - assert_eq(block_map, {}) - for block in blocks: - assert_does_not_have(block_map, block.block_name, "Block name %s is duplicated" % block.block_name) - block_map[block.block_name] = block - - -func free_block_map(block_map: Dictionary): - for block in block_map.values(): - block.free() - block_map.clear() - assert_eq(block_map, {}) - - -func dup_node(node: Node) -> Node: - return node.duplicate(DUPLICATE_USE_INSTANTIATION) - - -func before_each(): - build_block_map(general_blocks, CategoryFactory.get_general_blocks()) - - -func after_each(): - free_block_map(general_blocks) - - -func test_single_node_text(): - var node = InstructionTree.TreeNode.new("blah") - var text: String = InstructionTree.generate_text(node, 0) - assert_eq(text, "blah\n") - - -func test_root_depth_text(): - var node = InstructionTree.TreeNode.new("blah") - var text: String - for depth in range(5): - text = InstructionTree.generate_text(node, depth) - assert_eq(text, "\t".repeat(depth) + "blah\n") - - -func test_child_node_text(): - var parent = InstructionTree.TreeNode.new("parent") - var child = InstructionTree.TreeNode.new("child") - var grandchild = InstructionTree.TreeNode.new("grandchild") - parent.add_child(child) - child.add_child(grandchild) - var text: String = InstructionTree.generate_text(parent, 0) - assert_eq(text, "parent\n\tchild\n\t\tgrandchild\n") - - -func test_sibling_node_text(): - var node = InstructionTree.TreeNode.new("node") - var brother = InstructionTree.TreeNode.new("brother") - var sister = InstructionTree.TreeNode.new("sister") - node.next = brother - brother.next = sister - var text: String = InstructionTree.generate_text(node, 0) - assert_eq(text, "node\nbrother\nsister\n") - - -## Test recursive node first, depth first text generation. -func test_tree_node_text(): - var root = InstructionTree.TreeNode.new("root") - var child1 = InstructionTree.TreeNode.new("child1") - var child2 = InstructionTree.TreeNode.new("child2") - var grandchild = InstructionTree.TreeNode.new("grandchild") - var sibling = InstructionTree.TreeNode.new("sibling") - var nephew = InstructionTree.TreeNode.new("nephew") - - root.add_child(child1) - root.add_child(child2) - child1.add_child(grandchild) - root.next = sibling - sibling.add_child(nephew) - - var text: String = InstructionTree.generate_text(root, 0) - assert_eq(text, "root\n\tchild1\n\t\tgrandchild\n\tchild2\nsibling\n\tnephew\n") - - -func test_script_no_nodes(): - var block_script := BlockScriptSerialization.new("Foo") - var text_script := BlockTreeUtil.generate_script_from_nodes([], block_script) - assert_eq( - text_script, - ( - """\ - extends Foo - - - """ - . dedent() - ) - ) - - -func test_script_no_entry_blocks(): - var block_script := BlockScriptSerialization.new("Foo") - var nodes: Array[Node] = [Node.new(), Node2D.new(), Control.new()] - var text_script := BlockTreeUtil.generate_script_from_nodes(nodes, block_script) - assert_eq( - text_script, - ( - """\ - extends Foo - - - """ - . dedent() - ) - ) - for node in nodes: - node.free() - - -func test_basic_script(): - var ready_block: Block = dup_node(general_blocks[&"ready"]) - - var print_block: Block = dup_node(general_blocks["print"]) - # XXX: It seems like this should substitute {text} in the statement, - # but it doesn't. I can't make sense of StatementBlock. - # print_block.param_input_strings = {"text": "this is a test"} - # print_block._ready() - - # XXX: Why does insert_snapped_block add_child but not set snapped_block? - ready_block.bottom_snap.insert_snapped_block(print_block) - ready_block.bottom_snap.snapped_block = print_block - assert_true(ready_block.bottom_snap.has_snapped_block()) - assert_eq(ready_block.bottom_snap.get_snapped_block(), print_block) - - var block_script := BlockScriptSerialization.new("Node2D") - var text_script := BlockTreeUtil.generate_script_from_nodes([ready_block], block_script) - assert_eq( - text_script, - ( - """\ - extends Node2D - - - func _ready(): - print({text}) - - """ - . dedent() - ) - ) - - ready_block.free() - - -func test_multiple_entry_script(): - var ready_block: Block = dup_node(general_blocks[&"ready"]) - var print_block: Block = dup_node(general_blocks[&"print"]) - ready_block.bottom_snap.insert_snapped_block(print_block) - ready_block.bottom_snap.snapped_block = print_block - - var ready_block_2: Block = dup_node(general_blocks[&"ready"]) - var print_block_2: Block = dup_node(general_blocks[&"print"]) - ready_block_2.bottom_snap.insert_snapped_block(print_block_2) - ready_block_2.bottom_snap.snapped_block = print_block_2 - - var block_script := BlockScriptSerialization.new("Node2D") - var text_script := BlockTreeUtil.generate_script_from_nodes([ready_block, ready_block_2], block_script) - assert_eq( - text_script, - ( - """\ - extends Node2D - - - func _ready(): - print({text}) - - print({text}) - - """ - . dedent() - ) - ) - - ready_block.free() - ready_block_2.free() - - -func test_signal_script(): - var area2d_blocks: Dictionary - build_block_map(area2d_blocks, CategoryFactory.get_inherited_blocks("Area2D")) - var entered_block: Block = dup_node(area2d_blocks["area2d_on_entered"]) - var print_block: Block = dup_node(general_blocks["print"]) - entered_block.bottom_snap.insert_snapped_block(print_block) - entered_block.bottom_snap.snapped_block = print_block - - var block_script := BlockScriptSerialization.new("Area2D") - var text_script = BlockTreeUtil.generate_script_from_nodes([entered_block], block_script) - assert_eq( - text_script, - ( - """\ - extends Area2D - - - func _on_body_entered(body: Node2D): - - print({text}) - - func _init(): - body_entered.connect(_on_body_entered) - """ - . dedent() - ) - ) - - entered_block.free() - free_block_map(area2d_blocks) From 6bc2e8e008db6d5ad5dce6429704e0636bbf9ee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Fri, 6 Sep 2024 10:44:49 -0300 Subject: [PATCH 204/423] fixup! Refactor serialization classes --- .../examples/pong_game/pong_game.tscn | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/addons/block_code/examples/pong_game/pong_game.tscn b/addons/block_code/examples/pong_game/pong_game.tscn index 57cd062a..ef359575 100644 --- a/addons/block_code/examples/pong_game/pong_game.tscn +++ b/addons/block_code/examples/pong_game/pong_game.tscn @@ -492,7 +492,7 @@ func _on_body_entered(body: Node2D): " version = 0 -[sub_resource type="Resource" id="Resource_hyh0v"] +[sub_resource type="Resource" id="Resource_o7ugj"] script = ExtResource("4_qtggh") name = &"simplescoring_set_score_player_1" children = Array[ExtResource("4_qtggh")]([]) @@ -500,7 +500,7 @@ arguments = { "score": 0 } -[sub_resource type="Resource" id="Resource_nnat8"] +[sub_resource type="Resource" id="Resource_spykn"] script = ExtResource("4_qtggh") name = &"simplescoring_set_score_player_2" children = Array[ExtResource("4_qtggh")]([]) @@ -508,7 +508,7 @@ arguments = { "score": 0 } -[sub_resource type="Resource" id="Resource_qf8bl"] +[sub_resource type="Resource" id="Resource_nucg0"] script = ExtResource("4_qtggh") name = &"add_to_group" children = Array[ExtResource("4_qtggh")]([]) @@ -516,18 +516,18 @@ arguments = { "group": "scoring" } -[sub_resource type="Resource" id="Resource_7dyjv"] +[sub_resource type="Resource" id="Resource_6brri"] script = ExtResource("4_qtggh") name = &"ready" -children = Array[ExtResource("4_qtggh")]([SubResource("Resource_hyh0v"), SubResource("Resource_nnat8"), SubResource("Resource_qf8bl")]) +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_o7ugj"), SubResource("Resource_spykn"), SubResource("Resource_nucg0")]) arguments = {} -[sub_resource type="Resource" id="Resource_g0f0k"] +[sub_resource type="Resource" id="Resource_v71gd"] script = ExtResource("5_omlge") -root = SubResource("Resource_7dyjv") +root = SubResource("Resource_6brri") canvas_position = Vector2(25, 0) -[sub_resource type="Resource" id="Resource_0ak1s"] +[sub_resource type="Resource" id="Resource_4y2px"] script = ExtResource("4_qtggh") name = &"simplescoring_change_score_player_1" children = Array[ExtResource("4_qtggh")]([]) @@ -535,20 +535,20 @@ arguments = { "score": 1 } -[sub_resource type="Resource" id="Resource_7rjjw"] +[sub_resource type="Resource" id="Resource_ilawr"] script = ExtResource("4_qtggh") name = &"define_method" -children = Array[ExtResource("4_qtggh")]([SubResource("Resource_0ak1s")]) +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_4y2px")]) arguments = { -"method_name": "goal_right" +"method_name": &"goal_right" } -[sub_resource type="Resource" id="Resource_hiqld"] +[sub_resource type="Resource" id="Resource_8e220"] script = ExtResource("5_omlge") -root = SubResource("Resource_7rjjw") +root = SubResource("Resource_ilawr") canvas_position = Vector2(25, 250) -[sub_resource type="Resource" id="Resource_e7bsf"] +[sub_resource type="Resource" id="Resource_1fx1n"] script = ExtResource("4_qtggh") name = &"simplescoring_change_score_player_2" children = Array[ExtResource("4_qtggh")]([]) @@ -556,23 +556,23 @@ arguments = { "score": 1 } -[sub_resource type="Resource" id="Resource_8gvgu"] +[sub_resource type="Resource" id="Resource_mef5h"] script = ExtResource("4_qtggh") name = &"define_method" -children = Array[ExtResource("4_qtggh")]([SubResource("Resource_e7bsf")]) +children = Array[ExtResource("4_qtggh")]([SubResource("Resource_1fx1n")]) arguments = { -"method_name": "goal_left" +"method_name": &"goal_left" } -[sub_resource type="Resource" id="Resource_3kxo7"] +[sub_resource type="Resource" id="Resource_uty0f"] script = ExtResource("5_omlge") -root = SubResource("Resource_8gvgu") +root = SubResource("Resource_mef5h") canvas_position = Vector2(25, 400) [sub_resource type="Resource" id="Resource_q418f"] script = ExtResource("7_uuuue") script_inherits = "SimpleScoring" -block_serialization_trees = Array[ExtResource("5_omlge")]([SubResource("Resource_g0f0k"), SubResource("Resource_hiqld"), SubResource("Resource_3kxo7")]) +block_serialization_trees = Array[ExtResource("5_omlge")]([SubResource("Resource_v71gd"), SubResource("Resource_8e220"), SubResource("Resource_uty0f")]) variables = Array[ExtResource("9_lo3p1")]([]) generated_script = "extends SimpleScoring @@ -582,10 +582,10 @@ func _ready(): score_right = 0 add_to_group('scoring') -func 'goal_right'(): +func goal_right(): score_left += 1 -func 'goal_left'(): +func goal_left(): score_right += 1 " From 3b78183394f29ea4b6e9e6879ef7f389a9ad412c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 10 Sep 2024 14:55:16 -0300 Subject: [PATCH 205/423] Blocks catalog: Make property setter optional The properties may be read-only. Also indent properly the changer definition, which was wrong. --- .../code_generation/blocks_catalog.gd | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/addons/block_code/code_generation/blocks_catalog.gd b/addons/block_code/code_generation/blocks_catalog.gd index 8ab6f73a..f1fd8e62 100644 --- a/addons/block_code/code_generation/blocks_catalog.gd +++ b/addons/block_code/code_generation/blocks_catalog.gd @@ -141,22 +141,24 @@ static func _add_property_definitions(_class_name: String, property_list: Array[ _by_class_name[_class_name] = {} # Setter - var block_definition: BlockDefinition = ( - BlockDefinition - . new( - &"%s_set_%s" % [_class_name, property.name], - _class_name, - "Set the %s property" % property.name, - block_settings.category, - Types.BlockType.STATEMENT, - TYPE_NIL, - "Set %s to {value: %s}" % [property.name.capitalize(), type_string], - "%s = {value}" % property.name, - {"value": block_settings.get("default_set", _FALLBACK_SET_FOR_TYPE[property.type])}, + var block_definition: BlockDefinition + if block_settings.get("has_setter", true): + block_definition = ( + BlockDefinition + . new( + &"%s_set_%s" % [_class_name, property.name], + _class_name, + "Set the %s property" % property.name, + block_settings.category, + Types.BlockType.STATEMENT, + TYPE_NIL, + "Set %s to {value: %s}" % [property.name.capitalize(), type_string], + "%s = {value}" % property.name, + {"value": block_settings.get("default_set", _FALLBACK_SET_FOR_TYPE[property.type])}, + ) ) - ) - _catalog[block_definition.name] = block_definition - _by_class_name[_class_name][block_definition.name] = block_definition + _catalog[block_definition.name] = block_definition + _by_class_name[_class_name][block_definition.name] = block_definition # Changer if block_settings.get("has_change", true): @@ -174,8 +176,8 @@ static func _add_property_definitions(_class_name: String, property_list: Array[ {"value": block_settings.get("default_change", _FALLBACK_CHANGE_FOR_TYPE[property.type])}, ) ) - _catalog[block_definition.name] = block_definition - _by_class_name[_class_name][block_definition.name] = block_definition + _catalog[block_definition.name] = block_definition + _by_class_name[_class_name][block_definition.name] = block_definition # Getter block_definition = ( From 2be89f3d4b57339620d43d8ba8808588ad1c71e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 10 Sep 2024 14:57:33 -0300 Subject: [PATCH 206/423] Simple Character: Add value block for Direction X So users can check where the character is heading: * -1: to the left * 1: to the right * 0: not moving --- .../simple_nodes/simple_character/simple_character.gd | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/addons/block_code/simple_nodes/simple_character/simple_character.gd b/addons/block_code/simple_nodes/simple_character/simple_character.gd index e73dd7e3..faadfcbe 100644 --- a/addons/block_code/simple_nodes/simple_character/simple_character.gd +++ b/addons/block_code/simple_nodes/simple_character/simple_character.gd @@ -38,6 +38,7 @@ var collision: CollisionShape2D var gravity = ProjectSettings.get_setting("physics/2d/default_gravity") var _jumping = false +var direction_x: int = 0 func _set_texture(new_texture): @@ -100,6 +101,7 @@ func _player_input_to_direction(player: String): func move_with_player_buttons(player: String, kind: String, delta: float): var direction = _player_input_to_direction(player) + direction_x = direction.x if kind == "top-down": velocity = direction * speed @@ -153,6 +155,10 @@ static func setup_custom_blocks(): "name": "speed", "type": TYPE_VECTOR2, }, + { + "name": "direction_x", + "type": TYPE_INT, + }, ] var property_settings = { @@ -160,6 +166,11 @@ static func setup_custom_blocks(): { "category": "Physics | Velocity", }, + "direction_x": + { + "category": "Physics | Velocity", + "has_setter": false, + }, } BlocksCatalog.add_custom_blocks(_class_name, block_list, property_list, property_settings) From a2cfe776f2fdafd9abc06d1b86c87cf06be7fa04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 10 Sep 2024 14:59:43 -0300 Subject: [PATCH 207/423] CharacterBody2D: Add "Is on floor" value block So users can check if the character is on the floor or not. --- .../input/characterbody2d_is_on_floor.tres | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 addons/block_code/blocks/input/characterbody2d_is_on_floor.tres diff --git a/addons/block_code/blocks/input/characterbody2d_is_on_floor.tres b/addons/block_code/blocks/input/characterbody2d_is_on_floor.tres new file mode 100644 index 00000000..f6f3b807 --- /dev/null +++ b/addons/block_code/blocks/input/characterbody2d_is_on_floor.tres @@ -0,0 +1,17 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://cbpicqif1ddro"] + +[ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_btxic"] + +[resource] +script = ExtResource("1_btxic") +name = &"characterbody2d_is_on_floor" +target_node_class = "CharacterBody2D" +description = "True if the character is on the floor." +category = "Physics | Velocity" +type = 3 +variant_type = 1 +display_template = "Is on floor" +code_template = "is_on_floor()" +defaults = {} +signal_name = "" +scope = "" From 9209a40fed6017ee00c8292617c1a9322a0c86a5 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Wed, 11 Sep 2024 16:20:00 -0600 Subject: [PATCH 208/423] ParameterInput: Don't snap blocks for option inputs Option inputs only allow selecting from a set of predefined OptionData values. Prevent trying to snap a block to an option input by making the snap point invisible. Fixes: #167 --- .../utilities/parameter_input/parameter_input.gd | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd index fdf2cd66..7dc719d5 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd +++ b/addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd @@ -11,7 +11,8 @@ signal modified @export var variant_type: Variant.Type = TYPE_STRING @export var block_type: Types.BlockType = Types.BlockType.VALUE -var option: bool = false +var option: bool = false: + set = _set_option @onready var _panel := %Panel @onready var snap_point := %SnapPoint @@ -103,11 +104,22 @@ func _set_placeholder(new_placeholder: String) -> void: _line_edit.placeholder_text = placeholder +func _set_option(value: bool) -> void: + option = value + + if not is_node_ready(): + return + + # If options are being provided, you can't snap blocks. + snap_point.visible = not option + + func _ready(): var stylebox = _panel.get_theme_stylebox("panel") stylebox.bg_color = Color.WHITE _set_placeholder(placeholder) + _set_option(option) snap_point.block_type = block_type snap_point.variant_type = variant_type From a413faf2b98d574a8cd21115226d7291f8b27606 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Thu, 12 Sep 2024 11:12:58 +0100 Subject: [PATCH 209/423] README: Document installing a development snapshot --- addons/block_code/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/addons/block_code/README.md b/addons/block_code/README.md index 9fdf4771..ab20c9a6 100644 --- a/addons/block_code/README.md +++ b/addons/block_code/README.md @@ -90,3 +90,18 @@ There are several other GUT command line options for running specific tests. For example, `-gtest=path/to/test_script_1.gd,path/to/test_script_2.gd` can be used to run specific test scripts. A specific test function can be specified with `-gunit_test_name=test_to_run`. + +### Using the Development Version of the Plugin + +1. If your project already has the BlockCode plugin installed: + 1. Ensure you have committed your project to Git, including the `addons/block_code` directory. + At this stage of development, **block code programs written for an older plugin version will + likely not work with a newer version of the plugin**, so it is essential that you take a + snapshot of your project before changing the plugin version. + 2. Under *Project* → *Project Settings…* → *Plugins*, disable the BlockCode plugin + 3. In the *FileSystem* sidebar, delete the `res://addons/block_code` directory +2. Download + [a development snapshot](https://github.com/endlessm/godot-block-coding/archive/main.zip) +3. Under *AssetLib*, click *Import…*, and browse to the `main.zip` file you just downloaded +4. Check the *☑ Ignore assert root* option, and click *Install* +5. Under *Project* → *Project Settings…* → *Plugins*, enable the BlockCode plugin From 703c66df517c8b145984c953acc4d76bf7b9322a Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Thu, 12 Sep 2024 14:37:12 -0700 Subject: [PATCH 210/423] Improve keyboard accessibility in create_variable_dialog When the dialog is focused, we need to focus the custom dialog's own controls instead of the dialog's buttons. In addition, set focus_next and focus_previous properties so focus flows between child widgets and the dialog's ok / cancel buttons. The focus loops around within the dialog, as is conventional with other dialogs in the Godot editor. --- .../create_variable_button.gd | 2 +- .../create_variable_dialog.gd | 27 ++++++++++++++++--- .../create_variable_dialog.tscn | 11 ++++++-- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd b/addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd index 3f69b2e2..80f507ec 100644 --- a/addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd +++ b/addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd @@ -7,7 +7,7 @@ signal create_variable(var_name: String, var_type: String) func _on_create_button_pressed(): - _create_variable_dialog.visible = true + _create_variable_dialog.popup() func _on_create_variable_dialog_create_variable(var_name, var_type): diff --git a/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd index cc3957a2..cc818d43 100644 --- a/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd +++ b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd @@ -14,16 +14,20 @@ const available_types = ["STRING", "BOOL", "INT", "FLOAT", "VECTOR2", "COLOR"] func _ready(): _type_option.clear() + _type_option.focus_next = get_cancel_button().get_path() + get_cancel_button().focus_previous = _type_option.get_path() + get_ok_button().focus_next = _variable_input.get_path() + _variable_input.focus_previous = get_ok_button().get_path() for type in available_types: _type_option.add_item(type) - check_errors(_variable_input.text) + _clear() func _clear(): _variable_input.text = "" - check_errors(_variable_input.text) + get_ok_button().disabled = check_errors(_variable_input.text) _type_option.select(0) @@ -93,10 +97,25 @@ func check_errors(new_var_name: String) -> bool: func _on_confirmed(): - if not check_errors(_variable_input.text): - create_variable.emit(_variable_input.text, _type_option.get_item_text(_type_option.selected)) + if check_errors(_variable_input.text): + return + + create_variable.emit(_variable_input.text, _type_option.get_item_text(_type_option.selected)) + hide() _clear() func _on_canceled(): _clear() + + +func _on_about_to_popup() -> void: + _variable_input.grab_focus() + + +func _on_focus_entered() -> void: + _variable_input.grab_focus() + + +func _on_variable_input_text_submitted(new_text: String) -> void: + _on_confirmed() diff --git a/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.tscn b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.tscn index f8678a2f..0ccb15ab 100644 --- a/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.tscn +++ b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.tscn @@ -8,6 +8,7 @@ initial_position = 1 size = Vector2i(300, 183) visible = true ok_button_text = "Create" +dialog_hide_on_ok = false script = ExtResource("1_b52me") [node name="VBoxContainer" type="VBoxContainer" parent="."] @@ -27,6 +28,8 @@ text = "Name " [node name="VariableInput" type="LineEdit" parent="VBoxContainer/GridContainer"] unique_name_in_owner = true layout_mode = 2 +focus_neighbor_bottom = NodePath("../TypeOption") +focus_next = NodePath("../TypeOption") [node name="Label2" type="Label" parent="VBoxContainer/GridContainer"] layout_mode = 2 @@ -36,10 +39,11 @@ text = "Type " unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 -item_count = 6 +focus_neighbor_top = NodePath("../VariableInput") +focus_previous = NodePath("../VariableInput") selected = 0 +item_count = 6 popup/item_0/text = "STRING" -popup/item_0/id = 0 popup/item_1/text = "BOOL" popup/item_1/id = 1 popup/item_2/text = "INT" @@ -63,6 +67,9 @@ layout_mode = 2 theme_override_constants/line_separation = 4 fit_content = true +[connection signal="about_to_popup" from="." to="." method="_on_about_to_popup"] [connection signal="canceled" from="." to="." method="_on_canceled"] [connection signal="confirmed" from="." to="." method="_on_confirmed"] +[connection signal="focus_entered" from="." to="." method="_on_focus_entered"] [connection signal="text_changed" from="VBoxContainer/GridContainer/VariableInput" to="." method="_on_variable_input_text_changed"] +[connection signal="text_submitted" from="VBoxContainer/GridContainer/VariableInput" to="." method="_on_variable_input_text_submitted"] From e5161f397e2d5cbe9c6967b9d466dade2f42d2a8 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 28 Aug 2024 17:43:12 -0700 Subject: [PATCH 211/423] BlockScriptSerialization: Add block library and instantiation This changes BlockScriptSerialization to manage its own list of available block definitions and instantiate them, replacing the existing functionality that was in CategoryFactory and ui/util.gd. The change makes it easier to understand the state of the block catalog, because it is a component of the block script itself instead of spread across different static variables. In addition, this adds a singleton block editor context, which keeps track of the current block code node and its associated block script. The context object provides enough information for different UI components to update automatically when the block script changes. https://phabricator.endlessm.com/T35564 --- addons/block_code/block_code_plugin.gd | 7 +- .../code_generation/blocks_catalog.gd | 36 --- .../block_code/drag_manager/drag_manager.gd | 8 +- .../block_script_serialization.gd | 217 ++++++++++++++++-- .../ui/block_canvas/block_canvas.gd | 28 ++- addons/block_code/ui/block_editor_context.gd | 33 +++ addons/block_code/ui/blocks/block/block.gd | 3 - .../parameter_output/parameter_output.gd | 22 +- addons/block_code/ui/main_panel.gd | 77 ++++--- .../ui/picker/categories/block_category.gd | 13 +- .../categories/block_category_display.gd | 11 +- .../ui/picker/categories/category_factory.gd | 107 +-------- .../create_variable_dialog.gd | 15 +- addons/block_code/ui/picker/picker.gd | 63 +++-- addons/block_code/ui/title_bar/title_bar.gd | 16 +- addons/block_code/ui/util.gd | 43 ---- tests/test_category_factory.gd | 29 ++- tests/test_code_generation.gd | 5 +- 18 files changed, 396 insertions(+), 337 deletions(-) create mode 100644 addons/block_code/ui/block_editor_context.gd diff --git a/addons/block_code/block_code_plugin.gd b/addons/block_code/block_code_plugin.gd index c4370d6b..96b9b7ab 100644 --- a/addons/block_code/block_code_plugin.gd +++ b/addons/block_code/block_code_plugin.gd @@ -1,5 +1,6 @@ @tool extends EditorPlugin + const MainPanelScene := preload("res://addons/block_code/ui/main_panel.tscn") const MainPanel = preload("res://addons/block_code/ui/main_panel.gd") const Types = preload("res://addons/block_code/types/types.gd") @@ -93,16 +94,10 @@ func _exit_tree(): func _ready(): - connect("scene_changed", _on_scene_changed) editor_inspector.connect("edited_object_changed", _on_editor_inspector_edited_object_changed) - _on_scene_changed(EditorInterface.get_edited_scene_root()) _on_editor_inspector_edited_object_changed() -func _on_scene_changed(scene_root: Node): - main_panel.switch_scene(scene_root) - - func _on_editor_inspector_edited_object_changed(): var edited_object = editor_inspector.get_edited_object() #var edited_node = edited_object as Node diff --git a/addons/block_code/code_generation/blocks_catalog.gd b/addons/block_code/code_generation/blocks_catalog.gd index f1fd8e62..6fd38e84 100644 --- a/addons/block_code/code_generation/blocks_catalog.gd +++ b/addons/block_code/code_generation/blocks_catalog.gd @@ -96,40 +96,6 @@ static func _setup_definitions_from_files(): _by_class_name[target][block_definition.name] = block_definition -static func _add_output_definitions(definitions: Array[BlockDefinition]): - # Capture things of format [test] - var _output_regex := RegEx.create_from_string("\\[([^\\]]+)\\]") - - for definition in definitions: - if definition.type != Types.BlockType.ENTRY: - continue - - for reg_match in _output_regex.search_all(definition.display_template): - var parts := reg_match.get_string(1).split(": ") - var param_name := parts[0] - var param_type: Variant.Type = Types.STRING_TO_VARIANT_TYPE[parts[1]] - - var output_def := BlockDefinition.new() - output_def.name = &"%s_%s" % [definition.name, param_name] - output_def.target_node_class = definition.target_node_class - output_def.category = definition.category - output_def.type = Types.BlockType.VALUE - output_def.variant_type = param_type - output_def.display_template = param_name - output_def.code_template = param_name - output_def.scope = definition.code_template - - # Note that these are not added to the _by_class_name dict - # because they only make sense within the entry block scope. - _catalog[output_def.name] = output_def - - -static func _setup_output_definitions(): - var definitions: Array[BlockDefinition] - definitions.assign(_catalog.values()) - _add_output_definitions(definitions) - - static func _add_property_definitions(_class_name: String, property_list: Array[Dictionary], property_settings: Dictionary): for property in property_list: if not property.name in property_settings: @@ -256,7 +222,6 @@ static func setup(): _catalog = {} _setup_definitions_from_files() - _setup_output_definitions() _setup_properties_for_class() _setup_input_block() @@ -330,7 +295,6 @@ static func add_custom_blocks( _catalog[block_definition.name] = block_definition _by_class_name[_class_name][block_definition.name] = block_definition - _add_output_definitions(block_definitions) _add_property_definitions(_class_name, property_list, property_settings) diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index 033f1e8d..74a3fa85 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -15,6 +15,8 @@ const Util = preload("res://addons/block_code/ui/util.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") +@onready var _context := BlockEditorContext.get_default() + var _picker: Picker var _block_canvas: BlockCanvas @@ -64,9 +66,9 @@ func drag_block(block: Block, copied_from: Block = null): func copy_block(block: Block) -> Block: - var new_block = Util.instantiate_block(block.definition) - new_block.color = block.color - return new_block + if _context.block_script == null: + return null + return _context.block_script.instantiate_block(block.definition) func copy_picked_block_and_drag(block: Block): diff --git a/addons/block_code/serialization/block_script_serialization.gd b/addons/block_code/serialization/block_script_serialization.gd index 02d61d22..f45844b1 100644 --- a/addons/block_code/serialization/block_script_serialization.gd +++ b/addons/block_code/serialization/block_script_serialization.gd @@ -4,14 +4,23 @@ extends Resource const ASTList = preload("res://addons/block_code/code_generation/ast_list.gd") const BlockAST = preload("res://addons/block_code/code_generation/block_ast.gd") -const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") const BlockSerialization = preload("res://addons/block_code/serialization/block_serialization.gd") const BlockSerializationTree = preload("res://addons/block_code/serialization/block_serialization_tree.gd") +const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") +const CategoryFactory = preload("res://addons/block_code/ui/picker/categories/category_factory.gd") +const Types = preload("res://addons/block_code/types/types.gd") const ValueBlockSerialization = preload("res://addons/block_code/serialization/value_block_serialization.gd") const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") +const SCENE_PER_TYPE = { + Types.BlockType.ENTRY: preload("res://addons/block_code/ui/blocks/entry_block/entry_block.tscn"), + Types.BlockType.STATEMENT: preload("res://addons/block_code/ui/blocks/statement_block/statement_block.tscn"), + Types.BlockType.VALUE: preload("res://addons/block_code/ui/blocks/parameter_block/parameter_block.tscn"), + Types.BlockType.CONTROL: preload("res://addons/block_code/ui/blocks/control_block/control_block.tscn"), +} + @export var script_inherits: String @export var block_serialization_trees: Array[BlockSerializationTree] @export var variables: Array[VariableDefinition]: @@ -19,7 +28,8 @@ const VariableDefinition = preload("res://addons/block_code/code_generation/vari @export var generated_script: String @export var version: int -var _var_block_definitions: Dictionary # String, BlockDefinition +var _available_blocks: Array[BlockDefinition] +var _categories: Array[BlockCategory] func _init( @@ -32,36 +42,108 @@ func _init( version = p_version +func initialize(): + _update_block_definitions() + + func _set_variables(value): variables = value - _refresh_var_block_definitions() + _update_block_definitions() -func _refresh_var_block_definitions(): - _var_block_definitions.clear() - for block_def in BlocksCatalog.get_variable_block_definitions(variables): - _var_block_definitions[block_def.name] = block_def +func instantiate_block(block_definition: BlockDefinition) -> Block: + if block_definition == null: + push_error("Cannot construct block from null block definition.") + return null + var scene := SCENE_PER_TYPE.get(block_definition.type) + if scene == null: + push_error("Cannot instantiate Block from type %s" % block_definition.type) + return null -func _get_block(block_name: StringName) -> BlockDefinition: - var block_def: BlockDefinition = _var_block_definitions.get(block_name) - if block_def == null: - block_def = BlocksCatalog.get_block(block_name) - return block_def + var block_category := _get_category_by_name(block_definition.category) + var block: Block = scene.instantiate() + block.definition = block_definition + block.color = block_category.color if block_category else Color.WHITE + return block -func get_definitions() -> Array[BlockDefinition]: - for class_dict in ProjectSettings.get_global_class_list(): - if class_dict.class == script_inherits: - var script = load(class_dict.path) - if script.has_method("setup_custom_blocks"): - script.setup_custom_blocks() - break - return BlocksCatalog.get_inherited_blocks(script_inherits) +func instantiate_block_by_name(block_name: String) -> Block: + var block_definition := get_block_definition(block_name) + + if block_definition == null: + push_warning("Cannot find a block definition for %s" % block_name) + return null + + return instantiate_block(block_definition) + + +func get_block_definition(block_name: String) -> BlockDefinition: + var split := block_name.split(":", true, 1) + + if len(split) > 1: + return _get_parameter_block_definition(split[0], split[1]) + + var block_definition = _get_base_block_definition(block_name) + + if block_definition == null: + # FIXME: This is a workaround for old-style output block references. + # These were generated ahead of time using a block name that has + # a "_" before the parameter name. Now, these parameter blocks + # are generated on demand for any block name containing a ":". + # Please remove this fallback when it is no longer necessary. + split = block_name.rsplit("_", true, 1) + return _get_parameter_block_definition(split[0], split[1]) + + return block_definition + + +func _get_base_block_definition(block_name: String) -> BlockDefinition: + for block_definition in _available_blocks: + if block_definition.name == block_name: + return block_definition + return null + + +func _get_parameter_block_definition(block_name: String, parameter_name: String) -> BlockDefinition: + var base_block_definition := _get_base_block_definition(block_name) + + if base_block_definition == null: + return null + + var parent_out_parameters = base_block_definition.get_output_parameters() + + if not parent_out_parameters.has(parameter_name): + push_error("The parameter name %s is not an output parameter in %s." % [parameter_name, block_name]) + return null + + var parameter_type: Variant.Type = parent_out_parameters[parameter_name] + + var block_definition := BlockDefinition.new() + block_definition.name = &"%s:%s" % [block_name, parameter_name] + block_definition.target_node_class = base_block_definition.target_node_class + block_definition.category = base_block_definition.category + block_definition.type = Types.BlockType.VALUE + block_definition.variant_type = parameter_type + block_definition.display_template = parameter_name + block_definition.code_template = parameter_name + block_definition.scope = base_block_definition.code_template + + return block_definition + + +func _update_block_definitions(): + _available_blocks.clear() + _available_blocks.append_array(_get_default_block_definitions()) + _available_blocks.append_array(_get_inherited_block_definitions()) + _available_blocks.append_array(_get_variable_block_definitions()) + + var custom_categories: Array[BlockCategory] = _get_custom_categories() + _categories = CategoryFactory.get_all_categories(custom_categories) -func get_categories() -> Array[BlockCategory]: +func _get_custom_categories() -> Array[BlockCategory]: for class_dict in ProjectSettings.get_global_class_list(): if class_dict.class == script_inherits: var script = load(class_dict.path) @@ -71,6 +153,95 @@ func get_categories() -> Array[BlockCategory]: return [] +func get_available_blocks() -> Array[BlockDefinition]: + return _available_blocks + + +func get_available_categories() -> Array[BlockCategory]: + return _categories.filter(func(category): return _available_blocks.any(BlockDefinition.has_category.bind(category.name))) + + +func get_blocks_in_category(category: BlockCategory) -> Array[BlockDefinition]: + return _available_blocks.filter(BlockDefinition.has_category.bind(category.name)) + + +func _get_category_by_name(category_name: String) -> BlockCategory: + return _categories.filter(func(category): return category.name == category_name).front() + + +func load_object_script() -> Object: + for class_dict in ProjectSettings.get_global_class_list(): + if class_dict.class == script_inherits: + return load(class_dict.path) as Object + return null + + +func _get_default_block_definitions() -> Array[BlockDefinition]: + var block: BlockDefinition + var block_list: Array[BlockDefinition] = [] + + # Lifecycle + for block_name in [&"ready", &"process", &"physics_process", &"queue_free"]: + block = BlocksCatalog.get_block(block_name) + block_list.append(block) + + # Loops + for block_name in [&"for", &"while", &"break", &"continue", &"await_scene_ready"]: + block = BlocksCatalog.get_block(block_name) + block_list.append(block) + + # Logs + block = BlocksCatalog.get_block(&"print") + block_list.append(block) + + # Communication + for block_name in [&"define_method", &"call_method_group", &"call_method_node"]: + block = BlocksCatalog.get_block(block_name) + block_list.append(block) + + for block_name in [&"add_to_group", &"add_node_to_group", &"remove_from_group", &"remove_node_from_group", &"is_in_group", &"is_node_in_group"]: + block = BlocksCatalog.get_block(block_name) + block_list.append(block) + + # Variables + block = BlocksCatalog.get_block(&"vector2") + block_list.append(block) + + # Math + for block_name in [&"add", &"subtract", &"multiply", &"divide", &"pow", &"randf_range", &"randi_range", &"sin", &"cos", &"tan"]: + block = BlocksCatalog.get_block(block_name) + block_list.append(block) + + # Logic + for block_name in [&"if", &"else_if", &"else", &"compare", &"and", &"or", &"not"]: + block = BlocksCatalog.get_block(block_name) + block_list.append(block) + + # Input + block = BlocksCatalog.get_block(&"is_input_actioned") + block_list.append(block) + + # Sounds + for block_name in [&"load_sound", &"play_sound", &"pause_continue_sound", &"stop_sound"]: + block = BlocksCatalog.get_block(block_name) + block_list.append(block) + + # Graphics + for block_name in [&"viewport_width", &"viewport_height", &"viewport_center"]: + block = BlocksCatalog.get_block(block_name) + block_list.append(block) + + return block_list + + +func _get_inherited_block_definitions() -> Array[BlockDefinition]: + return BlocksCatalog.get_inherited_blocks(script_inherits) + + +func _get_variable_block_definitions() -> Array[BlockDefinition]: + return BlocksCatalog.get_variable_block_definitions(variables) + + func generate_ast_list() -> ASTList: var ast_list := ASTList.new() for tree in block_serialization_trees: @@ -87,7 +258,7 @@ func _tree_to_ast(tree: BlockSerializationTree) -> BlockAST: func _block_to_ast_node(node: BlockSerialization) -> BlockAST.ASTNode: var ast_node := BlockAST.ASTNode.new() - ast_node.data = _get_block(node.name) + ast_node.data = get_block_definition(node.name) for arg_name in node.arguments: var argument = node.arguments[arg_name] @@ -105,7 +276,7 @@ func _block_to_ast_node(node: BlockSerialization) -> BlockAST.ASTNode: func _value_to_ast_value(value_node: ValueBlockSerialization) -> BlockAST.ASTValueNode: var ast_value_node := BlockAST.ASTValueNode.new() - ast_value_node.data = _get_block(value_node.name) + ast_value_node.data = get_block_definition(value_node.name) for arg_name in value_node.arguments: var argument = value_node.arguments[arg_name] diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index c3095170..34b1c3e8 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -15,6 +15,8 @@ const DEFAULT_WINDOW_MARGIN: Vector2 = Vector2(25, 25) const SNAP_GRID: Vector2 = Vector2(25, 25) const ZOOM_FACTOR: float = 1.1 +@onready var _context := BlockEditorContext.get_default() + @onready var _window: Control = %Window @onready var _empty_box: BoxContainer = %EmptyBox @@ -52,6 +54,8 @@ signal replace_block_code func _ready(): + _context.changed.connect(_on_context_changed) + if not _open_scene_button.icon and not Util.node_is_part_of_edited_scene(self): _open_scene_button.icon = _open_scene_icon @@ -87,12 +91,12 @@ func set_child(n: Node): set_child(c) -func block_script_selected(block_script: BlockScriptSerialization): +func _on_context_changed(): clear_canvas() var edited_node = EditorInterface.get_inspector().get_edited_object() as Node - if block_script != _current_block_script: + if _context.block_script != _current_block_script: _window.position = Vector2(0, 0) zoom = 1 @@ -106,12 +110,12 @@ func block_script_selected(block_script: BlockScriptSerialization): _open_scene_button.disabled = true _replace_block_code_button.disabled = true - if block_script != null: - _load_block_script(block_script) + if _context.block_script != null: + _load_block_script(_context.block_script) _window.visible = true _zoom_button.visible = true - if block_script != _current_block_script: + if _context.block_script != _current_block_script: reset_window_position() elif edited_node == null: _empty_box.visible = true @@ -130,7 +134,7 @@ func block_script_selected(block_script: BlockScriptSerialization): _selected_node_label.text = _selected_node_label_format.format({"node": edited_node.name}) _add_block_code_button.disabled = false - _current_block_script = block_script + _current_block_script = _context.block_script func _load_block_script(block_script: BlockScriptSerialization): @@ -146,8 +150,8 @@ func reload_ui_from_ast_list(): func ui_tree_from_ast_node(ast_node: BlockAST.ASTNode) -> Block: - var block: Block = Util.instantiate_block(ast_node.data) - block.color = Util.get_category_color(ast_node.data.category) + var block: Block = _context.block_script.instantiate_block(ast_node.data) + # Args for arg_name in ast_node.arguments: var argument = ast_node.arguments[arg_name] @@ -177,8 +181,8 @@ func ui_tree_from_ast_node(ast_node: BlockAST.ASTNode) -> Block: func ui_tree_from_ast_value_node(ast_value_node: BlockAST.ASTValueNode) -> Block: - var block: Block = Util.instantiate_block(ast_value_node.data) - block.color = Util.get_category_color(ast_value_node.data.category) + var block: Block = _context.block_script.instantiate_block(ast_value_node.data) + # Args for arg_name in ast_value_node.arguments: var argument = ast_value_node.arguments[arg_name] @@ -259,7 +263,7 @@ func build_value_ast(block: ParameterBlock) -> BlockAST.ASTValueNode: func rebuild_block_serialization_trees(): - _current_block_script.update_from_ast_list(_current_ast_list) + _context.block_script.update_from_ast_list(_current_ast_list) func find_snaps(node: Node) -> Array[SnapPoint]: @@ -383,7 +387,7 @@ func set_mouse_override(override: bool): func generate_script_from_current_window() -> String: - return ScriptGenerator.generate_script(_current_ast_list, _current_block_script) + return ScriptGenerator.generate_script(_current_ast_list, _context.block_script) func _on_zoom_button_pressed(): diff --git a/addons/block_code/ui/block_editor_context.gd b/addons/block_code/ui/block_editor_context.gd new file mode 100644 index 00000000..6c36bba1 --- /dev/null +++ b/addons/block_code/ui/block_editor_context.gd @@ -0,0 +1,33 @@ +class_name BlockEditorContext +extends Object + +signal changed + +static var _instance: BlockEditorContext + +var block_code_node: BlockCode: + set(value): + block_code_node = value + changed.emit() + +var block_script: BlockScriptSerialization: + get: + if block_code_node == null: + return null + return block_code_node.block_script + +var parent_node: Node: + get: + if block_code_node == null: + return null + return block_code_node.get_parent() + + +func force_update() -> void: + changed.emit() + + +static func get_default() -> BlockEditorContext: + if _instance == null: + _instance = BlockEditorContext.new() + return _instance diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 741d31c4..499927ca 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -10,9 +10,6 @@ signal modified ## Color of block (optionally used to draw block color) @export var color: Color = Color(1., 1., 1.) -## Category to add the block to -@export var category: String - # FIXME Note: This used to be a NodePath. There is a bug in Godot 4.2 that causes the # reference to not be set properly when the node is duplicated. Since we don't # use the Node duplicate function anymore, this is okay. diff --git a/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd b/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd index 0fb715cc..579d3102 100644 --- a/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd +++ b/addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd @@ -5,10 +5,15 @@ extends MarginContainer const Types = preload("res://addons/block_code/types/types.gd") var block: Block -var output_block: Block +var parameter_name: String +var _block_name: String: + get: + return block.definition.name if block else "" @export var block_params: Dictionary +@onready var _context := BlockEditorContext.get_default() + @onready var _snap_point := %SnapPoint @@ -22,10 +27,17 @@ func _update_parameter_block(): if _snap_point.has_snapped_block(): return - var parameter_block = preload("res://addons/block_code/ui/blocks/parameter_block/parameter_block.tscn").instantiate() - for key in block_params: - parameter_block[key] = block_params[key] - parameter_block.spawned_by = self + if _context.block_script == null: + return + + var block_name = &"%s:%s" % [_block_name, parameter_name] + var parameter_block: ParameterBlock = _context.block_script.instantiate_block_by_name(block_name) + + if parameter_block == null: + # FIXME: This sometimes occurs when a script is loaded but it is unclear why + #push_error("Unable to create output block %s." % block_name) + return + _snap_point.add_child.call_deferred(parameter_block) diff --git a/addons/block_code/ui/main_panel.gd b/addons/block_code/ui/main_panel.gd index 64ea1f90..cb4dabd5 100644 --- a/addons/block_code/ui/main_panel.gd +++ b/addons/block_code/ui/main_panel.gd @@ -5,11 +5,14 @@ signal script_window_requested(script: String) const BlockCanvas = preload("res://addons/block_code/ui/block_canvas/block_canvas.gd") const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd") +const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd") const Picker = preload("res://addons/block_code/ui/picker/picker.gd") const TitleBar = preload("res://addons/block_code/ui/title_bar/title_bar.gd") const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") +@onready var _context := BlockEditorContext.get_default() + @onready var _picker: Picker = %Picker @onready var _block_canvas: BlockCanvas = %BlockCanvas @onready var _drag_manager: DragManager = %DragManager @@ -25,7 +28,6 @@ const VariableDefinition = preload("res://addons/block_code/code_generation/vari const Constants = preload("res://addons/block_code/ui/constants.gd") -var _current_block_code_node: BlockCode var _block_code_nodes: Array var _collapsed: bool = false @@ -39,6 +41,8 @@ var undo_redo: EditorUndoRedoManager: func _ready(): + _context.changed.connect(_on_context_changed) + _picker.block_picked.connect(_drag_manager.copy_picked_block_and_drag) _picker.variable_created.connect(_create_variable) _block_canvas.reconnect_block.connect(_drag_manager.connect_block_canvas_signals) @@ -52,13 +56,7 @@ func _ready(): func _on_undo_redo_version_changed(): - if _current_block_code_node == null: - return - - var block_script: BlockScriptSerialization = _current_block_code_node.block_script - _picker.block_script_selected(block_script) - _title_bar.block_script_selected(block_script) - _block_canvas.block_script_selected(block_script) + _context.force_update() func _on_show_script_button_pressed(): @@ -73,15 +71,14 @@ func _on_delete_node_button_pressed(): if not scene_root: return - if not _current_block_code_node: + if not _context.block_code_node: return var dialog = ConfirmationDialog.new() var text_format: String = 'Delete block code ("{node}") for "{parent}"?' - dialog.dialog_text = text_format.format({"node": _current_block_code_node.name, "parent": _current_block_code_node.get_parent().name}) + dialog.dialog_text = text_format.format({"node": _context.block_code_node.name, "parent": _context.parent_node.name}) EditorInterface.popup_dialog_centered(dialog) - dialog.connect("confirmed", _on_delete_dialog_confirmed.bind(_current_block_code_node)) - pass # Replace with function body. + dialog.connect("confirmed", _on_delete_dialog_confirmed.bind(_context.block_code_node)) func _on_delete_dialog_confirmed(block_code_node: BlockCode): @@ -90,7 +87,7 @@ func _on_delete_dialog_confirmed(block_code_node: BlockCode): if not parent_node: return - undo_redo.create_action("Delete %s's block code script" % _current_block_code_node.get_parent().name, UndoRedo.MERGE_DISABLE, parent_node) + undo_redo.create_action("Delete %s's block code script" % parent_node.name, UndoRedo.MERGE_DISABLE, parent_node) undo_redo.add_do_property(block_code_node, "owner", null) undo_redo.add_do_method(parent_node, "remove_child", block_code_node) undo_redo.add_undo_method(parent_node, "add_child", block_code_node) @@ -100,53 +97,59 @@ func _on_delete_dialog_confirmed(block_code_node: BlockCode): func _try_migration(): - var version: int = _current_block_code_node.block_script.version + var version: int = _context.block_script.version if version == Constants.CURRENT_DATA_VERSION: # No migration needed. return push_warning("Migration not implemented from %d to %d" % [version, Constants.CURRENT_DATA_VERSION]) -func switch_scene(scene_root: Node): - _title_bar.scene_selected(scene_root) +func switch_block_code_node(block_code_node: BlockCode): + BlocksCatalog.setup() + + var block_script := block_code_node.block_script if block_code_node != null else null + var object_script := block_script.load_object_script() if block_script != null else null + if object_script and object_script.has_method("setup_custom_blocks"): + object_script.setup_custom_blocks() -func switch_block_code_node(block_code_node: BlockCode): - var block_script: BlockScriptSerialization = block_code_node.block_script if block_code_node else null - _current_block_code_node = block_code_node - _delete_node_button.disabled = _current_block_code_node == null - if _current_block_code_node != null: + if block_script: + block_script.initialize() + + _context.block_code_node = block_code_node + + +func _on_context_changed(): + _delete_node_button.disabled = _context.block_code_node == null + if _context.block_code_node != null: _try_migration() - _picker.block_script_selected(block_script) - _title_bar.block_script_selected(block_script) - _block_canvas.block_script_selected(block_script) func save_script(): - if _current_block_code_node == null: + if _context.block_code_node == null: print("No script loaded to save.") return var scene_node = EditorInterface.get_edited_scene_root() - if not BlockCodePlugin.is_block_code_editable(_current_block_code_node): - print("Block code for {node} is not editable.".format({"node": _current_block_code_node})) + if not BlockCodePlugin.is_block_code_editable(_context.block_code_node): + print("Block code for {node} is not editable.".format({"node": _context.block_code_node})) return - var block_script: BlockScriptSerialization = _current_block_code_node.block_script + var block_script: BlockScriptSerialization = _context.block_script var resource_path_split = block_script.resource_path.split("::", true, 1) var resource_scene = resource_path_split[0] - undo_redo.create_action("Modify %s's block code script" % _current_block_code_node.get_parent().name, UndoRedo.MERGE_DISABLE, _current_block_code_node) + undo_redo.create_action("Modify %s's block code script" % _context.parent_node.name, UndoRedo.MERGE_DISABLE, _context.block_code_node) if resource_scene and resource_scene != scene_node.scene_file_path: # This resource is from another scene. Since the user is changing it # here, we'll make a copy for this scene rather than changing it in the # other scene file. - undo_redo.add_undo_property(_current_block_code_node, "block_script", _current_block_code_node.block_script) + undo_redo.add_undo_property(_context.block_code_node, "block_script", _context.block_script) block_script = block_script.duplicate(true) - undo_redo.add_do_property(_current_block_code_node, "block_script", block_script) + undo_redo.add_do_property(_context.block_code_node, "block_script", block_script) undo_redo.add_undo_property(block_script, "block_serialization_trees", block_script.block_serialization_trees) _block_canvas.rebuild_ast_list() @@ -264,19 +267,19 @@ func _set_selection(nodes: Array[Node]): func _create_variable(variable: VariableDefinition): - if _current_block_code_node == null: + if _context.block_code_node == null: print("No script loaded to add variable to.") return - var block_script: BlockScriptSerialization = _current_block_code_node.block_script + var block_script: BlockScriptSerialization = _context.block_script - undo_redo.create_action("Create variable %s in %s's block code script" % [variable.var_name, _current_block_code_node.get_parent().name]) - undo_redo.add_undo_property(_current_block_code_node.block_script, "variables", _current_block_code_node.block_script.variables) + undo_redo.create_action("Create variable %s in %s's block code script" % [variable.var_name, _context.parent_node.name]) + undo_redo.add_undo_property(_context.block_script, "variables", _context.block_script.variables) var new_variables = block_script.variables.duplicate() new_variables.append(variable) - undo_redo.add_do_property(_current_block_code_node.block_script, "variables", new_variables) + undo_redo.add_do_property(_context.block_script, "variables", new_variables) undo_redo.commit_action() - _picker.reload_variables(new_variables) + _picker.reload_blocks() diff --git a/addons/block_code/ui/picker/categories/block_category.gd b/addons/block_code/ui/picker/categories/block_category.gd index e076865d..1169c35a 100644 --- a/addons/block_code/ui/picker/categories/block_category.gd +++ b/addons/block_code/ui/picker/categories/block_category.gd @@ -1,15 +1,18 @@ extends RefCounted -const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") - var name: String -var block_list: Array[BlockDefinition] var color: Color var order: int -func _init(p_name: String = "", p_color: Color = Color.WHITE, p_order: int = 0, p_block_list: Array[BlockDefinition] = []): +func _init(p_name: String = "", p_color: Color = Color.WHITE, p_order: int = 0): name = p_name - block_list = p_block_list color = p_color order = p_order + + +## Compare block categories for sorting. Compare by order then name. +static func sort_by_order(a, b) -> bool: + if a.order != b.order: + return a.order < b.order + return a.name.naturalcasecmp_to(b.name) < 0 diff --git a/addons/block_code/ui/picker/categories/block_category_display.gd b/addons/block_code/ui/picker/categories/block_category_display.gd index 5145836a..73fd1e63 100644 --- a/addons/block_code/ui/picker/categories/block_category_display.gd +++ b/addons/block_code/ui/picker/categories/block_category_display.gd @@ -8,15 +8,20 @@ const Util = preload("res://addons/block_code/ui/util.gd") var category: BlockCategory +@onready var _context := BlockEditorContext.get_default() + @onready var _label := %Label @onready var _blocks := %Blocks func _ready(): - _label.text = category.name + _label.text = category.name if category != null else "" + + if _context.block_script == null: + return - for block_definition in category.block_list: - var block: Block = Util.instantiate_block(block_definition) + for block_definition in _context.block_script.get_blocks_in_category(category): + var block: Block = _context.block_script.instantiate_block(block_definition) block.color = category.color block.can_delete = false diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index 02eda12b..2a508d33 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -2,105 +2,20 @@ class_name CategoryFactory extends Object const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") -const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") -const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") -const Types = preload("res://addons/block_code/types/types.gd") -const Util = preload("res://addons/block_code/ui/util.gd") const Constants = preload("res://addons/block_code/ui/constants.gd") -## Compare block categories for sorting. Compare by order then name. -static func _category_cmp(a: BlockCategory, b: BlockCategory) -> bool: - if a.order != b.order: - return a.order < b.order - return a.name.naturalcasecmp_to(b.name) < 0 +## Returns a list of BlockCategory instances for all block categories. +static func get_all_categories(custom_categories: Array[BlockCategory] = []) -> Array[BlockCategory]: + var result: Array[BlockCategory] + for category_name in Constants.BUILTIN_CATEGORIES_PROPS: + var props: Dictionary = Constants.BUILTIN_CATEGORIES_PROPS.get(category_name, {}) + var color: Color = props.get("color", Color.SLATE_GRAY) + var order: int = props.get("order", 0) + result.append(BlockCategory.new(category_name, color, order)) -static func get_categories(blocks: Array[BlockDefinition], extra_categories: Array[BlockCategory] = []) -> Array[BlockCategory]: - var cat_map: Dictionary = {} - var extra_cat_map: Dictionary = {} + # TODO: Should we deduplicate custom_categories here? + result.append_array(custom_categories) - for cat in extra_categories: - extra_cat_map[cat.name] = cat - - for block in blocks: - var cat: BlockCategory = cat_map.get(block.category) - if cat == null: - cat = extra_cat_map.get(block.category) - if cat == null: - var props: Dictionary = Constants.BUILTIN_CATEGORIES_PROPS.get(block.category, {}) - var color: Color = props.get("color", Color.SLATE_GRAY) - var order: int = props.get("order", 0) - cat = BlockCategory.new(block.category, color, order) - cat_map[block.category] = cat - cat.block_list.append(block) - - # Dictionary.values() returns an untyped Array and there's no way to - # convert an array type besides Array.assign(). - var cats: Array[BlockCategory] = [] - cats.assign(cat_map.values()) - # Accessing a static Callable from a static function fails in 4.2.1. - # Use the fully qualified name. - # https://github.com/godotengine/godot/issues/86032 - cats.sort_custom(CategoryFactory._category_cmp) - return cats - - -static func get_general_blocks() -> Array[BlockDefinition]: - var block: BlockDefinition - var block_list: Array[BlockDefinition] = [] - - BlocksCatalog.setup() - - # Lifecycle - for block_name in [&"ready", &"process", &"physics_process", &"queue_free"]: - block = BlocksCatalog.get_block(block_name) - block_list.append(block) - - # Loops - for block_name in [&"for", &"while", &"break", &"continue", &"await_scene_ready"]: - block = BlocksCatalog.get_block(block_name) - block_list.append(block) - - # Logs - block = BlocksCatalog.get_block(&"print") - block_list.append(block) - - # Communication - for block_name in [&"define_method", &"call_method_group", &"call_method_node"]: - block = BlocksCatalog.get_block(block_name) - block_list.append(block) - - for block_name in [&"add_to_group", &"add_node_to_group", &"remove_from_group", &"remove_node_from_group", &"is_in_group", &"is_node_in_group"]: - block = BlocksCatalog.get_block(block_name) - block_list.append(block) - - # Variables - block = BlocksCatalog.get_block(&"vector2") - block_list.append(block) - - # Math - for block_name in [&"add", &"subtract", &"multiply", &"divide", &"pow", &"randf_range", &"randi_range", &"sin", &"cos", &"tan"]: - block = BlocksCatalog.get_block(block_name) - block_list.append(block) - - # Logic - for block_name in [&"if", &"else_if", &"else", &"compare", &"and", &"or", &"not"]: - block = BlocksCatalog.get_block(block_name) - block_list.append(block) - - # Input - block = BlocksCatalog.get_block(&"is_input_actioned") - block_list.append(block) - - # Sounds - for block_name in [&"load_sound", &"play_sound", &"pause_continue_sound", &"stop_sound"]: - block = BlocksCatalog.get_block(block_name) - block_list.append(block) - - # Graphics - for block_name in [&"viewport_width", &"viewport_height", &"viewport_center"]: - block = BlocksCatalog.get_block(block_name) - block_list.append(block) - - return block_list + return result diff --git a/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd index cc818d43..8383bbb5 100644 --- a/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd +++ b/addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.gd @@ -5,6 +5,8 @@ const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd") signal create_variable(var_name: String, var_type: String) +@onready var _context := BlockEditorContext.get_default() + @onready var _variable_input := %VariableInput @onready var _type_option := %TypeOption @onready var _messages := %Messages @@ -60,14 +62,11 @@ func check_errors(new_var_name: String) -> bool: errors.append("Variable name cannot contain special characters") var duplicate_variable_name := false - var current_block_code = BlockCodePlugin.main_panel._current_block_code_node - if current_block_code: - var current_block_script = current_block_code.block_script - if current_block_script: - for variable in current_block_script.variables: - if variable.var_name == new_var_name: - duplicate_variable_name = true - break + if _context.block_script: + for variable in _context.block_script.variables: + if variable.var_name == new_var_name: + duplicate_variable_name = true + break if duplicate_variable_name: errors.append("Variable already exists") diff --git a/addons/block_code/ui/picker/picker.gd b/addons/block_code/ui/picker/picker.gd index d2fbd4c2..49b90d81 100644 --- a/addons/block_code/ui/picker/picker.gd +++ b/addons/block_code/ui/picker/picker.gd @@ -6,7 +6,6 @@ const BlockCategory = preload("res://addons/block_code/ui/picker/categories/bloc const BlockCategoryButtonScene = preload("res://addons/block_code/ui/picker/categories/block_category_button.tscn") const BlockCategoryButton = preload("res://addons/block_code/ui/picker/categories/block_category_button.gd") const BlockCategoryDisplay = preload("res://addons/block_code/ui/picker/categories/block_category_display.gd") -const CategoryFactory = preload("res://addons/block_code/ui/picker/categories/category_factory.gd") const Util = preload("res://addons/block_code/ui/util.gd") const VariableCategoryDisplay = preload("res://addons/block_code/ui/picker/categories/variable_category/variable_category_display.gd") const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") @@ -14,6 +13,8 @@ const VariableDefinition = preload("res://addons/block_code/code_generation/vari signal block_picked(block: Block) signal variable_created(variable: VariableDefinition) +@onready var _context := BlockEditorContext.get_default() + @onready var _block_list := %BlockList @onready var _block_scroll := %BlockScroll @onready var _category_list := %CategoryList @@ -23,35 +24,31 @@ var scroll_tween: Tween var _variable_category_display: VariableCategoryDisplay = null -func block_script_selected(block_script: BlockScriptSerialization): - if not block_script: - reset_picker() - return +func _ready() -> void: + _context.changed.connect(_on_context_changed) - var blocks_to_add: Array[BlockDefinition] = block_script.get_definitions() - var categories_to_add: Array[BlockCategory] = block_script.get_categories() - init_picker(blocks_to_add, categories_to_add) - reload_variables(block_script.variables) +func _on_context_changed(): + _block_scroll.scroll_vertical = 0 + _update_block_components() -func reset_picker(): - for c in _category_list.get_children(): - c.queue_free() +func reload_blocks(): + _update_block_components() - for c in _block_list.get_children(): - c.queue_free() +func _update_block_components(): + # FIXME: Instead, we should reuse existing CategoryList and BlockList components. + _reset_picker() -func init_picker(extra_blocks: Array[BlockDefinition] = [], extra_categories: Array[BlockCategory] = []): - reset_picker() + if not _context.block_script: + return - var blocks := CategoryFactory.get_general_blocks() + extra_blocks - var block_categories := CategoryFactory.get_categories(blocks, extra_categories) + var block_categories := _context.block_script.get_available_categories() - for _category in block_categories: - var category: BlockCategory = _category as BlockCategory + block_categories.sort_custom(BlockCategory.sort_by_order) + for category in block_categories: var block_category_button: BlockCategoryButton = BlockCategoryButtonScene.instantiate() block_category_button.category = category block_category_button.selected.connect(_category_selected) @@ -71,7 +68,15 @@ func init_picker(extra_blocks: Array[BlockDefinition] = [], extra_categories: Ar _block_list.add_child(block_category_display) - _block_scroll.scroll_vertical = 0 + +func _reset_picker(): + for node in _category_list.get_children(): + _category_list.remove_child(node) + node.queue_free() + + for node in _block_list.get_children(): + _block_list.remove_child(node) + node.queue_free() func scroll_to(y: float): @@ -90,19 +95,3 @@ func _category_selected(category: BlockCategory): func set_collapsed(collapsed: bool): _widget_container.visible = not collapsed - - -func reload_variables(variables: Array[VariableDefinition]): - if _variable_category_display: - for c in _variable_category_display.variable_blocks.get_children(): - c.queue_free() - - var i := 1 - for block in Util.instantiate_variable_blocks(variables): - _variable_category_display.variable_blocks.add_child(block) - block.drag_started.connect(func(block: Block): block_picked.emit(block)) - if i % 2 == 0: - var spacer := Control.new() - spacer.custom_minimum_size.y = 12 - _variable_category_display.variable_blocks.add_child(spacer) - i += 1 diff --git a/addons/block_code/ui/title_bar/title_bar.gd b/addons/block_code/ui/title_bar/title_bar.gd index 710c4344..f2dfc45c 100644 --- a/addons/block_code/ui/title_bar/title_bar.gd +++ b/addons/block_code/ui/title_bar/title_bar.gd @@ -5,6 +5,8 @@ const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd") signal node_name_changed(node_name: String) +@onready var _context := BlockEditorContext.get_default() + @onready var _block_code_icon = load("res://addons/block_code/block_code_node/block_code_node.svg") as Texture2D @onready var _editor_inspector: EditorInspector = EditorInterface.get_inspector() @onready var _editor_selection: EditorSelection = EditorInterface.get_selection() @@ -12,17 +14,11 @@ signal node_name_changed(node_name: String) func _ready(): + _context.changed.connect(_on_context_changed) _node_option_button.connect("item_selected", _on_node_option_button_item_selected) -func scene_selected(scene_root: Node): - _update_node_option_button_items() - var current_block_code = _editor_inspector.get_edited_object() as BlockCode - if not current_block_code: - block_script_selected(null) - - -func block_script_selected(block_script: BlockScriptSerialization): +func _on_context_changed(): # TODO: We should listen for property changes in all BlockCode nodes and # their parents. As a workaround for the UI displaying stale data, # we'll crudely update the list of BlockCode nodes whenever the @@ -30,7 +26,7 @@ func block_script_selected(block_script: BlockScriptSerialization): _update_node_option_button_items() - var select_index = _get_block_script_index(block_script) + var select_index = _get_block_script_index(_context.block_script) if _node_option_button.selected != select_index: _node_option_button.select(select_index) @@ -53,6 +49,8 @@ func _update_node_option_button_items(): _node_option_button.set_item_icon(node_item_index, _block_code_icon) _node_option_button.set_item_metadata(node_item_index, block_code) + _node_option_button.disabled = _node_option_button.item_count == 0 + func _get_block_script_index(block_script: BlockScriptSerialization) -> int: for index in range(_node_option_button.item_count): diff --git a/addons/block_code/ui/util.gd b/addons/block_code/ui/util.gd index 076d1f84..46918d2f 100644 --- a/addons/block_code/ui/util.gd +++ b/addons/block_code/ui/util.gd @@ -1,48 +1,5 @@ extends Object -const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") -const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") -const Types = preload("res://addons/block_code/types/types.gd") -const Constants = preload("res://addons/block_code/ui/constants.gd") -const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd") - -const SCENE_PER_TYPE = { - Types.BlockType.ENTRY: preload("res://addons/block_code/ui/blocks/entry_block/entry_block.tscn"), - Types.BlockType.STATEMENT: preload("res://addons/block_code/ui/blocks/statement_block/statement_block.tscn"), - Types.BlockType.VALUE: preload("res://addons/block_code/ui/blocks/parameter_block/parameter_block.tscn"), - Types.BlockType.CONTROL: preload("res://addons/block_code/ui/blocks/control_block/control_block.tscn"), -} - - -static func get_category_color(category: String) -> Color: - var category_props: Dictionary = Constants.BUILTIN_CATEGORIES_PROPS.get(category, {}) - return category_props.get("color", Color.SLATE_GRAY) - - -static func instantiate_block(block_definition: BlockDefinition) -> Block: - if block_definition == null: - push_error("Cannot construct block from null block definition.") - return null - - var scene = SCENE_PER_TYPE.get(block_definition.type) - if scene == null: - push_error("Cannot instantiate Block from type %s" % block_definition.type) - return null - - var block = scene.instantiate() - block.definition = block_definition - return block - - -static func instantiate_variable_blocks(variables: Array[VariableDefinition]) -> Array[Block]: - var blocks: Array[Block] = [] - for block_definition in BlocksCatalog.get_variable_block_definitions(variables): - var block = instantiate_block(block_definition) - block.color = get_category_color(block_definition.category) - blocks.append(block) - - return blocks - ## Polyfill of Node.is_part_of_edited_scene(), available to GDScript in Godot 4.3+. static func node_is_part_of_edited_scene(node: Node) -> bool: diff --git a/tests/test_category_factory.gd b/tests/test_category_factory.gd index 99dbfd11..4273b7f6 100644 --- a/tests/test_category_factory.gd +++ b/tests/test_category_factory.gd @@ -1,27 +1,36 @@ extends GutTest -## Tests for CategoryFactory +## Tests for BlockFactory const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd") const BlockCategory = preload("res://addons/block_code/ui/picker/categories/block_category.gd") const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") +var block_script: BlockScriptSerialization + func get_category_names(categories: Array[BlockCategory]) -> Array[String]: - var names: Array[String] = [] - for category in categories: - names.append(category.name) - return names + var categories_sorted: Array[BlockCategory] + categories_sorted.assign(categories) + categories_sorted.sort_custom(BlockCategory.sort_by_order) + var result: Array[String] + result.assign(categories_sorted.map(func(category): return category.name)) + return result func get_class_category_names(_class_name: String) -> Array[String]: var blocks: Array[BlockDefinition] = BlocksCatalog.get_inherited_blocks(_class_name) - var names: Array[String] = get_category_names(CategoryFactory.get_categories(blocks)) - return names + var categories: Array[BlockCategory] = block_script._categories.filter(func(category): return blocks.any(func(block): return block.category == category.name)) + return get_category_names(categories) + + +func before_each(): + block_script = BlockScriptSerialization.new() + block_script.initialize() func test_general_category_names(): - var blocks: Array[BlockDefinition] = CategoryFactory.get_general_blocks() - var names: Array[String] = get_category_names(CategoryFactory.get_categories(blocks)) + var blocks: Array[BlockDefinition] = block_script.get_available_blocks() + var names: Array[String] = get_category_names(block_script.get_available_categories()) assert_eq( names, [ @@ -55,7 +64,7 @@ func test_inherited_category_names(params = use_parameters(class_category_names) func test_unique_block_names(): - var blocks: Array[BlockDefinition] = CategoryFactory.get_general_blocks() + var blocks: Array[BlockDefinition] = block_script.get_available_blocks() var block_names: Dictionary for block in blocks: assert_does_not_have(block_names, block.name, "Block name %s is duplicated" % block.name) diff --git a/tests/test_code_generation.gd b/tests/test_code_generation.gd index 7e61602e..9e960480 100644 --- a/tests/test_code_generation.gd +++ b/tests/test_code_generation.gd @@ -9,6 +9,7 @@ const BlockDefinition = preload("res://addons/block_code/code_generation/block_d const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd") var general_blocks: Dictionary +var block_script: BlockScriptSerialization func build_block_map(block_map: Dictionary, blocks: Array[BlockDefinition]): @@ -24,7 +25,9 @@ func free_block_map(block_map: Dictionary): func before_each(): - build_block_map(general_blocks, CategoryFactory.get_general_blocks()) + block_script = BlockScriptSerialization.new() + block_script.initialize() + build_block_map(general_blocks, block_script.get_available_blocks()) func after_each(): From 4118bae8efd175e7b8ae57fc167ff455db57222b Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 18 Sep 2024 14:49:57 -0700 Subject: [PATCH 212/423] BlocksCatalog: Remove by_class_name cache Instead, the list of blocks by class name is generated as needed inside get_blocks_by_class. --- .../code_generation/blocks_catalog.gd | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/addons/block_code/code_generation/blocks_catalog.gd b/addons/block_code/code_generation/blocks_catalog.gd index 6fd38e84..4bc8bb71 100644 --- a/addons/block_code/code_generation/blocks_catalog.gd +++ b/addons/block_code/code_generation/blocks_catalog.gd @@ -80,7 +80,6 @@ const _SETTINGS_FOR_CLASS_PROPERTY = { } static var _catalog: Dictionary -static var _by_class_name: Dictionary static func _setup_definitions_from_files(): @@ -91,9 +90,6 @@ static func _setup_definitions_from_files(): var target = block_definition.target_node_class if not target: continue - if not target in _by_class_name: - _by_class_name[target] = {} - _by_class_name[target][block_definition.name] = block_definition static func _add_property_definitions(_class_name: String, property_list: Array[Dictionary], property_settings: Dictionary): @@ -103,9 +99,6 @@ static func _add_property_definitions(_class_name: String, property_list: Array[ var block_settings = property_settings[property.name] var type_string: String = Types.VARIANT_TYPE_TO_STRING[property.type] - if not _class_name in _by_class_name: - _by_class_name[_class_name] = {} - # Setter var block_definition: BlockDefinition if block_settings.get("has_setter", true): @@ -124,7 +117,6 @@ static func _add_property_definitions(_class_name: String, property_list: Array[ ) ) _catalog[block_definition.name] = block_definition - _by_class_name[_class_name][block_definition.name] = block_definition # Changer if block_settings.get("has_change", true): @@ -143,7 +135,6 @@ static func _add_property_definitions(_class_name: String, property_list: Array[ ) ) _catalog[block_definition.name] = block_definition - _by_class_name[_class_name][block_definition.name] = block_definition # Getter block_definition = ( @@ -160,7 +151,6 @@ static func _add_property_definitions(_class_name: String, property_list: Array[ ) ) _catalog[block_definition.name] = block_definition - _by_class_name[_class_name][block_definition.name] = block_definition static func _get_inputmap_actions() -> Array[StringName]: @@ -234,11 +224,19 @@ static func has_block(block_name: StringName): return block_name in _catalog -static func get_blocks_by_class(_class_name: String): - if not _class_name in _by_class_name: - return [] - var block_definitions = _by_class_name[_class_name] as Dictionary - return block_definitions.values() +static func get_blocks_by_class(_class_name: String) -> Array[BlockDefinition]: + var result: Array[BlockDefinition] + + if not _class_name: + return result + + result.assign(_catalog.values().filter(_block_definition_has_class_name.bind(_class_name))) + + return result + + +static func _block_definition_has_class_name(block_definition: BlockDefinition, _class_name: String) -> bool: + return block_definition.target_node_class == _class_name static func _get_builtin_parents(_class_name: String) -> Array[String]: @@ -288,12 +286,8 @@ static func add_custom_blocks( ): setup() - if not _class_name in _by_class_name: - _by_class_name[_class_name] = {} - for block_definition in block_definitions: _catalog[block_definition.name] = block_definition - _by_class_name[_class_name][block_definition.name] = block_definition _add_property_definitions(_class_name, property_list, property_settings) From dc99328d28b94dafc2a835ed90e85f7c85d577b9 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 28 Aug 2024 17:58:10 -0700 Subject: [PATCH 213/423] BlockDefinition: Support extension scripts An extension script can implement functions which refine a block's presentation depending on the current context, such as the node it is attached to. https://phabricator.endlessm.com/T35564 --- addons/block_code/code_generation/block_definition.gd | 10 ++++++++++ addons/block_code/code_generation/block_extension.gd | 3 +++ 2 files changed, 13 insertions(+) create mode 100644 addons/block_code/code_generation/block_extension.gd diff --git a/addons/block_code/code_generation/block_definition.gd b/addons/block_code/code_generation/block_definition.gd index 9f3bbb90..c5b6521f 100644 --- a/addons/block_code/code_generation/block_definition.gd +++ b/addons/block_code/code_generation/block_definition.gd @@ -27,6 +27,14 @@ const Types = preload("res://addons/block_code/types/types.gd") ## Empty except for blocks that have a defined scope @export var scope: String +@export var extension_script: GDScript + +var _extension: BlockExtension: + get: + if _extension == null and extension_script and extension_script.can_instantiate(): + _extension = extension_script.new() + return _extension as BlockExtension + func _init( p_name: StringName = &"", @@ -40,6 +48,7 @@ func _init( p_defaults = {}, p_signal_name: String = "", p_scope: String = "", + p_extension_script: GDScript = null, ): name = p_name target_node_class = p_target_node_class @@ -52,6 +61,7 @@ func _init( defaults = p_defaults signal_name = p_signal_name scope = p_scope + extension_script = p_extension_script func _to_string(): diff --git a/addons/block_code/code_generation/block_extension.gd b/addons/block_code/code_generation/block_extension.gd new file mode 100644 index 00000000..2a2fef97 --- /dev/null +++ b/addons/block_code/code_generation/block_extension.gd @@ -0,0 +1,3 @@ +@tool +class_name BlockExtension +extends Object From 3517792376dc1b79519f6b58a82a5074ceb5db68 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 28 Aug 2024 18:05:15 -0700 Subject: [PATCH 214/423] animationplayer_play: Add an extension script to generate an option list This extension customizes the block's "animation" options list using the list of animations in the block script's context node. https://phabricator.endlessm.com/T35564 --- .../blocks/graphics/animationplayer_play.gd | 15 +++++++++++++++ .../blocks/graphics/animationplayer_play.tres | 10 ++++++---- .../code_generation/block_definition.gd | 10 ++++++++++ .../block_code/code_generation/block_extension.gd | 4 ++++ 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 addons/block_code/blocks/graphics/animationplayer_play.gd diff --git a/addons/block_code/blocks/graphics/animationplayer_play.gd b/addons/block_code/blocks/graphics/animationplayer_play.gd new file mode 100644 index 00000000..63c603a2 --- /dev/null +++ b/addons/block_code/blocks/graphics/animationplayer_play.gd @@ -0,0 +1,15 @@ +@tool +extends BlockExtension + +const OptionData = preload("res://addons/block_code/code_generation/option_data.gd") + + +func get_defaults_for_node(context_node: Node) -> Dictionary: + var animation_player = context_node as AnimationPlayer + + if not animation_player: + return {} + + var animation_list = animation_player.get_animation_list() + + return {"animation": OptionData.new(animation_list)} diff --git a/addons/block_code/blocks/graphics/animationplayer_play.tres b/addons/block_code/blocks/graphics/animationplayer_play.tres index 2a2f373f..7868406a 100644 --- a/addons/block_code/blocks/graphics/animationplayer_play.tres +++ b/addons/block_code/blocks/graphics/animationplayer_play.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" load_steps=4 format=3 uid="uid://c5e1byehtxwc0"] +[gd_resource type="Resource" load_steps=5 format=3 uid="uid://c5e1byehtxwc0"] [ext_resource type="Script" path="res://addons/block_code/code_generation/block_definition.gd" id="1_emeuv"] [ext_resource type="Script" path="res://addons/block_code/code_generation/option_data.gd" id="1_xu43h"] +[ext_resource type="Script" path="res://addons/block_code/blocks/graphics/animationplayer_play.gd" id="2_7ymgi"] [sub_resource type="Resource" id="Resource_vnp2w"] script = ExtResource("1_xu43h") @@ -16,14 +17,15 @@ description = "Play the animation." category = "Graphics | Animation" type = 2 variant_type = 0 -display_template = "Play {animation: STRING} {direction: OPTION}" +display_template = "Play {animation: OPTION} {direction: OPTION}" code_template = "if \"{direction}\" == \"ahead\": - play({animation}) + play(\"{animation}\") else: - play_backwards({animation}) + play_backwards(\"{animation}\") " defaults = { "direction": SubResource("Resource_vnp2w") } signal_name = "" scope = "" +extension_script = ExtResource("2_7ymgi") diff --git a/addons/block_code/code_generation/block_definition.gd b/addons/block_code/code_generation/block_definition.gd index c5b6521f..d1bb05a1 100644 --- a/addons/block_code/code_generation/block_definition.gd +++ b/addons/block_code/code_generation/block_definition.gd @@ -64,5 +64,15 @@ func _init( extension_script = p_extension_script +func get_defaults_for_node(parent_node: Node) -> Dictionary: + if not _extension: + return defaults + + # Use Dictionary.merge instead of Dictionary.merged for Godot 4.2 compatibility + var new_defaults := _extension.get_defaults_for_node(parent_node) + new_defaults.merge(defaults) + return new_defaults + + func _to_string(): return "%s - %s" % [name, target_node_class] diff --git a/addons/block_code/code_generation/block_extension.gd b/addons/block_code/code_generation/block_extension.gd index 2a2fef97..3e68a312 100644 --- a/addons/block_code/code_generation/block_extension.gd +++ b/addons/block_code/code_generation/block_extension.gd @@ -1,3 +1,7 @@ @tool class_name BlockExtension extends Object + + +func get_defaults_for_node(context_node: Node) -> Dictionary: + return {} From 81b645679afa9c0710167e6de358efae7c8e7f04 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Tue, 3 Sep 2024 18:00:04 -0700 Subject: [PATCH 215/423] Add TemplateEditor to generate UI based on a block format string This new component replaces StatementBlock.format_string in favour of a more declarative API. https://phabricator.endlessm.com/T35564 --- .../code_generation/block_definition.gd | 53 +++++++ .../ui/block_canvas/block_canvas.gd | 44 +++--- addons/block_code/ui/blocks/block/block.gd | 33 ++++- .../ui/blocks/control_block/control_block.gd | 20 +-- .../blocks/control_block/control_block.tscn | 11 +- .../ui/blocks/entry_block/entry_block.tscn | 12 +- .../blocks/parameter_block/parameter_block.gd | 17 +-- .../parameter_block/parameter_block.tscn | 18 +-- .../blocks/statement_block/statement_block.gd | 96 +------------ .../statement_block/statement_block.tscn | 12 +- .../parameter_input/parameter_input.gd | 55 ++++---- .../parameter_input/parameter_input.tscn | 27 ++-- .../parameter_output/parameter_output.gd | 9 +- .../parameter_output/parameter_output.tscn | 4 +- .../blocks/utilities/snap_point/snap_point.gd | 10 ++ .../template_editor/template_editor.gd | 132 ++++++++++++++++++ .../template_editor/template_editor.tscn | 17 +++ 17 files changed, 354 insertions(+), 216 deletions(-) create mode 100644 addons/block_code/ui/blocks/utilities/template_editor/template_editor.gd create mode 100644 addons/block_code/ui/blocks/utilities/template_editor/template_editor.tscn diff --git a/addons/block_code/code_generation/block_definition.gd b/addons/block_code/code_generation/block_definition.gd index d1bb05a1..fe36c001 100644 --- a/addons/block_code/code_generation/block_definition.gd +++ b/addons/block_code/code_generation/block_definition.gd @@ -4,6 +4,8 @@ extends Resource const Types = preload("res://addons/block_code/types/types.gd") +const FORMAT_STRING_PATTERN = "\\[(?[^\\]]+)\\]|\\{(?[^}]+)\\}|(?