From 42cbcdd379309b8437fb70722d28fd5a16e30610 Mon Sep 17 00:00:00 2001 From: Dylan McCall Date: Wed, 19 Jun 2024 14:10:18 -0700 Subject: [PATCH] WIP: Add named classes for final blocks Instead of defining blocks in category_factory.gd, define blocks ahead of time, each in their own GDScript file. Although it is not a concept in GDScript itself, we can consider block classes such as EntryBlock to be abstract block types. By doing this, we are able to reduce duplication in the block script resource associated with each BlockCode node. In particular, the serialized data can simply refer to "PrintBlock", and all of the EntryBlock properties expected for the print block are implied. This commit only adds ReadyBlock and PrintBlock as an example, and likely breaks everything else. --- .../block_code/drag_manager/drag_manager.gd | 2 +- .../ui/block_canvas/block_canvas.gd | 11 ++++- .../ui/picker/categories/category_factory.gd | 13 ++---- .../ui/picker/categories/print_block.gd | 37 +++++++++++++++ .../ui/picker/categories/ready_block.gd | 37 +++++++++++++++ test_game/test_game.tscn | 45 ++++++++++++++++++- 6 files changed, 132 insertions(+), 13 deletions(-) create mode 100644 addons/block_code/ui/picker/categories/print_block.gd create mode 100644 addons/block_code/ui/picker/categories/ready_block.gd diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index 9c6aa9c8..bdcae3d5 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -117,7 +117,7 @@ func drag_block(block: Block, copied_from: Block = null): func copy_block(block: Block) -> Block: - return block.duplicate(DUPLICATE_USE_INSTANTIATION) # use instantiation + return block.copy_block() func copy_picked_block_and_drag(block: Block): diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index c37667cc..aea1591d 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -71,7 +71,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 _block_scene_resource = load(_block_scene_path) + var scene: Block + if _block_scene_resource is PackedScene: + scene = _block_scene_resource.instantiate() + elif _block_scene_resource is Script: + scene = _block_scene_resource.new() + else: + push_error("Unable to instantiate block type: ", _block_scene_path) + return + for prop_pair in node.serialized_block.serialized_props: scene.set(prop_pair[0], prop_pair[1]) diff --git a/addons/block_code/ui/picker/categories/category_factory.gd b/addons/block_code/ui/picker/categories/category_factory.gd index f664001c..f299a597 100644 --- a/addons/block_code/ui/picker/categories/category_factory.gd +++ b/addons/block_code/ui/picker/categories/category_factory.gd @@ -15,11 +15,8 @@ static func get_general_categories() -> Array[BlockCategory]: # Lifecycle var lifecycle_list: Array[Block] = [] - b = BLOCKS["entry_block"].instantiate() - b.block_name = "ready_block" - b.block_format = "On Ready" - b.statement = "func _ready():" - lifecycle_list.append(b) + + lifecycle_list.append(ReadyBlock.new()) b = BLOCKS["entry_block"].instantiate() b.block_name = "process_block" @@ -78,11 +75,7 @@ static func get_general_categories() -> Array[BlockCategory]: # Test var test_list: Array[Block] = [] - b = BLOCKS["statement_block"].instantiate() - b.block_format = "print {text: STRING}" - b.statement = "print({text})" - b.defaults = {"text": "Hello"} - test_list.append(b) + test_list.append(PrintBlock.new()) var test_category: BlockCategory = BlockCategory.new("Test", test_list, Color("9989df")) diff --git a/addons/block_code/ui/picker/categories/print_block.gd b/addons/block_code/ui/picker/categories/print_block.gd new file mode 100644 index 00000000..faeee9df --- /dev/null +++ b/addons/block_code/ui/picker/categories/print_block.gd @@ -0,0 +1,37 @@ +@tool +class_name PrintBlock +extends StatementBlock + + +func _init(): + var _block = load(StatementBlock.get_scene_path()).instantiate() as Node + _block.replace_by(self, true) + block_name = _block.block_name + label = _block.label + color = _block.color + block_type = _block.block_type + bottom_snap_path = _block.bottom_snap_path + _block.queue_free() + + block_name = "print_block" + block_format = "print {text: STRING}" + statement = "print({text})" + color = Color("9989df") + + +func copy_block(): + return PrintBlock.new() + + +static func get_block_class(): + return "PrintBlock" + + +static func get_scene_path(): + return "res://addons/block_code/ui/picker/categories/print_block.gd" + + +# Strip out properties that never change for this block type +func get_serialized_props() -> Array: + var props = super() + return props.filter(func(prop): return prop[0] not in ["block_name", "label", "color", "block_type", "block_format", "statement"]) diff --git a/addons/block_code/ui/picker/categories/ready_block.gd b/addons/block_code/ui/picker/categories/ready_block.gd new file mode 100644 index 00000000..b25dd214 --- /dev/null +++ b/addons/block_code/ui/picker/categories/ready_block.gd @@ -0,0 +1,37 @@ +@tool +class_name ReadyBlock +extends EntryBlock + + +func _init(): + var _block = load(EntryBlock.get_scene_path()).instantiate() as Node + _block.replace_by(self, true) + block_name = _block.block_name + label = _block.label + color = _block.color + block_type = _block.block_type + bottom_snap_path = _block.bottom_snap_path + _block.queue_free() + + block_name = "ready_block" + block_format = "On Ready" + statement = "func _ready():" + color = Color("fa5956") + + +func copy_block(): + return ReadyBlock.new() + + +static func get_block_class(): + return "ReadyBlock" + + +static func get_scene_path(): + return "res://addons/block_code/ui/picker/categories/ready_block.gd" + + +# Strip out properties that never change for this block type +func get_serialized_props() -> Array: + var props = super() + return props.filter(func(prop): return prop[0] not in ["block_name", "label", "color", "block_type", "block_format", "statement"]) diff --git a/test_game/test_game.tscn b/test_game/test_game.tscn index 29153639..deab33ff 100644 --- a/test_game/test_game.tscn +++ b/test_game/test_game.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=177 format=3 uid="uid://bbwmxee7ukgul"] +[gd_scene load_steps=183 format=3 uid="uid://bbwmxee7ukgul"] [ext_resource type="PackedScene" uid="uid://ddx1cd5q6t61o" path="res://addons/block_code/simple_nodes/simple_character/simple_character.tscn" id="1_hrpwq"] [ext_resource type="Script" path="res://addons/block_code/block_code_node/block_code.gd" id="2_ewral"] @@ -8,6 +8,45 @@ [ext_resource type="Script" path="res://addons/block_code/block_script_data/block_script_data.gd" id="5_q37d3"] [ext_resource type="Texture2D" uid="uid://dr8e0tvfxjy1f" path="res://icon.svg" id="7_a27o8"] +[sub_resource type="Resource" id="Resource_bkrpj"] +script = ExtResource("3_dpt5n") +block_class = &"PrintBlock" +serialized_props = [["position", Vector2(0, 0)], ["param_input_strings", { +"text": "test" +}]] + +[sub_resource type="Resource" id="Resource_8i26i"] +script = ExtResource("2_pqvcj") +serialized_block = SubResource("Resource_bkrpj") +path_child_pairs = [] + +[sub_resource type="Resource" id="Resource_l25ts"] +script = ExtResource("3_dpt5n") +block_class = &"ReadyBlock" +serialized_props = [["position", Vector2(156, 133)], ["param_input_strings", {}]] + +[sub_resource type="Resource" id="Resource_o5do6"] +script = ExtResource("2_pqvcj") +serialized_block = SubResource("Resource_l25ts") +path_child_pairs = [[NodePath("VBoxContainer/SnapPoint"), SubResource("Resource_8i26i")]] + +[sub_resource type="Resource" id="Resource_vhdmi"] +script = ExtResource("4_xt862") +array = Array[ExtResource("2_pqvcj")]([SubResource("Resource_o5do6")]) + +[sub_resource type="Resource" id="Resource_t3mtx"] +script = ExtResource("5_q37d3") +script_inherits = "Camera2D" +block_trees = SubResource("Resource_vhdmi") +generated_script = "extends Camera2D + +var VAR_DICT := {} + +func _ready(): + print('test') + +" + [sub_resource type="Resource" id="Resource_uwmna"] script = ExtResource("3_dpt5n") block_class = &"StatementBlock" @@ -1109,6 +1148,10 @@ func _process(delta): [node name="Camera2D" type="Camera2D" parent="."] +[node name="BlockCode" type="Node" parent="Camera2D"] +script = ExtResource("2_ewral") +block_script = SubResource("Resource_t3mtx") + [node name="Will" parent="." instance=ExtResource("1_hrpwq")] position = Vector2(-71, -18)