@@ -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 ()
0 commit comments