diff --git a/addons/block_code/drag_manager/drag_manager.gd b/addons/block_code/drag_manager/drag_manager.gd index 9b86eba0..e2f2959c 100644 --- a/addons/block_code/drag_manager/drag_manager.gd +++ b/addons/block_code/drag_manager/drag_manager.gd @@ -16,6 +16,7 @@ enum DragAction { NONE, PLACE, REMOVE } class Drag: extends Control var _block: Block + var _block_scope: String var _block_canvas: BlockCanvas var _preview_block: Control var action: DragAction: @@ -38,13 +39,14 @@ class Drag: get: return target_snap_point.block if target_snap_point else null - func _init(block: Block, offset: Vector2, block_canvas: BlockCanvas): + func _init(block: Block, block_scope: String, offset: Vector2, block_canvas: BlockCanvas): assert(block.get_parent() == null) add_child(block) block.position = -offset _block = block + _block_scope = block_scope _block_canvas = block_canvas func apply_drag() -> Block: @@ -108,12 +110,24 @@ class Drag: # Check if any parent node is this node var parent = _snap_point + var top_block while parent is SnapPoint: if parent.block == _block: return false + top_block = parent.block parent = parent.block.get_parent() + # Check if scope is valid + if _block_scope != "": + if top_block is EntryBlock: + if _block_scope != top_block.get_entry_statement(): + return false + else: + var tree_scope := DragManager.get_tree_scope(top_block) + if tree_scope != "" and _block_scope != tree_scope: + return false + return true func sort_snap_points_by_distance(a: SnapPoint, b: SnapPoint): @@ -198,7 +212,11 @@ func drag_block(block: Block, copied_from: Block = null): block.disconnect_signals() - drag = Drag.new(block, offset, _block_canvas) + var block_scope := get_tree_scope(block) + if block_scope != "": + _block_canvas.set_scope(block_scope) + + drag = Drag.new(block, block_scope, offset, _block_canvas) add_child(drag) @@ -222,6 +240,8 @@ func drag_ended(): if block: connect_block_canvas_signals(block) + _block_canvas.release_scope() + drag.queue_free() drag = null @@ -237,7 +257,27 @@ func connect_block_canvas_signals(block: Block): var statement_block := block as StatementBlock for pair in statement_block.param_name_input_pairs: var param_input: ParameterInput = pair[1] - var b := param_input.get_snapped_block() - if b: - if b.drag_started.get_connections().size() == 0: - b.drag_started.connect(copy_picked_block_and_drag) + var copy_block := param_input.get_snapped_block() + if copy_block == null: + continue + if copy_block.drag_started.get_connections().size() == 0: + copy_block.drag_started.connect(func(b: Block): drag_copy_parameter(b, block)) + + +func drag_copy_parameter(block: Block, parent: Block): + if parent is EntryBlock: + block.scope = parent.get_entry_statement() + copy_picked_block_and_drag(block) + + +## Returns the scope of the first non-empty scope child block +static func get_tree_scope(node: Node) -> String: + if node is Block: + if node.scope != "": + return node.scope + + for c in node.get_children(): + var scope := get_tree_scope(c) + if scope != "": + return scope + return "" diff --git a/addons/block_code/ui/block_canvas/block_canvas.gd b/addons/block_code/ui/block_canvas/block_canvas.gd index b3e0857d..b84a1201 100644 --- a/addons/block_code/ui/block_canvas/block_canvas.gd +++ b/addons/block_code/ui/block_canvas/block_canvas.gd @@ -121,3 +121,24 @@ func find_snaps(node: Node) -> Array: snaps.append_array(find_snaps(c)) return snaps + + +func set_scope(scope: String): + for block in _window.get_children(): + var valid := false + + if block is EntryBlock: + if scope == block.get_entry_statement(): + valid = true + else: + var tree_scope := DragManager.get_tree_scope(block) + if tree_scope == "" or scope == tree_scope: + valid = true + + if not valid: + block.modulate = Color(0.5, 0.5, 0.5, 1) + + +func release_scope(): + for block in _window.get_children(): + block.modulate = Color.WHITE diff --git a/addons/block_code/ui/blocks/block/block.gd b/addons/block_code/ui/blocks/block/block.gd index 51e021b9..9966fe8f 100644 --- a/addons/block_code/ui/blocks/block/block.gd +++ b/addons/block_code/ui/blocks/block/block.gd @@ -23,6 +23,9 @@ signal modified ## The next block in the line of execution (can be null if end) @export var bottom_snap_path: NodePath +## The scope of the block (statement of matching entry block) +@export var scope: String = "" + var bottom_snap: SnapPoint @@ -62,7 +65,7 @@ func get_instruction_node() -> InstructionTree.TreeNode: # Override this method to add more serialized properties func get_serialized_props() -> Array: - return serialize_props(["block_name", "label", "color", "block_type", "position"]) + return serialize_props(["block_name", "label", "color", "block_type", "position", "scope"]) func serialize_props(prop_names: Array) -> Array: