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 001/316] 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 002/316] 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 003/316] 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 004/316] 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 005/316] 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 006/316] 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 007/316] 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 008/316] 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 009/316] 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 010/316] 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 011/316] 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 012/316] 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 013/316] 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 014/316] 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 015/316] 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 016/316] 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 017/316] 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 018/316] 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 019/316] 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 020/316] 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 021/316] 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 022/316] 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 023/316] 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 024/316] 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 025/316] 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 026/316] 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 027/316] 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 028/316] 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 029/316] 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 030/316] 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 031/316] 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 032/316] 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 033/316] 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 034/316] 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 035/316] 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 036/316] 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 037/316] 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 038/316] 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 039/316] 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 040/316] 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 041/316] 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 042/316] 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 043/316] 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 044/316] 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 045/316] 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 046/316] 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 047/316] 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 048/316] 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 049/316] 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 050/316] 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 051/316] 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 052/316] 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 053/316] 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 054/316] 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 055/316] 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 056/316] 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 057/316] 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 058/316] 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 059/316] 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 060/316] 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 061/316] 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 062/316] 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 063/316] 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 064/316] 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 065/316] 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 066/316] 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 067/316] 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 068/316] 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 069/316] 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 070/316] 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 071/316] 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 072/316] 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 073/316] 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 074/316] 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 075/316] 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 076/316] 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 077/316] 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 078/316] 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 079/316] 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 080/316] 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 081/316] 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 082/316] 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 083/316] 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 084/316] 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 085/316] 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 086/316] 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 087/316] 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 088/316] 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 089/316] 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 090/316] 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 091/316] 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 092/316] 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 093/316] 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 094/316] 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 095/316] 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 096/316] 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 097/316] 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 098/316] 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 099/316] 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 100/316] 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 101/316] 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 102/316] 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 103/316] 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 104/316] 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 105/316] 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 106/316] 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 107/316] 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 108/316] 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 = "\\[(?[^\\]]+)\\]|\\{(?[^}]+)\\}|(?