Skip to content

Commit 380d186

Browse files
authored
Merge pull request #99 from endlessm/fix-multiple-snap-point-attachments
Add ParameterOutput and monitor node children in SnapPoint
2 parents 896b230 + 031b29e commit 380d186

File tree

11 files changed

+460
-577
lines changed

11 files changed

+460
-577
lines changed

addons/block_code/drag_manager/drag_manager.gd

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class Drag:
3737

3838
var snap_block: Block:
3939
get:
40-
return target_snap_point.block if target_snap_point else null
40+
return target_snap_point.get_parent_block() if target_snap_point else null
4141

4242
func _init(block: Block, block_scope: String, offset: Vector2, block_canvas: BlockCanvas):
4343
assert(block.get_parent() == null)
@@ -72,7 +72,7 @@ class Drag:
7272

7373
if target_snap_point:
7474
# Snap the block to the point
75-
var orphaned_block = target_snap_point.set_snapped_block(_block)
75+
var orphaned_block = target_snap_point.insert_snapped_block(_block)
7676
if orphaned_block:
7777
# Place the orphan block somewhere outside the snap point
7878
_block_canvas.arrange_block(orphaned_block, snap_block)
@@ -89,10 +89,6 @@ class Drag:
8989
push_error("Warning: node %s is not of class SnapPoint." % node)
9090
return false
9191

92-
if _snap_point.block == null:
93-
push_error("Warning: snap point %s does not reference its parent block." % _snap_point)
94-
return false
95-
9692
if not _block_canvas.is_ancestor_of(_snap_point):
9793
# We only snap to blocks on the canvas:
9894
return false
@@ -109,27 +105,29 @@ class Drag:
109105
return false
110106

111107
# Check if any parent node is this node
112-
var parent = _snap_point
113-
var top_block
114-
while parent is SnapPoint:
115-
if parent.block == _block:
116-
return false
108+
if _snap_point.is_ancestor_of(_block):
109+
return false
117110

118-
top_block = parent.block
119-
parent = parent.block.get_parent()
111+
var top_block = _get_top_block_for_node(_snap_point)
120112

121113
# Check if scope is valid
122114
if _block_scope != "":
123115
if top_block is EntryBlock:
124116
if _block_scope != top_block.get_entry_statement():
125117
return false
126-
else:
118+
elif top_block:
127119
var tree_scope := DragManager.get_tree_scope(top_block)
128120
if tree_scope != "" and _block_scope != tree_scope:
129121
return false
130122

131123
return true
132124

125+
func _get_top_block_for_node(node: Node) -> Block:
126+
for top_block in _block_canvas.get_blocks():
127+
if top_block.is_ancestor_of(node):
128+
return top_block
129+
return null
130+
133131
func sort_snap_points_by_distance(a: SnapPoint, b: SnapPoint):
134132
return _get_distance_to_snap_point(a) < _get_distance_to_snap_point(b)
135133

@@ -205,9 +203,7 @@ func drag_block(block: Block, copied_from: Block = null):
205203

206204
var parent = block.get_parent()
207205

208-
if parent is SnapPoint:
209-
parent.remove_snapped_block(block)
210-
elif parent:
206+
if parent:
211207
parent.remove_child(block)
212208

213209
block.disconnect_signals()
@@ -252,23 +248,6 @@ func connect_block_canvas_signals(block: Block):
252248
block.drag_started.connect(drag_block)
253249
block.modified.connect(func(): block_modified.emit())
254250

255-
# HACK: for statement blocks connect copy_blocks to necessary signal
256-
if block is StatementBlock:
257-
var statement_block := block as StatementBlock
258-
for pair in statement_block.param_name_input_pairs:
259-
var param_input: ParameterInput = pair[1]
260-
var copy_block := param_input.get_snapped_block()
261-
if copy_block == null:
262-
continue
263-
if copy_block.drag_started.get_connections().size() == 0:
264-
copy_block.drag_started.connect(func(b: Block): drag_copy_parameter(b, block))
265-
266-
267-
func drag_copy_parameter(block: Block, parent: Block):
268-
if parent is EntryBlock:
269-
block.scope = parent.get_entry_statement()
270-
copy_picked_block_and_drag(block)
271-
272251

273252
## Returns the scope of the first non-empty scope child block
274253
static func get_tree_scope(node: Node) -> String:

addons/block_code/examples/pong_game/pong_game.tscn

