1 /*************************************************************************/
2 /*  visual_script.cpp                                                    */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 
31 #include "visual_script.h"
32 
33 #include "core/core_string_names.h"
34 #include "core/os/os.h"
35 #include "core/project_settings.h"
36 #include "scene/main/node.h"
37 #include "visual_script_nodes.h"
38 
39 //used by editor, this is not really saved
set_breakpoint(bool p_breakpoint)40 void VisualScriptNode::set_breakpoint(bool p_breakpoint) {
41 	breakpoint = p_breakpoint;
42 }
43 
is_breakpoint() const44 bool VisualScriptNode::is_breakpoint() const {
45 
46 	return breakpoint;
47 }
48 
ports_changed_notify()49 void VisualScriptNode::ports_changed_notify() {
50 	emit_signal("ports_changed");
51 }
52 
set_default_input_value(int p_port,const Variant & p_value)53 void VisualScriptNode::set_default_input_value(int p_port, const Variant &p_value) {
54 
55 	ERR_FAIL_INDEX(p_port, default_input_values.size());
56 
57 	default_input_values[p_port] = p_value;
58 
59 #ifdef TOOLS_ENABLED
60 	for (Set<VisualScript *>::Element *E = scripts_used.front(); E; E = E->next()) {
61 		E->get()->set_edited(true);
62 	}
63 #endif
64 }
65 
get_default_input_value(int p_port) const66 Variant VisualScriptNode::get_default_input_value(int p_port) const {
67 
68 	ERR_FAIL_INDEX_V(p_port, default_input_values.size(), Variant());
69 	return default_input_values[p_port];
70 }
71 
_set_default_input_values(Array p_values)72 void VisualScriptNode::_set_default_input_values(Array p_values) {
73 
74 	default_input_values = p_values;
75 }
76 
validate_input_default_values()77 void VisualScriptNode::validate_input_default_values() {
78 	default_input_values.resize(MAX(default_input_values.size(), get_input_value_port_count())); //let it grow as big as possible, we don't want to lose values on resize
79 
80 	//actually validate on save
81 	for (int i = 0; i < get_input_value_port_count(); i++) {
82 
83 		Variant::Type expected = get_input_value_port_info(i).type;
84 
85 		if (expected == Variant::NIL || expected == default_input_values[i].get_type()) {
86 			continue;
87 		} else {
88 			//not the same, reconvert
89 			Variant::CallError ce;
90 			Variant existing = default_input_values[i];
91 			const Variant *existingp = &existing;
92 			default_input_values[i] = Variant::construct(expected, &existingp, 1, ce, false);
93 			if (ce.error != Variant::CallError::CALL_OK) {
94 				//could not convert? force..
95 				default_input_values[i] = Variant::construct(expected, NULL, 0, ce, false);
96 			}
97 		}
98 	}
99 }
100 
_get_default_input_values() const101 Array VisualScriptNode::_get_default_input_values() const {
102 
103 	//validate on save, since on load there is little info about this
104 	Array values = default_input_values;
105 	values.resize(get_input_value_port_count());
106 
107 	return values;
108 }
109 
get_text() const110 String VisualScriptNode::get_text() const {
111 	return "";
112 }
113 
_bind_methods()114 void VisualScriptNode::_bind_methods() {
115 
116 	ClassDB::bind_method(D_METHOD("get_visual_script"), &VisualScriptNode::get_visual_script);
117 	ClassDB::bind_method(D_METHOD("set_default_input_value", "port_idx", "value"), &VisualScriptNode::set_default_input_value);
118 	ClassDB::bind_method(D_METHOD("get_default_input_value", "port_idx"), &VisualScriptNode::get_default_input_value);
119 	ClassDB::bind_method(D_METHOD("ports_changed_notify"), &VisualScriptNode::ports_changed_notify);
120 	ClassDB::bind_method(D_METHOD("_set_default_input_values", "values"), &VisualScriptNode::_set_default_input_values);
121 	ClassDB::bind_method(D_METHOD("_get_default_input_values"), &VisualScriptNode::_get_default_input_values);
122 
123 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_default_input_values", "_get_default_input_values");
124 	ADD_SIGNAL(MethodInfo("ports_changed"));
125 }
126 
guess_output_type(TypeGuess * p_inputs,int p_output) const127 VisualScriptNode::TypeGuess VisualScriptNode::guess_output_type(TypeGuess *p_inputs, int p_output) const {
128 
129 	PropertyInfo pinfo = get_output_value_port_info(p_output);
130 
131 	TypeGuess tg;
132 
133 	tg.type = pinfo.type;
134 	if (pinfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
135 		tg.gdclass = pinfo.hint_string;
136 	}
137 
138 	return tg;
139 }
140 
get_visual_script() const141 Ref<VisualScript> VisualScriptNode::get_visual_script() const {
142 
143 	if (scripts_used.size())
144 		return Ref<VisualScript>(scripts_used.front()->get());
145 
146 	return Ref<VisualScript>();
147 }
148 
VisualScriptNode()149 VisualScriptNode::VisualScriptNode() {
150 	breakpoint = false;
151 }
152 
153 ////////////////
154 
155 /////////////////////
156 
VisualScriptNodeInstance()157 VisualScriptNodeInstance::VisualScriptNodeInstance() {
158 
159 	sequence_outputs = NULL;
160 	input_ports = NULL;
161 }
162 
~VisualScriptNodeInstance()163 VisualScriptNodeInstance::~VisualScriptNodeInstance() {
164 
165 	if (sequence_outputs) {
166 		memdelete_arr(sequence_outputs);
167 	}
168 
169 	if (input_ports) {
170 		memdelete_arr(input_ports);
171 	}
172 
173 	if (output_ports) {
174 		memdelete_arr(output_ports);
175 	}
176 }
177 
add_function(const StringName & p_name)178 void VisualScript::add_function(const StringName &p_name) {
179 
180 	ERR_FAIL_COND(instances.size());
181 	ERR_FAIL_COND(!String(p_name).is_valid_identifier());
182 	ERR_FAIL_COND(functions.has(p_name));
183 
184 	functions[p_name] = Function();
185 	functions[p_name].scroll = Vector2(-50, -100);
186 }
187 
has_function(const StringName & p_name) const188 bool VisualScript::has_function(const StringName &p_name) const {
189 
190 	return functions.has(p_name);
191 }
remove_function(const StringName & p_name)192 void VisualScript::remove_function(const StringName &p_name) {
193 
194 	ERR_FAIL_COND(instances.size());
195 	ERR_FAIL_COND(!functions.has(p_name));
196 
197 	for (Map<int, Function::NodeData>::Element *E = functions[p_name].nodes.front(); E; E = E->next()) {
198 
199 		E->get().node->disconnect("ports_changed", this, "_node_ports_changed");
200 		E->get().node->scripts_used.erase(this);
201 	}
202 
203 	functions.erase(p_name);
204 }
205 
rename_function(const StringName & p_name,const StringName & p_new_name)206 void VisualScript::rename_function(const StringName &p_name, const StringName &p_new_name) {
207 
208 	ERR_FAIL_COND(instances.size());
209 	ERR_FAIL_COND(!functions.has(p_name));
210 	if (p_new_name == p_name)
211 		return;
212 
213 	ERR_FAIL_COND(!String(p_new_name).is_valid_identifier());
214 
215 	ERR_FAIL_COND(functions.has(p_new_name));
216 	ERR_FAIL_COND(variables.has(p_new_name));
217 	ERR_FAIL_COND(custom_signals.has(p_new_name));
218 
219 	functions[p_new_name] = functions[p_name];
220 	functions.erase(p_name);
221 }
222 
set_function_scroll(const StringName & p_name,const Vector2 & p_scroll)223 void VisualScript::set_function_scroll(const StringName &p_name, const Vector2 &p_scroll) {
224 
225 	ERR_FAIL_COND(!functions.has(p_name));
226 	functions[p_name].scroll = p_scroll;
227 }
228 
get_function_scroll(const StringName & p_name) const229 Vector2 VisualScript::get_function_scroll(const StringName &p_name) const {
230 
231 	ERR_FAIL_COND_V(!functions.has(p_name), Vector2());
232 	return functions[p_name].scroll;
233 }
234 
get_function_list(List<StringName> * r_functions) const235 void VisualScript::get_function_list(List<StringName> *r_functions) const {
236 
237 	for (const Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) {
238 		r_functions->push_back(E->key());
239 	}
240 
241 	r_functions->sort_custom<StringName::AlphCompare>();
242 }
243 
get_function_node_id(const StringName & p_name) const244 int VisualScript::get_function_node_id(const StringName &p_name) const {
245 
246 	ERR_FAIL_COND_V(!functions.has(p_name), -1);
247 
248 	return functions[p_name].function_id;
249 }
250 
_node_ports_changed(int p_id)251 void VisualScript::_node_ports_changed(int p_id) {
252 
253 	StringName function;
254 
255 	for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) {
256 
257 		if (E->get().nodes.has(p_id)) {
258 			function = E->key();
259 			break;
260 		}
261 	}
262 
263 	ERR_FAIL_COND(function == StringName());
264 
265 	Function &func = functions[function];
266 	Ref<VisualScriptNode> vsn = func.nodes[p_id].node;
267 
268 	vsn->validate_input_default_values();
269 
270 	//must revalidate all the functions
271 
272 	{
273 		List<SequenceConnection> to_remove;
274 
275 		for (Set<SequenceConnection>::Element *E = func.sequence_connections.front(); E; E = E->next()) {
276 			if (E->get().from_node == p_id && E->get().from_output >= vsn->get_output_sequence_port_count()) {
277 
278 				to_remove.push_back(E->get());
279 			}
280 			if (E->get().to_node == p_id && !vsn->has_input_sequence_port()) {
281 
282 				to_remove.push_back(E->get());
283 			}
284 		}
285 
286 		while (to_remove.size()) {
287 			func.sequence_connections.erase(to_remove.front()->get());
288 			to_remove.pop_front();
289 		}
290 	}
291 
292 	{
293 
294 		List<DataConnection> to_remove;
295 
296 		for (Set<DataConnection>::Element *E = func.data_connections.front(); E; E = E->next()) {
297 			if (E->get().from_node == p_id && E->get().from_port >= vsn->get_output_value_port_count()) {
298 				to_remove.push_back(E->get());
299 			}
300 			if (E->get().to_node == p_id && E->get().to_port >= vsn->get_input_value_port_count()) {
301 				to_remove.push_back(E->get());
302 			}
303 		}
304 
305 		while (to_remove.size()) {
306 			func.data_connections.erase(to_remove.front()->get());
307 			to_remove.pop_front();
308 		}
309 	}
310 
311 #ifdef TOOLS_ENABLED
312 	set_edited(true); //something changed, let's set as edited
313 	emit_signal("node_ports_changed", function, p_id);
314 #endif
315 }
316 
add_node(const StringName & p_func,int p_id,const Ref<VisualScriptNode> & p_node,const Point2 & p_pos)317 void VisualScript::add_node(const StringName &p_func, int p_id, const Ref<VisualScriptNode> &p_node, const Point2 &p_pos) {
318 
319 	ERR_FAIL_COND(instances.size());
320 	ERR_FAIL_COND(!functions.has(p_func));
321 
322 	for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) {
323 
324 		ERR_FAIL_COND(E->get().nodes.has(p_id)); //id can exist only one in script, even for different functions
325 	}
326 
327 	Function &func = functions[p_func];
328 
329 	if (Object::cast_to<VisualScriptFunction>(*p_node)) {
330 		//the function indeed
331 		ERR_FAIL_COND_MSG(func.function_id >= 0, "A function node has already been set here.");
332 
333 		func.function_id = p_id;
334 	}
335 
336 	Function::NodeData nd;
337 	nd.node = p_node;
338 	nd.pos = p_pos;
339 
340 	Ref<VisualScriptNode> vsn = p_node;
341 	vsn->connect("ports_changed", this, "_node_ports_changed", varray(p_id));
342 	vsn->scripts_used.insert(this);
343 	vsn->validate_input_default_values(); // Validate when fully loaded
344 
345 	func.nodes[p_id] = nd;
346 }
347 
remove_node(const StringName & p_func,int p_id)348 void VisualScript::remove_node(const StringName &p_func, int p_id) {
349 
350 	ERR_FAIL_COND(instances.size());
351 	ERR_FAIL_COND(!functions.has(p_func));
352 	Function &func = functions[p_func];
353 
354 	ERR_FAIL_COND(!func.nodes.has(p_id));
355 	{
356 		List<SequenceConnection> to_remove;
357 
358 		for (Set<SequenceConnection>::Element *E = func.sequence_connections.front(); E; E = E->next()) {
359 			if (E->get().from_node == p_id || E->get().to_node == p_id) {
360 				to_remove.push_back(E->get());
361 			}
362 		}
363 
364 		while (to_remove.size()) {
365 			func.sequence_connections.erase(to_remove.front()->get());
366 			to_remove.pop_front();
367 		}
368 	}
369 
370 	{
371 
372 		List<DataConnection> to_remove;
373 
374 		for (Set<DataConnection>::Element *E = func.data_connections.front(); E; E = E->next()) {
375 			if (E->get().from_node == p_id || E->get().to_node == p_id) {
376 				to_remove.push_back(E->get());
377 			}
378 		}
379 
380 		while (to_remove.size()) {
381 			func.data_connections.erase(to_remove.front()->get());
382 			to_remove.pop_front();
383 		}
384 	}
385 
386 	if (Object::cast_to<VisualScriptFunction>(func.nodes[p_id].node.ptr())) {
387 		func.function_id = -1; //revert to invalid
388 	}
389 
390 	func.nodes[p_id].node->disconnect("ports_changed", this, "_node_ports_changed");
391 	func.nodes[p_id].node->scripts_used.erase(this);
392 
393 	func.nodes.erase(p_id);
394 }
395 
has_node(const StringName & p_func,int p_id) const396 bool VisualScript::has_node(const StringName &p_func, int p_id) const {
397 
398 	ERR_FAIL_COND_V(!functions.has(p_func), false);
399 	const Function &func = functions[p_func];
400 
401 	return func.nodes.has(p_id);
402 }
403 
get_node(const StringName & p_func,int p_id) const404 Ref<VisualScriptNode> VisualScript::get_node(const StringName &p_func, int p_id) const {
405 
406 	ERR_FAIL_COND_V(!functions.has(p_func), Ref<VisualScriptNode>());
407 	const Function &func = functions[p_func];
408 
409 	ERR_FAIL_COND_V(!func.nodes.has(p_id), Ref<VisualScriptNode>());
410 
411 	return func.nodes[p_id].node;
412 }
413 
set_node_position(const StringName & p_func,int p_id,const Point2 & p_pos)414 void VisualScript::set_node_position(const StringName &p_func, int p_id, const Point2 &p_pos) {
415 
416 	ERR_FAIL_COND(instances.size());
417 	ERR_FAIL_COND(!functions.has(p_func));
418 	Function &func = functions[p_func];
419 
420 	ERR_FAIL_COND(!func.nodes.has(p_id));
421 	func.nodes[p_id].pos = p_pos;
422 }
423 
get_node_position(const StringName & p_func,int p_id) const424 Point2 VisualScript::get_node_position(const StringName &p_func, int p_id) const {
425 
426 	ERR_FAIL_COND_V(!functions.has(p_func), Point2());
427 	const Function &func = functions[p_func];
428 
429 	ERR_FAIL_COND_V(!func.nodes.has(p_id), Point2());
430 	return func.nodes[p_id].pos;
431 }
432 
get_node_list(const StringName & p_func,List<int> * r_nodes) const433 void VisualScript::get_node_list(const StringName &p_func, List<int> *r_nodes) const {
434 
435 	ERR_FAIL_COND(!functions.has(p_func));
436 	const Function &func = functions[p_func];
437 
438 	for (const Map<int, Function::NodeData>::Element *E = func.nodes.front(); E; E = E->next()) {
439 		r_nodes->push_back(E->key());
440 	}
441 }
442 
sequence_connect(const StringName & p_func,int p_from_node,int p_from_output,int p_to_node)443 void VisualScript::sequence_connect(const StringName &p_func, int p_from_node, int p_from_output, int p_to_node) {
444 
445 	ERR_FAIL_COND(instances.size());
446 	ERR_FAIL_COND(!functions.has(p_func));
447 	Function &func = functions[p_func];
448 
449 	SequenceConnection sc;
450 	sc.from_node = p_from_node;
451 	sc.from_output = p_from_output;
452 	sc.to_node = p_to_node;
453 	ERR_FAIL_COND(func.sequence_connections.has(sc));
454 
455 	func.sequence_connections.insert(sc);
456 }
457 
sequence_disconnect(const StringName & p_func,int p_from_node,int p_from_output,int p_to_node)458 void VisualScript::sequence_disconnect(const StringName &p_func, int p_from_node, int p_from_output, int p_to_node) {
459 
460 	ERR_FAIL_COND(!functions.has(p_func));
461 	Function &func = functions[p_func];
462 
463 	SequenceConnection sc;
464 	sc.from_node = p_from_node;
465 	sc.from_output = p_from_output;
466 	sc.to_node = p_to_node;
467 	ERR_FAIL_COND(!func.sequence_connections.has(sc));
468 
469 	func.sequence_connections.erase(sc);
470 }
471 
has_sequence_connection(const StringName & p_func,int p_from_node,int p_from_output,int p_to_node) const472 bool VisualScript::has_sequence_connection(const StringName &p_func, int p_from_node, int p_from_output, int p_to_node) const {
473 
474 	ERR_FAIL_COND_V(!functions.has(p_func), false);
475 	const Function &func = functions[p_func];
476 
477 	SequenceConnection sc;
478 	sc.from_node = p_from_node;
479 	sc.from_output = p_from_output;
480 	sc.to_node = p_to_node;
481 
482 	return func.sequence_connections.has(sc);
483 }
484 
get_sequence_connection_list(const StringName & p_func,List<SequenceConnection> * r_connection) const485 void VisualScript::get_sequence_connection_list(const StringName &p_func, List<SequenceConnection> *r_connection) const {
486 
487 	ERR_FAIL_COND(!functions.has(p_func));
488 	const Function &func = functions[p_func];
489 
490 	for (const Set<SequenceConnection>::Element *E = func.sequence_connections.front(); E; E = E->next()) {
491 		r_connection->push_back(E->get());
492 	}
493 }
494 
data_connect(const StringName & p_func,int p_from_node,int p_from_port,int p_to_node,int p_to_port)495 void VisualScript::data_connect(const StringName &p_func, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
496 
497 	ERR_FAIL_COND(instances.size());
498 	ERR_FAIL_COND(!functions.has(p_func));
499 	Function &func = functions[p_func];
500 
501 	DataConnection dc;
502 	dc.from_node = p_from_node;
503 	dc.from_port = p_from_port;
504 	dc.to_node = p_to_node;
505 	dc.to_port = p_to_port;
506 
507 	ERR_FAIL_COND(func.data_connections.has(dc));
508 
509 	func.data_connections.insert(dc);
510 }
511 
data_disconnect(const StringName & p_func,int p_from_node,int p_from_port,int p_to_node,int p_to_port)512 void VisualScript::data_disconnect(const StringName &p_func, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
513 
514 	ERR_FAIL_COND(!functions.has(p_func));
515 	Function &func = functions[p_func];
516 
517 	DataConnection dc;
518 	dc.from_node = p_from_node;
519 	dc.from_port = p_from_port;
520 	dc.to_node = p_to_node;
521 	dc.to_port = p_to_port;
522 
523 	ERR_FAIL_COND(!func.data_connections.has(dc));
524 
525 	func.data_connections.erase(dc);
526 }
527 
has_data_connection(const StringName & p_func,int p_from_node,int p_from_port,int p_to_node,int p_to_port) const528 bool VisualScript::has_data_connection(const StringName &p_func, int p_from_node, int p_from_port, int p_to_node, int p_to_port) const {
529 
530 	ERR_FAIL_COND_V(!functions.has(p_func), false);
531 	const Function &func = functions[p_func];
532 
533 	DataConnection dc;
534 	dc.from_node = p_from_node;
535 	dc.from_port = p_from_port;
536 	dc.to_node = p_to_node;
537 	dc.to_port = p_to_port;
538 
539 	return func.data_connections.has(dc);
540 }
541 
is_input_value_port_connected(const StringName & p_func,int p_node,int p_port) const542 bool VisualScript::is_input_value_port_connected(const StringName &p_func, int p_node, int p_port) const {
543 
544 	ERR_FAIL_COND_V(!functions.has(p_func), false);
545 	const Function &func = functions[p_func];
546 
547 	for (const Set<DataConnection>::Element *E = func.data_connections.front(); E; E = E->next()) {
548 		if (E->get().to_node == p_node && E->get().to_port == p_port)
549 			return true;
550 	}
551 
552 	return false;
553 }
554 
get_input_value_port_connection_source(const StringName & p_func,int p_node,int p_port,int * r_node,int * r_port) const555 bool VisualScript::get_input_value_port_connection_source(const StringName &p_func, int p_node, int p_port, int *r_node, int *r_port) const {
556 
557 	ERR_FAIL_COND_V(!functions.has(p_func), false);
558 	const Function &func = functions[p_func];
559 
560 	for (const Set<DataConnection>::Element *E = func.data_connections.front(); E; E = E->next()) {
561 		if (E->get().to_node == p_node && E->get().to_port == p_port) {
562 			*r_node = E->get().from_node;
563 			*r_port = E->get().from_port;
564 			return true;
565 		}
566 	}
567 
568 	return false;
569 }
570 
get_data_connection_list(const StringName & p_func,List<DataConnection> * r_connection) const571 void VisualScript::get_data_connection_list(const StringName &p_func, List<DataConnection> *r_connection) const {
572 
573 	ERR_FAIL_COND(!functions.has(p_func));
574 	const Function &func = functions[p_func];
575 
576 	for (const Set<DataConnection>::Element *E = func.data_connections.front(); E; E = E->next()) {
577 		r_connection->push_back(E->get());
578 	}
579 }
580 
set_tool_enabled(bool p_enabled)581 void VisualScript::set_tool_enabled(bool p_enabled) {
582 	is_tool_script = p_enabled;
583 }
584 
add_variable(const StringName & p_name,const Variant & p_default_value,bool p_export)585 void VisualScript::add_variable(const StringName &p_name, const Variant &p_default_value, bool p_export) {
586 
587 	ERR_FAIL_COND(instances.size());
588 	ERR_FAIL_COND(!String(p_name).is_valid_identifier());
589 	ERR_FAIL_COND(variables.has(p_name));
590 
591 	Variable v;
592 	v.default_value = p_default_value;
593 	v.info.type = p_default_value.get_type();
594 	v.info.name = p_name;
595 	v.info.hint = PROPERTY_HINT_NONE;
596 	v._export = p_export;
597 
598 	variables[p_name] = v;
599 
600 #ifdef TOOLS_ENABLED
601 	_update_placeholders();
602 #endif
603 }
604 
has_variable(const StringName & p_name) const605 bool VisualScript::has_variable(const StringName &p_name) const {
606 
607 	return variables.has(p_name);
608 }
609 
remove_variable(const StringName & p_name)610 void VisualScript::remove_variable(const StringName &p_name) {
611 
612 	ERR_FAIL_COND(!variables.has(p_name));
613 	variables.erase(p_name);
614 
615 #ifdef TOOLS_ENABLED
616 	_update_placeholders();
617 #endif
618 }
619 
set_variable_default_value(const StringName & p_name,const Variant & p_value)620 void VisualScript::set_variable_default_value(const StringName &p_name, const Variant &p_value) {
621 
622 	ERR_FAIL_COND(!variables.has(p_name));
623 
624 	variables[p_name].default_value = p_value;
625 
626 #ifdef TOOLS_ENABLED
627 	_update_placeholders();
628 #endif
629 }
get_variable_default_value(const StringName & p_name) const630 Variant VisualScript::get_variable_default_value(const StringName &p_name) const {
631 
632 	ERR_FAIL_COND_V(!variables.has(p_name), Variant());
633 	return variables[p_name].default_value;
634 }
set_variable_info(const StringName & p_name,const PropertyInfo & p_info)635 void VisualScript::set_variable_info(const StringName &p_name, const PropertyInfo &p_info) {
636 
637 	ERR_FAIL_COND(instances.size());
638 	ERR_FAIL_COND(!variables.has(p_name));
639 	variables[p_name].info = p_info;
640 	variables[p_name].info.name = p_name;
641 
642 #ifdef TOOLS_ENABLED
643 	_update_placeholders();
644 #endif
645 }
get_variable_info(const StringName & p_name) const646 PropertyInfo VisualScript::get_variable_info(const StringName &p_name) const {
647 
648 	ERR_FAIL_COND_V(!variables.has(p_name), PropertyInfo());
649 	return variables[p_name].info;
650 }
651 
set_variable_export(const StringName & p_name,bool p_export)652 void VisualScript::set_variable_export(const StringName &p_name, bool p_export) {
653 
654 	ERR_FAIL_COND(!variables.has(p_name));
655 
656 	variables[p_name]._export = p_export;
657 #ifdef TOOLS_ENABLED
658 	_update_placeholders();
659 #endif
660 }
661 
get_variable_export(const StringName & p_name) const662 bool VisualScript::get_variable_export(const StringName &p_name) const {
663 
664 	ERR_FAIL_COND_V(!variables.has(p_name), false);
665 	return variables[p_name]._export;
666 }
667 
_set_variable_info(const StringName & p_name,const Dictionary & p_info)668 void VisualScript::_set_variable_info(const StringName &p_name, const Dictionary &p_info) {
669 
670 	PropertyInfo pinfo;
671 	if (p_info.has("type"))
672 		pinfo.type = Variant::Type(int(p_info["type"]));
673 	if (p_info.has("name"))
674 		pinfo.name = p_info["name"];
675 	if (p_info.has("hint"))
676 		pinfo.hint = PropertyHint(int(p_info["hint"]));
677 	if (p_info.has("hint_string"))
678 		pinfo.hint_string = p_info["hint_string"];
679 	if (p_info.has("usage"))
680 		pinfo.usage = p_info["usage"];
681 
682 	set_variable_info(p_name, pinfo);
683 }
684 
_get_variable_info(const StringName & p_name) const685 Dictionary VisualScript::_get_variable_info(const StringName &p_name) const {
686 
687 	PropertyInfo pinfo = get_variable_info(p_name);
688 	Dictionary d;
689 	d["type"] = pinfo.type;
690 	d["name"] = pinfo.name;
691 	d["hint"] = pinfo.hint;
692 	d["hint_string"] = pinfo.hint_string;
693 	d["usage"] = pinfo.usage;
694 
695 	return d;
696 }
697 
get_variable_list(List<StringName> * r_variables) const698 void VisualScript::get_variable_list(List<StringName> *r_variables) const {
699 
700 	for (Map<StringName, Variable>::Element *E = variables.front(); E; E = E->next()) {
701 		r_variables->push_back(E->key());
702 	}
703 
704 	r_variables->sort_custom<StringName::AlphCompare>();
705 }
706 
set_instance_base_type(const StringName & p_type)707 void VisualScript::set_instance_base_type(const StringName &p_type) {
708 
709 	ERR_FAIL_COND(instances.size());
710 	base_type = p_type;
711 }
712 
rename_variable(const StringName & p_name,const StringName & p_new_name)713 void VisualScript::rename_variable(const StringName &p_name, const StringName &p_new_name) {
714 
715 	ERR_FAIL_COND(instances.size());
716 	ERR_FAIL_COND(!variables.has(p_name));
717 	if (p_new_name == p_name)
718 		return;
719 
720 	ERR_FAIL_COND(!String(p_new_name).is_valid_identifier());
721 
722 	ERR_FAIL_COND(functions.has(p_new_name));
723 	ERR_FAIL_COND(variables.has(p_new_name));
724 	ERR_FAIL_COND(custom_signals.has(p_new_name));
725 
726 	variables[p_new_name] = variables[p_name];
727 	variables.erase(p_name);
728 }
729 
add_custom_signal(const StringName & p_name)730 void VisualScript::add_custom_signal(const StringName &p_name) {
731 
732 	ERR_FAIL_COND(instances.size());
733 	ERR_FAIL_COND(!String(p_name).is_valid_identifier());
734 	ERR_FAIL_COND(custom_signals.has(p_name));
735 
736 	custom_signals[p_name] = Vector<Argument>();
737 }
738 
has_custom_signal(const StringName & p_name) const739 bool VisualScript::has_custom_signal(const StringName &p_name) const {
740 
741 	return custom_signals.has(p_name);
742 }
custom_signal_add_argument(const StringName & p_func,Variant::Type p_type,const String & p_name,int p_index)743 void VisualScript::custom_signal_add_argument(const StringName &p_func, Variant::Type p_type, const String &p_name, int p_index) {
744 
745 	ERR_FAIL_COND(instances.size());
746 	ERR_FAIL_COND(!custom_signals.has(p_func));
747 	Argument arg;
748 	arg.type = p_type;
749 	arg.name = p_name;
750 	if (p_index < 0)
751 		custom_signals[p_func].push_back(arg);
752 	else
753 		custom_signals[p_func].insert(0, arg);
754 }
custom_signal_set_argument_type(const StringName & p_func,int p_argidx,Variant::Type p_type)755 void VisualScript::custom_signal_set_argument_type(const StringName &p_func, int p_argidx, Variant::Type p_type) {
756 
757 	ERR_FAIL_COND(instances.size());
758 	ERR_FAIL_COND(!custom_signals.has(p_func));
759 	ERR_FAIL_INDEX(p_argidx, custom_signals[p_func].size());
760 	custom_signals[p_func].write[p_argidx].type = p_type;
761 }
custom_signal_get_argument_type(const StringName & p_func,int p_argidx) const762 Variant::Type VisualScript::custom_signal_get_argument_type(const StringName &p_func, int p_argidx) const {
763 
764 	ERR_FAIL_COND_V(!custom_signals.has(p_func), Variant::NIL);
765 	ERR_FAIL_INDEX_V(p_argidx, custom_signals[p_func].size(), Variant::NIL);
766 	return custom_signals[p_func][p_argidx].type;
767 }
custom_signal_set_argument_name(const StringName & p_func,int p_argidx,const String & p_name)768 void VisualScript::custom_signal_set_argument_name(const StringName &p_func, int p_argidx, const String &p_name) {
769 	ERR_FAIL_COND(instances.size());
770 	ERR_FAIL_COND(!custom_signals.has(p_func));
771 	ERR_FAIL_INDEX(p_argidx, custom_signals[p_func].size());
772 	custom_signals[p_func].write[p_argidx].name = p_name;
773 }
custom_signal_get_argument_name(const StringName & p_func,int p_argidx) const774 String VisualScript::custom_signal_get_argument_name(const StringName &p_func, int p_argidx) const {
775 
776 	ERR_FAIL_COND_V(!custom_signals.has(p_func), String());
777 	ERR_FAIL_INDEX_V(p_argidx, custom_signals[p_func].size(), String());
778 	return custom_signals[p_func][p_argidx].name;
779 }
custom_signal_remove_argument(const StringName & p_func,int p_argidx)780 void VisualScript::custom_signal_remove_argument(const StringName &p_func, int p_argidx) {
781 
782 	ERR_FAIL_COND(instances.size());
783 	ERR_FAIL_COND(!custom_signals.has(p_func));
784 	ERR_FAIL_INDEX(p_argidx, custom_signals[p_func].size());
785 	custom_signals[p_func].remove(p_argidx);
786 }
787 
custom_signal_get_argument_count(const StringName & p_func) const788 int VisualScript::custom_signal_get_argument_count(const StringName &p_func) const {
789 
790 	ERR_FAIL_COND_V(!custom_signals.has(p_func), 0);
791 	return custom_signals[p_func].size();
792 }
custom_signal_swap_argument(const StringName & p_func,int p_argidx,int p_with_argidx)793 void VisualScript::custom_signal_swap_argument(const StringName &p_func, int p_argidx, int p_with_argidx) {
794 
795 	ERR_FAIL_COND(instances.size());
796 	ERR_FAIL_COND(!custom_signals.has(p_func));
797 	ERR_FAIL_INDEX(p_argidx, custom_signals[p_func].size());
798 	ERR_FAIL_INDEX(p_with_argidx, custom_signals[p_func].size());
799 
800 	SWAP(custom_signals[p_func].write[p_argidx], custom_signals[p_func].write[p_with_argidx]);
801 }
remove_custom_signal(const StringName & p_name)802 void VisualScript::remove_custom_signal(const StringName &p_name) {
803 
804 	ERR_FAIL_COND(instances.size());
805 	ERR_FAIL_COND(!custom_signals.has(p_name));
806 	custom_signals.erase(p_name);
807 }
808 
rename_custom_signal(const StringName & p_name,const StringName & p_new_name)809 void VisualScript::rename_custom_signal(const StringName &p_name, const StringName &p_new_name) {
810 
811 	ERR_FAIL_COND(instances.size());
812 	ERR_FAIL_COND(!custom_signals.has(p_name));
813 	if (p_new_name == p_name)
814 		return;
815 
816 	ERR_FAIL_COND(!String(p_new_name).is_valid_identifier());
817 
818 	ERR_FAIL_COND(functions.has(p_new_name));
819 	ERR_FAIL_COND(variables.has(p_new_name));
820 	ERR_FAIL_COND(custom_signals.has(p_new_name));
821 
822 	custom_signals[p_new_name] = custom_signals[p_name];
823 	custom_signals.erase(p_name);
824 }
825 
get_custom_signal_list(List<StringName> * r_custom_signals) const826 void VisualScript::get_custom_signal_list(List<StringName> *r_custom_signals) const {
827 
828 	for (const Map<StringName, Vector<Argument> >::Element *E = custom_signals.front(); E; E = E->next()) {
829 		r_custom_signals->push_back(E->key());
830 	}
831 
832 	r_custom_signals->sort_custom<StringName::AlphCompare>();
833 }
834 
get_available_id() const835 int VisualScript::get_available_id() const {
836 
837 	int max_id = 0;
838 	for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) {
839 		if (E->get().nodes.empty())
840 			continue;
841 
842 		int last_id = E->get().nodes.back()->key();
843 		max_id = MAX(max_id, last_id + 1);
844 	}
845 
846 	return max_id;
847 }
848 
849 /////////////////////////////////
850 
can_instance() const851 bool VisualScript::can_instance() const {
852 
853 	return true; //ScriptServer::is_scripting_enabled();
854 }
855 
get_instance_base_type() const856 StringName VisualScript::get_instance_base_type() const {
857 
858 	return base_type;
859 }
860 
get_base_script() const861 Ref<Script> VisualScript::get_base_script() const {
862 	return Ref<Script>(); // no inheritance in visual script
863 }
864 
865 #ifdef TOOLS_ENABLED
_placeholder_erased(PlaceHolderScriptInstance * p_placeholder)866 void VisualScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) {
867 
868 	placeholders.erase(p_placeholder);
869 }
870 
_update_placeholders()871 void VisualScript::_update_placeholders() {
872 
873 	if (placeholders.size() == 0)
874 		return; //no bother if no placeholders
875 	List<PropertyInfo> pinfo;
876 	Map<StringName, Variant> values;
877 
878 	for (Map<StringName, Variable>::Element *E = variables.front(); E; E = E->next()) {
879 
880 		if (!E->get()._export)
881 			continue;
882 
883 		PropertyInfo p = E->get().info;
884 		p.name = String(E->key());
885 		pinfo.push_back(p);
886 		values[p.name] = E->get().default_value;
887 	}
888 
889 	for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
890 
891 		E->get()->update(pinfo, values);
892 	}
893 }
894 
895 #endif
896 
instance_create(Object * p_this)897 ScriptInstance *VisualScript::instance_create(Object *p_this) {
898 
899 #ifdef TOOLS_ENABLED
900 
901 	if (!ScriptServer::is_scripting_enabled() && !is_tool_script) {
902 
903 		PlaceHolderScriptInstance *sins = memnew(PlaceHolderScriptInstance(VisualScriptLanguage::singleton, Ref<Script>((Script *)this), p_this));
904 		placeholders.insert(sins);
905 
906 		List<PropertyInfo> pinfo;
907 		Map<StringName, Variant> values;
908 
909 		for (Map<StringName, Variable>::Element *E = variables.front(); E; E = E->next()) {
910 
911 			if (!E->get()._export)
912 				continue;
913 
914 			PropertyInfo p = E->get().info;
915 			p.name = String(E->key());
916 			pinfo.push_back(p);
917 			values[p.name] = E->get().default_value;
918 		}
919 
920 		sins->update(pinfo, values);
921 
922 		return sins;
923 	}
924 #endif
925 
926 	VisualScriptInstance *instance = memnew(VisualScriptInstance);
927 	instance->create(Ref<VisualScript>(this), p_this);
928 
929 	if (VisualScriptLanguage::singleton->lock)
930 		VisualScriptLanguage::singleton->lock->lock();
931 
932 	instances[p_this] = instance;
933 
934 	if (VisualScriptLanguage::singleton->lock)
935 		VisualScriptLanguage::singleton->lock->unlock();
936 
937 	return instance;
938 }
939 
instance_has(const Object * p_this) const940 bool VisualScript::instance_has(const Object *p_this) const {
941 
942 	return instances.has((Object *)p_this);
943 }
944 
has_source_code() const945 bool VisualScript::has_source_code() const {
946 
947 	return false;
948 }
949 
get_source_code() const950 String VisualScript::get_source_code() const {
951 
952 	return String();
953 }
954 
set_source_code(const String & p_code)955 void VisualScript::set_source_code(const String &p_code) {
956 }
957 
reload(bool p_keep_state)958 Error VisualScript::reload(bool p_keep_state) {
959 
960 	return OK;
961 }
962 
is_tool() const963 bool VisualScript::is_tool() const {
964 
965 	return is_tool_script;
966 }
967 
is_valid() const968 bool VisualScript::is_valid() const {
969 	return true; //always valid
970 }
971 
get_language() const972 ScriptLanguage *VisualScript::get_language() const {
973 
974 	return VisualScriptLanguage::singleton;
975 }
976 
has_script_signal(const StringName & p_signal) const977 bool VisualScript::has_script_signal(const StringName &p_signal) const {
978 
979 	return custom_signals.has(p_signal);
980 }
981 
get_script_signal_list(List<MethodInfo> * r_signals) const982 void VisualScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
983 
984 	for (const Map<StringName, Vector<Argument> >::Element *E = custom_signals.front(); E; E = E->next()) {
985 
986 		MethodInfo mi;
987 		mi.name = E->key();
988 		for (int i = 0; i < E->get().size(); i++) {
989 			PropertyInfo arg;
990 			arg.type = E->get()[i].type;
991 			arg.name = E->get()[i].name;
992 			mi.arguments.push_back(arg);
993 		}
994 
995 		r_signals->push_back(mi);
996 	}
997 }
998 
get_property_default_value(const StringName & p_property,Variant & r_value) const999 bool VisualScript::get_property_default_value(const StringName &p_property, Variant &r_value) const {
1000 
1001 	if (!variables.has(p_property))
1002 		return false;
1003 
1004 	r_value = variables[p_property].default_value;
1005 	return true;
1006 }
get_script_method_list(List<MethodInfo> * p_list) const1007 void VisualScript::get_script_method_list(List<MethodInfo> *p_list) const {
1008 
1009 	for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) {
1010 
1011 		MethodInfo mi;
1012 		mi.name = E->key();
1013 		if (E->get().function_id >= 0) {
1014 
1015 			Ref<VisualScriptFunction> func = E->get().nodes[E->get().function_id].node;
1016 			if (func.is_valid()) {
1017 				for (int i = 0; i < func->get_argument_count(); i++) {
1018 					PropertyInfo arg;
1019 					arg.name = func->get_argument_name(i);
1020 					arg.type = func->get_argument_type(i);
1021 					mi.arguments.push_back(arg);
1022 				}
1023 
1024 				p_list->push_back(mi);
1025 			}
1026 		}
1027 	}
1028 }
1029 
has_method(const StringName & p_method) const1030 bool VisualScript::has_method(const StringName &p_method) const {
1031 
1032 	return functions.has(p_method);
1033 }
get_method_info(const StringName & p_method) const1034 MethodInfo VisualScript::get_method_info(const StringName &p_method) const {
1035 
1036 	const Map<StringName, Function>::Element *E = functions.find(p_method);
1037 	if (!E)
1038 		return MethodInfo();
1039 
1040 	MethodInfo mi;
1041 	mi.name = E->key();
1042 	if (E->get().function_id >= 0) {
1043 
1044 		Ref<VisualScriptFunction> func = E->get().nodes[E->get().function_id].node;
1045 		if (func.is_valid()) {
1046 
1047 			for (int i = 0; i < func->get_argument_count(); i++) {
1048 				PropertyInfo arg;
1049 				arg.name = func->get_argument_name(i);
1050 				arg.type = func->get_argument_type(i);
1051 				mi.arguments.push_back(arg);
1052 			}
1053 
1054 			if (!func->is_sequenced()) {
1055 				mi.flags |= METHOD_FLAG_CONST;
1056 			}
1057 		}
1058 	}
1059 
1060 	return mi;
1061 }
1062 
get_script_property_list(List<PropertyInfo> * p_list) const1063 void VisualScript::get_script_property_list(List<PropertyInfo> *p_list) const {
1064 
1065 	List<StringName> vars;
1066 	get_variable_list(&vars);
1067 
1068 	for (List<StringName>::Element *E = vars.front(); E; E = E->next()) {
1069 		//if (!variables[E->get()]._export)
1070 		//	continue;
1071 		PropertyInfo pi = variables[E->get()].info;
1072 		pi.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
1073 		p_list->push_back(pi);
1074 	}
1075 }
1076 
get_member_line(const StringName & p_member) const1077 int VisualScript::get_member_line(const StringName &p_member) const {
1078 #ifdef TOOLS_ENABLED
1079 	if (has_function(p_member)) {
1080 		for (Map<int, Function::NodeData>::Element *E = functions[p_member].nodes.front(); E; E = E->next()) {
1081 			if (Object::cast_to<VisualScriptFunction>(E->get().node.ptr()))
1082 				return E->key();
1083 		}
1084 	}
1085 #endif
1086 	return -1;
1087 }
1088 
1089 #ifdef TOOLS_ENABLED
are_subnodes_edited() const1090 bool VisualScript::are_subnodes_edited() const {
1091 
1092 	for (const Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) {
1093 
1094 		for (const Map<int, Function::NodeData>::Element *F = E->get().nodes.front(); F; F = F->next()) {
1095 			if (F->get().node->is_edited()) {
1096 				return true;
1097 			}
1098 		}
1099 	}
1100 
1101 	return false;
1102 }
1103 #endif
1104 
_set_data(const Dictionary & p_data)1105 void VisualScript::_set_data(const Dictionary &p_data) {
1106 
1107 	Dictionary d = p_data;
1108 	if (d.has("base_type"))
1109 		base_type = d["base_type"];
1110 
1111 	variables.clear();
1112 	Array vars = d["variables"];
1113 	for (int i = 0; i < vars.size(); i++) {
1114 
1115 		Dictionary v = vars[i];
1116 		StringName name = v["name"];
1117 		add_variable(name);
1118 		_set_variable_info(name, v);
1119 		set_variable_default_value(name, v["default_value"]);
1120 		set_variable_export(name, v.has("export") && bool(v["export"]));
1121 	}
1122 
1123 	custom_signals.clear();
1124 	Array sigs = d["signals"];
1125 	for (int i = 0; i < sigs.size(); i++) {
1126 
1127 		Dictionary cs = sigs[i];
1128 		add_custom_signal(cs["name"]);
1129 
1130 		Array args = cs["arguments"];
1131 		for (int j = 0; j < args.size(); j += 2) {
1132 			custom_signal_add_argument(cs["name"], Variant::Type(int(args[j + 1])), args[j]);
1133 		}
1134 	}
1135 
1136 	Array funcs = d["functions"];
1137 	functions.clear();
1138 
1139 	Vector2 last_pos = Vector2(-100 * funcs.size(), -100 * funcs.size()); // this is the center of the last fn box
1140 	Vector2 last_size = Vector2(0.0, 0.0);
1141 
1142 	for (int i = 0; i < funcs.size(); i++) {
1143 
1144 		Dictionary func = funcs[i];
1145 
1146 		StringName name = func["name"];
1147 		//int id=func["function_id"];
1148 		add_function(name);
1149 
1150 		set_function_scroll(name, func["scroll"]);
1151 
1152 		Array nodes = func["nodes"];
1153 
1154 		if (!d.has("vs_unify") && nodes.size() > 0) {
1155 			Vector2 top_left = nodes[1];
1156 			Vector2 bottom_right = nodes[1];
1157 
1158 			for (int j = 0; j < nodes.size(); j += 3) {
1159 				Point2 pos = nodes[j + 1];
1160 				if (pos.y > top_left.y) {
1161 					top_left.y = pos.y;
1162 				}
1163 				if (pos.y < bottom_right.y) {
1164 					bottom_right.y = pos.y;
1165 				}
1166 				if (pos.x > bottom_right.x) {
1167 					bottom_right.x = pos.x;
1168 				}
1169 				if (pos.x < top_left.x) {
1170 					top_left.x = pos.x;
1171 				}
1172 			}
1173 
1174 			Vector2 size = Vector2(bottom_right.x - top_left.x, top_left.y - bottom_right.y);
1175 
1176 			Vector2 offset = last_pos + (last_size / 2.0) + (size / 2.0); // dunno I might just keep it in one axis but diagonal feels better....
1177 
1178 			last_pos = offset;
1179 			last_size = size;
1180 
1181 			for (int j = 0; j < nodes.size(); j += 3) {
1182 				add_node(name, nodes[j], nodes[j + 2], offset + nodes[j + 1]); // also add an additional buffer if you want to
1183 			}
1184 
1185 		} else {
1186 			for (int j = 0; j < nodes.size(); j += 3) {
1187 				add_node(name, nodes[j], nodes[j + 2], nodes[j + 1]);
1188 			}
1189 		}
1190 		Array sequence_connections = func["sequence_connections"];
1191 
1192 		for (int j = 0; j < sequence_connections.size(); j += 3) {
1193 
1194 			sequence_connect(name, sequence_connections[j + 0], sequence_connections[j + 1], sequence_connections[j + 2]);
1195 		}
1196 
1197 		Array data_connections = func["data_connections"];
1198 
1199 		for (int j = 0; j < data_connections.size(); j += 4) {
1200 
1201 			data_connect(name, data_connections[j + 0], data_connections[j + 1], data_connections[j + 2], data_connections[j + 3]);
1202 		}
1203 	}
1204 
1205 	if (d.has("is_tool_script"))
1206 		is_tool_script = d["is_tool_script"];
1207 	else
1208 		is_tool_script = false;
1209 }
1210 
_get_data() const1211 Dictionary VisualScript::_get_data() const {
1212 
1213 	Dictionary d;
1214 	d["base_type"] = base_type;
1215 	Array vars;
1216 	for (const Map<StringName, Variable>::Element *E = variables.front(); E; E = E->next()) {
1217 
1218 		Dictionary var = _get_variable_info(E->key());
1219 		var["name"] = E->key(); //make sure it's the right one
1220 		var["default_value"] = E->get().default_value;
1221 		var["export"] = E->get()._export;
1222 		vars.push_back(var);
1223 	}
1224 	d["variables"] = vars;
1225 
1226 	Array sigs;
1227 	for (const Map<StringName, Vector<Argument> >::Element *E = custom_signals.front(); E; E = E->next()) {
1228 
1229 		Dictionary cs;
1230 		cs["name"] = E->key();
1231 		Array args;
1232 		for (int i = 0; i < E->get().size(); i++) {
1233 			args.push_back(E->get()[i].name);
1234 			args.push_back(E->get()[i].type);
1235 		}
1236 		cs["arguments"] = args;
1237 
1238 		sigs.push_back(cs);
1239 	}
1240 
1241 	d["signals"] = sigs;
1242 
1243 	Array funcs;
1244 
1245 	for (const Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) {
1246 
1247 		Dictionary func;
1248 		func["name"] = E->key();
1249 		func["function_id"] = E->get().function_id;
1250 		func["scroll"] = E->get().scroll;
1251 
1252 		Array nodes;
1253 
1254 		for (const Map<int, Function::NodeData>::Element *F = E->get().nodes.front(); F; F = F->next()) {
1255 
1256 			nodes.push_back(F->key());
1257 			nodes.push_back(F->get().pos);
1258 			nodes.push_back(F->get().node);
1259 		}
1260 
1261 		func["nodes"] = nodes;
1262 
1263 		Array sequence_connections;
1264 
1265 		for (const Set<SequenceConnection>::Element *F = E->get().sequence_connections.front(); F; F = F->next()) {
1266 
1267 			sequence_connections.push_back(F->get().from_node);
1268 			sequence_connections.push_back(F->get().from_output);
1269 			sequence_connections.push_back(F->get().to_node);
1270 		}
1271 
1272 		func["sequence_connections"] = sequence_connections;
1273 
1274 		Array data_connections;
1275 
1276 		for (const Set<DataConnection>::Element *F = E->get().data_connections.front(); F; F = F->next()) {
1277 
1278 			data_connections.push_back(F->get().from_node);
1279 			data_connections.push_back(F->get().from_port);
1280 			data_connections.push_back(F->get().to_node);
1281 			data_connections.push_back(F->get().to_port);
1282 		}
1283 
1284 		func["data_connections"] = data_connections;
1285 
1286 		funcs.push_back(func);
1287 	}
1288 
1289 	d["functions"] = funcs;
1290 	d["is_tool_script"] = is_tool_script;
1291 	d["vs_unify"] = true;
1292 
1293 	return d;
1294 }
1295 
_bind_methods()1296 void VisualScript::_bind_methods() {
1297 
1298 	ClassDB::bind_method(D_METHOD("_node_ports_changed"), &VisualScript::_node_ports_changed);
1299 
1300 	ClassDB::bind_method(D_METHOD("add_function", "name"), &VisualScript::add_function);
1301 	ClassDB::bind_method(D_METHOD("has_function", "name"), &VisualScript::has_function);
1302 	ClassDB::bind_method(D_METHOD("remove_function", "name"), &VisualScript::remove_function);
1303 	ClassDB::bind_method(D_METHOD("rename_function", "name", "new_name"), &VisualScript::rename_function);
1304 	ClassDB::bind_method(D_METHOD("set_function_scroll", "name", "ofs"), &VisualScript::set_function_scroll);
1305 	ClassDB::bind_method(D_METHOD("get_function_scroll", "name"), &VisualScript::get_function_scroll);
1306 
1307 	ClassDB::bind_method(D_METHOD("add_node", "func", "id", "node", "position"), &VisualScript::add_node, DEFVAL(Point2()));
1308 	ClassDB::bind_method(D_METHOD("remove_node", "func", "id"), &VisualScript::remove_node);
1309 	ClassDB::bind_method(D_METHOD("get_function_node_id", "name"), &VisualScript::get_function_node_id);
1310 
1311 	ClassDB::bind_method(D_METHOD("get_node", "func", "id"), &VisualScript::get_node);
1312 	ClassDB::bind_method(D_METHOD("has_node", "func", "id"), &VisualScript::has_node);
1313 	ClassDB::bind_method(D_METHOD("set_node_position", "func", "id", "position"), &VisualScript::set_node_position);
1314 	ClassDB::bind_method(D_METHOD("get_node_position", "func", "id"), &VisualScript::get_node_position);
1315 
1316 	ClassDB::bind_method(D_METHOD("sequence_connect", "func", "from_node", "from_output", "to_node"), &VisualScript::sequence_connect);
1317 	ClassDB::bind_method(D_METHOD("sequence_disconnect", "func", "from_node", "from_output", "to_node"), &VisualScript::sequence_disconnect);
1318 	ClassDB::bind_method(D_METHOD("has_sequence_connection", "func", "from_node", "from_output", "to_node"), &VisualScript::has_sequence_connection);
1319 
1320 	ClassDB::bind_method(D_METHOD("data_connect", "func", "from_node", "from_port", "to_node", "to_port"), &VisualScript::data_connect);
1321 	ClassDB::bind_method(D_METHOD("data_disconnect", "func", "from_node", "from_port", "to_node", "to_port"), &VisualScript::data_disconnect);
1322 	ClassDB::bind_method(D_METHOD("has_data_connection", "func", "from_node", "from_port", "to_node", "to_port"), &VisualScript::has_data_connection);
1323 
1324 	ClassDB::bind_method(D_METHOD("add_variable", "name", "default_value", "export"), &VisualScript::add_variable, DEFVAL(Variant()), DEFVAL(false));
1325 	ClassDB::bind_method(D_METHOD("has_variable", "name"), &VisualScript::has_variable);
1326 	ClassDB::bind_method(D_METHOD("remove_variable", "name"), &VisualScript::remove_variable);
1327 	ClassDB::bind_method(D_METHOD("set_variable_default_value", "name", "value"), &VisualScript::set_variable_default_value);
1328 	ClassDB::bind_method(D_METHOD("get_variable_default_value", "name"), &VisualScript::get_variable_default_value);
1329 	ClassDB::bind_method(D_METHOD("set_variable_info", "name", "value"), &VisualScript::_set_variable_info);
1330 	ClassDB::bind_method(D_METHOD("get_variable_info", "name"), &VisualScript::_get_variable_info);
1331 	ClassDB::bind_method(D_METHOD("set_variable_export", "name", "enable"), &VisualScript::set_variable_export);
1332 	ClassDB::bind_method(D_METHOD("get_variable_export", "name"), &VisualScript::get_variable_export);
1333 	ClassDB::bind_method(D_METHOD("rename_variable", "name", "new_name"), &VisualScript::rename_variable);
1334 
1335 	ClassDB::bind_method(D_METHOD("add_custom_signal", "name"), &VisualScript::add_custom_signal);
1336 	ClassDB::bind_method(D_METHOD("has_custom_signal", "name"), &VisualScript::has_custom_signal);
1337 	ClassDB::bind_method(D_METHOD("custom_signal_add_argument", "name", "type", "argname", "index"), &VisualScript::custom_signal_add_argument, DEFVAL(-1));
1338 	ClassDB::bind_method(D_METHOD("custom_signal_set_argument_type", "name", "argidx", "type"), &VisualScript::custom_signal_set_argument_type);
1339 	ClassDB::bind_method(D_METHOD("custom_signal_get_argument_type", "name", "argidx"), &VisualScript::custom_signal_get_argument_type);
1340 	ClassDB::bind_method(D_METHOD("custom_signal_set_argument_name", "name", "argidx", "argname"), &VisualScript::custom_signal_set_argument_name);
1341 	ClassDB::bind_method(D_METHOD("custom_signal_get_argument_name", "name", "argidx"), &VisualScript::custom_signal_get_argument_name);
1342 	ClassDB::bind_method(D_METHOD("custom_signal_remove_argument", "name", "argidx"), &VisualScript::custom_signal_remove_argument);
1343 	ClassDB::bind_method(D_METHOD("custom_signal_get_argument_count", "name"), &VisualScript::custom_signal_get_argument_count);
1344 	ClassDB::bind_method(D_METHOD("custom_signal_swap_argument", "name", "argidx", "withidx"), &VisualScript::custom_signal_swap_argument);
1345 	ClassDB::bind_method(D_METHOD("remove_custom_signal", "name"), &VisualScript::remove_custom_signal);
1346 	ClassDB::bind_method(D_METHOD("rename_custom_signal", "name", "new_name"), &VisualScript::rename_custom_signal);
1347 
1348 	//ClassDB::bind_method(D_METHOD("set_variable_info","name","info"),&VScript::set_variable_info);
1349 	//ClassDB::bind_method(D_METHOD("get_variable_info","name"),&VScript::set_variable_info);
1350 
1351 	ClassDB::bind_method(D_METHOD("set_instance_base_type", "type"), &VisualScript::set_instance_base_type);
1352 
1353 	ClassDB::bind_method(D_METHOD("_set_data", "data"), &VisualScript::_set_data);
1354 	ClassDB::bind_method(D_METHOD("_get_data"), &VisualScript::_get_data);
1355 
1356 	ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data");
1357 
1358 	ADD_SIGNAL(MethodInfo("node_ports_changed", PropertyInfo(Variant::STRING, "function"), PropertyInfo(Variant::INT, "id")));
1359 }
1360 
VisualScript()1361 VisualScript::VisualScript() {
1362 
1363 	base_type = "Object";
1364 	is_tool_script = false;
1365 }
1366 
get_default_func() const1367 StringName VisualScript::get_default_func() const {
1368 	return StringName("f_312843592");
1369 }
1370 
get_output_sequence_ports_connected(const String & edited_func,int from_node)1371 Set<int> VisualScript::get_output_sequence_ports_connected(const String &edited_func, int from_node) {
1372 	List<VisualScript::SequenceConnection> *sc = memnew(List<VisualScript::SequenceConnection>);
1373 	get_sequence_connection_list(edited_func, sc);
1374 	Set<int> connected;
1375 	for (List<VisualScript::SequenceConnection>::Element *E = sc->front(); E; E = E->next()) {
1376 		if (E->get().from_node == from_node) {
1377 			connected.insert(E->get().from_output);
1378 		}
1379 	}
1380 	memdelete(sc);
1381 	return connected;
1382 }
1383 
~VisualScript()1384 VisualScript::~VisualScript() {
1385 
1386 	while (!functions.empty()) {
1387 		remove_function(functions.front()->key());
1388 	}
1389 }
1390 
1391 ////////////////////////////////////////////
1392 
set(const StringName & p_name,const Variant & p_value)1393 bool VisualScriptInstance::set(const StringName &p_name, const Variant &p_value) {
1394 
1395 	Map<StringName, Variant>::Element *E = variables.find(p_name);
1396 	if (!E)
1397 		return false;
1398 
1399 	E->get() = p_value;
1400 
1401 	return true;
1402 }
1403 
get(const StringName & p_name,Variant & r_ret) const1404 bool VisualScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
1405 
1406 	const Map<StringName, Variant>::Element *E = variables.find(p_name);
1407 	if (!E)
1408 		return false;
1409 
1410 	r_ret = E->get();
1411 	return true;
1412 }
get_property_list(List<PropertyInfo> * p_properties) const1413 void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const {
1414 
1415 	for (const Map<StringName, VisualScript::Variable>::Element *E = script->variables.front(); E; E = E->next()) {
1416 
1417 		if (!E->get()._export)
1418 			continue;
1419 		PropertyInfo p = E->get().info;
1420 		p.name = String(E->key());
1421 		p.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
1422 		p_properties->push_back(p);
1423 	}
1424 }
get_property_type(const StringName & p_name,bool * r_is_valid) const1425 Variant::Type VisualScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const {
1426 
1427 	const Map<StringName, VisualScript::Variable>::Element *E = script->variables.find(p_name);
1428 	if (!E) {
1429 		if (r_is_valid)
1430 			*r_is_valid = false;
1431 		ERR_FAIL_V(Variant::NIL);
1432 	}
1433 
1434 	if (r_is_valid)
1435 		*r_is_valid = true;
1436 
1437 	return E->get().info.type;
1438 }
1439 
get_method_list(List<MethodInfo> * p_list) const1440 void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
1441 
1442 	for (const Map<StringName, VisualScript::Function>::Element *E = script->functions.front(); E; E = E->next()) {
1443 
1444 		if (E->key() == script->get_default_func()) {
1445 			continue;
1446 		}
1447 
1448 		MethodInfo mi;
1449 		mi.name = E->key();
1450 		if (E->get().function_id >= 0 && E->get().nodes.has(E->get().function_id)) {
1451 
1452 			Ref<VisualScriptFunction> vsf = E->get().nodes[E->get().function_id].node;
1453 			if (vsf.is_valid()) {
1454 
1455 				for (int i = 0; i < vsf->get_argument_count(); i++) {
1456 					PropertyInfo arg;
1457 					arg.name = vsf->get_argument_name(i);
1458 					arg.type = vsf->get_argument_type(i);
1459 
1460 					mi.arguments.push_back(arg);
1461 				}
1462 
1463 				if (!vsf->is_sequenced()) { //assumed constant if not sequenced
1464 					mi.flags |= METHOD_FLAG_CONST;
1465 				}
1466 			}
1467 		}
1468 
1469 		p_list->push_back(mi);
1470 	}
1471 }
has_method(const StringName & p_method) const1472 bool VisualScriptInstance::has_method(const StringName &p_method) const {
1473 
1474 	if (p_method == script->get_default_func())
1475 		return false;
1476 
1477 	return script->functions.has(p_method);
1478 }
1479 
1480 //#define VSDEBUG(m_text) print_line(m_text)
1481 #define VSDEBUG(m_text)
1482 
_dependency_step(VisualScriptNodeInstance * node,int p_pass,int * pass_stack,const Variant ** input_args,Variant ** output_args,Variant * variant_stack,Variant::CallError & r_error,String & error_str,VisualScriptNodeInstance ** r_error_node)1483 void VisualScriptInstance::_dependency_step(VisualScriptNodeInstance *node, int p_pass, int *pass_stack, const Variant **input_args, Variant **output_args, Variant *variant_stack, Variant::CallError &r_error, String &error_str, VisualScriptNodeInstance **r_error_node) {
1484 
1485 	ERR_FAIL_COND(node->pass_idx == -1);
1486 
1487 	if (pass_stack[node->pass_idx] == p_pass)
1488 		return;
1489 
1490 	pass_stack[node->pass_idx] = p_pass;
1491 
1492 	if (!node->dependencies.empty()) {
1493 
1494 		int dc = node->dependencies.size();
1495 		VisualScriptNodeInstance **deps = node->dependencies.ptrw();
1496 
1497 		for (int i = 0; i < dc; i++) {
1498 
1499 			_dependency_step(deps[i], p_pass, pass_stack, input_args, output_args, variant_stack, r_error, error_str, r_error_node);
1500 			if (r_error.error != Variant::CallError::CALL_OK)
1501 				return;
1502 		}
1503 	}
1504 
1505 	for (int i = 0; i < node->input_port_count; i++) {
1506 
1507 		int index = node->input_ports[i] & VisualScriptNodeInstance::INPUT_MASK;
1508 
1509 		if (node->input_ports[i] & VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT) {
1510 			//is a default value (unassigned input port)
1511 			input_args[i] = &default_values[index];
1512 		} else {
1513 			//regular temporary in stack
1514 			input_args[i] = &variant_stack[index];
1515 		}
1516 	}
1517 	for (int i = 0; i < node->output_port_count; i++) {
1518 		output_args[i] = &variant_stack[node->output_ports[i]];
1519 	}
1520 
1521 	Variant *working_mem = node->working_mem_idx >= 0 ? &variant_stack[node->working_mem_idx] : (Variant *)NULL;
1522 
1523 	node->step(input_args, output_args, VisualScriptNodeInstance::START_MODE_BEGIN_SEQUENCE, working_mem, r_error, error_str);
1524 	//ignore return
1525 	if (r_error.error != Variant::CallError::CALL_OK) {
1526 		*r_error_node = node;
1527 	}
1528 }
1529 
_call_internal(const StringName & p_method,void * p_stack,int p_stack_size,VisualScriptNodeInstance * p_node,int p_flow_stack_pos,int p_pass,bool p_resuming_yield,Variant::CallError & r_error)1530 Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p_stack, int p_stack_size, VisualScriptNodeInstance *p_node, int p_flow_stack_pos, int p_pass, bool p_resuming_yield, Variant::CallError &r_error) {
1531 
1532 	Map<StringName, Function>::Element *F = functions.find(p_method);
1533 	ERR_FAIL_COND_V(!F, Variant());
1534 	Function *f = &F->get();
1535 
1536 	//this call goes separate, so it can e yielded and suspended
1537 	Variant *variant_stack = (Variant *)p_stack;
1538 	bool *sequence_bits = (bool *)(variant_stack + f->max_stack);
1539 	const Variant **input_args = (const Variant **)(sequence_bits + f->node_count);
1540 	Variant **output_args = (Variant **)(input_args + max_input_args);
1541 	int flow_max = f->flow_stack_size;
1542 	int *flow_stack = flow_max ? (int *)(output_args + max_output_args) : (int *)NULL;
1543 	int *pass_stack = flow_stack ? (int *)(flow_stack + flow_max) : (int *)NULL;
1544 
1545 	String error_str;
1546 
1547 	VisualScriptNodeInstance *node = p_node;
1548 	bool error = false;
1549 	int current_node_id = f->node;
1550 	Variant return_value;
1551 	Variant *working_mem = NULL;
1552 
1553 	int flow_stack_pos = p_flow_stack_pos;
1554 
1555 #ifdef DEBUG_ENABLED
1556 	if (ScriptDebugger::get_singleton()) {
1557 		VisualScriptLanguage::singleton->enter_function(this, &p_method, variant_stack, &working_mem, &current_node_id);
1558 	}
1559 #endif
1560 
1561 	while (true) {
1562 
1563 		p_pass++; //increment pass
1564 		current_node_id = node->get_id();
1565 
1566 		VSDEBUG("==========AT NODE: " + itos(current_node_id) + " base: " + node->get_base_node()->get_class_name());
1567 		VSDEBUG("AT STACK POS: " + itos(flow_stack_pos));
1568 
1569 		//setup working mem
1570 		working_mem = node->working_mem_idx >= 0 ? &variant_stack[node->working_mem_idx] : (Variant *)NULL;
1571 
1572 		VSDEBUG("WORKING MEM: " + itos(node->working_mem_idx));
1573 
1574 		if (current_node_id == f->node) {
1575 			//if function node, set up function arguments from beginning of stack
1576 
1577 			for (int i = 0; i < f->argument_count; i++) {
1578 				input_args[i] = &variant_stack[i];
1579 			}
1580 		} else {
1581 
1582 			//run dependencies first
1583 
1584 			if (!node->dependencies.empty()) {
1585 
1586 				int dc = node->dependencies.size();
1587 				VisualScriptNodeInstance **deps = node->dependencies.ptrw();
1588 
1589 				for (int i = 0; i < dc; i++) {
1590 
1591 					_dependency_step(deps[i], p_pass, pass_stack, input_args, output_args, variant_stack, r_error, error_str, &node);
1592 					if (r_error.error != Variant::CallError::CALL_OK) {
1593 						error = true;
1594 						current_node_id = node->id;
1595 						break;
1596 					}
1597 				}
1598 			}
1599 
1600 			if (!error) {
1601 
1602 				//setup input pointers normally
1603 				VSDEBUG("INPUT PORTS: " + itos(node->input_port_count));
1604 
1605 				for (int i = 0; i < node->input_port_count; i++) {
1606 
1607 					int index = node->input_ports[i] & VisualScriptNodeInstance::INPUT_MASK;
1608 
1609 					if (node->input_ports[i] & VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT) {
1610 						//is a default value (unassigned input port)
1611 						input_args[i] = &default_values[index];
1612 						VSDEBUG("\tPORT " + itos(i) + " DEFAULT VAL");
1613 					} else {
1614 						//regular temporary in stack
1615 						input_args[i] = &variant_stack[index];
1616 						VSDEBUG("PORT " + itos(i) + " AT STACK " + itos(index));
1617 					}
1618 				}
1619 			}
1620 		}
1621 
1622 		if (error)
1623 			break;
1624 
1625 		//setup output pointers
1626 
1627 		VSDEBUG("OUTPUT PORTS: " + itos(node->output_port_count));
1628 		for (int i = 0; i < node->output_port_count; i++) {
1629 			output_args[i] = &variant_stack[node->output_ports[i]];
1630 			VSDEBUG("PORT " + itos(i) + " AT STACK " + itos(node->output_ports[i]));
1631 		}
1632 
1633 		//do step
1634 
1635 		VisualScriptNodeInstance::StartMode start_mode;
1636 		{
1637 			if (p_resuming_yield) {
1638 				start_mode = VisualScriptNodeInstance::START_MODE_RESUME_YIELD;
1639 				p_resuming_yield = false; // should resume only the first time
1640 			} else if (flow_stack && (flow_stack[flow_stack_pos] & VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT)) {
1641 				//if there is a push bit, it means we are continuing a sequence
1642 				start_mode = VisualScriptNodeInstance::START_MODE_CONTINUE_SEQUENCE;
1643 			} else {
1644 				start_mode = VisualScriptNodeInstance::START_MODE_BEGIN_SEQUENCE;
1645 			}
1646 		}
1647 
1648 		VSDEBUG("STEP - STARTSEQ: " + itos(start_mode));
1649 
1650 		int ret = node->step(input_args, output_args, start_mode, working_mem, r_error, error_str);
1651 
1652 		if (r_error.error != Variant::CallError::CALL_OK) {
1653 			//use error from step
1654 			error = true;
1655 			break;
1656 		}
1657 
1658 		if (ret & VisualScriptNodeInstance::STEP_YIELD_BIT) {
1659 			//yielded!
1660 			if (node->get_working_memory_size() == 0) {
1661 				r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1662 				error_str = RTR("A node yielded without working memory, please read the docs on how to yield properly!");
1663 				error = true;
1664 				break;
1665 
1666 			} else {
1667 				Ref<VisualScriptFunctionState> state = *working_mem;
1668 				if (!state.is_valid()) {
1669 
1670 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1671 					error_str = RTR("Node yielded, but did not return a function state in the first working memory.");
1672 					error = true;
1673 					break;
1674 				}
1675 
1676 				//step 1, capture all state
1677 				state->instance_id = get_owner_ptr()->get_instance_id();
1678 				state->script_id = get_script()->get_instance_id();
1679 				state->instance = this;
1680 				state->function = p_method;
1681 				state->working_mem_index = node->working_mem_idx;
1682 				state->variant_stack_size = f->max_stack;
1683 				state->node = node;
1684 				state->flow_stack_pos = flow_stack_pos;
1685 				state->stack.resize(p_stack_size);
1686 				state->pass = p_pass;
1687 				copymem(state->stack.ptrw(), p_stack, p_stack_size);
1688 				//step 2, run away, return directly
1689 				r_error.error = Variant::CallError::CALL_OK;
1690 
1691 #ifdef DEBUG_ENABLED
1692 				//will re-enter later, so exiting
1693 				if (ScriptDebugger::get_singleton()) {
1694 					VisualScriptLanguage::singleton->exit_function();
1695 				}
1696 #endif
1697 
1698 				return state;
1699 			}
1700 		}
1701 
1702 #ifdef DEBUG_ENABLED
1703 		if (ScriptDebugger::get_singleton()) {
1704 			// line
1705 			bool do_break = false;
1706 
1707 			if (ScriptDebugger::get_singleton()->get_lines_left() > 0) {
1708 
1709 				if (ScriptDebugger::get_singleton()->get_depth() <= 0)
1710 					ScriptDebugger::get_singleton()->set_lines_left(ScriptDebugger::get_singleton()->get_lines_left() - 1);
1711 				if (ScriptDebugger::get_singleton()->get_lines_left() <= 0)
1712 					do_break = true;
1713 			}
1714 
1715 			if (ScriptDebugger::get_singleton()->is_breakpoint(current_node_id, source))
1716 				do_break = true;
1717 
1718 			if (do_break) {
1719 				VisualScriptLanguage::singleton->debug_break("Breakpoint", true);
1720 			}
1721 
1722 			ScriptDebugger::get_singleton()->line_poll();
1723 		}
1724 #endif
1725 		int output = ret & VisualScriptNodeInstance::STEP_MASK;
1726 
1727 		VSDEBUG("STEP RETURN: " + itos(ret));
1728 
1729 		if (ret & VisualScriptNodeInstance::STEP_EXIT_FUNCTION_BIT) {
1730 			if (node->get_working_memory_size() == 0) {
1731 
1732 				r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1733 				error_str = RTR("Return value must be assigned to first element of node working memory! Fix your node please.");
1734 				error = true;
1735 			} else {
1736 				//assign from working memory, first element
1737 				return_value = *working_mem;
1738 			}
1739 
1740 			VSDEBUG("EXITING FUNCTION - VALUE " + String(return_value));
1741 			break; //exit function requested, bye
1742 		}
1743 
1744 		VisualScriptNodeInstance *next = NULL; //next node
1745 
1746 		if ((ret == output || ret & VisualScriptNodeInstance::STEP_FLAG_PUSH_STACK_BIT) && node->sequence_output_count) {
1747 			//if no exit bit was set, and has sequence outputs, guess next node
1748 			if (output >= node->sequence_output_count) {
1749 				r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1750 				error_str = RTR("Node returned an invalid sequence output: ") + itos(output);
1751 				error = true;
1752 				break;
1753 			}
1754 
1755 			next = node->sequence_outputs[output];
1756 			if (next) {
1757 				VSDEBUG("GOT NEXT NODE - " + itos(next->get_id()));
1758 			} else {
1759 				VSDEBUG("GOT NEXT NODE - NULL");
1760 			}
1761 		}
1762 
1763 		if (flow_stack) {
1764 
1765 			//update flow stack pos (may have changed)
1766 			flow_stack[flow_stack_pos] = current_node_id;
1767 
1768 			//add stack push bit if requested
1769 			if (ret & VisualScriptNodeInstance::STEP_FLAG_PUSH_STACK_BIT) {
1770 
1771 				flow_stack[flow_stack_pos] |= VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT;
1772 				sequence_bits[node->sequence_index] = true; //remember sequence bit
1773 				VSDEBUG("NEXT SEQ - FLAG BIT");
1774 			} else {
1775 				sequence_bits[node->sequence_index] = false; //forget sequence bit
1776 				VSDEBUG("NEXT SEQ - NORMAL");
1777 			}
1778 
1779 			if (ret & VisualScriptNodeInstance::STEP_FLAG_GO_BACK_BIT) {
1780 				//go back request
1781 
1782 				if (flow_stack_pos > 0) {
1783 					flow_stack_pos--;
1784 					node = instances[flow_stack[flow_stack_pos] & VisualScriptNodeInstance::FLOW_STACK_MASK];
1785 					VSDEBUG("NEXT IS GO BACK");
1786 				} else {
1787 					VSDEBUG("NEXT IS GO BACK, BUT NO NEXT SO EXIT");
1788 					break; //simply exit without value or error
1789 				}
1790 			} else if (next) {
1791 
1792 				if (sequence_bits[next->sequence_index]) {
1793 					// what happened here is that we are entering a node that is in the middle of doing a sequence (pushed stack) from the front
1794 					// because each node has a working memory, we can't really do a sub-sequence
1795 					// as a result, the sequence will be restarted and the stack will roll back to find where this node
1796 					// started the sequence
1797 
1798 					bool found = false;
1799 
1800 					for (int i = flow_stack_pos; i >= 0; i--) {
1801 
1802 						if ((flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_MASK) == next->get_id()) {
1803 							flow_stack_pos = i; //roll back and remove bit
1804 							flow_stack[i] = next->get_id();
1805 							sequence_bits[next->sequence_index] = false;
1806 							found = true;
1807 						}
1808 					}
1809 
1810 					if (!found) {
1811 						r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1812 						error_str = RTR("Found sequence bit but not the node in the stack, report bug!");
1813 						error = true;
1814 						break;
1815 					}
1816 
1817 					node = next;
1818 					VSDEBUG("RE-ENTERED A LOOP, RETURNED STACK POS TO - " + itos(flow_stack_pos));
1819 
1820 				} else {
1821 					// check for stack overflow
1822 					if (flow_stack_pos + 1 >= flow_max) {
1823 						r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1824 						error_str = RTR("Stack overflow with stack depth: ") + itos(output);
1825 						error = true;
1826 						break;
1827 					}
1828 
1829 					node = next;
1830 
1831 					flow_stack_pos++;
1832 					flow_stack[flow_stack_pos] = node->get_id();
1833 
1834 					VSDEBUG("INCREASE FLOW STACK");
1835 				}
1836 
1837 			} else {
1838 				//no next node, try to go back in stack to pushed bit
1839 
1840 				bool found = false;
1841 
1842 				for (int i = flow_stack_pos; i >= 0; i--) {
1843 
1844 					VSDEBUG("FS " + itos(i) + " - " + itos(flow_stack[i]));
1845 					if (flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT) {
1846 
1847 						node = instances[flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_MASK];
1848 						flow_stack_pos = i;
1849 						found = true;
1850 						break;
1851 					}
1852 				}
1853 
1854 				if (!found) {
1855 					VSDEBUG("NO NEXT NODE, NO GO BACK, EXITING");
1856 					break; //done, couldn't find a push stack bit
1857 				}
1858 
1859 				VSDEBUG("NO NEXT NODE, GO BACK TO: " + itos(flow_stack_pos));
1860 			}
1861 		} else {
1862 
1863 			node = next; //stackless mode, simply assign next node
1864 		}
1865 	}
1866 
1867 	if (error) {
1868 
1869 		//error
1870 		// function, file, line, error, explanation
1871 		String err_file = script->get_path();
1872 		String err_func = p_method;
1873 		int err_line = current_node_id; //not a line but it works as one
1874 
1875 		if (node && (r_error.error != Variant::CallError::CALL_ERROR_INVALID_METHOD || error_str == String())) {
1876 
1877 			if (error_str != String()) {
1878 				error_str += " ";
1879 			}
1880 
1881 			if (r_error.error == Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) {
1882 				int errorarg = r_error.argument;
1883 				error_str += "Cannot convert argument " + itos(errorarg + 1) + " to " + Variant::get_type_name(r_error.expected) + ".";
1884 			} else if (r_error.error == Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
1885 				error_str += "Expected " + itos(r_error.argument) + " arguments.";
1886 			} else if (r_error.error == Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
1887 				error_str += "Expected " + itos(r_error.argument) + " arguments.";
1888 			} else if (r_error.error == Variant::CallError::CALL_ERROR_INVALID_METHOD) {
1889 				error_str += "Invalid Call.";
1890 			} else if (r_error.error == Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
1891 				error_str += "Base Instance is null";
1892 			}
1893 		}
1894 
1895 		//if (!GDScriptLanguage::get_singleton()->debug_break(err_text,false)) {
1896 		// debugger break did not happen
1897 
1898 		if (!VisualScriptLanguage::singleton->debug_break(error_str, false)) {
1899 
1900 			_err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, error_str.utf8().get_data(), ERR_HANDLER_SCRIPT);
1901 		}
1902 
1903 		//}
1904 	} else {
1905 
1906 		//return_value=
1907 	}
1908 
1909 #ifdef DEBUG_ENABLED
1910 	if (ScriptDebugger::get_singleton()) {
1911 		VisualScriptLanguage::singleton->exit_function();
1912 	}
1913 #endif
1914 
1915 	//clean up variant stack
1916 	for (int i = 0; i < f->max_stack; i++) {
1917 		variant_stack[i].~Variant();
1918 	}
1919 
1920 	return return_value;
1921 }
1922 
call(const StringName & p_method,const Variant ** p_args,int p_argcount,Variant::CallError & r_error)1923 Variant VisualScriptInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
1924 
1925 	r_error.error = Variant::CallError::CALL_OK; //ok by default
1926 
1927 	Map<StringName, Function>::Element *F = functions.find(p_method);
1928 	if (!F) {
1929 		r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1930 		return Variant();
1931 	}
1932 
1933 	VSDEBUG("CALLING: " + String(p_method));
1934 
1935 	Function *f = &F->get();
1936 
1937 	int total_stack_size = 0;
1938 
1939 	total_stack_size += f->max_stack * sizeof(Variant); //variants
1940 	total_stack_size += f->node_count * sizeof(bool);
1941 	total_stack_size += (max_input_args + max_output_args) * sizeof(Variant *); //arguments
1942 	total_stack_size += f->flow_stack_size * sizeof(int); //flow
1943 	total_stack_size += f->pass_stack_size * sizeof(int);
1944 
1945 	VSDEBUG("STACK SIZE: " + itos(total_stack_size));
1946 	VSDEBUG("STACK VARIANTS: : " + itos(f->max_stack));
1947 	VSDEBUG("SEQBITS: : " + itos(f->node_count));
1948 	VSDEBUG("MAX INPUT: " + itos(max_input_args));
1949 	VSDEBUG("MAX OUTPUT: " + itos(max_output_args));
1950 	VSDEBUG("FLOW STACK SIZE: " + itos(f->flow_stack_size));
1951 	VSDEBUG("PASS STACK SIZE: " + itos(f->pass_stack_size));
1952 
1953 	void *stack = alloca(total_stack_size);
1954 
1955 	Variant *variant_stack = (Variant *)stack;
1956 	bool *sequence_bits = (bool *)(variant_stack + f->max_stack);
1957 	const Variant **input_args = (const Variant **)(sequence_bits + f->node_count);
1958 	Variant **output_args = (Variant **)(input_args + max_input_args);
1959 	int flow_max = f->flow_stack_size;
1960 	int *flow_stack = flow_max ? (int *)(output_args + max_output_args) : (int *)NULL;
1961 	int *pass_stack = flow_stack ? (int *)(flow_stack + flow_max) : (int *)NULL;
1962 
1963 	for (int i = 0; i < f->node_count; i++) {
1964 		sequence_bits[i] = false; //all starts as false
1965 	}
1966 
1967 	zeromem(pass_stack, f->pass_stack_size * sizeof(int));
1968 
1969 	Map<int, VisualScriptNodeInstance *>::Element *E = instances.find(f->node);
1970 	if (!E) {
1971 		r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1972 
1973 		ERR_FAIL_V_MSG(Variant(), "No VisualScriptFunction node in function.");
1974 	}
1975 
1976 	VisualScriptNodeInstance *node = E->get();
1977 
1978 	if (flow_stack) {
1979 		flow_stack[0] = node->get_id();
1980 	}
1981 
1982 	VSDEBUG("ARGUMENTS: " + itos(f->argument_count) = " RECEIVED: " + itos(p_argcount));
1983 
1984 	if (p_argcount < f->argument_count) {
1985 		r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
1986 		r_error.argument = node->get_input_port_count();
1987 
1988 		return Variant();
1989 	}
1990 
1991 	if (p_argcount > f->argument_count) {
1992 		r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
1993 		r_error.argument = node->get_input_port_count();
1994 
1995 		return Variant();
1996 	}
1997 
1998 	//allocate variant stack
1999 	for (int i = 0; i < f->max_stack; i++) {
2000 		memnew_placement(&variant_stack[i], Variant);
2001 	}
2002 
2003 	//allocate function arguments (must be copied for yield to work properly)
2004 	for (int i = 0; i < p_argcount; i++) {
2005 		variant_stack[i] = *p_args[i];
2006 	}
2007 
2008 	return _call_internal(p_method, stack, total_stack_size, node, 0, 0, false, r_error);
2009 }
2010 
notification(int p_notification)2011 void VisualScriptInstance::notification(int p_notification) {
2012 
2013 	//do nothing as this is called using virtual
2014 
2015 	Variant what = p_notification;
2016 	const Variant *whatp = &what;
2017 	Variant::CallError ce;
2018 	call(VisualScriptLanguage::singleton->notification, &whatp, 1, ce); //do as call
2019 }
2020 
to_string(bool * r_valid)2021 String VisualScriptInstance::to_string(bool *r_valid) {
2022 	if (has_method(CoreStringNames::get_singleton()->_to_string)) {
2023 		Variant::CallError ce;
2024 		Variant ret = call(CoreStringNames::get_singleton()->_to_string, NULL, 0, ce);
2025 		if (ce.error == Variant::CallError::CALL_OK) {
2026 			if (ret.get_type() != Variant::STRING) {
2027 				if (r_valid)
2028 					*r_valid = false;
2029 				ERR_FAIL_V_MSG(String(), "Wrong type for " + CoreStringNames::get_singleton()->_to_string + ", must be a String.");
2030 			}
2031 			if (r_valid)
2032 				*r_valid = true;
2033 			return ret.operator String();
2034 		}
2035 	}
2036 	if (r_valid)
2037 		*r_valid = false;
2038 	return String();
2039 }
2040 
get_script() const2041 Ref<Script> VisualScriptInstance::get_script() const {
2042 
2043 	return script;
2044 }
2045 
get_rpc_mode(const StringName & p_method) const2046 MultiplayerAPI::RPCMode VisualScriptInstance::get_rpc_mode(const StringName &p_method) const {
2047 
2048 	if (p_method == script->get_default_func())
2049 		return MultiplayerAPI::RPC_MODE_DISABLED;
2050 
2051 	const Map<StringName, VisualScript::Function>::Element *E = script->functions.find(p_method);
2052 	if (!E) {
2053 		return MultiplayerAPI::RPC_MODE_DISABLED;
2054 	}
2055 
2056 	if (E->get().function_id >= 0 && E->get().nodes.has(E->get().function_id)) {
2057 
2058 		Ref<VisualScriptFunction> vsf = E->get().nodes[E->get().function_id].node;
2059 		if (vsf.is_valid()) {
2060 
2061 			return vsf->get_rpc_mode();
2062 		}
2063 	}
2064 
2065 	return MultiplayerAPI::RPC_MODE_DISABLED;
2066 }
2067 
get_rset_mode(const StringName & p_variable) const2068 MultiplayerAPI::RPCMode VisualScriptInstance::get_rset_mode(const StringName &p_variable) const {
2069 
2070 	return MultiplayerAPI::RPC_MODE_DISABLED;
2071 }
2072 
create(const Ref<VisualScript> & p_script,Object * p_owner)2073 void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_owner) {
2074 
2075 	script = p_script;
2076 	owner = p_owner;
2077 	source = p_script->get_path();
2078 
2079 	max_input_args = 0;
2080 	max_output_args = 0;
2081 
2082 	if (Object::cast_to<Node>(p_owner)) {
2083 		//turn on these if they exist and base is a node
2084 		Node *node = Object::cast_to<Node>(p_owner);
2085 		if (p_script->functions.has("_process"))
2086 			node->set_process(true);
2087 		if (p_script->functions.has("_physics_process"))
2088 			node->set_physics_process(true);
2089 		if (p_script->functions.has("_input"))
2090 			node->set_process_input(true);
2091 		if (p_script->functions.has("_unhandled_input"))
2092 			node->set_process_unhandled_input(true);
2093 		if (p_script->functions.has("_unhandled_key_input"))
2094 			node->set_process_unhandled_key_input(true);
2095 	}
2096 
2097 	for (const Map<StringName, VisualScript::Variable>::Element *E = script->variables.front(); E; E = E->next()) {
2098 		variables[E->key()] = E->get().default_value;
2099 	}
2100 
2101 	for (const Map<StringName, VisualScript::Function>::Element *E = script->functions.front(); E; E = E->next()) {
2102 
2103 		if (E->key() == script->get_default_func()) {
2104 			continue;
2105 		}
2106 
2107 		Function function;
2108 		function.node = E->get().function_id;
2109 		function.max_stack = 0;
2110 		function.flow_stack_size = 0;
2111 		function.pass_stack_size = 0;
2112 		function.node_count = 0;
2113 
2114 		Map<StringName, int> local_var_indices;
2115 
2116 		if (function.node < 0) {
2117 			VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No start node in function: " + String(E->key()));
2118 
2119 			ERR_CONTINUE(function.node < 0);
2120 		}
2121 
2122 		{
2123 			Ref<VisualScriptFunction> func_node = script->get_node(E->key(), E->get().function_id);
2124 
2125 			if (func_node.is_null()) {
2126 				VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No VisualScriptFunction typed start node in function: " + String(E->key()));
2127 			}
2128 
2129 			ERR_CONTINUE(!func_node.is_valid());
2130 
2131 			function.argument_count = func_node->get_argument_count();
2132 			function.max_stack += function.argument_count;
2133 			function.flow_stack_size = func_node->is_stack_less() ? 0 : func_node->get_stack_size();
2134 			max_input_args = MAX(max_input_args, function.argument_count);
2135 		}
2136 
2137 		//multiple passes are required to set up this complex thing..
2138 
2139 		//first create the nodes
2140 		for (const Map<int, VisualScript::Function::NodeData>::Element *F = E->get().nodes.front(); F; F = F->next()) {
2141 
2142 			Ref<VisualScriptNode> node = F->get().node;
2143 
2144 			VisualScriptNodeInstance *instance = node->instance(this); //create instance
2145 			ERR_FAIL_COND(!instance);
2146 
2147 			instance->base = node.ptr();
2148 
2149 			instance->id = F->key();
2150 			instance->input_port_count = node->get_input_value_port_count();
2151 			instance->input_ports = NULL;
2152 			instance->output_port_count = node->get_output_value_port_count();
2153 			instance->output_ports = NULL;
2154 			instance->sequence_output_count = node->get_output_sequence_port_count();
2155 			instance->sequence_index = function.node_count++;
2156 			instance->sequence_outputs = NULL;
2157 			instance->pass_idx = -1;
2158 
2159 			if (instance->input_port_count) {
2160 				instance->input_ports = memnew_arr(int, instance->input_port_count);
2161 				for (int i = 0; i < instance->input_port_count; i++) {
2162 
2163 					instance->input_ports[i] = -1; //if not assigned, will become default value
2164 				}
2165 			}
2166 
2167 			if (instance->output_port_count) {
2168 				instance->output_ports = memnew_arr(int, instance->output_port_count);
2169 				for (int i = 0; i < instance->output_port_count; i++) {
2170 					instance->output_ports[i] = -1; //if not assigned, will output to trash
2171 				}
2172 			}
2173 
2174 			if (instance->sequence_output_count) {
2175 				instance->sequence_outputs = memnew_arr(VisualScriptNodeInstance *, instance->sequence_output_count);
2176 				for (int i = 0; i < instance->sequence_output_count; i++) {
2177 					instance->sequence_outputs[i] = NULL; //if it remains null, flow ends here
2178 				}
2179 			}
2180 
2181 			if (Object::cast_to<VisualScriptLocalVar>(node.ptr()) || Object::cast_to<VisualScriptLocalVarSet>(*node)) {
2182 				//working memory is shared only for this node, for the same variables
2183 				Ref<VisualScriptLocalVar> vslv = node;
2184 
2185 				StringName var_name;
2186 
2187 				if (Object::cast_to<VisualScriptLocalVar>(*node))
2188 					var_name = String(Object::cast_to<VisualScriptLocalVar>(*node)->get_var_name()).strip_edges();
2189 				else
2190 					var_name = String(Object::cast_to<VisualScriptLocalVarSet>(*node)->get_var_name()).strip_edges();
2191 
2192 				if (!local_var_indices.has(var_name)) {
2193 					local_var_indices[var_name] = function.max_stack;
2194 					function.max_stack++;
2195 				}
2196 
2197 				instance->working_mem_idx = local_var_indices[var_name];
2198 
2199 			} else if (instance->get_working_memory_size()) {
2200 				instance->working_mem_idx = function.max_stack;
2201 				function.max_stack += instance->get_working_memory_size();
2202 			} else {
2203 				instance->working_mem_idx = -1; //no working mem
2204 			}
2205 
2206 			max_input_args = MAX(max_input_args, instance->input_port_count);
2207 			max_output_args = MAX(max_output_args, instance->output_port_count);
2208 
2209 			instances[F->key()] = instance;
2210 		}
2211 
2212 		function.trash_pos = function.max_stack++; //create pos for trash
2213 
2214 		//second pass, do data connections
2215 
2216 		for (const Set<VisualScript::DataConnection>::Element *F = E->get().data_connections.front(); F; F = F->next()) {
2217 
2218 			VisualScript::DataConnection dc = F->get();
2219 			ERR_CONTINUE(!instances.has(dc.from_node));
2220 			VisualScriptNodeInstance *from = instances[dc.from_node];
2221 			ERR_CONTINUE(!instances.has(dc.to_node));
2222 			VisualScriptNodeInstance *to = instances[dc.to_node];
2223 			ERR_CONTINUE(dc.from_port >= from->output_port_count);
2224 			ERR_CONTINUE(dc.to_port >= to->input_port_count);
2225 
2226 			if (from->output_ports[dc.from_port] == -1) {
2227 
2228 				int stack_pos = function.max_stack++;
2229 				from->output_ports[dc.from_port] = stack_pos;
2230 			}
2231 
2232 			if (from->get_sequence_output_count() == 0 && to->dependencies.find(from) == -1) {
2233 				//if the node we are reading from has no output sequence, we must call step() before reading from it.
2234 				if (from->pass_idx == -1) {
2235 					from->pass_idx = function.pass_stack_size;
2236 					function.pass_stack_size++;
2237 				}
2238 				to->dependencies.push_back(from);
2239 			}
2240 
2241 			to->input_ports[dc.to_port] = from->output_ports[dc.from_port]; //read from wherever the stack is
2242 		}
2243 
2244 		//third pass, do sequence connections
2245 
2246 		for (const Set<VisualScript::SequenceConnection>::Element *F = E->get().sequence_connections.front(); F; F = F->next()) {
2247 
2248 			VisualScript::SequenceConnection sc = F->get();
2249 			ERR_CONTINUE(!instances.has(sc.from_node));
2250 			VisualScriptNodeInstance *from = instances[sc.from_node];
2251 			ERR_CONTINUE(!instances.has(sc.to_node));
2252 			VisualScriptNodeInstance *to = instances[sc.to_node];
2253 			ERR_CONTINUE(sc.from_output >= from->sequence_output_count);
2254 
2255 			from->sequence_outputs[sc.from_output] = to;
2256 		}
2257 
2258 		//fourth pass:
2259 		// 1) unassigned input ports to default values
2260 		// 2) connect unassigned output ports to trash
2261 
2262 		for (const Map<int, VisualScript::Function::NodeData>::Element *F = E->get().nodes.front(); F; F = F->next()) {
2263 
2264 			ERR_CONTINUE(!instances.has(F->key()));
2265 
2266 			Ref<VisualScriptNode> node = F->get().node;
2267 			VisualScriptNodeInstance *instance = instances[F->key()];
2268 
2269 			// connect to default values
2270 			for (int i = 0; i < instance->input_port_count; i++) {
2271 				if (instance->input_ports[i] == -1) {
2272 
2273 					//unassigned, connect to default val
2274 					instance->input_ports[i] = default_values.size() | VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT;
2275 					default_values.push_back(node->get_default_input_value(i));
2276 				}
2277 			}
2278 
2279 			// connect to trash
2280 			for (int i = 0; i < instance->output_port_count; i++) {
2281 				if (instance->output_ports[i] == -1) {
2282 					instance->output_ports[i] = function.trash_pos; //trash is same for all
2283 				}
2284 			}
2285 		}
2286 
2287 		functions[E->key()] = function;
2288 	}
2289 }
2290 
get_language()2291 ScriptLanguage *VisualScriptInstance::get_language() {
2292 
2293 	return VisualScriptLanguage::singleton;
2294 }
2295 
VisualScriptInstance()2296 VisualScriptInstance::VisualScriptInstance() {
2297 }
2298 
~VisualScriptInstance()2299 VisualScriptInstance::~VisualScriptInstance() {
2300 
2301 	if (VisualScriptLanguage::singleton->lock)
2302 		VisualScriptLanguage::singleton->lock->lock();
2303 
2304 	script->instances.erase(owner);
2305 
2306 	if (VisualScriptLanguage::singleton->lock)
2307 		VisualScriptLanguage::singleton->lock->unlock();
2308 
2309 	for (Map<int, VisualScriptNodeInstance *>::Element *E = instances.front(); E; E = E->next()) {
2310 		memdelete(E->get());
2311 	}
2312 }
2313 
2314 /////////////////////////////////////////////
2315 
2316 /////////////////////
2317 
_signal_callback(const Variant ** p_args,int p_argcount,Variant::CallError & r_error)2318 Variant VisualScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
2319 
2320 	ERR_FAIL_COND_V(function == StringName(), Variant());
2321 
2322 #ifdef DEBUG_ENABLED
2323 
2324 	ERR_FAIL_COND_V_MSG(instance_id && !ObjectDB::get_instance(instance_id), Variant(), "Resumed after yield, but class instance is gone.");
2325 	ERR_FAIL_COND_V_MSG(script_id && !ObjectDB::get_instance(script_id), Variant(), "Resumed after yield, but script is gone.");
2326 
2327 #endif
2328 
2329 	r_error.error = Variant::CallError::CALL_OK;
2330 
2331 	Array args;
2332 
2333 	if (p_argcount == 0) {
2334 		r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
2335 		r_error.argument = 1;
2336 		return Variant();
2337 	} else if (p_argcount == 1) {
2338 		//noooneee, reserved for me, me and only me.
2339 	} else {
2340 
2341 		for (int i = 0; i < p_argcount - 1; i++) {
2342 			args.push_back(*p_args[i]);
2343 		}
2344 	}
2345 
2346 	Ref<VisualScriptFunctionState> self = *p_args[p_argcount - 1]; //hi, I'm myself, needed this to remain alive.
2347 
2348 	if (self.is_null()) {
2349 		r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
2350 		r_error.argument = p_argcount - 1;
2351 		r_error.expected = Variant::OBJECT;
2352 		return Variant();
2353 	}
2354 
2355 	r_error.error = Variant::CallError::CALL_OK;
2356 
2357 	Variant *working_mem = ((Variant *)stack.ptr()) + working_mem_index;
2358 
2359 	*working_mem = args; //arguments go to working mem.
2360 
2361 	Variant ret = instance->_call_internal(function, stack.ptrw(), stack.size(), node, flow_stack_pos, pass, true, r_error);
2362 	function = StringName(); //invalidate
2363 	return ret;
2364 }
2365 
connect_to_signal(Object * p_obj,const String & p_signal,Array p_binds)2366 void VisualScriptFunctionState::connect_to_signal(Object *p_obj, const String &p_signal, Array p_binds) {
2367 
2368 	Vector<Variant> binds;
2369 	for (int i = 0; i < p_binds.size(); i++) {
2370 		binds.push_back(p_binds[i]);
2371 	}
2372 	binds.push_back(Ref<VisualScriptFunctionState>(this)); //add myself on the back to avoid dying from unreferencing
2373 	p_obj->connect(p_signal, this, "_signal_callback", binds, CONNECT_ONESHOT);
2374 }
2375 
is_valid() const2376 bool VisualScriptFunctionState::is_valid() const {
2377 
2378 	return function != StringName();
2379 }
2380 
resume(Array p_args)2381 Variant VisualScriptFunctionState::resume(Array p_args) {
2382 
2383 	ERR_FAIL_COND_V(function == StringName(), Variant());
2384 #ifdef DEBUG_ENABLED
2385 
2386 	ERR_FAIL_COND_V_MSG(instance_id && !ObjectDB::get_instance(instance_id), Variant(), "Resumed after yield, but class instance is gone.");
2387 	ERR_FAIL_COND_V_MSG(script_id && !ObjectDB::get_instance(script_id), Variant(), "Resumed after yield, but script is gone.");
2388 
2389 #endif
2390 
2391 	Variant::CallError r_error;
2392 	r_error.error = Variant::CallError::CALL_OK;
2393 
2394 	Variant *working_mem = ((Variant *)stack.ptr()) + working_mem_index;
2395 
2396 	*working_mem = p_args; //arguments go to working mem.
2397 
2398 	Variant ret = instance->_call_internal(function, stack.ptrw(), stack.size(), node, flow_stack_pos, pass, true, r_error);
2399 	function = StringName(); //invalidate
2400 	return ret;
2401 }
2402 
_bind_methods()2403 void VisualScriptFunctionState::_bind_methods() {
2404 
2405 	ClassDB::bind_method(D_METHOD("connect_to_signal", "obj", "signals", "args"), &VisualScriptFunctionState::connect_to_signal);
2406 	ClassDB::bind_method(D_METHOD("resume", "args"), &VisualScriptFunctionState::resume, DEFVAL(Variant()));
2407 	ClassDB::bind_method(D_METHOD("is_valid"), &VisualScriptFunctionState::is_valid);
2408 	ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "_signal_callback", &VisualScriptFunctionState::_signal_callback, MethodInfo("_signal_callback"));
2409 }
2410 
VisualScriptFunctionState()2411 VisualScriptFunctionState::VisualScriptFunctionState() {
2412 }
2413 
~VisualScriptFunctionState()2414 VisualScriptFunctionState::~VisualScriptFunctionState() {
2415 
2416 	if (function != StringName()) {
2417 		Variant *s = ((Variant *)stack.ptr());
2418 		for (int i = 0; i < variant_stack_size; i++) {
2419 			s[i].~Variant();
2420 		}
2421 	}
2422 }
2423 
2424 ///////////////////////////////////////////////
2425 
get_name() const2426 String VisualScriptLanguage::get_name() const {
2427 
2428 	return "VisualScript";
2429 }
2430 
2431 /* LANGUAGE FUNCTIONS */
init()2432 void VisualScriptLanguage::init() {
2433 }
get_type() const2434 String VisualScriptLanguage::get_type() const {
2435 
2436 	return "VisualScript";
2437 }
get_extension() const2438 String VisualScriptLanguage::get_extension() const {
2439 
2440 	return "vs";
2441 }
execute_file(const String & p_path)2442 Error VisualScriptLanguage::execute_file(const String &p_path) {
2443 
2444 	return OK;
2445 }
finish()2446 void VisualScriptLanguage::finish() {
2447 }
2448 
2449 /* EDITOR FUNCTIONS */
get_reserved_words(List<String> * p_words) const2450 void VisualScriptLanguage::get_reserved_words(List<String> *p_words) const {
2451 }
get_comment_delimiters(List<String> * p_delimiters) const2452 void VisualScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const {
2453 }
get_string_delimiters(List<String> * p_delimiters) const2454 void VisualScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const {
2455 }
get_template(const String & p_class_name,const String & p_base_class_name) const2456 Ref<Script> VisualScriptLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const {
2457 
2458 	Ref<VisualScript> script;
2459 	script.instance();
2460 	script->set_instance_base_type(p_base_class_name);
2461 	return script;
2462 }
2463 
is_using_templates()2464 bool VisualScriptLanguage::is_using_templates() {
2465 
2466 	return true;
2467 }
2468 
make_template(const String & p_class_name,const String & p_base_class_name,Ref<Script> & p_script)2469 void VisualScriptLanguage::make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) {
2470 	Ref<VisualScript> script = p_script;
2471 	script->set_instance_base_type(p_base_class_name);
2472 }
2473 
validate(const String & p_script,int & r_line_error,int & r_col_error,String & r_test_error,const String & p_path,List<String> * r_functions,List<ScriptLanguage::Warning> * r_warnings,Set<int> * r_safe_lines) const2474 bool VisualScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions, List<ScriptLanguage::Warning> *r_warnings, Set<int> *r_safe_lines) const {
2475 
2476 	return false;
2477 }
create_script() const2478 Script *VisualScriptLanguage::create_script() const {
2479 
2480 	return memnew(VisualScript);
2481 }
has_named_classes() const2482 bool VisualScriptLanguage::has_named_classes() const {
2483 
2484 	return false;
2485 }
supports_builtin_mode() const2486 bool VisualScriptLanguage::supports_builtin_mode() const {
2487 
2488 	return true;
2489 }
find_function(const String & p_function,const String & p_code) const2490 int VisualScriptLanguage::find_function(const String &p_function, const String &p_code) const {
2491 
2492 	return -1;
2493 }
make_function(const String & p_class,const String & p_name,const PoolStringArray & p_args) const2494 String VisualScriptLanguage::make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const {
2495 
2496 	return String();
2497 }
2498 
auto_indent_code(String & p_code,int p_from_line,int p_to_line) const2499 void VisualScriptLanguage::auto_indent_code(String &p_code, int p_from_line, int p_to_line) const {
2500 }
add_global_constant(const StringName & p_variable,const Variant & p_value)2501 void VisualScriptLanguage::add_global_constant(const StringName &p_variable, const Variant &p_value) {
2502 }
2503 
2504 /* DEBUGGER FUNCTIONS */
2505 
debug_break_parse(const String & p_file,int p_node,const String & p_error)2506 bool VisualScriptLanguage::debug_break_parse(const String &p_file, int p_node, const String &p_error) {
2507 	//break because of parse error
2508 
2509 	if (ScriptDebugger::get_singleton() && Thread::get_caller_id() == Thread::get_main_id()) {
2510 
2511 		_debug_parse_err_node = p_node;
2512 		_debug_parse_err_file = p_file;
2513 		_debug_error = p_error;
2514 		ScriptDebugger::get_singleton()->debug(this, false, true);
2515 		return true;
2516 	} else {
2517 		return false;
2518 	}
2519 }
2520 
debug_break(const String & p_error,bool p_allow_continue)2521 bool VisualScriptLanguage::debug_break(const String &p_error, bool p_allow_continue) {
2522 
2523 	if (ScriptDebugger::get_singleton() && Thread::get_caller_id() == Thread::get_main_id()) {
2524 
2525 		_debug_parse_err_node = -1;
2526 		_debug_parse_err_file = "";
2527 		_debug_error = p_error;
2528 		ScriptDebugger::get_singleton()->debug(this, p_allow_continue, true);
2529 		return true;
2530 	} else {
2531 		return false;
2532 	}
2533 }
2534 
debug_get_error() const2535 String VisualScriptLanguage::debug_get_error() const {
2536 
2537 	return _debug_error;
2538 }
2539 
debug_get_stack_level_count() const2540 int VisualScriptLanguage::debug_get_stack_level_count() const {
2541 
2542 	if (_debug_parse_err_node >= 0)
2543 		return 1;
2544 
2545 	return _debug_call_stack_pos;
2546 }
debug_get_stack_level_line(int p_level) const2547 int VisualScriptLanguage::debug_get_stack_level_line(int p_level) const {
2548 
2549 	if (_debug_parse_err_node >= 0)
2550 		return _debug_parse_err_node;
2551 
2552 	ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, -1);
2553 
2554 	int l = _debug_call_stack_pos - p_level - 1;
2555 
2556 	return *(_call_stack[l].current_id);
2557 }
debug_get_stack_level_function(int p_level) const2558 String VisualScriptLanguage::debug_get_stack_level_function(int p_level) const {
2559 
2560 	if (_debug_parse_err_node >= 0)
2561 		return "";
2562 
2563 	ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, "");
2564 	int l = _debug_call_stack_pos - p_level - 1;
2565 	return *_call_stack[l].function;
2566 }
debug_get_stack_level_source(int p_level) const2567 String VisualScriptLanguage::debug_get_stack_level_source(int p_level) const {
2568 
2569 	if (_debug_parse_err_node >= 0)
2570 		return _debug_parse_err_file;
2571 
2572 	ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, "");
2573 	int l = _debug_call_stack_pos - p_level - 1;
2574 	return _call_stack[l].instance->get_script_ptr()->get_path();
2575 }
debug_get_stack_level_locals(int p_level,List<String> * p_locals,List<Variant> * p_values,int p_max_subitems,int p_max_depth)2576 void VisualScriptLanguage::debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
2577 
2578 	if (_debug_parse_err_node >= 0)
2579 		return;
2580 
2581 	ERR_FAIL_INDEX(p_level, _debug_call_stack_pos);
2582 
2583 	int l = _debug_call_stack_pos - p_level - 1;
2584 	const StringName *f = _call_stack[l].function;
2585 
2586 	ERR_FAIL_COND(!_call_stack[l].instance->functions.has(*f));
2587 	//VisualScriptInstance::Function *func = &_call_stack[l].instance->functions[*f];
2588 
2589 	VisualScriptNodeInstance *node = _call_stack[l].instance->instances[*_call_stack[l].current_id];
2590 	ERR_FAIL_COND(!node);
2591 
2592 	p_locals->push_back("node_name");
2593 	p_values->push_back(node->get_base_node()->get_text());
2594 
2595 	for (int i = 0; i < node->input_port_count; i++) {
2596 		String name = node->get_base_node()->get_input_value_port_info(i).name;
2597 		if (name == String()) {
2598 			name = "in_" + itos(i);
2599 		}
2600 
2601 		p_locals->push_back("input/" + name);
2602 
2603 		//value is trickier
2604 
2605 		int in_from = node->input_ports[i];
2606 		int in_value = in_from & VisualScriptNodeInstance::INPUT_MASK;
2607 
2608 		if (in_from & VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT) {
2609 			p_values->push_back(_call_stack[l].instance->default_values[in_value]);
2610 		} else {
2611 			p_values->push_back(_call_stack[l].stack[in_value]);
2612 		}
2613 	}
2614 
2615 	for (int i = 0; i < node->output_port_count; i++) {
2616 
2617 		String name = node->get_base_node()->get_output_value_port_info(i).name;
2618 		if (name == String()) {
2619 			name = "out_" + itos(i);
2620 		}
2621 
2622 		p_locals->push_back("output/" + name);
2623 
2624 		//value is trickier
2625 
2626 		int in_from = node->output_ports[i];
2627 		p_values->push_back(_call_stack[l].stack[in_from]);
2628 	}
2629 
2630 	for (int i = 0; i < node->get_working_memory_size(); i++) {
2631 		p_locals->push_back("working_mem/mem_" + itos(i));
2632 		p_values->push_back((*_call_stack[l].work_mem)[i]);
2633 	}
2634 
2635 	/*
2636     ERR_FAIL_INDEX(p_level,_debug_call_stack_pos);
2637 
2638 
2639     VisualFunction *f = _call_stack[l].function;
2640 
2641     List<Pair<StringName,int> > locals;
2642 
2643     f->debug_get_stack_member_state(*_call_stack[l].line,&locals);
2644     for( List<Pair<StringName,int> >::Element *E = locals.front();E;E=E->next() ) {
2645 
2646 	p_locals->push_back(E->get().first);
2647 	p_values->push_back(_call_stack[l].stack[E->get().second]);
2648     }
2649 */
2650 }
debug_get_stack_level_members(int p_level,List<String> * p_members,List<Variant> * p_values,int p_max_subitems,int p_max_depth)2651 void VisualScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
2652 
2653 	if (_debug_parse_err_node >= 0)
2654 		return;
2655 
2656 	ERR_FAIL_INDEX(p_level, _debug_call_stack_pos);
2657 	int l = _debug_call_stack_pos - p_level - 1;
2658 
2659 	Ref<VisualScript> vs = _call_stack[l].instance->get_script();
2660 	if (vs.is_null())
2661 		return;
2662 
2663 	List<StringName> vars;
2664 	vs->get_variable_list(&vars);
2665 	for (List<StringName>::Element *E = vars.front(); E; E = E->next()) {
2666 		Variant v;
2667 		if (_call_stack[l].instance->get_variable(E->get(), &v)) {
2668 			p_members->push_back("variables/" + E->get());
2669 			p_values->push_back(v);
2670 		}
2671 	}
2672 }
2673 
debug_get_globals(List<String> * p_locals,List<Variant> * p_values,int p_max_subitems,int p_max_depth)2674 void VisualScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
2675 
2676 	//no globals are really reachable in gdscript
2677 }
debug_parse_stack_level_expression(int p_level,const String & p_expression,int p_max_subitems,int p_max_depth)2678 String VisualScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) {
2679 
2680 	return "";
2681 }
2682 
reload_all_scripts()2683 void VisualScriptLanguage::reload_all_scripts() {
2684 }
reload_tool_script(const Ref<Script> & p_script,bool p_soft_reload)2685 void VisualScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) {
2686 }
2687 /* LOADER FUNCTIONS */
2688 
get_recognized_extensions(List<String> * p_extensions) const2689 void VisualScriptLanguage::get_recognized_extensions(List<String> *p_extensions) const {
2690 
2691 	p_extensions->push_back("vs");
2692 }
get_public_functions(List<MethodInfo> * p_functions) const2693 void VisualScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const {
2694 }
get_public_constants(List<Pair<String,Variant>> * p_constants) const2695 void VisualScriptLanguage::get_public_constants(List<Pair<String, Variant> > *p_constants) const {
2696 }
2697 
profiling_start()2698 void VisualScriptLanguage::profiling_start() {
2699 }
profiling_stop()2700 void VisualScriptLanguage::profiling_stop() {
2701 }
2702 
profiling_get_accumulated_data(ProfilingInfo * p_info_arr,int p_info_max)2703 int VisualScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) {
2704 
2705 	return 0;
2706 }
2707 
profiling_get_frame_data(ProfilingInfo * p_info_arr,int p_info_max)2708 int VisualScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) {
2709 
2710 	return 0;
2711 }
2712 
2713 VisualScriptLanguage *VisualScriptLanguage::singleton = NULL;
2714 
add_register_func(const String & p_name,VisualScriptNodeRegisterFunc p_func)2715 void VisualScriptLanguage::add_register_func(const String &p_name, VisualScriptNodeRegisterFunc p_func) {
2716 
2717 	ERR_FAIL_COND(register_funcs.has(p_name));
2718 	register_funcs[p_name] = p_func;
2719 }
2720 
remove_register_func(const String & p_name)2721 void VisualScriptLanguage::remove_register_func(const String &p_name) {
2722 	ERR_FAIL_COND(!register_funcs.has(p_name));
2723 	register_funcs.erase(p_name);
2724 }
2725 
create_node_from_name(const String & p_name)2726 Ref<VisualScriptNode> VisualScriptLanguage::create_node_from_name(const String &p_name) {
2727 
2728 	ERR_FAIL_COND_V(!register_funcs.has(p_name), Ref<VisualScriptNode>());
2729 
2730 	return register_funcs[p_name](p_name);
2731 }
2732 
get_registered_node_names(List<String> * r_names)2733 void VisualScriptLanguage::get_registered_node_names(List<String> *r_names) {
2734 
2735 	for (Map<String, VisualScriptNodeRegisterFunc>::Element *E = register_funcs.front(); E; E = E->next()) {
2736 		r_names->push_back(E->key());
2737 	}
2738 }
2739 
VisualScriptLanguage()2740 VisualScriptLanguage::VisualScriptLanguage() {
2741 
2742 	notification = "_notification";
2743 	_step = "_step";
2744 	_subcall = "_subcall";
2745 	singleton = this;
2746 #ifndef NO_THREADS
2747 	lock = Mutex::create();
2748 #endif
2749 
2750 	_debug_parse_err_node = -1;
2751 	_debug_parse_err_file = "";
2752 	_debug_call_stack_pos = 0;
2753 	int dmcs = GLOBAL_DEF("debug/settings/visual_script/max_call_stack", 1024);
2754 	ProjectSettings::get_singleton()->set_custom_property_info("debug/settings/visual_script/max_call_stack", PropertyInfo(Variant::INT, "debug/settings/visual_script/max_call_stack", PROPERTY_HINT_RANGE, "1024,4096,1,or_greater")); //minimum is 1024
2755 
2756 	if (ScriptDebugger::get_singleton()) {
2757 		//debugging enabled!
2758 		_debug_max_call_stack = dmcs;
2759 		_call_stack = memnew_arr(CallLevel, _debug_max_call_stack + 1);
2760 
2761 	} else {
2762 		_debug_max_call_stack = 0;
2763 		_call_stack = NULL;
2764 	}
2765 }
2766 
~VisualScriptLanguage()2767 VisualScriptLanguage::~VisualScriptLanguage() {
2768 
2769 	if (lock)
2770 		memdelete(lock);
2771 
2772 	if (_call_stack) {
2773 		memdelete_arr(_call_stack);
2774 	}
2775 	singleton = NULL;
2776 }
2777