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