Lines changed: 259 additions & 472 deletions
Large diffs are not rendered by default.

addons/block_code/ui/block_canvas/block_canvas.gd

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ func add_block(block: Block, position: Vector2 = Vector2.ZERO) -> void:
3636
_window.custom_minimum_size.y = max(block.position.y + EXTEND_MARGIN, _window.custom_minimum_size.y)
3737

3838

39+
func get_blocks() -> Array[Block]:
40+
var blocks: Array[Block] = []
41+
for child in _window.get_children():
42+
var block = child as Block
43+
if block:
44+
blocks.append(block)
45+
return blocks
46+
47+
3948
func arrange_block(block: Block, nearby_block: Block) -> void:
4049
add_block(block)
4150
block.global_position = (nearby_block.global_position + (nearby_block.get_size() * Vector2.RIGHT) + BLOCK_AUTO_PLACE_MARGIN)

addons/block_code/ui/blocks/control_block/control_block.gd

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ func format():
145145
snap_container.add_theme_constant_override("margin_left", Constants.CONTROL_MARGIN)
146146

147147
var snap_point: SnapPoint = preload("res://addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn").instantiate()
148-
snap_point.block = self
149148
snap_container.add_child(snap_point)
150149

151150
snaps.append(snap_point)

addons/block_code/ui/blocks/entry_block/entry_block.tscn

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55

66
[node name="EntryBlock" instance=ExtResource("1_byjbb")]
77
script = ExtResource("2_3ik8h")
8-
defaults = null
8+
signal_name = ""
9+
defaults = {}
910
block_name = "entry_block"
1011
label = "EntryBlock"
1112
block_type = 1
1213

13-
1414
[node name="Background" parent="VBoxContainer/TopMarginContainer" index="0"]
1515
show_top = false

