Skip to content

Commit f01b3fd

Browse files
authored
Merge pull request #32 from endlessm/refactor-block-types
Type casting
2 parents 77ddcc3 + c82d8ea commit f01b3fd

File tree

4 files changed

+161
-17
lines changed

4 files changed

+161
-17
lines changed

addons/block_code/block_code_plugin.gd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ const DISABLED_CLASSES := [
4545

4646

4747
func _enter_tree():
48+
Types.init_cast_graph()
49+
4850
main_panel = MainPanel.instantiate()
4951
main_panel.undo_redo = get_undo_redo()
5052

addons/block_code/drag_manager/drag_manager.gd

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,23 @@ func _process(_delta):
4545
if snap_point.block == null:
4646
push_error("Warning: a snap point does not reference it's parent block.")
4747
continue
48-
if snap_point.block.on_canvas and snap_point.block_type == dragging.block_type:
49-
var snap_global_pos: Vector2 = snap_point.get_global_rect().position
50-
var temp_dist: float = dragging_global_pos.distance_to(snap_global_pos)
51-
if temp_dist < closest_dist:
52-
# Check if any parent node is this node
53-
var is_child: bool = false
54-
var parent = snap_point
55-
while parent is SnapPoint:
56-
if parent.block == dragging:
57-
is_child = true
58-
59-
parent = parent.block.get_parent()
60-
61-
if not is_child:
62-
closest_dist = temp_dist
63-
closest_snap_point = snap_point
48+
if snap_point.block.on_canvas:
49+
if Types.can_cast(dragging.block_type, snap_point.block_type):
50+
var snap_global_pos: Vector2 = snap_point.get_global_rect().position
51+
var temp_dist: float = dragging_global_pos.distance_to(snap_global_pos)
52+
if temp_dist < closest_dist:
53+
# Check if any parent node is this node
54+
var is_child: bool = false
55+
var parent = snap_point
56+
while parent is SnapPoint:
57+
if parent.block == dragging:
58+
is_child = true
59+
60+
parent = parent.block.get_parent()
61+
62+
if not is_child:
63+
closest_dist = temp_dist
64+
closest_snap_point = snap_point
6465

6566
if closest_dist > 80.0:
6667
closest_snap_point = null

addons/block_code/types/types.gd

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,143 @@ enum BlockType {
1414
COLOR,
1515
NODE
1616
}
17+
18+
const cast_relationships = [
19+
[BlockType.INT, BlockType.FLOAT, "float(%s)"],
20+
[BlockType.FLOAT, BlockType.INT, "int(%s)"],
21+
[BlockType.INT, BlockType.STRING, "str(%s)"],
22+
[BlockType.FLOAT, BlockType.STRING, "str(%s)"],
23+
]
24+
25+
# Directed graph, edges are CastGraphEdge
26+
static var cast_graph: Dictionary
27+
28+
29+
class CastGraphEdge:
30+
var to: BlockType
31+
var cast_format: String
32+
33+
func _init(p_to: BlockType, p_cast_format: String):
34+
to = p_to
35+
cast_format = p_cast_format
36+
37+
38+
static func init_cast_graph():
39+
cast_graph = {}
40+
41+
for rel in cast_relationships:
42+
if not cast_graph.has(rel[0]):
43+
cast_graph[rel[0]] = []
44+
45+
if not cast_graph.has(rel[1]):
46+
cast_graph[rel[1]] = []
47+
48+
var edges: Array = cast_graph[rel[0]]
49+
50+
edges.append(CastGraphEdge.new(rel[1], rel[2]))
51+
52+
53+
# Graph recursive utils
54+
static var prev: Dictionary
55+
static var dist: Dictionary
56+
const INT_MAX: int = 1000000000
57+
58+
59+
static func dijkstra(source: BlockType):
60+
prev = {}
61+
dist = {}
62+
63+
var queue := PriorityQueue.new()
64+
65+
dist[source] = 0
66+
queue.push(source, 0)
67+
68+
for v in cast_graph.keys():
69+
if v != source:
70+
dist[v] = INT_MAX
71+
prev[v] = null
72+
queue.push(v, INT_MAX)
73+
74+
while not queue.is_empty():
75+
var u = queue.pop()
76+
77+
if !cast_graph.has(u):
78+
continue
79+
80+
for edge in cast_graph[u]:
81+
var v = edge.to
82+
var alt = dist[u] + 1
83+
if alt < dist[v]:
84+
dist[v] = alt
85+
prev[v] = CastGraphEdge.new(u, edge.cast_format)
86+
queue.update_priority(v, alt)
87+
88+
89+
static func can_cast(type: BlockType, parent_type: BlockType) -> bool:
90+
if type == parent_type:
91+
return true
92+
93+
if cast_graph.has(type) and cast_graph.has(parent_type):
94+
dijkstra(type)
95+
return dist[parent_type] < INT_MAX
96+
return false
97+
98+
99+
static func cast(val: String, type: BlockType, parent_type: BlockType):
100+
if type == parent_type:
101+
return val
102+
103+
if cast_graph.has(type) and cast_graph.has(parent_type):
104+
dijkstra(type)
105+
if dist[parent_type] < INT_MAX:
106+
var prev_edge = prev[parent_type]
107+
var cast_string = "%s"
108+
while prev_edge:
109+
cast_string %= prev_edge.cast_format
110+
if prev.has(prev_edge.to):
111+
prev_edge = prev[prev_edge.to]
112+
else:
113+
prev_edge = null
114+
115+
return cast_string % val
116+
117+
return null
118+
119+
120+
# TODO: replace with max heap
121+
class PriorityQueue:
122+
var data: Array = []
123+
124+
func _init():
125+
data = []
126+
127+
func push(element, priority):
128+
data.append([element, priority])
129+
_sort()
130+
131+
func _sort():
132+
data.sort_custom(func(a, b): a[1] < b[1])
133+
134+
func pop():
135+
if data.size() > 0:
136+
return data.pop_front()[0]
137+
return null
138+
139+
func peek():
140+
if data.size() > 0:
141+
return data[0][0]
142+
return null
143+
144+
func is_empty():
145+
return data.size() == 0
146+
147+
func update_priority(element, priority):
148+
var found_pair = null
149+
for pair in data:
150+
if pair[0] == element:
151+
found_pair = pair
152+
break
153+
154+
if found_pair:
155+
found_pair[1] = priority
156+
_sort()

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ func get_snapped_block() -> Block:
5252
func get_string() -> String:
5353
var snapped_block: Block = get_snapped_block()
5454
if snapped_block:
55-
return snapped_block.get_parameter_string()
55+
var generated_string = snapped_block.get_parameter_string()
56+
return Types.cast(generated_string, snapped_block.block_type, block_type)
5657

5758
var text: String = get_plain_text()
5859

0 commit comments

Comments
 (0)