1 /*************************************************************************/
2 /*  visual_script_func_nodes.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_func_nodes.h"
32 
33 #include "core/engine.h"
34 #include "core/io/resource_loader.h"
35 #include "core/os/os.h"
36 #include "scene/main/node.h"
37 #include "scene/main/scene_tree.h"
38 #include "visual_script_nodes.h"
39 
40 //////////////////////////////////////////
41 ////////////////CALL//////////////////////
42 //////////////////////////////////////////
43 
get_output_sequence_port_count() const44 int VisualScriptFunctionCall::get_output_sequence_port_count() const {
45 
46 	if ((method_cache.flags & METHOD_FLAG_CONST && call_mode != CALL_MODE_INSTANCE) || (call_mode == CALL_MODE_BASIC_TYPE && Variant::is_method_const(basic_type, function)))
47 		return 0;
48 	else
49 		return 1;
50 }
51 
has_input_sequence_port() const52 bool VisualScriptFunctionCall::has_input_sequence_port() const {
53 
54 	return !((method_cache.flags & METHOD_FLAG_CONST && call_mode != CALL_MODE_INSTANCE) || (call_mode == CALL_MODE_BASIC_TYPE && Variant::is_method_const(basic_type, function)));
55 }
56 #ifdef TOOLS_ENABLED
57 
_find_script_node(Node * p_edited_scene,Node * p_current_node,const Ref<Script> & script)58 static Node *_find_script_node(Node *p_edited_scene, Node *p_current_node, const Ref<Script> &script) {
59 
60 	if (p_edited_scene != p_current_node && p_current_node->get_owner() != p_edited_scene)
61 		return NULL;
62 
63 	Ref<Script> scr = p_current_node->get_script();
64 
65 	if (scr.is_valid() && scr == script)
66 		return p_current_node;
67 
68 	for (int i = 0; i < p_current_node->get_child_count(); i++) {
69 		Node *n = _find_script_node(p_edited_scene, p_current_node->get_child(i), script);
70 		if (n)
71 			return n;
72 	}
73 
74 	return NULL;
75 }
76 
77 #endif
_get_base_node() const78 Node *VisualScriptFunctionCall::_get_base_node() const {
79 
80 #ifdef TOOLS_ENABLED
81 	Ref<Script> script = get_visual_script();
82 	if (!script.is_valid())
83 		return NULL;
84 
85 	MainLoop *main_loop = OS::get_singleton()->get_main_loop();
86 	SceneTree *scene_tree = Object::cast_to<SceneTree>(main_loop);
87 
88 	if (!scene_tree)
89 		return NULL;
90 
91 	Node *edited_scene = scene_tree->get_edited_scene_root();
92 
93 	if (!edited_scene)
94 		return NULL;
95 
96 	Node *script_node = _find_script_node(edited_scene, edited_scene, script);
97 
98 	if (!script_node)
99 		return NULL;
100 
101 	if (!script_node->has_node(base_path))
102 		return NULL;
103 
104 	Node *path_to = script_node->get_node(base_path);
105 
106 	return path_to;
107 #else
108 
109 	return NULL;
110 #endif
111 }
112 
_get_base_type() const113 StringName VisualScriptFunctionCall::_get_base_type() const {
114 
115 	if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid())
116 		return get_visual_script()->get_instance_base_type();
117 	else if (call_mode == CALL_MODE_NODE_PATH && get_visual_script().is_valid()) {
118 		Node *path = _get_base_node();
119 		if (path)
120 			return path->get_class();
121 	}
122 
123 	return base_type;
124 }
125 
get_input_value_port_count() const126 int VisualScriptFunctionCall::get_input_value_port_count() const {
127 
128 	if (call_mode == CALL_MODE_BASIC_TYPE) {
129 		Vector<Variant::Type> types = Variant::get_method_argument_types(basic_type, function);
130 		return types.size() + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) + 1;
131 
132 	} else {
133 
134 		MethodBind *mb = ClassDB::get_method(_get_base_type(), function);
135 		if (mb) {
136 			int defaulted_args = mb->get_argument_count() < use_default_args ? mb->get_argument_count() : use_default_args;
137 			return mb->get_argument_count() + (call_mode == CALL_MODE_INSTANCE ? 1 : 0) + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) - defaulted_args;
138 		}
139 
140 		int defaulted_args = method_cache.arguments.size() < use_default_args ? method_cache.arguments.size() : use_default_args;
141 		return method_cache.arguments.size() + (call_mode == CALL_MODE_INSTANCE ? 1 : 0) + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) - defaulted_args;
142 	}
143 }
get_output_value_port_count() const144 int VisualScriptFunctionCall::get_output_value_port_count() const {
145 
146 	if (call_mode == CALL_MODE_BASIC_TYPE) {
147 
148 		bool returns = false;
149 		Variant::get_method_return_type(basic_type, function, &returns);
150 		return returns ? 1 : 0;
151 
152 	} else {
153 		int ret;
154 		MethodBind *mb = ClassDB::get_method(_get_base_type(), function);
155 		if (mb) {
156 			ret = mb->has_return() ? 1 : 0;
157 		} else
158 			ret = 1; //it is assumed that script always returns something
159 
160 		if (call_mode == CALL_MODE_INSTANCE) {
161 			ret++;
162 		}
163 
164 		return ret;
165 	}
166 }
167 
get_output_sequence_port_text(int p_port) const168 String VisualScriptFunctionCall::get_output_sequence_port_text(int p_port) const {
169 
170 	return String();
171 }
172 
get_input_value_port_info(int p_idx) const173 PropertyInfo VisualScriptFunctionCall::get_input_value_port_info(int p_idx) const {
174 
175 	if (call_mode == CALL_MODE_INSTANCE || call_mode == CALL_MODE_BASIC_TYPE) {
176 		if (p_idx == 0) {
177 			PropertyInfo pi;
178 			pi.type = (call_mode == CALL_MODE_INSTANCE ? Variant::OBJECT : basic_type);
179 			pi.name = (call_mode == CALL_MODE_INSTANCE ? String("instance") : Variant::get_type_name(basic_type).to_lower());
180 			return pi;
181 		} else {
182 			p_idx--;
183 		}
184 	}
185 
186 	if (rpc_call_mode >= RPC_RELIABLE_TO_ID) {
187 
188 		if (p_idx == 0) {
189 			return PropertyInfo(Variant::INT, "peer_id");
190 		} else {
191 			p_idx--;
192 		}
193 	}
194 
195 #ifdef DEBUG_METHODS_ENABLED
196 
197 	if (call_mode == CALL_MODE_BASIC_TYPE) {
198 
199 		Vector<StringName> names = Variant::get_method_argument_names(basic_type, function);
200 		Vector<Variant::Type> types = Variant::get_method_argument_types(basic_type, function);
201 		return PropertyInfo(types[p_idx], names[p_idx]);
202 
203 	} else {
204 
205 		MethodBind *mb = ClassDB::get_method(_get_base_type(), function);
206 		if (mb) {
207 			return mb->get_argument_info(p_idx);
208 		}
209 
210 		if (p_idx >= 0 && p_idx < method_cache.arguments.size()) {
211 			return method_cache.arguments[p_idx];
212 		}
213 
214 		return PropertyInfo();
215 	}
216 #else
217 	return PropertyInfo();
218 #endif
219 }
220 
get_output_value_port_info(int p_idx) const221 PropertyInfo VisualScriptFunctionCall::get_output_value_port_info(int p_idx) const {
222 
223 #ifdef DEBUG_METHODS_ENABLED
224 
225 	if (call_mode == CALL_MODE_BASIC_TYPE) {
226 
227 		return PropertyInfo(Variant::get_method_return_type(basic_type, function), "");
228 	} else {
229 
230 		if (call_mode == CALL_MODE_INSTANCE) {
231 			if (p_idx == 0) {
232 				return PropertyInfo(Variant::OBJECT, "pass", PROPERTY_HINT_TYPE_STRING, get_base_type());
233 			} else {
234 				p_idx--;
235 			}
236 		}
237 
238 		PropertyInfo ret;
239 
240 		/*MethodBind *mb = ClassDB::get_method(_get_base_type(),function);
241 		if (mb) {
242 
243 			ret = mb->get_argument_info(-1);
244 		} else {*/
245 
246 		ret = method_cache.return_val;
247 
248 		//}
249 
250 		if (call_mode == CALL_MODE_INSTANCE) {
251 			ret.name = "return";
252 		} else {
253 			ret.name = "";
254 		}
255 		return ret;
256 	}
257 #else
258 	return PropertyInfo();
259 #endif
260 }
261 
get_caption() const262 String VisualScriptFunctionCall::get_caption() const {
263 	if (call_mode == CALL_MODE_SELF)
264 		return "  " + String(function) + "()";
265 	if (call_mode == CALL_MODE_SINGLETON)
266 		return String(singleton) + ":" + String(function) + "()";
267 	else if (call_mode == CALL_MODE_BASIC_TYPE)
268 		return Variant::get_type_name(basic_type) + "." + String(function) + "()";
269 	else if (call_mode == CALL_MODE_NODE_PATH)
270 		return " [" + String(base_path.simplified()) + "]." + String(function) + "()";
271 	else
272 		return "  " + base_type + "." + String(function) + "()";
273 }
274 
get_text() const275 String VisualScriptFunctionCall::get_text() const {
276 
277 	if (rpc_call_mode) {
278 		return "RPC";
279 	}
280 	return "";
281 }
282 
set_basic_type(Variant::Type p_type)283 void VisualScriptFunctionCall::set_basic_type(Variant::Type p_type) {
284 
285 	if (basic_type == p_type)
286 		return;
287 	basic_type = p_type;
288 
289 	_change_notify();
290 	ports_changed_notify();
291 }
292 
get_basic_type() const293 Variant::Type VisualScriptFunctionCall::get_basic_type() const {
294 
295 	return basic_type;
296 }
297 
set_base_type(const StringName & p_type)298 void VisualScriptFunctionCall::set_base_type(const StringName &p_type) {
299 
300 	if (base_type == p_type)
301 		return;
302 
303 	base_type = p_type;
304 	_change_notify();
305 	ports_changed_notify();
306 }
307 
get_base_type() const308 StringName VisualScriptFunctionCall::get_base_type() const {
309 
310 	return base_type;
311 }
312 
set_base_script(const String & p_path)313 void VisualScriptFunctionCall::set_base_script(const String &p_path) {
314 
315 	if (base_script == p_path)
316 		return;
317 
318 	base_script = p_path;
319 	_change_notify();
320 	ports_changed_notify();
321 }
322 
get_base_script() const323 String VisualScriptFunctionCall::get_base_script() const {
324 
325 	return base_script;
326 }
327 
set_singleton(const StringName & p_type)328 void VisualScriptFunctionCall::set_singleton(const StringName &p_type) {
329 
330 	if (singleton == p_type)
331 		return;
332 
333 	singleton = p_type;
334 	Object *obj = Engine::get_singleton()->get_singleton_object(singleton);
335 	if (obj) {
336 		base_type = obj->get_class();
337 	}
338 
339 	_change_notify();
340 	ports_changed_notify();
341 }
342 
get_singleton() const343 StringName VisualScriptFunctionCall::get_singleton() const {
344 
345 	return singleton;
346 }
347 
_update_method_cache()348 void VisualScriptFunctionCall::_update_method_cache() {
349 	StringName type;
350 	Ref<Script> script;
351 
352 	if (call_mode == CALL_MODE_NODE_PATH) {
353 
354 		Node *node = _get_base_node();
355 		if (node) {
356 			type = node->get_class();
357 			base_type = type; //cache, too
358 			script = node->get_script();
359 		}
360 	} else if (call_mode == CALL_MODE_SELF) {
361 
362 		if (get_visual_script().is_valid()) {
363 			type = get_visual_script()->get_instance_base_type();
364 			base_type = type; //cache, too
365 			script = get_visual_script();
366 		}
367 
368 	} else if (call_mode == CALL_MODE_SINGLETON) {
369 
370 		Object *obj = Engine::get_singleton()->get_singleton_object(singleton);
371 		if (obj) {
372 			type = obj->get_class();
373 			script = obj->get_script();
374 		}
375 
376 	} else if (call_mode == CALL_MODE_INSTANCE) {
377 
378 		type = base_type;
379 		if (base_script != String()) {
380 
381 			if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) {
382 
383 				ScriptServer::edit_request_func(base_script); //make sure it's loaded
384 			}
385 
386 			if (ResourceCache::has(base_script)) {
387 
388 				script = Ref<Resource>(ResourceCache::get(base_script));
389 			} else {
390 				return;
391 			}
392 		}
393 	}
394 
395 	MethodBind *mb = ClassDB::get_method(type, function);
396 	if (mb) {
397 		use_default_args = mb->get_default_argument_count();
398 		method_cache = MethodInfo();
399 		for (int i = 0; i < mb->get_argument_count(); i++) {
400 #ifdef DEBUG_METHODS_ENABLED
401 			method_cache.arguments.push_back(mb->get_argument_info(i));
402 #else
403 			method_cache.arguments.push_back(PropertyInfo());
404 #endif
405 		}
406 
407 		if (mb->is_const()) {
408 			method_cache.flags |= METHOD_FLAG_CONST;
409 		}
410 
411 #ifdef DEBUG_METHODS_ENABLED
412 
413 		method_cache.return_val = mb->get_return_info();
414 #endif
415 
416 		if (mb->is_vararg()) {
417 			//for vararg just give it 10 arguments (should be enough for most use cases)
418 			for (int i = 0; i < 10; i++) {
419 				method_cache.arguments.push_back(PropertyInfo(Variant::NIL, "arg" + itos(i)));
420 				use_default_args++;
421 			}
422 		}
423 	} else if (script.is_valid() && script->has_method(function)) {
424 
425 		method_cache = script->get_method_info(function);
426 		use_default_args = method_cache.default_arguments.size();
427 	}
428 }
429 
set_function(const StringName & p_type)430 void VisualScriptFunctionCall::set_function(const StringName &p_type) {
431 
432 	if (function == p_type)
433 		return;
434 
435 	function = p_type;
436 
437 	if (call_mode == CALL_MODE_BASIC_TYPE) {
438 		use_default_args = Variant::get_method_default_arguments(basic_type, function).size();
439 	} else {
440 		//update all caches
441 
442 		_update_method_cache();
443 	}
444 
445 	_change_notify();
446 	ports_changed_notify();
447 }
get_function() const448 StringName VisualScriptFunctionCall::get_function() const {
449 
450 	return function;
451 }
452 
set_base_path(const NodePath & p_type)453 void VisualScriptFunctionCall::set_base_path(const NodePath &p_type) {
454 
455 	if (base_path == p_type)
456 		return;
457 
458 	base_path = p_type;
459 	_change_notify();
460 	ports_changed_notify();
461 }
462 
get_base_path() const463 NodePath VisualScriptFunctionCall::get_base_path() const {
464 
465 	return base_path;
466 }
467 
set_call_mode(CallMode p_mode)468 void VisualScriptFunctionCall::set_call_mode(CallMode p_mode) {
469 
470 	if (call_mode == p_mode)
471 		return;
472 
473 	call_mode = p_mode;
474 	_change_notify();
475 	ports_changed_notify();
476 }
get_call_mode() const477 VisualScriptFunctionCall::CallMode VisualScriptFunctionCall::get_call_mode() const {
478 
479 	return call_mode;
480 }
481 
set_use_default_args(int p_amount)482 void VisualScriptFunctionCall::set_use_default_args(int p_amount) {
483 
484 	if (use_default_args == p_amount)
485 		return;
486 
487 	use_default_args = p_amount;
488 	ports_changed_notify();
489 }
490 
set_rpc_call_mode(VisualScriptFunctionCall::RPCCallMode p_mode)491 void VisualScriptFunctionCall::set_rpc_call_mode(VisualScriptFunctionCall::RPCCallMode p_mode) {
492 
493 	if (rpc_call_mode == p_mode)
494 		return;
495 	rpc_call_mode = p_mode;
496 	ports_changed_notify();
497 	_change_notify();
498 }
499 
get_rpc_call_mode() const500 VisualScriptFunctionCall::RPCCallMode VisualScriptFunctionCall::get_rpc_call_mode() const {
501 
502 	return rpc_call_mode;
503 }
504 
get_use_default_args() const505 int VisualScriptFunctionCall::get_use_default_args() const {
506 
507 	return use_default_args;
508 }
509 
set_validate(bool p_amount)510 void VisualScriptFunctionCall::set_validate(bool p_amount) {
511 
512 	validate = p_amount;
513 }
514 
get_validate() const515 bool VisualScriptFunctionCall::get_validate() const {
516 
517 	return validate;
518 }
519 
_set_argument_cache(const Dictionary & p_cache)520 void VisualScriptFunctionCall::_set_argument_cache(const Dictionary &p_cache) {
521 	//so everything works in case all else fails
522 	method_cache = MethodInfo::from_dict(p_cache);
523 }
524 
_get_argument_cache() const525 Dictionary VisualScriptFunctionCall::_get_argument_cache() const {
526 
527 	return method_cache;
528 }
529 
_validate_property(PropertyInfo & property) const530 void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const {
531 
532 	if (property.name == "base_type") {
533 		if (call_mode != CALL_MODE_INSTANCE) {
534 			property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
535 		}
536 	}
537 
538 	if (property.name == "base_script") {
539 		if (call_mode != CALL_MODE_INSTANCE) {
540 			property.usage = 0;
541 		}
542 	}
543 
544 	if (property.name == "basic_type") {
545 		if (call_mode != CALL_MODE_BASIC_TYPE) {
546 			property.usage = 0;
547 		}
548 	}
549 
550 	if (property.name == "singleton") {
551 		if (call_mode != CALL_MODE_SINGLETON) {
552 			property.usage = 0;
553 		} else {
554 			List<Engine::Singleton> names;
555 			Engine::get_singleton()->get_singletons(&names);
556 			property.hint = PROPERTY_HINT_ENUM;
557 			String sl;
558 			for (List<Engine::Singleton>::Element *E = names.front(); E; E = E->next()) {
559 				if (sl != String())
560 					sl += ",";
561 				sl += E->get().name;
562 			}
563 			property.hint_string = sl;
564 		}
565 	}
566 
567 	if (property.name == "node_path") {
568 		if (call_mode != CALL_MODE_NODE_PATH) {
569 			property.usage = 0;
570 		} else {
571 
572 			Node *bnode = _get_base_node();
573 			if (bnode) {
574 				property.hint_string = bnode->get_path(); //convert to loong string
575 			}
576 		}
577 	}
578 
579 	if (property.name == "function") {
580 
581 		if (call_mode == CALL_MODE_BASIC_TYPE) {
582 
583 			property.hint = PROPERTY_HINT_METHOD_OF_VARIANT_TYPE;
584 			property.hint_string = Variant::get_type_name(basic_type);
585 
586 		} else if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid()) {
587 			property.hint = PROPERTY_HINT_METHOD_OF_SCRIPT;
588 			property.hint_string = itos(get_visual_script()->get_instance_id());
589 		} else if (call_mode == CALL_MODE_SINGLETON) {
590 
591 			Object *obj = Engine::get_singleton()->get_singleton_object(singleton);
592 			if (obj) {
593 				property.hint = PROPERTY_HINT_METHOD_OF_INSTANCE;
594 				property.hint_string = itos(obj->get_instance_id());
595 			} else {
596 
597 				property.hint = PROPERTY_HINT_METHOD_OF_BASE_TYPE;
598 				property.hint_string = base_type; //should be cached
599 			}
600 		} else if (call_mode == CALL_MODE_INSTANCE) {
601 			property.hint = PROPERTY_HINT_METHOD_OF_BASE_TYPE;
602 			property.hint_string = base_type;
603 
604 			if (base_script != String()) {
605 				if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) {
606 
607 					ScriptServer::edit_request_func(base_script); //make sure it's loaded
608 				}
609 
610 				if (ResourceCache::has(base_script)) {
611 
612 					Ref<Script> script = Ref<Resource>(ResourceCache::get(base_script));
613 					if (script.is_valid()) {
614 
615 						property.hint = PROPERTY_HINT_METHOD_OF_SCRIPT;
616 						property.hint_string = itos(script->get_instance_id());
617 					}
618 				}
619 			}
620 
621 		} else if (call_mode == CALL_MODE_NODE_PATH) {
622 			Node *node = _get_base_node();
623 			if (node) {
624 				property.hint = PROPERTY_HINT_METHOD_OF_INSTANCE;
625 				property.hint_string = itos(node->get_instance_id());
626 			} else {
627 				property.hint = PROPERTY_HINT_METHOD_OF_BASE_TYPE;
628 				property.hint_string = get_base_type();
629 			}
630 		}
631 	}
632 
633 	if (property.name == "use_default_args") {
634 
635 		property.hint = PROPERTY_HINT_RANGE;
636 
637 		int mc = 0;
638 
639 		if (call_mode == CALL_MODE_BASIC_TYPE) {
640 
641 			mc = Variant::get_method_default_arguments(basic_type, function).size();
642 		} else {
643 			MethodBind *mb = ClassDB::get_method(_get_base_type(), function);
644 			if (mb) {
645 
646 				mc = mb->get_default_argument_count();
647 			}
648 		}
649 
650 		if (mc == 0) {
651 			property.usage = 0; //do not show
652 		} else {
653 
654 			property.hint_string = "0," + itos(mc) + ",1";
655 		}
656 	}
657 
658 	if (property.name == "rpc_call_mode") {
659 		if (call_mode == CALL_MODE_BASIC_TYPE) {
660 			property.usage = 0;
661 		}
662 	}
663 }
664 
_bind_methods()665 void VisualScriptFunctionCall::_bind_methods() {
666 
667 	ClassDB::bind_method(D_METHOD("set_base_type", "base_type"), &VisualScriptFunctionCall::set_base_type);
668 	ClassDB::bind_method(D_METHOD("get_base_type"), &VisualScriptFunctionCall::get_base_type);
669 
670 	ClassDB::bind_method(D_METHOD("set_base_script", "base_script"), &VisualScriptFunctionCall::set_base_script);
671 	ClassDB::bind_method(D_METHOD("get_base_script"), &VisualScriptFunctionCall::get_base_script);
672 
673 	ClassDB::bind_method(D_METHOD("set_basic_type", "basic_type"), &VisualScriptFunctionCall::set_basic_type);
674 	ClassDB::bind_method(D_METHOD("get_basic_type"), &VisualScriptFunctionCall::get_basic_type);
675 
676 	ClassDB::bind_method(D_METHOD("set_singleton", "singleton"), &VisualScriptFunctionCall::set_singleton);
677 	ClassDB::bind_method(D_METHOD("get_singleton"), &VisualScriptFunctionCall::get_singleton);
678 
679 	ClassDB::bind_method(D_METHOD("set_function", "function"), &VisualScriptFunctionCall::set_function);
680 	ClassDB::bind_method(D_METHOD("get_function"), &VisualScriptFunctionCall::get_function);
681 
682 	ClassDB::bind_method(D_METHOD("set_call_mode", "mode"), &VisualScriptFunctionCall::set_call_mode);
683 	ClassDB::bind_method(D_METHOD("get_call_mode"), &VisualScriptFunctionCall::get_call_mode);
684 
685 	ClassDB::bind_method(D_METHOD("set_base_path", "base_path"), &VisualScriptFunctionCall::set_base_path);
686 	ClassDB::bind_method(D_METHOD("get_base_path"), &VisualScriptFunctionCall::get_base_path);
687 
688 	ClassDB::bind_method(D_METHOD("set_use_default_args", "amount"), &VisualScriptFunctionCall::set_use_default_args);
689 	ClassDB::bind_method(D_METHOD("get_use_default_args"), &VisualScriptFunctionCall::get_use_default_args);
690 
691 	ClassDB::bind_method(D_METHOD("_set_argument_cache", "argument_cache"), &VisualScriptFunctionCall::_set_argument_cache);
692 	ClassDB::bind_method(D_METHOD("_get_argument_cache"), &VisualScriptFunctionCall::_get_argument_cache);
693 
694 	ClassDB::bind_method(D_METHOD("set_rpc_call_mode", "mode"), &VisualScriptFunctionCall::set_rpc_call_mode);
695 	ClassDB::bind_method(D_METHOD("get_rpc_call_mode"), &VisualScriptFunctionCall::get_rpc_call_mode);
696 
697 	ClassDB::bind_method(D_METHOD("set_validate", "enable"), &VisualScriptFunctionCall::set_validate);
698 	ClassDB::bind_method(D_METHOD("get_validate"), &VisualScriptFunctionCall::get_validate);
699 
700 	String bt;
701 	for (int i = 0; i < Variant::VARIANT_MAX; i++) {
702 		if (i > 0)
703 			bt += ",";
704 
705 		bt += Variant::get_type_name(Variant::Type(i));
706 	}
707 
708 	List<String> script_extensions;
709 	for (int i = 0; i < ScriptServer::get_language_count(); i++) {
710 		ScriptServer::get_language(i)->get_recognized_extensions(&script_extensions);
711 	}
712 
713 	String script_ext_hint;
714 	for (List<String>::Element *E = script_extensions.front(); E; E = E->next()) {
715 		if (script_ext_hint != String())
716 			script_ext_hint += ",";
717 		script_ext_hint += "*." + E->get();
718 	}
719 
720 	ADD_PROPERTY(PropertyInfo(Variant::INT, "call_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type,Singleton"), "set_call_mode", "get_call_mode");
721 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type");
722 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_script", PROPERTY_HINT_FILE, script_ext_hint), "set_base_script", "get_base_script");
723 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "singleton"), "set_singleton", "get_singleton");
724 	ADD_PROPERTY(PropertyInfo(Variant::INT, "basic_type", PROPERTY_HINT_ENUM, bt), "set_basic_type", "get_basic_type");
725 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path");
726 	ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "argument_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_argument_cache", "_get_argument_cache");
727 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "function"), "set_function", "get_function"); //when set, if loaded properly, will override argument count.
728 	ADD_PROPERTY(PropertyInfo(Variant::INT, "use_default_args"), "set_use_default_args", "get_use_default_args");
729 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "validate"), "set_validate", "get_validate");
730 	ADD_PROPERTY(PropertyInfo(Variant::INT, "rpc_call_mode", PROPERTY_HINT_ENUM, "Disabled,Reliable,Unreliable,ReliableToID,UnreliableToID"), "set_rpc_call_mode", "get_rpc_call_mode"); //when set, if loaded properly, will override argument count.
731 
732 	BIND_ENUM_CONSTANT(CALL_MODE_SELF);
733 	BIND_ENUM_CONSTANT(CALL_MODE_NODE_PATH);
734 	BIND_ENUM_CONSTANT(CALL_MODE_INSTANCE);
735 	BIND_ENUM_CONSTANT(CALL_MODE_BASIC_TYPE);
736 	BIND_ENUM_CONSTANT(CALL_MODE_SINGLETON);
737 
738 	BIND_ENUM_CONSTANT(RPC_DISABLED);
739 	BIND_ENUM_CONSTANT(RPC_RELIABLE);
740 	BIND_ENUM_CONSTANT(RPC_UNRELIABLE);
741 	BIND_ENUM_CONSTANT(RPC_RELIABLE_TO_ID);
742 	BIND_ENUM_CONSTANT(RPC_UNRELIABLE_TO_ID);
743 }
744 
745 class VisualScriptNodeInstanceFunctionCall : public VisualScriptNodeInstance {
746 public:
747 	VisualScriptFunctionCall::CallMode call_mode;
748 	NodePath node_path;
749 	int input_args;
750 	bool validate;
751 	int returns;
752 	VisualScriptFunctionCall::RPCCallMode rpc_mode;
753 	StringName function;
754 	StringName singleton;
755 
756 	VisualScriptFunctionCall *node;
757 	VisualScriptInstance *instance;
758 
759 	//virtual int get_working_memory_size() const { return 0; }
760 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
761 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
762 
call_rpc(Object * p_base,const Variant ** p_args,int p_argcount)763 	_FORCE_INLINE_ bool call_rpc(Object *p_base, const Variant **p_args, int p_argcount) {
764 
765 		if (!p_base)
766 			return false;
767 
768 		Node *node = Object::cast_to<Node>(p_base);
769 		if (!node)
770 			return false;
771 
772 		int to_id = 0;
773 		bool reliable = true;
774 
775 		if (rpc_mode >= VisualScriptFunctionCall::RPC_RELIABLE_TO_ID) {
776 			to_id = *p_args[0];
777 			p_args += 1;
778 			p_argcount -= 1;
779 			if (rpc_mode == VisualScriptFunctionCall::RPC_UNRELIABLE_TO_ID) {
780 				reliable = false;
781 			}
782 		} else if (rpc_mode == VisualScriptFunctionCall::RPC_UNRELIABLE) {
783 			reliable = false;
784 		}
785 
786 		node->rpcp(to_id, !reliable, function, p_args, p_argcount);
787 
788 		return true;
789 	}
790 
step(const Variant ** p_inputs,Variant ** p_outputs,StartMode p_start_mode,Variant * p_working_mem,Variant::CallError & r_error,String & r_error_str)791 	virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) {
792 
793 		switch (call_mode) {
794 
795 			case VisualScriptFunctionCall::CALL_MODE_SELF: {
796 
797 				Object *object = instance->get_owner_ptr();
798 
799 				if (rpc_mode) {
800 					call_rpc(object, p_inputs, input_args);
801 				} else if (returns) {
802 					*p_outputs[0] = object->call(function, p_inputs, input_args, r_error);
803 				} else {
804 					object->call(function, p_inputs, input_args, r_error);
805 				}
806 			} break;
807 			case VisualScriptFunctionCall::CALL_MODE_NODE_PATH: {
808 
809 				Node *node = Object::cast_to<Node>(instance->get_owner_ptr());
810 				if (!node) {
811 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
812 					r_error_str = "Base object is not a Node!";
813 					return 0;
814 				}
815 
816 				Node *another = node->get_node(node_path);
817 				if (!another) {
818 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
819 					r_error_str = "Path does not lead Node!";
820 					return 0;
821 				}
822 
823 				if (rpc_mode) {
824 					call_rpc(node, p_inputs, input_args);
825 				} else if (returns) {
826 					*p_outputs[0] = another->call(function, p_inputs, input_args, r_error);
827 				} else {
828 					another->call(function, p_inputs, input_args, r_error);
829 				}
830 
831 			} break;
832 			case VisualScriptFunctionCall::CALL_MODE_INSTANCE:
833 			case VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE: {
834 
835 				Variant v = *p_inputs[0];
836 
837 				if (rpc_mode) {
838 					Object *obj = v;
839 					if (obj) {
840 						call_rpc(obj, p_inputs + 1, input_args - 1);
841 					}
842 				} else if (returns) {
843 					if (call_mode == VisualScriptFunctionCall::CALL_MODE_INSTANCE) {
844 						if (returns >= 2) {
845 							*p_outputs[1] = v.call(function, p_inputs + 1, input_args, r_error);
846 						} else if (returns == 1) {
847 							v.call(function, p_inputs + 1, input_args, r_error);
848 						} else {
849 							r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
850 							r_error_str = "Invalid returns count for call_mode == CALL_MODE_INSTANCE";
851 							return 0;
852 						}
853 					} else {
854 						*p_outputs[0] = v.call(function, p_inputs + 1, input_args, r_error);
855 					}
856 				} else {
857 					v.call(function, p_inputs + 1, input_args, r_error);
858 				}
859 
860 				if (call_mode == VisualScriptFunctionCall::CALL_MODE_INSTANCE) {
861 					*p_outputs[0] = *p_inputs[0];
862 				}
863 
864 			} break;
865 			case VisualScriptFunctionCall::CALL_MODE_SINGLETON: {
866 
867 				Object *object = Engine::get_singleton()->get_singleton_object(singleton);
868 				if (!object) {
869 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
870 					r_error_str = "Invalid singleton name: '" + String(singleton) + "'";
871 					return 0;
872 				}
873 
874 				if (rpc_mode) {
875 					call_rpc(object, p_inputs, input_args);
876 				} else if (returns) {
877 					*p_outputs[0] = object->call(function, p_inputs, input_args, r_error);
878 				} else {
879 					object->call(function, p_inputs, input_args, r_error);
880 				}
881 			} break;
882 		}
883 
884 		if (!validate) {
885 
886 			//ignore call errors if validation is disabled
887 			r_error.error = Variant::CallError::CALL_OK;
888 			r_error_str = String();
889 		}
890 
891 		return 0;
892 	}
893 };
894 
instance(VisualScriptInstance * p_instance)895 VisualScriptNodeInstance *VisualScriptFunctionCall::instance(VisualScriptInstance *p_instance) {
896 
897 	VisualScriptNodeInstanceFunctionCall *instance = memnew(VisualScriptNodeInstanceFunctionCall);
898 	instance->node = this;
899 	instance->instance = p_instance;
900 	instance->singleton = singleton;
901 	instance->function = function;
902 	instance->call_mode = call_mode;
903 	instance->returns = get_output_value_port_count();
904 	instance->node_path = base_path;
905 	instance->input_args = get_input_value_port_count() - ((call_mode == CALL_MODE_BASIC_TYPE || call_mode == CALL_MODE_INSTANCE) ? 1 : 0);
906 	instance->rpc_mode = rpc_call_mode;
907 	instance->validate = validate;
908 	return instance;
909 }
910 
guess_output_type(TypeGuess * p_inputs,int p_output) const911 VisualScriptFunctionCall::TypeGuess VisualScriptFunctionCall::guess_output_type(TypeGuess *p_inputs, int p_output) const {
912 
913 	if (p_output == 0 && call_mode == CALL_MODE_INSTANCE) {
914 		return p_inputs[0];
915 	}
916 
917 	return VisualScriptNode::guess_output_type(p_inputs, p_output);
918 }
919 
VisualScriptFunctionCall()920 VisualScriptFunctionCall::VisualScriptFunctionCall() {
921 
922 	validate = true;
923 	call_mode = CALL_MODE_SELF;
924 	basic_type = Variant::NIL;
925 	use_default_args = 0;
926 	base_type = "Object";
927 	rpc_call_mode = RPC_DISABLED;
928 }
929 
930 template <VisualScriptFunctionCall::CallMode cmode>
create_function_call_node(const String & p_name)931 static Ref<VisualScriptNode> create_function_call_node(const String &p_name) {
932 
933 	Ref<VisualScriptFunctionCall> node;
934 	node.instance();
935 	node->set_call_mode(cmode);
936 	return node;
937 }
938 
939 //////////////////////////////////////////
940 ////////////////SET//////////////////////
941 //////////////////////////////////////////
942 
get_output_sequence_port_count() const943 int VisualScriptPropertySet::get_output_sequence_port_count() const {
944 
945 	return call_mode != CALL_MODE_BASIC_TYPE ? 1 : 0;
946 }
947 
has_input_sequence_port() const948 bool VisualScriptPropertySet::has_input_sequence_port() const {
949 
950 	return call_mode != CALL_MODE_BASIC_TYPE;
951 }
952 
_get_base_node() const953 Node *VisualScriptPropertySet::_get_base_node() const {
954 
955 #ifdef TOOLS_ENABLED
956 	Ref<Script> script = get_visual_script();
957 	if (!script.is_valid())
958 		return NULL;
959 
960 	MainLoop *main_loop = OS::get_singleton()->get_main_loop();
961 
962 	SceneTree *scene_tree = Object::cast_to<SceneTree>(main_loop);
963 
964 	if (!scene_tree)
965 		return NULL;
966 
967 	Node *edited_scene = scene_tree->get_edited_scene_root();
968 
969 	if (!edited_scene)
970 		return NULL;
971 
972 	Node *script_node = _find_script_node(edited_scene, edited_scene, script);
973 
974 	if (!script_node)
975 		return NULL;
976 
977 	if (!script_node->has_node(base_path))
978 		return NULL;
979 
980 	Node *path_to = script_node->get_node(base_path);
981 
982 	return path_to;
983 #else
984 
985 	return NULL;
986 #endif
987 }
988 
_get_base_type() const989 StringName VisualScriptPropertySet::_get_base_type() const {
990 
991 	if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid())
992 		return get_visual_script()->get_instance_base_type();
993 	else if (call_mode == CALL_MODE_NODE_PATH && get_visual_script().is_valid()) {
994 		Node *path = _get_base_node();
995 		if (path)
996 			return path->get_class();
997 	}
998 
999 	return base_type;
1000 }
1001 
get_input_value_port_count() const1002 int VisualScriptPropertySet::get_input_value_port_count() const {
1003 
1004 	int pc = (call_mode == CALL_MODE_BASIC_TYPE || call_mode == CALL_MODE_INSTANCE) ? 2 : 1;
1005 
1006 	return pc;
1007 }
get_output_value_port_count() const1008 int VisualScriptPropertySet::get_output_value_port_count() const {
1009 
1010 	return (call_mode == CALL_MODE_BASIC_TYPE || call_mode == CALL_MODE_INSTANCE) ? 1 : 0;
1011 }
1012 
get_output_sequence_port_text(int p_port) const1013 String VisualScriptPropertySet::get_output_sequence_port_text(int p_port) const {
1014 
1015 	return String();
1016 }
1017 
_adjust_input_index(PropertyInfo & pinfo) const1018 void VisualScriptPropertySet::_adjust_input_index(PropertyInfo &pinfo) const {
1019 
1020 	if (index != StringName()) {
1021 
1022 		Variant v;
1023 		Variant::CallError ce;
1024 		v = Variant::construct(pinfo.type, NULL, 0, ce);
1025 		Variant i = v.get(index);
1026 		pinfo.type = i.get_type();
1027 	}
1028 }
1029 
get_input_value_port_info(int p_idx) const1030 PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const {
1031 	if (call_mode == CALL_MODE_INSTANCE || call_mode == CALL_MODE_BASIC_TYPE) {
1032 		if (p_idx == 0) {
1033 			PropertyInfo pi;
1034 			pi.type = (call_mode == CALL_MODE_INSTANCE ? Variant::OBJECT : basic_type);
1035 			pi.name = (call_mode == CALL_MODE_INSTANCE ? String("instance") : Variant::get_type_name(basic_type).to_lower());
1036 			_adjust_input_index(pi);
1037 			return pi;
1038 		}
1039 	}
1040 
1041 	List<PropertyInfo> props;
1042 	ClassDB::get_property_list(_get_base_type(), &props, false);
1043 	for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
1044 		if (E->get().name == property) {
1045 			PropertyInfo pinfo = PropertyInfo(E->get().type, "value", PROPERTY_HINT_TYPE_STRING, E->get().hint_string);
1046 			_adjust_input_index(pinfo);
1047 			return pinfo;
1048 		}
1049 	}
1050 
1051 	PropertyInfo pinfo = type_cache;
1052 	pinfo.name = "value";
1053 	_adjust_input_index(pinfo);
1054 	return pinfo;
1055 }
1056 
get_output_value_port_info(int p_idx) const1057 PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) const {
1058 	if (call_mode == CALL_MODE_BASIC_TYPE) {
1059 		return PropertyInfo(basic_type, "out");
1060 	} else if (call_mode == CALL_MODE_INSTANCE) {
1061 		return PropertyInfo(Variant::OBJECT, "pass", PROPERTY_HINT_TYPE_STRING, get_base_type());
1062 	} else {
1063 		return PropertyInfo();
1064 	}
1065 }
1066 
get_caption() const1067 String VisualScriptPropertySet::get_caption() const {
1068 
1069 	static const char *opname[ASSIGN_OP_MAX] = {
1070 		"Set", "Add", "Subtract", "Multiply", "Divide", "Mod", "ShiftLeft", "ShiftRight", "BitAnd", "BitOr", "BitXor"
1071 	};
1072 
1073 	String prop = String(opname[assign_op]) + " " + property;
1074 	if (index != StringName()) {
1075 		prop += "." + String(index);
1076 	}
1077 
1078 	return prop;
1079 }
1080 
get_text() const1081 String VisualScriptPropertySet::get_text() const {
1082 
1083 	if (call_mode == CALL_MODE_BASIC_TYPE) {
1084 		return String("On ") + Variant::get_type_name(basic_type);
1085 	}
1086 
1087 	static const char *cname[3] = {
1088 		"Self",
1089 		"Scene Node",
1090 		"Instance"
1091 	};
1092 
1093 	return String("On ") + cname[call_mode];
1094 }
1095 
_update_base_type()1096 void VisualScriptPropertySet::_update_base_type() {
1097 	//cache it because this information may not be available on load
1098 	if (call_mode == CALL_MODE_NODE_PATH) {
1099 
1100 		Node *node = _get_base_node();
1101 		if (node) {
1102 			base_type = node->get_class();
1103 		}
1104 	} else if (call_mode == CALL_MODE_SELF) {
1105 
1106 		if (get_visual_script().is_valid()) {
1107 			base_type = get_visual_script()->get_instance_base_type();
1108 		}
1109 	}
1110 }
set_basic_type(Variant::Type p_type)1111 void VisualScriptPropertySet::set_basic_type(Variant::Type p_type) {
1112 
1113 	if (basic_type == p_type)
1114 		return;
1115 	basic_type = p_type;
1116 
1117 	_change_notify();
1118 	_update_base_type();
1119 	ports_changed_notify();
1120 }
1121 
get_basic_type() const1122 Variant::Type VisualScriptPropertySet::get_basic_type() const {
1123 
1124 	return basic_type;
1125 }
1126 
set_base_type(const StringName & p_type)1127 void VisualScriptPropertySet::set_base_type(const StringName &p_type) {
1128 
1129 	if (base_type == p_type)
1130 		return;
1131 
1132 	base_type = p_type;
1133 	_change_notify();
1134 	ports_changed_notify();
1135 }
1136 
get_base_type() const1137 StringName VisualScriptPropertySet::get_base_type() const {
1138 
1139 	return base_type;
1140 }
1141 
set_base_script(const String & p_path)1142 void VisualScriptPropertySet::set_base_script(const String &p_path) {
1143 
1144 	if (base_script == p_path)
1145 		return;
1146 
1147 	base_script = p_path;
1148 	_change_notify();
1149 	ports_changed_notify();
1150 }
1151 
get_base_script() const1152 String VisualScriptPropertySet::get_base_script() const {
1153 
1154 	return base_script;
1155 }
1156 
_update_cache()1157 void VisualScriptPropertySet::_update_cache() {
1158 
1159 	if (!Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop()))
1160 		return;
1161 
1162 	if (!Engine::get_singleton()->is_editor_hint()) //only update cache if editor exists, it's pointless otherwise
1163 		return;
1164 
1165 	if (call_mode == CALL_MODE_BASIC_TYPE) {
1166 
1167 		//not super efficient..
1168 
1169 		Variant v;
1170 		Variant::CallError ce;
1171 		v = Variant::construct(basic_type, NULL, 0, ce);
1172 
1173 		List<PropertyInfo> pinfo;
1174 		v.get_property_list(&pinfo);
1175 
1176 		for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
1177 
1178 			if (E->get().name == property) {
1179 
1180 				type_cache = E->get();
1181 			}
1182 		}
1183 
1184 	} else {
1185 
1186 		StringName type;
1187 		Ref<Script> script;
1188 		Node *node = NULL;
1189 
1190 		if (call_mode == CALL_MODE_NODE_PATH) {
1191 
1192 			node = _get_base_node();
1193 			if (node) {
1194 				type = node->get_class();
1195 				base_type = type; //cache, too
1196 				script = node->get_script();
1197 			}
1198 		} else if (call_mode == CALL_MODE_SELF) {
1199 
1200 			if (get_visual_script().is_valid()) {
1201 				type = get_visual_script()->get_instance_base_type();
1202 				base_type = type; //cache, too
1203 				script = get_visual_script();
1204 			}
1205 		} else if (call_mode == CALL_MODE_INSTANCE) {
1206 
1207 			type = base_type;
1208 			if (base_script != String()) {
1209 
1210 				if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) {
1211 
1212 					ScriptServer::edit_request_func(base_script); //make sure it's loaded
1213 				}
1214 
1215 				if (ResourceCache::has(base_script)) {
1216 
1217 					script = Ref<Resource>(ResourceCache::get(base_script));
1218 				} else {
1219 					return;
1220 				}
1221 			}
1222 		}
1223 
1224 		List<PropertyInfo> pinfo;
1225 
1226 		if (node) {
1227 
1228 			node->get_property_list(&pinfo);
1229 		} else {
1230 			ClassDB::get_property_list(type, &pinfo);
1231 		}
1232 
1233 		if (script.is_valid()) {
1234 
1235 			script->get_script_property_list(&pinfo);
1236 		}
1237 
1238 		for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
1239 
1240 			if (E->get().name == property) {
1241 				type_cache = E->get();
1242 				return;
1243 			}
1244 		}
1245 	}
1246 }
1247 
set_property(const StringName & p_type)1248 void VisualScriptPropertySet::set_property(const StringName &p_type) {
1249 
1250 	if (property == p_type)
1251 		return;
1252 
1253 	property = p_type;
1254 	index = StringName();
1255 	_update_cache();
1256 	_change_notify();
1257 	ports_changed_notify();
1258 }
get_property() const1259 StringName VisualScriptPropertySet::get_property() const {
1260 
1261 	return property;
1262 }
1263 
set_base_path(const NodePath & p_type)1264 void VisualScriptPropertySet::set_base_path(const NodePath &p_type) {
1265 
1266 	if (base_path == p_type)
1267 		return;
1268 
1269 	base_path = p_type;
1270 	_update_base_type();
1271 	_change_notify();
1272 	ports_changed_notify();
1273 }
1274 
get_base_path() const1275 NodePath VisualScriptPropertySet::get_base_path() const {
1276 
1277 	return base_path;
1278 }
1279 
set_call_mode(CallMode p_mode)1280 void VisualScriptPropertySet::set_call_mode(CallMode p_mode) {
1281 
1282 	if (call_mode == p_mode)
1283 		return;
1284 
1285 	call_mode = p_mode;
1286 	_update_base_type();
1287 	_change_notify();
1288 	ports_changed_notify();
1289 }
get_call_mode() const1290 VisualScriptPropertySet::CallMode VisualScriptPropertySet::get_call_mode() const {
1291 
1292 	return call_mode;
1293 }
1294 
_set_type_cache(const Dictionary & p_type)1295 void VisualScriptPropertySet::_set_type_cache(const Dictionary &p_type) {
1296 	type_cache = PropertyInfo::from_dict(p_type);
1297 }
1298 
_get_type_cache() const1299 Dictionary VisualScriptPropertySet::_get_type_cache() const {
1300 
1301 	return type_cache;
1302 }
1303 
set_index(const StringName & p_type)1304 void VisualScriptPropertySet::set_index(const StringName &p_type) {
1305 
1306 	if (index == p_type)
1307 		return;
1308 	index = p_type;
1309 	_update_cache();
1310 	_change_notify();
1311 	ports_changed_notify();
1312 }
1313 
get_index() const1314 StringName VisualScriptPropertySet::get_index() const {
1315 
1316 	return index;
1317 }
1318 
set_assign_op(AssignOp p_op)1319 void VisualScriptPropertySet::set_assign_op(AssignOp p_op) {
1320 
1321 	ERR_FAIL_INDEX(p_op, ASSIGN_OP_MAX);
1322 	if (assign_op == p_op)
1323 		return;
1324 
1325 	assign_op = p_op;
1326 	_update_cache();
1327 	_change_notify();
1328 	ports_changed_notify();
1329 }
1330 
get_assign_op() const1331 VisualScriptPropertySet::AssignOp VisualScriptPropertySet::get_assign_op() const {
1332 	return assign_op;
1333 }
1334 
_validate_property(PropertyInfo & property) const1335 void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const {
1336 
1337 	if (property.name == "base_type") {
1338 		if (call_mode != CALL_MODE_INSTANCE) {
1339 			property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
1340 		}
1341 	}
1342 
1343 	if (property.name == "base_script") {
1344 		if (call_mode != CALL_MODE_INSTANCE) {
1345 			property.usage = 0;
1346 		}
1347 	}
1348 
1349 	if (property.name == "basic_type") {
1350 		if (call_mode != CALL_MODE_BASIC_TYPE) {
1351 			property.usage = 0;
1352 		}
1353 	}
1354 
1355 	if (property.name == "node_path") {
1356 		if (call_mode != CALL_MODE_NODE_PATH) {
1357 			property.usage = 0;
1358 		} else {
1359 
1360 			Node *bnode = _get_base_node();
1361 			if (bnode) {
1362 				property.hint_string = bnode->get_path(); //convert to loong string
1363 			}
1364 		}
1365 	}
1366 
1367 	if (property.name == "property") {
1368 
1369 		if (call_mode == CALL_MODE_BASIC_TYPE) {
1370 
1371 			property.hint = PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE;
1372 			property.hint_string = Variant::get_type_name(basic_type);
1373 
1374 		} else if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid()) {
1375 			property.hint = PROPERTY_HINT_PROPERTY_OF_SCRIPT;
1376 			property.hint_string = itos(get_visual_script()->get_instance_id());
1377 		} else if (call_mode == CALL_MODE_INSTANCE) {
1378 			property.hint = PROPERTY_HINT_PROPERTY_OF_BASE_TYPE;
1379 			property.hint_string = base_type;
1380 
1381 			if (base_script != String()) {
1382 				if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) {
1383 
1384 					ScriptServer::edit_request_func(base_script); //make sure it's loaded
1385 				}
1386 
1387 				if (ResourceCache::has(base_script)) {
1388 
1389 					Ref<Script> script = Ref<Resource>(ResourceCache::get(base_script));
1390 					if (script.is_valid()) {
1391 
1392 						property.hint = PROPERTY_HINT_PROPERTY_OF_SCRIPT;
1393 						property.hint_string = itos(script->get_instance_id());
1394 					}
1395 				}
1396 			}
1397 
1398 		} else if (call_mode == CALL_MODE_NODE_PATH) {
1399 			Node *node = _get_base_node();
1400 			if (node) {
1401 				property.hint = PROPERTY_HINT_PROPERTY_OF_INSTANCE;
1402 				property.hint_string = itos(node->get_instance_id());
1403 			} else {
1404 				property.hint = PROPERTY_HINT_PROPERTY_OF_BASE_TYPE;
1405 				property.hint_string = get_base_type();
1406 			}
1407 		}
1408 	}
1409 
1410 	if (property.name == "index") {
1411 
1412 		Variant::CallError ce;
1413 		Variant v = Variant::construct(type_cache.type, NULL, 0, ce);
1414 		List<PropertyInfo> plist;
1415 		v.get_property_list(&plist);
1416 		String options = "";
1417 		for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
1418 			options += "," + E->get().name;
1419 		}
1420 
1421 		property.hint = PROPERTY_HINT_ENUM;
1422 		property.hint_string = options;
1423 		property.type = Variant::STRING;
1424 		if (options == "")
1425 			property.usage = 0; //hide if type has no usable index
1426 	}
1427 }
1428 
_bind_methods()1429 void VisualScriptPropertySet::_bind_methods() {
1430 
1431 	ClassDB::bind_method(D_METHOD("set_base_type", "base_type"), &VisualScriptPropertySet::set_base_type);
1432 	ClassDB::bind_method(D_METHOD("get_base_type"), &VisualScriptPropertySet::get_base_type);
1433 
1434 	ClassDB::bind_method(D_METHOD("set_base_script", "base_script"), &VisualScriptPropertySet::set_base_script);
1435 	ClassDB::bind_method(D_METHOD("get_base_script"), &VisualScriptPropertySet::get_base_script);
1436 
1437 	ClassDB::bind_method(D_METHOD("set_basic_type", "basic_type"), &VisualScriptPropertySet::set_basic_type);
1438 	ClassDB::bind_method(D_METHOD("get_basic_type"), &VisualScriptPropertySet::get_basic_type);
1439 
1440 	ClassDB::bind_method(D_METHOD("_set_type_cache", "type_cache"), &VisualScriptPropertySet::_set_type_cache);
1441 	ClassDB::bind_method(D_METHOD("_get_type_cache"), &VisualScriptPropertySet::_get_type_cache);
1442 
1443 	ClassDB::bind_method(D_METHOD("set_property", "property"), &VisualScriptPropertySet::set_property);
1444 	ClassDB::bind_method(D_METHOD("get_property"), &VisualScriptPropertySet::get_property);
1445 
1446 	ClassDB::bind_method(D_METHOD("set_call_mode", "mode"), &VisualScriptPropertySet::set_call_mode);
1447 	ClassDB::bind_method(D_METHOD("get_call_mode"), &VisualScriptPropertySet::get_call_mode);
1448 
1449 	ClassDB::bind_method(D_METHOD("set_base_path", "base_path"), &VisualScriptPropertySet::set_base_path);
1450 	ClassDB::bind_method(D_METHOD("get_base_path"), &VisualScriptPropertySet::get_base_path);
1451 
1452 	ClassDB::bind_method(D_METHOD("set_index", "index"), &VisualScriptPropertySet::set_index);
1453 	ClassDB::bind_method(D_METHOD("get_index"), &VisualScriptPropertySet::get_index);
1454 
1455 	ClassDB::bind_method(D_METHOD("set_assign_op", "assign_op"), &VisualScriptPropertySet::set_assign_op);
1456 	ClassDB::bind_method(D_METHOD("get_assign_op"), &VisualScriptPropertySet::get_assign_op);
1457 
1458 	String bt;
1459 	for (int i = 0; i < Variant::VARIANT_MAX; i++) {
1460 		if (i > 0)
1461 			bt += ",";
1462 
1463 		bt += Variant::get_type_name(Variant::Type(i));
1464 	}
1465 
1466 	List<String> script_extensions;
1467 	for (int i = 0; i < ScriptServer::get_language_count(); i++) {
1468 		ScriptServer::get_language(i)->get_recognized_extensions(&script_extensions);
1469 	}
1470 
1471 	String script_ext_hint;
1472 	for (List<String>::Element *E = script_extensions.front(); E; E = E->next()) {
1473 		if (script_ext_hint != String())
1474 			script_ext_hint += ",";
1475 		script_ext_hint += "*." + E->get();
1476 	}
1477 
1478 	ADD_PROPERTY(PropertyInfo(Variant::INT, "set_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type"), "set_call_mode", "get_call_mode");
1479 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type");
1480 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_script", PROPERTY_HINT_FILE, script_ext_hint), "set_base_script", "get_base_script");
1481 	ADD_PROPERTY(PropertyInfo(Variant::INT, "type_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_type_cache", "_get_type_cache");
1482 	ADD_PROPERTY(PropertyInfo(Variant::INT, "basic_type", PROPERTY_HINT_ENUM, bt), "set_basic_type", "get_basic_type");
1483 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path");
1484 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "property"), "set_property", "get_property");
1485 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "index"), "set_index", "get_index");
1486 	ADD_PROPERTY(PropertyInfo(Variant::INT, "assign_op", PROPERTY_HINT_ENUM, "Assign,Add,Sub,Mul,Div,Mod,ShiftLeft,ShiftRight,BitAnd,BitOr,Bitxor"), "set_assign_op", "get_assign_op");
1487 
1488 	BIND_ENUM_CONSTANT(CALL_MODE_SELF);
1489 	BIND_ENUM_CONSTANT(CALL_MODE_NODE_PATH);
1490 	BIND_ENUM_CONSTANT(CALL_MODE_INSTANCE);
1491 	BIND_ENUM_CONSTANT(CALL_MODE_BASIC_TYPE);
1492 
1493 	BIND_ENUM_CONSTANT(ASSIGN_OP_NONE);
1494 	BIND_ENUM_CONSTANT(ASSIGN_OP_ADD);
1495 	BIND_ENUM_CONSTANT(ASSIGN_OP_SUB);
1496 	BIND_ENUM_CONSTANT(ASSIGN_OP_MUL);
1497 	BIND_ENUM_CONSTANT(ASSIGN_OP_DIV);
1498 	BIND_ENUM_CONSTANT(ASSIGN_OP_MOD);
1499 	BIND_ENUM_CONSTANT(ASSIGN_OP_SHIFT_LEFT);
1500 	BIND_ENUM_CONSTANT(ASSIGN_OP_SHIFT_RIGHT);
1501 	BIND_ENUM_CONSTANT(ASSIGN_OP_BIT_AND);
1502 	BIND_ENUM_CONSTANT(ASSIGN_OP_BIT_OR);
1503 	BIND_ENUM_CONSTANT(ASSIGN_OP_BIT_XOR);
1504 }
1505 
1506 class VisualScriptNodeInstancePropertySet : public VisualScriptNodeInstance {
1507 public:
1508 	VisualScriptPropertySet::CallMode call_mode;
1509 	NodePath node_path;
1510 	StringName property;
1511 
1512 	VisualScriptPropertySet *node;
1513 	VisualScriptInstance *instance;
1514 	VisualScriptPropertySet::AssignOp assign_op;
1515 	StringName index;
1516 	bool needs_get;
1517 
1518 	//virtual int get_working_memory_size() const { return 0; }
1519 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
1520 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
1521 
_process_get(Variant & source,const Variant & p_argument,bool & valid)1522 	_FORCE_INLINE_ void _process_get(Variant &source, const Variant &p_argument, bool &valid) {
1523 
1524 		if (index != StringName() && assign_op == VisualScriptPropertySet::ASSIGN_OP_NONE) {
1525 			source.set_named(index, p_argument, &valid);
1526 		} else {
1527 
1528 			Variant value;
1529 			if (index != StringName()) {
1530 				value = source.get_named(index, &valid);
1531 			} else {
1532 				value = source;
1533 			}
1534 
1535 			switch (assign_op) {
1536 				case VisualScriptPropertySet::ASSIGN_OP_NONE: {
1537 					//should never get here
1538 				} break;
1539 				case VisualScriptPropertySet::ASSIGN_OP_ADD: {
1540 					value = Variant::evaluate(Variant::OP_ADD, value, p_argument);
1541 				} break;
1542 				case VisualScriptPropertySet::ASSIGN_OP_SUB: {
1543 					value = Variant::evaluate(Variant::OP_SUBTRACT, value, p_argument);
1544 				} break;
1545 				case VisualScriptPropertySet::ASSIGN_OP_MUL: {
1546 					value = Variant::evaluate(Variant::OP_MULTIPLY, value, p_argument);
1547 				} break;
1548 				case VisualScriptPropertySet::ASSIGN_OP_DIV: {
1549 					value = Variant::evaluate(Variant::OP_DIVIDE, value, p_argument);
1550 				} break;
1551 				case VisualScriptPropertySet::ASSIGN_OP_MOD: {
1552 					value = Variant::evaluate(Variant::OP_MODULE, value, p_argument);
1553 				} break;
1554 				case VisualScriptPropertySet::ASSIGN_OP_SHIFT_LEFT: {
1555 					value = Variant::evaluate(Variant::OP_SHIFT_LEFT, value, p_argument);
1556 				} break;
1557 				case VisualScriptPropertySet::ASSIGN_OP_SHIFT_RIGHT: {
1558 					value = Variant::evaluate(Variant::OP_SHIFT_RIGHT, value, p_argument);
1559 				} break;
1560 				case VisualScriptPropertySet::ASSIGN_OP_BIT_AND: {
1561 					value = Variant::evaluate(Variant::OP_BIT_AND, value, p_argument);
1562 				} break;
1563 				case VisualScriptPropertySet::ASSIGN_OP_BIT_OR: {
1564 					value = Variant::evaluate(Variant::OP_BIT_OR, value, p_argument);
1565 				} break;
1566 				case VisualScriptPropertySet::ASSIGN_OP_BIT_XOR: {
1567 					value = Variant::evaluate(Variant::OP_BIT_XOR, value, p_argument);
1568 				} break;
1569 				default: {
1570 				}
1571 			}
1572 
1573 			if (index != StringName()) {
1574 				source.set_named(index, value, &valid);
1575 			} else {
1576 				source = value;
1577 			}
1578 		}
1579 	}
1580 
step(const Variant ** p_inputs,Variant ** p_outputs,StartMode p_start_mode,Variant * p_working_mem,Variant::CallError & r_error,String & r_error_str)1581 	virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) {
1582 
1583 		switch (call_mode) {
1584 
1585 			case VisualScriptPropertySet::CALL_MODE_SELF: {
1586 
1587 				Object *object = instance->get_owner_ptr();
1588 
1589 				bool valid;
1590 
1591 				if (needs_get) {
1592 					Variant value = object->get(property, &valid);
1593 					_process_get(value, *p_inputs[0], valid);
1594 					object->set(property, value, &valid);
1595 				} else {
1596 					object->set(property, *p_inputs[0], &valid);
1597 				}
1598 
1599 				if (!valid) {
1600 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1601 					r_error_str = "Invalid set value '" + String(*p_inputs[0]) + "' on property '" + String(property) + "' of type " + object->get_class();
1602 				}
1603 			} break;
1604 			case VisualScriptPropertySet::CALL_MODE_NODE_PATH: {
1605 
1606 				Node *node = Object::cast_to<Node>(instance->get_owner_ptr());
1607 				if (!node) {
1608 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1609 					r_error_str = "Base object is not a Node!";
1610 					return 0;
1611 				}
1612 
1613 				Node *another = node->get_node(node_path);
1614 				if (!another) {
1615 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1616 					r_error_str = "Path does not lead Node!";
1617 					return 0;
1618 				}
1619 
1620 				bool valid;
1621 
1622 				if (needs_get) {
1623 
1624 					Variant value = another->get(property, &valid);
1625 					_process_get(value, *p_inputs[0], valid);
1626 					another->set(property, value, &valid);
1627 				} else {
1628 					another->set(property, *p_inputs[0], &valid);
1629 				}
1630 
1631 				if (!valid) {
1632 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1633 					r_error_str = "Invalid set value '" + String(*p_inputs[0]) + "' on property '" + String(property) + "' of type " + another->get_class();
1634 				}
1635 
1636 			} break;
1637 			case VisualScriptPropertySet::CALL_MODE_INSTANCE:
1638 			case VisualScriptPropertySet::CALL_MODE_BASIC_TYPE: {
1639 
1640 				Variant v = *p_inputs[0];
1641 
1642 				bool valid;
1643 
1644 				if (needs_get) {
1645 					Variant value = v.get_named(property, &valid);
1646 					_process_get(value, *p_inputs[1], valid);
1647 					v.set_named(property, value, &valid);
1648 
1649 				} else {
1650 					v.set_named(property, *p_inputs[1], &valid);
1651 				}
1652 
1653 				if (!valid) {
1654 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1655 					r_error_str = "Invalid set value '" + String(*p_inputs[1]) + "' (" + Variant::get_type_name(p_inputs[1]->get_type()) + ") on property '" + String(property) + "' of type " + Variant::get_type_name(v.get_type());
1656 				}
1657 
1658 				*p_outputs[0] = v;
1659 
1660 			} break;
1661 		}
1662 		return 0;
1663 	}
1664 };
1665 
instance(VisualScriptInstance * p_instance)1666 VisualScriptNodeInstance *VisualScriptPropertySet::instance(VisualScriptInstance *p_instance) {
1667 
1668 	VisualScriptNodeInstancePropertySet *instance = memnew(VisualScriptNodeInstancePropertySet);
1669 	instance->node = this;
1670 	instance->instance = p_instance;
1671 	instance->property = property;
1672 	instance->call_mode = call_mode;
1673 	instance->node_path = base_path;
1674 	instance->assign_op = assign_op;
1675 	instance->index = index;
1676 	instance->needs_get = index != StringName() || assign_op != ASSIGN_OP_NONE;
1677 	return instance;
1678 }
1679 
guess_output_type(TypeGuess * p_inputs,int p_output) const1680 VisualScriptPropertySet::TypeGuess VisualScriptPropertySet::guess_output_type(TypeGuess *p_inputs, int p_output) const {
1681 
1682 	if (p_output == 0 && call_mode == CALL_MODE_INSTANCE) {
1683 		return p_inputs[0];
1684 	}
1685 
1686 	return VisualScriptNode::guess_output_type(p_inputs, p_output);
1687 }
VisualScriptPropertySet()1688 VisualScriptPropertySet::VisualScriptPropertySet() {
1689 
1690 	assign_op = ASSIGN_OP_NONE;
1691 	call_mode = CALL_MODE_SELF;
1692 	base_type = "Object";
1693 	basic_type = Variant::NIL;
1694 }
1695 
1696 template <VisualScriptPropertySet::CallMode cmode>
create_property_set_node(const String & p_name)1697 static Ref<VisualScriptNode> create_property_set_node(const String &p_name) {
1698 
1699 	Ref<VisualScriptPropertySet> node;
1700 	node.instance();
1701 	node->set_call_mode(cmode);
1702 	return node;
1703 }
1704 
1705 //////////////////////////////////////////
1706 ////////////////GET//////////////////////
1707 //////////////////////////////////////////
1708 
get_output_sequence_port_count() const1709 int VisualScriptPropertyGet::get_output_sequence_port_count() const {
1710 
1711 	return 0; // (call_mode==CALL_MODE_SELF || call_mode==CALL_MODE_NODE_PATH)?0:1;
1712 }
1713 
has_input_sequence_port() const1714 bool VisualScriptPropertyGet::has_input_sequence_port() const {
1715 
1716 	return false; //(call_mode==CALL_MODE_SELF || call_mode==CALL_MODE_NODE_PATH)?false:true;
1717 }
_update_base_type()1718 void VisualScriptPropertyGet::_update_base_type() {
1719 	//cache it because this information may not be available on load
1720 	if (call_mode == CALL_MODE_NODE_PATH) {
1721 
1722 		Node *node = _get_base_node();
1723 		if (node) {
1724 			base_type = node->get_class();
1725 		}
1726 	} else if (call_mode == CALL_MODE_SELF) {
1727 
1728 		if (get_visual_script().is_valid()) {
1729 			base_type = get_visual_script()->get_instance_base_type();
1730 		}
1731 	}
1732 }
_get_base_node() const1733 Node *VisualScriptPropertyGet::_get_base_node() const {
1734 
1735 #ifdef TOOLS_ENABLED
1736 	Ref<Script> script = get_visual_script();
1737 	if (!script.is_valid())
1738 		return NULL;
1739 
1740 	MainLoop *main_loop = OS::get_singleton()->get_main_loop();
1741 
1742 	SceneTree *scene_tree = Object::cast_to<SceneTree>(main_loop);
1743 
1744 	if (!scene_tree)
1745 		return NULL;
1746 
1747 	Node *edited_scene = scene_tree->get_edited_scene_root();
1748 
1749 	if (!edited_scene)
1750 		return NULL;
1751 
1752 	Node *script_node = _find_script_node(edited_scene, edited_scene, script);
1753 
1754 	if (!script_node)
1755 		return NULL;
1756 
1757 	if (!script_node->has_node(base_path))
1758 		return NULL;
1759 
1760 	Node *path_to = script_node->get_node(base_path);
1761 
1762 	return path_to;
1763 #else
1764 
1765 	return NULL;
1766 #endif
1767 }
1768 
_get_base_type() const1769 StringName VisualScriptPropertyGet::_get_base_type() const {
1770 
1771 	if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid())
1772 		return get_visual_script()->get_instance_base_type();
1773 	else if (call_mode == CALL_MODE_NODE_PATH && get_visual_script().is_valid()) {
1774 		Node *path = _get_base_node();
1775 		if (path)
1776 			return path->get_class();
1777 	}
1778 
1779 	return base_type;
1780 }
1781 
get_input_value_port_count() const1782 int VisualScriptPropertyGet::get_input_value_port_count() const {
1783 
1784 	return (call_mode == CALL_MODE_BASIC_TYPE || call_mode == CALL_MODE_INSTANCE) ? 1 : 0;
1785 }
get_output_value_port_count() const1786 int VisualScriptPropertyGet::get_output_value_port_count() const {
1787 
1788 	return 1;
1789 }
1790 
get_output_sequence_port_text(int p_port) const1791 String VisualScriptPropertyGet::get_output_sequence_port_text(int p_port) const {
1792 
1793 	return String();
1794 }
1795 
get_input_value_port_info(int p_idx) const1796 PropertyInfo VisualScriptPropertyGet::get_input_value_port_info(int p_idx) const {
1797 
1798 	if (call_mode == CALL_MODE_INSTANCE || call_mode == CALL_MODE_BASIC_TYPE) {
1799 		if (p_idx == 0) {
1800 			PropertyInfo pi;
1801 			pi.type = (call_mode == CALL_MODE_INSTANCE ? Variant::OBJECT : basic_type);
1802 			pi.name = (call_mode == CALL_MODE_INSTANCE ? String("instance") : Variant::get_type_name(basic_type).to_lower());
1803 			return pi;
1804 		}
1805 	}
1806 	return PropertyInfo();
1807 }
1808 
get_output_value_port_info(int p_idx) const1809 PropertyInfo VisualScriptPropertyGet::get_output_value_port_info(int p_idx) const {
1810 	List<PropertyInfo> props;
1811 	ClassDB::get_property_list(_get_base_type(), &props, false);
1812 	for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
1813 		if (E->get().name == property) {
1814 			return PropertyInfo(E->get().type, "value." + String(index));
1815 		}
1816 	}
1817 
1818 	return PropertyInfo(type_cache, "value");
1819 }
1820 
get_caption() const1821 String VisualScriptPropertyGet::get_caption() const {
1822 
1823 	return String("Get ") + property;
1824 }
1825 
get_text() const1826 String VisualScriptPropertyGet::get_text() const {
1827 
1828 	if (call_mode == CALL_MODE_BASIC_TYPE) {
1829 		return String("On ") + Variant::get_type_name(basic_type);
1830 	}
1831 
1832 	static const char *cname[3] = {
1833 		"Self",
1834 		"Scene Node",
1835 		"Instance"
1836 	};
1837 
1838 	return String("On ") + cname[call_mode];
1839 }
1840 
set_base_type(const StringName & p_type)1841 void VisualScriptPropertyGet::set_base_type(const StringName &p_type) {
1842 
1843 	if (base_type == p_type)
1844 		return;
1845 
1846 	base_type = p_type;
1847 	_change_notify();
1848 	ports_changed_notify();
1849 }
1850 
get_base_type() const1851 StringName VisualScriptPropertyGet::get_base_type() const {
1852 
1853 	return base_type;
1854 }
1855 
set_base_script(const String & p_path)1856 void VisualScriptPropertyGet::set_base_script(const String &p_path) {
1857 
1858 	if (base_script == p_path)
1859 		return;
1860 
1861 	base_script = p_path;
1862 	_change_notify();
1863 	ports_changed_notify();
1864 }
1865 
get_base_script() const1866 String VisualScriptPropertyGet::get_base_script() const {
1867 
1868 	return base_script;
1869 }
1870 
_update_cache()1871 void VisualScriptPropertyGet::_update_cache() {
1872 
1873 	if (call_mode == CALL_MODE_BASIC_TYPE) {
1874 
1875 		//not super efficient..
1876 
1877 		Variant v;
1878 		Variant::CallError ce;
1879 		v = Variant::construct(basic_type, NULL, 0, ce);
1880 
1881 		List<PropertyInfo> pinfo;
1882 		v.get_property_list(&pinfo);
1883 
1884 		for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
1885 
1886 			if (E->get().name == property) {
1887 
1888 				type_cache = E->get().type;
1889 				return;
1890 			}
1891 		}
1892 
1893 	} else {
1894 
1895 		StringName type;
1896 		Ref<Script> script;
1897 		Node *node = NULL;
1898 
1899 		if (call_mode == CALL_MODE_NODE_PATH) {
1900 
1901 			node = _get_base_node();
1902 			if (node) {
1903 				type = node->get_class();
1904 				base_type = type; //cache, too
1905 				script = node->get_script();
1906 			}
1907 		} else if (call_mode == CALL_MODE_SELF) {
1908 
1909 			if (get_visual_script().is_valid()) {
1910 				type = get_visual_script()->get_instance_base_type();
1911 				base_type = type; //cache, too
1912 				script = get_visual_script();
1913 			}
1914 		} else if (call_mode == CALL_MODE_INSTANCE) {
1915 
1916 			type = base_type;
1917 			if (base_script != String()) {
1918 
1919 				if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) {
1920 
1921 					ScriptServer::edit_request_func(base_script); //make sure it's loaded
1922 				}
1923 
1924 				if (ResourceCache::has(base_script)) {
1925 
1926 					script = Ref<Resource>(ResourceCache::get(base_script));
1927 				} else {
1928 					return;
1929 				}
1930 			}
1931 		}
1932 
1933 		bool valid = false;
1934 
1935 		Variant::Type type_ret;
1936 
1937 		type_ret = ClassDB::get_property_type(base_type, property, &valid);
1938 
1939 		if (valid) {
1940 			type_cache = type_ret;
1941 			return; //all dandy
1942 		}
1943 
1944 		if (node) {
1945 
1946 			Variant prop = node->get(property, &valid);
1947 			if (valid) {
1948 				type_cache = prop.get_type();
1949 				return; //all dandy again
1950 			}
1951 		}
1952 
1953 		if (script.is_valid()) {
1954 
1955 			type_ret = script->get_static_property_type(property, &valid);
1956 
1957 			if (valid) {
1958 				type_cache = type_ret;
1959 				return; //all dandy
1960 			}
1961 		}
1962 	}
1963 }
1964 
set_property(const StringName & p_type)1965 void VisualScriptPropertyGet::set_property(const StringName &p_type) {
1966 
1967 	if (property == p_type)
1968 		return;
1969 
1970 	property = p_type;
1971 
1972 	_update_cache();
1973 	_change_notify();
1974 	ports_changed_notify();
1975 }
get_property() const1976 StringName VisualScriptPropertyGet::get_property() const {
1977 
1978 	return property;
1979 }
1980 
set_base_path(const NodePath & p_type)1981 void VisualScriptPropertyGet::set_base_path(const NodePath &p_type) {
1982 
1983 	if (base_path == p_type)
1984 		return;
1985 
1986 	base_path = p_type;
1987 	_change_notify();
1988 	_update_base_type();
1989 	ports_changed_notify();
1990 }
1991 
get_base_path() const1992 NodePath VisualScriptPropertyGet::get_base_path() const {
1993 
1994 	return base_path;
1995 }
1996 
set_call_mode(CallMode p_mode)1997 void VisualScriptPropertyGet::set_call_mode(CallMode p_mode) {
1998 
1999 	if (call_mode == p_mode)
2000 		return;
2001 
2002 	call_mode = p_mode;
2003 	_change_notify();
2004 	_update_base_type();
2005 	ports_changed_notify();
2006 }
get_call_mode() const2007 VisualScriptPropertyGet::CallMode VisualScriptPropertyGet::get_call_mode() const {
2008 
2009 	return call_mode;
2010 }
2011 
set_basic_type(Variant::Type p_type)2012 void VisualScriptPropertyGet::set_basic_type(Variant::Type p_type) {
2013 
2014 	if (basic_type == p_type)
2015 		return;
2016 	basic_type = p_type;
2017 
2018 	_change_notify();
2019 	ports_changed_notify();
2020 }
2021 
get_basic_type() const2022 Variant::Type VisualScriptPropertyGet::get_basic_type() const {
2023 
2024 	return basic_type;
2025 }
2026 
_set_type_cache(Variant::Type p_type)2027 void VisualScriptPropertyGet::_set_type_cache(Variant::Type p_type) {
2028 	type_cache = p_type;
2029 }
2030 
_get_type_cache() const2031 Variant::Type VisualScriptPropertyGet::_get_type_cache() const {
2032 
2033 	return type_cache;
2034 }
2035 
set_index(const StringName & p_type)2036 void VisualScriptPropertyGet::set_index(const StringName &p_type) {
2037 
2038 	if (index == p_type)
2039 		return;
2040 	index = p_type;
2041 	_update_cache();
2042 	_change_notify();
2043 	ports_changed_notify();
2044 }
2045 
get_index() const2046 StringName VisualScriptPropertyGet::get_index() const {
2047 
2048 	return index;
2049 }
2050 
_validate_property(PropertyInfo & property) const2051 void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const {
2052 
2053 	if (property.name == "base_type") {
2054 		if (call_mode != CALL_MODE_INSTANCE) {
2055 			property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
2056 		}
2057 	}
2058 
2059 	if (property.name == "base_script") {
2060 		if (call_mode != CALL_MODE_INSTANCE) {
2061 			property.usage = 0;
2062 		}
2063 	}
2064 
2065 	if (property.name == "basic_type") {
2066 		if (call_mode != CALL_MODE_BASIC_TYPE) {
2067 			property.usage = 0;
2068 		}
2069 	}
2070 
2071 	if (property.name == "node_path") {
2072 		if (call_mode != CALL_MODE_NODE_PATH) {
2073 			property.usage = 0;
2074 		} else {
2075 
2076 			Node *bnode = _get_base_node();
2077 			if (bnode) {
2078 				property.hint_string = bnode->get_path(); //convert to loong string
2079 			}
2080 		}
2081 	}
2082 
2083 	if (property.name == "property") {
2084 
2085 		if (call_mode == CALL_MODE_BASIC_TYPE) {
2086 
2087 			property.hint = PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE;
2088 			property.hint_string = Variant::get_type_name(basic_type);
2089 
2090 		} else if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid()) {
2091 			property.hint = PROPERTY_HINT_PROPERTY_OF_SCRIPT;
2092 			property.hint_string = itos(get_visual_script()->get_instance_id());
2093 		} else if (call_mode == CALL_MODE_INSTANCE) {
2094 			property.hint = PROPERTY_HINT_PROPERTY_OF_BASE_TYPE;
2095 			property.hint_string = base_type;
2096 
2097 			if (base_script != String()) {
2098 				if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) {
2099 
2100 					ScriptServer::edit_request_func(base_script); //make sure it's loaded
2101 				}
2102 
2103 				if (ResourceCache::has(base_script)) {
2104 
2105 					Ref<Script> script = Ref<Resource>(ResourceCache::get(base_script));
2106 					if (script.is_valid()) {
2107 
2108 						property.hint = PROPERTY_HINT_PROPERTY_OF_SCRIPT;
2109 						property.hint_string = itos(script->get_instance_id());
2110 					}
2111 				}
2112 			}
2113 		} else if (call_mode == CALL_MODE_NODE_PATH) {
2114 			Node *node = _get_base_node();
2115 			if (node) {
2116 				property.hint = PROPERTY_HINT_PROPERTY_OF_INSTANCE;
2117 				property.hint_string = itos(node->get_instance_id());
2118 			} else {
2119 				property.hint = PROPERTY_HINT_PROPERTY_OF_BASE_TYPE;
2120 				property.hint_string = get_base_type();
2121 			}
2122 		}
2123 	}
2124 
2125 	if (property.name == "index") {
2126 
2127 		Variant::CallError ce;
2128 		Variant v = Variant::construct(type_cache, NULL, 0, ce);
2129 		List<PropertyInfo> plist;
2130 		v.get_property_list(&plist);
2131 		String options = "";
2132 		for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
2133 			options += "," + E->get().name;
2134 		}
2135 
2136 		property.hint = PROPERTY_HINT_ENUM;
2137 		property.hint_string = options;
2138 		property.type = Variant::STRING;
2139 		if (options == "")
2140 			property.usage = 0; //hide if type has no usable index
2141 	}
2142 }
2143 
_bind_methods()2144 void VisualScriptPropertyGet::_bind_methods() {
2145 
2146 	ClassDB::bind_method(D_METHOD("set_base_type", "base_type"), &VisualScriptPropertyGet::set_base_type);
2147 	ClassDB::bind_method(D_METHOD("get_base_type"), &VisualScriptPropertyGet::get_base_type);
2148 
2149 	ClassDB::bind_method(D_METHOD("set_base_script", "base_script"), &VisualScriptPropertyGet::set_base_script);
2150 	ClassDB::bind_method(D_METHOD("get_base_script"), &VisualScriptPropertyGet::get_base_script);
2151 
2152 	ClassDB::bind_method(D_METHOD("set_basic_type", "basic_type"), &VisualScriptPropertyGet::set_basic_type);
2153 	ClassDB::bind_method(D_METHOD("get_basic_type"), &VisualScriptPropertyGet::get_basic_type);
2154 
2155 	ClassDB::bind_method(D_METHOD("_set_type_cache", "type_cache"), &VisualScriptPropertyGet::_set_type_cache);
2156 	ClassDB::bind_method(D_METHOD("_get_type_cache"), &VisualScriptPropertyGet::_get_type_cache);
2157 
2158 	ClassDB::bind_method(D_METHOD("set_property", "property"), &VisualScriptPropertyGet::set_property);
2159 	ClassDB::bind_method(D_METHOD("get_property"), &VisualScriptPropertyGet::get_property);
2160 
2161 	ClassDB::bind_method(D_METHOD("set_call_mode", "mode"), &VisualScriptPropertyGet::set_call_mode);
2162 	ClassDB::bind_method(D_METHOD("get_call_mode"), &VisualScriptPropertyGet::get_call_mode);
2163 
2164 	ClassDB::bind_method(D_METHOD("set_base_path", "base_path"), &VisualScriptPropertyGet::set_base_path);
2165 	ClassDB::bind_method(D_METHOD("get_base_path"), &VisualScriptPropertyGet::get_base_path);
2166 
2167 	ClassDB::bind_method(D_METHOD("set_index", "index"), &VisualScriptPropertyGet::set_index);
2168 	ClassDB::bind_method(D_METHOD("get_index"), &VisualScriptPropertyGet::get_index);
2169 
2170 	String bt;
2171 	for (int i = 0; i < Variant::VARIANT_MAX; i++) {
2172 		if (i > 0)
2173 			bt += ",";
2174 
2175 		bt += Variant::get_type_name(Variant::Type(i));
2176 	}
2177 
2178 	List<String> script_extensions;
2179 	for (int i = 0; i < ScriptServer::get_language_count(); i++) {
2180 		ScriptServer::get_language(i)->get_recognized_extensions(&script_extensions);
2181 	}
2182 
2183 	String script_ext_hint;
2184 	for (List<String>::Element *E = script_extensions.front(); E; E = E->next()) {
2185 		if (script_ext_hint != String())
2186 			script_ext_hint += ",";
2187 		script_ext_hint += "." + E->get();
2188 	}
2189 
2190 	ADD_PROPERTY(PropertyInfo(Variant::INT, "set_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type"), "set_call_mode", "get_call_mode");
2191 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type");
2192 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_script", PROPERTY_HINT_FILE, script_ext_hint), "set_base_script", "get_base_script");
2193 	ADD_PROPERTY(PropertyInfo(Variant::INT, "type_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_type_cache", "_get_type_cache");
2194 	ADD_PROPERTY(PropertyInfo(Variant::INT, "basic_type", PROPERTY_HINT_ENUM, bt), "set_basic_type", "get_basic_type");
2195 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path");
2196 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "property"), "set_property", "get_property");
2197 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "index", PROPERTY_HINT_ENUM), "set_index", "get_index");
2198 
2199 	BIND_ENUM_CONSTANT(CALL_MODE_SELF);
2200 	BIND_ENUM_CONSTANT(CALL_MODE_NODE_PATH);
2201 	BIND_ENUM_CONSTANT(CALL_MODE_INSTANCE);
2202 }
2203 
2204 class VisualScriptNodeInstancePropertyGet : public VisualScriptNodeInstance {
2205 public:
2206 	VisualScriptPropertyGet::CallMode call_mode;
2207 	NodePath node_path;
2208 	StringName property;
2209 	StringName index;
2210 
2211 	VisualScriptPropertyGet *node;
2212 	VisualScriptInstance *instance;
2213 
step(const Variant ** p_inputs,Variant ** p_outputs,StartMode p_start_mode,Variant * p_working_mem,Variant::CallError & r_error,String & r_error_str)2214 	virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) {
2215 
2216 		switch (call_mode) {
2217 
2218 			case VisualScriptPropertyGet::CALL_MODE_SELF: {
2219 
2220 				Object *object = instance->get_owner_ptr();
2221 
2222 				bool valid;
2223 
2224 				*p_outputs[0] = object->get(property, &valid);
2225 
2226 				if (index != StringName()) {
2227 					*p_outputs[0] = p_outputs[0]->get_named(index);
2228 				}
2229 
2230 				if (!valid) {
2231 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
2232 					r_error_str = RTR("Invalid index property name.");
2233 					return 0;
2234 				}
2235 			} break;
2236 			case VisualScriptPropertyGet::CALL_MODE_NODE_PATH: {
2237 
2238 				Node *node = Object::cast_to<Node>(instance->get_owner_ptr());
2239 				if (!node) {
2240 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
2241 					r_error_str = RTR("Base object is not a Node!");
2242 					return 0;
2243 				}
2244 
2245 				Node *another = node->get_node(node_path);
2246 				if (!another) {
2247 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
2248 					r_error_str = RTR("Path does not lead Node!");
2249 					return 0;
2250 				}
2251 
2252 				bool valid;
2253 
2254 				*p_outputs[0] = another->get(property, &valid);
2255 
2256 				if (index != StringName()) {
2257 					*p_outputs[0] = p_outputs[0]->get_named(index);
2258 				}
2259 
2260 				if (!valid) {
2261 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
2262 					r_error_str = vformat(RTR("Invalid index property name '%s' in node %s."), String(property), another->get_name());
2263 					return 0;
2264 				}
2265 
2266 			} break;
2267 			default: {
2268 
2269 				bool valid;
2270 				Variant v = *p_inputs[0];
2271 
2272 				*p_outputs[0] = v.get(property, &valid);
2273 				if (index != StringName()) {
2274 					*p_outputs[0] = p_outputs[0]->get_named(index);
2275 				}
2276 
2277 				if (!valid) {
2278 					r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
2279 					r_error_str = RTR("Invalid index property name.");
2280 				}
2281 			};
2282 		}
2283 
2284 		return 0;
2285 	}
2286 };
2287 
instance(VisualScriptInstance * p_instance)2288 VisualScriptNodeInstance *VisualScriptPropertyGet::instance(VisualScriptInstance *p_instance) {
2289 
2290 	VisualScriptNodeInstancePropertyGet *instance = memnew(VisualScriptNodeInstancePropertyGet);
2291 	instance->node = this;
2292 	instance->instance = p_instance;
2293 	instance->property = property;
2294 	instance->call_mode = call_mode;
2295 	instance->node_path = base_path;
2296 	instance->index = index;
2297 
2298 	return instance;
2299 }
2300 
VisualScriptPropertyGet()2301 VisualScriptPropertyGet::VisualScriptPropertyGet() {
2302 
2303 	call_mode = CALL_MODE_SELF;
2304 	base_type = "Object";
2305 	basic_type = Variant::NIL;
2306 	type_cache = Variant::NIL;
2307 }
2308 
2309 template <VisualScriptPropertyGet::CallMode cmode>
create_property_get_node(const String & p_name)2310 static Ref<VisualScriptNode> create_property_get_node(const String &p_name) {
2311 
2312 	Ref<VisualScriptPropertyGet> node;
2313 	node.instance();
2314 	node->set_call_mode(cmode);
2315 	return node;
2316 }
2317 
2318 //////////////////////////////////////////
2319 ////////////////EMIT//////////////////////
2320 //////////////////////////////////////////
2321 
get_output_sequence_port_count() const2322 int VisualScriptEmitSignal::get_output_sequence_port_count() const {
2323 
2324 	return 1;
2325 }
2326 
has_input_sequence_port() const2327 bool VisualScriptEmitSignal::has_input_sequence_port() const {
2328 
2329 	return true;
2330 }
2331 
get_input_value_port_count() const2332 int VisualScriptEmitSignal::get_input_value_port_count() const {
2333 
2334 	Ref<VisualScript> vs = get_visual_script();
2335 	if (vs.is_valid()) {
2336 
2337 		if (!vs->has_custom_signal(name))
2338 			return 0;
2339 
2340 		return vs->custom_signal_get_argument_count(name);
2341 	}
2342 
2343 	return 0;
2344 }
get_output_value_port_count() const2345 int VisualScriptEmitSignal::get_output_value_port_count() const {
2346 	return 0;
2347 }
2348 
get_output_sequence_port_text(int p_port) const2349 String VisualScriptEmitSignal::get_output_sequence_port_text(int p_port) const {
2350 
2351 	return String();
2352 }
2353 
get_input_value_port_info(int p_idx) const2354 PropertyInfo VisualScriptEmitSignal::get_input_value_port_info(int p_idx) const {
2355 
2356 	Ref<VisualScript> vs = get_visual_script();
2357 	if (vs.is_valid()) {
2358 
2359 		if (!vs->has_custom_signal(name))
2360 			return PropertyInfo();
2361 
2362 		return PropertyInfo(vs->custom_signal_get_argument_type(name, p_idx), vs->custom_signal_get_argument_name(name, p_idx));
2363 	}
2364 
2365 	return PropertyInfo();
2366 }
2367 
get_output_value_port_info(int p_idx) const2368 PropertyInfo VisualScriptEmitSignal::get_output_value_port_info(int p_idx) const {
2369 
2370 	return PropertyInfo();
2371 }
2372 
get_caption() const2373 String VisualScriptEmitSignal::get_caption() const {
2374 
2375 	return "Emit " + String(name);
2376 }
2377 
set_signal(const StringName & p_type)2378 void VisualScriptEmitSignal::set_signal(const StringName &p_type) {
2379 
2380 	if (name == p_type)
2381 		return;
2382 
2383 	name = p_type;
2384 
2385 	_change_notify();
2386 	ports_changed_notify();
2387 }
get_signal() const2388 StringName VisualScriptEmitSignal::get_signal() const {
2389 
2390 	return name;
2391 }
2392 
_validate_property(PropertyInfo & property) const2393 void VisualScriptEmitSignal::_validate_property(PropertyInfo &property) const {
2394 
2395 	if (property.name == "signal") {
2396 		property.hint = PROPERTY_HINT_ENUM;
2397 
2398 		List<StringName> sigs;
2399 
2400 		Ref<VisualScript> vs = get_visual_script();
2401 		if (vs.is_valid()) {
2402 
2403 			vs->get_custom_signal_list(&sigs);
2404 		}
2405 
2406 		String ml;
2407 		for (List<StringName>::Element *E = sigs.front(); E; E = E->next()) {
2408 
2409 			if (ml != String())
2410 				ml += ",";
2411 			ml += E->get();
2412 		}
2413 
2414 		property.hint_string = ml;
2415 	}
2416 }
2417 
_bind_methods()2418 void VisualScriptEmitSignal::_bind_methods() {
2419 
2420 	ClassDB::bind_method(D_METHOD("set_signal", "name"), &VisualScriptEmitSignal::set_signal);
2421 	ClassDB::bind_method(D_METHOD("get_signal"), &VisualScriptEmitSignal::get_signal);
2422 
2423 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "signal"), "set_signal", "get_signal");
2424 }
2425 
2426 class VisualScriptNodeInstanceEmitSignal : public VisualScriptNodeInstance {
2427 public:
2428 	VisualScriptEmitSignal *node;
2429 	VisualScriptInstance *instance;
2430 	int argcount;
2431 	StringName name;
2432 
2433 	//virtual int get_working_memory_size() const { return 0; }
2434 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
2435 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
2436 
step(const Variant ** p_inputs,Variant ** p_outputs,StartMode p_start_mode,Variant * p_working_mem,Variant::CallError & r_error,String & r_error_str)2437 	virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) {
2438 
2439 		Object *obj = instance->get_owner_ptr();
2440 
2441 		obj->emit_signal(name, p_inputs, argcount);
2442 
2443 		return 0;
2444 	}
2445 };
2446 
instance(VisualScriptInstance * p_instance)2447 VisualScriptNodeInstance *VisualScriptEmitSignal::instance(VisualScriptInstance *p_instance) {
2448 
2449 	VisualScriptNodeInstanceEmitSignal *instance = memnew(VisualScriptNodeInstanceEmitSignal);
2450 	instance->node = this;
2451 	instance->instance = p_instance;
2452 	instance->name = name;
2453 	instance->argcount = get_input_value_port_count();
2454 	return instance;
2455 }
2456 
VisualScriptEmitSignal()2457 VisualScriptEmitSignal::VisualScriptEmitSignal() {
2458 }
2459 
create_basic_type_call_node(const String & p_name)2460 static Ref<VisualScriptNode> create_basic_type_call_node(const String &p_name) {
2461 
2462 	Vector<String> path = p_name.split("/");
2463 	ERR_FAIL_COND_V(path.size() < 4, Ref<VisualScriptNode>());
2464 	String base_type = path[2];
2465 	String method = path[3];
2466 
2467 	Ref<VisualScriptFunctionCall> node;
2468 	node.instance();
2469 
2470 	Variant::Type type = Variant::VARIANT_MAX;
2471 
2472 	for (int i = 0; i < Variant::VARIANT_MAX; i++) {
2473 
2474 		if (Variant::get_type_name(Variant::Type(i)) == base_type) {
2475 			type = Variant::Type(i);
2476 			break;
2477 		}
2478 	}
2479 
2480 	ERR_FAIL_COND_V(type == Variant::VARIANT_MAX, Ref<VisualScriptNode>());
2481 
2482 	node->set_call_mode(VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE);
2483 	node->set_basic_type(type);
2484 	node->set_function(method);
2485 
2486 	return node;
2487 }
2488 
register_visual_script_func_nodes()2489 void register_visual_script_func_nodes() {
2490 
2491 	VisualScriptLanguage::singleton->add_register_func("functions/call", create_node_generic<VisualScriptFunctionCall>);
2492 	VisualScriptLanguage::singleton->add_register_func("functions/set", create_node_generic<VisualScriptPropertySet>);
2493 	VisualScriptLanguage::singleton->add_register_func("functions/get", create_node_generic<VisualScriptPropertyGet>);
2494 
2495 	//VisualScriptLanguage::singleton->add_register_func("functions/call_script/call_self",create_script_call_node<VisualScriptScriptCall::CALL_MODE_SELF>);
2496 	//VisualScriptLanguage::singleton->add_register_func("functions/call_script/call_node",create_script_call_node<VisualScriptScriptCall::CALL_MODE_NODE_PATH>);
2497 	VisualScriptLanguage::singleton->add_register_func("functions/emit_signal", create_node_generic<VisualScriptEmitSignal>);
2498 
2499 	for (int i = 0; i < Variant::VARIANT_MAX; i++) {
2500 
2501 		Variant::Type t = Variant::Type(i);
2502 		String type_name = Variant::get_type_name(t);
2503 		Variant::CallError ce;
2504 		Variant vt = Variant::construct(t, NULL, 0, ce);
2505 		List<MethodInfo> ml;
2506 		vt.get_method_list(&ml);
2507 
2508 		for (List<MethodInfo>::Element *E = ml.front(); E; E = E->next()) {
2509 			VisualScriptLanguage::singleton->add_register_func("functions/by_type/" + type_name + "/" + E->get().name, create_basic_type_call_node);
2510 		}
2511 	}
2512 }
2513