addons/block_code/ui/blocks/statement_block/statement_block.gd

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -113,31 +113,35 @@ static func format_string(parent_block: Block, attach_to: Node, string: String,
113113
if _defaults.has(param_name):
114114
param_default = _defaults[param_name]
115115

116-
var param_input: ParameterInput = preload("res://addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.tscn").instantiate()
117-
param_input.name = "ParameterInput%d" % start # Unique path
118-
param_input.placeholder = param_name
119-
if param_type != null:
120-
param_input.variant_type = param_type
121-
elif option:
122-
param_input.option = true
123-
param_input.block = parent_block
124-
param_input.modified.connect(func(): parent_block.modified.emit())
125-
126-
attach_to.add_child(param_input)
127-
if param_default:
128-
param_input.set_raw_input(param_default)
129-
130-
_param_name_input_pairs.append([param_name, param_input])
116+
var param_node: Node
131117

132118
if copy_block:
133-
var new_block: Block = preload("res://addons/block_code/ui/blocks/parameter_block/parameter_block.tscn").instantiate()
134-
new_block.block_format = param_name
135-
new_block.statement = param_name
136-
new_block.variant_type = param_type
137-
new_block.color = parent_block.color
138-
param_input.block_type = Types.BlockType.NONE
139-
param_input.snap_point.block_type = Types.BlockType.NONE # Necessary because already called ready
140-
param_input.snap_point.add_child(new_block)
119+
var parameter_output: ParameterOutput = preload("res://addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.tscn").instantiate()
120+
parameter_output.name = "ParameterOutput%d" % start # Unique path
121+
parameter_output.block_params = {
122+
"block_format": param_name,
123+
"statement": param_name,
124+
"variant_type": param_type,
125+
"color": parent_block.color,
126+
"scope": parent_block.get_entry_statement() if parent_block is EntryBlock else ""
127+
}
128+
parameter_output.block = parent_block
129+
attach_to.add_child(parameter_output)
130+
else:
131+
var parameter_input: ParameterInput = preload("res://addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.tscn").instantiate()
132+
parameter_input.name = "ParameterInput%d" % start # Unique path
133+
parameter_input.placeholder = param_name
134+
if param_type != null:
135+
parameter_input.variant_type = param_type
136+
elif option:
137+
parameter_input.option = true
138+
parameter_input.modified.connect(func(): parent_block.modified.emit())
139+
140+
attach_to.add_child(parameter_input)
141+
if param_default:
142+
parameter_input.set_raw_input(param_default)
143+
144+
_param_name_input_pairs.append([param_name, parameter_input])
141145

142146
start = result.get_end()
143147

addons/block_code/ui/blocks/utilities/parameter_input/parameter_input.gd

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,10 @@ signal modified
77
@export var placeholder: String = "Parameter":
88
set = _set_placeholder
99

10-
@export var block_path: NodePath
11-
1210
@export var variant_type: Variant.Type = TYPE_STRING
1311
@export var block_type: Types.BlockType = Types.BlockType.VALUE
1412
var option: bool = false
1513

16-
var block: Block
17-
1814
@onready var _panel := %Panel
1915
@onready var snap_point := %SnapPoint
2016
@onready var _input_switcher := %InputSwitcher
@@ -94,9 +90,6 @@ func _ready():
9490

9591
_set_placeholder(placeholder)
9692

97-
if block == null:
98-
block = get_node_or_null(block_path)
99-
snap_point.block = block
10093
snap_point.block_type = block_type
10194
snap_point.variant_type = variant_type
10295

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
@tool
2+
class_name ParameterOutput
3+
extends MarginContainer
4+
5+
var block: Block
6+
var output_block: Block
7+
8+
@export var block_params: Dictionary
9+
10+
@onready var _snap_point := %SnapPoint
11+
12+
13+
func _ready():
14+
_snap_point.block_type = Types.BlockType.NONE
15+
16+
_update_parameter_block()
17+
18+
19+
func _update_parameter_block():
20+
if _snap_point.has_snapped_block():
21+
return
22+
23+
var parameter_block = preload("res://addons/block_code/ui/blocks/parameter_block/parameter_block.tscn").instantiate()
24+
for key in block_params:
25+
parameter_block[key] = block_params[key]
26+
_snap_point.add_child.call_deferred(parameter_block)
27+
28+
29+
func _on_parameter_block_drag_started(drag_block: Block):
30+
block.drag_started.emit(drag_block)
31+
32+
33+
func _on_snap_point_snapped_block_changed(snap_block: Block):
34+
if snap_block == null:
35+
return
36+
snap_block.drag_started.connect(_on_parameter_block_drag_started)
37+
38+
39+
func _on_snap_point_snapped_block_removed(snap_block: Block):
40+
snap_block.drag_started.disconnect(_on_parameter_block_drag_started)
41+
_update_parameter_block()
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
[gd_scene load_steps=4 format=3 uid="uid://dp01u74qkty7r"]
2+
3+
[ext_resource type="Script" path="res://addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd" id="1_eebb2"]
4+
[ext_resource type="PackedScene" uid="uid://b1oge52xhjqnu" path="res://addons/block_code/ui/blocks/utilities/snap_point/snap_point.tscn" id="2_ngr7c"]
5+
6+
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_tn6h4"]
7+
bg_color = Color(1, 1, 1, 1)
8+
corner_radius_top_left = 40
9+
corner_radius_top_right = 40
10+
corner_radius_bottom_right = 40
11+
corner_radius_bottom_left = 40
12+
13+
[node name="ParameterOutput" type="MarginContainer"]
14+
anchors_preset = 15
15+
anchor_right = 1.0
16+
anchor_bottom = 1.0
17+
offset_right = -1052.0
18+
offset_bottom = -617.0
19+
grow_horizontal = 2
20+
grow_vertical = 2
21+
mouse_filter = 2
22+
script = ExtResource("1_eebb2")
23+
24+
[node name="Panel" type="Panel" parent="."]
25+
unique_name_in_owner = true
26+
layout_mode = 2
27+
mouse_filter = 2
28+
theme_override_styles/panel = SubResource("StyleBoxFlat_tn6h4")
29+
30+
[node name="SnapPoint" parent="." node_paths=PackedStringArray("snapped_block") instance=ExtResource("2_ngr7c")]
31+
unique_name_in_owner = true
32+
layout_mode = 2
33+
mouse_filter = 2
34+
block_type = 0
35+
snapped_block = NodePath("ParameterBlock")
36+
variant_type = 4
37+
38+
[connection signal="child_exiting_tree" from="." to="SnapPoint" method="_on_parameter_output_child_exiting_tree"]
39+
[connection signal="snapped_block_changed" from="SnapPoint" to="." method="_on_snap_point_snapped_block_changed"]
40+
[connection signal="snapped_block_removed" from="SnapPoint" to="." method="_on_snap_point_snapped_block_removed"]

0 commit comments

Comments
 (0)