summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/io/resource_format_binary.cpp24
-rw-r--r--core/method_bind.h1
-rw-r--r--core/object_type_db.cpp17
-rw-r--r--core/object_type_db.h1
-rw-r--r--core/os/keyboard.cpp21
-rw-r--r--core/os/keyboard.h3
-rw-r--r--core/script_language.h5
-rw-r--r--main/input_default.cpp2
-rwxr-xr-xmethods.py4
-rw-r--r--modules/gdscript/gd_editor.cpp30
-rw-r--r--modules/gdscript/gd_function.cpp3
-rw-r--r--modules/gdscript/gd_parser.cpp15
-rw-r--r--modules/gdscript/gd_parser.h3
-rw-r--r--modules/gdscript/gd_script.cpp31
-rw-r--r--modules/gdscript/gd_script.h4
-rw-r--r--modules/visual_script/register_types.cpp14
-rw-r--r--modules/visual_script/visual_script.cpp1402
-rw-r--r--modules/visual_script/visual_script.h286
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp672
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.h3
-rw-r--r--modules/visual_script/visual_script_editor.cpp291
-rw-r--r--modules/visual_script/visual_script_editor.h21
-rw-r--r--modules/visual_script/visual_script_flow_control.cpp1284
-rw-r--r--modules/visual_script/visual_script_flow_control.h94
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp695
-rw-r--r--modules/visual_script/visual_script_func_nodes.h29
-rw-r--r--modules/visual_script/visual_script_nodes.cpp1138
-rw-r--r--modules/visual_script/visual_script_nodes.h216
-rw-r--r--modules/visual_script/visual_script_yield_nodes.cpp622
-rw-r--r--modules/visual_script/visual_script_yield_nodes.h127
-rw-r--r--scene/gui/container.cpp8
-rw-r--r--scene/gui/control.cpp40
-rw-r--r--scene/gui/control.h4
-rw-r--r--scene/gui/graph_edit.cpp30
-rw-r--r--scene/gui/graph_edit.h2
-rw-r--r--scene/gui/graph_node.cpp51
-rw-r--r--scene/gui/graph_node.h19
-rw-r--r--scene/gui/tab_container.cpp3
-rw-r--r--scene/gui/text_edit.h4
-rw-r--r--scene/main/scene_main_loop.cpp53
-rw-r--r--scene/main/scene_main_loop.h20
-rw-r--r--scene/register_scene_types.cpp1
-rw-r--r--scene/resources/default_theme/default_theme.cpp5
-rw-r--r--scene/resources/default_theme/graph_node_breakpoint.pngbin0 -> 277 bytes
-rw-r--r--scene/resources/default_theme/graph_node_position.pngbin0 -> 278 bytes
-rw-r--r--scene/resources/default_theme/graph_node_selected.pngbin964 -> 920 bytes
-rw-r--r--scene/resources/default_theme/theme_data.h12
-rw-r--r--scene/resources/style_box.cpp21
-rw-r--r--scene/resources/style_box.h4
-rw-r--r--tools/editor/connections_dialog.cpp2
-rw-r--r--tools/editor/create_dialog.cpp4
-rw-r--r--tools/editor/editor_node.cpp16
-rw-r--r--tools/editor/editor_node.h12
-rw-r--r--tools/editor/editor_settings.cpp2
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp36
-rw-r--r--tools/editor/plugins/script_editor_plugin.h3
-rw-r--r--tools/editor/plugins/script_text_editor.cpp7
-rw-r--r--tools/editor/plugins/script_text_editor.h4
-rw-r--r--tools/editor/property_editor.cpp4
-rw-r--r--tools/editor/scene_tree_dock.cpp17
-rw-r--r--tools/editor/scene_tree_dock.h1
-rw-r--r--tools/editor/script_create_dialog.cpp16
-rw-r--r--tools/editor/script_editor_debugger.cpp3
63 files changed, 7179 insertions, 283 deletions
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 343a54e0d7..a620dc0fef 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -447,13 +447,17 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) {
} break;
case VARIANT_INPUT_EVENT: {
+ InputEvent ev;
+ ev.type=f->get_32(); //will only work for null though.
+ r_v=ev;
+
} break;
case VARIANT_DICTIONARY: {
- uint32_t len=f->get_32();
- Dictionary d(len&0x80000000); //last bit means shared
- len&=0x7FFFFFFF;
- for(uint32_t i=0;i<len;i++) {
+ uint32_t len=f->get_32();
+ Dictionary d(len&0x80000000); //last bit means shared
+ len&=0x7FFFFFFF;
+ for(uint32_t i=0;i<len;i++) {
Variant key;
Error err = parse_variant(key);
ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT);
@@ -466,11 +470,11 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) {
} break;
case VARIANT_ARRAY: {
- uint32_t len=f->get_32();
- Array a(len&0x80000000); //last bit means shared
- len&=0x7FFFFFFF;
+ uint32_t len=f->get_32();
+ Array a(len&0x80000000); //last bit means shared
+ len&=0x7FFFFFFF;
a.resize(len);
- for(uint32_t i=0;i<len;i++) {
+ for(uint32_t i=0;i<len;i++) {
Variant val;
Error err = parse_variant(val);
ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT);
@@ -1725,7 +1729,9 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant& p_property,
case Variant::INPUT_EVENT: {
f->store_32(VARIANT_INPUT_EVENT);
- WARN_PRINT("Can't save InputEvent (maybe it could..)");
+ InputEvent event=p_property;
+ f->store_32(0); //event type none, nothing else suported for now.
+
} break;
case Variant::DICTIONARY: {
diff --git a/core/method_bind.h b/core/method_bind.h
index 3d62e38daa..072953743c 100644
--- a/core/method_bind.h
+++ b/core/method_bind.h
@@ -156,6 +156,7 @@ VARIANT_ENUM_CAST( Orientation );
VARIANT_ENUM_CAST( HAlign );
VARIANT_ENUM_CAST( Variant::Type );
VARIANT_ENUM_CAST( Variant::Operator );
+VARIANT_ENUM_CAST( InputEvent::Type );
class MethodBind {
diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp
index 4998263961..ba98797a89 100644
--- a/core/object_type_db.cpp
+++ b/core/object_type_db.cpp
@@ -549,6 +549,23 @@ bool ObjectTypeDB::has_signal(StringName p_type,StringName p_signal) {
return false;
}
+bool ObjectTypeDB::get_signal(StringName p_type,StringName p_signal,MethodInfo *r_signal) {
+
+ TypeInfo *type=types.getptr(p_type);
+ TypeInfo *check=type;
+ while(check) {
+ if (check->signal_map.has(p_signal)) {
+ if (r_signal) {
+ *r_signal=check->signal_map[p_signal];
+ }
+ return true;
+ }
+ check=check->inherits_ptr;
+ }
+
+ return false;
+}
+
void ObjectTypeDB::add_property(StringName p_type,const PropertyInfo& p_pinfo, const StringName& p_setter, const StringName& p_getter, int p_index) {
diff --git a/core/object_type_db.h b/core/object_type_db.h
index 8313091acd..9f7463e58b 100644
--- a/core/object_type_db.h
+++ b/core/object_type_db.h
@@ -453,6 +453,7 @@ public:
static void add_signal(StringName p_type,const MethodInfo& p_signal);
static bool has_signal(StringName p_type,StringName p_signal);
+ static bool get_signal(StringName p_type,StringName p_signal,MethodInfo *r_signal);
static void get_signal_list(StringName p_type,List<MethodInfo> *p_signals,bool p_no_inheritance=false);
static void add_property(StringName p_type,const PropertyInfo& p_pinfo, const StringName& p_setter, const StringName& p_getter, int p_index=-1);
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
index 4c0a074a07..9710638234 100644
--- a/core/os/keyboard.cpp
+++ b/core/os/keyboard.cpp
@@ -429,6 +429,27 @@ static const _KeyCodeReplace _keycode_replace_neo[]={
{0,0}
};
+int keycode_get_count() {
+
+ const _KeyCodeText *kct =&_keycodes[0];
+
+ int count=0;
+ while(kct->text) {
+
+ count++;
+ kct++;
+ }
+ return count;
+}
+
+int keycode_get_value_by_index(int p_index) {
+ return _keycodes[p_index].code;
+}
+
+const char* keycode_get_name_by_index(int p_index) {
+ return _keycodes[p_index].text;
+}
+
int latin_keyboard_keycode_convert(int p_keycode) {
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index 80472acc09..fd52d331c8 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -328,6 +328,9 @@ enum KeyModifierMask {
String keycode_get_string(uint32_t p_code);
bool keycode_has_unicode(uint32_t p_unicode);
int find_keycode(const String& p_code);
+int keycode_get_count();
+int keycode_get_value_by_index(int p_index);
+const char* keycode_get_name_by_index(int p_index);
int latin_keyboard_keycode_convert(int p_keycode);
#endif
diff --git a/core/script_language.h b/core/script_language.h
index 499dbe14a7..0e3f298790 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -98,6 +98,9 @@ public:
virtual void set_source_code(const String& p_code)=0;
virtual Error reload(bool p_keep_state=false)=0;
+ virtual bool has_method(const StringName& p_method) const=0;
+ virtual MethodInfo get_method_info(const StringName& p_method) const=0;
+
virtual bool is_tool() const=0;
virtual String get_node_type() const=0;
@@ -178,7 +181,7 @@ public:
virtual void get_reserved_words(List<String> *p_words) const=0;
virtual void get_comment_delimiters(List<String> *p_delimiters) const=0;
virtual void get_string_delimiters(List<String> *p_delimiters) const=0;
- virtual String get_template(const String& p_class_name, const String& p_base_class_name) const=0;
+ virtual Ref<Script> get_template(const String& p_class_name, const String& p_base_class_name) const=0;
virtual bool validate(const String& p_script, int &r_line_error,int &r_col_error,String& r_test_error, const String& p_path="",List<String> *r_functions=NULL) const=0;
virtual Script *create_script() const=0;
virtual bool has_named_classes() const=0;
diff --git a/main/input_default.cpp b/main/input_default.cpp
index 618d0d4f7d..c655b409ff 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -588,7 +588,7 @@ static const char *s_ControllerMappings [] =
"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,",
"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
- "030000005e0400008e02000001000000,Microsoft X-Box 360 pad,leftx:a0,lefty:a1,dpdown:h0.1,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:h0.2,lefttrigger:a2,x:b2,dpup:h0.4,back:b6,leftshoulder:b4,y:b3,a:b0,dpright:h0.8,righttrigger:a5,b:b1,",
+ "030000005e0400008e02000001000000,Microsoft X-Box 360 pad,leftstick:b9,leftx:a0,lefty:a1,dpdown:h0.1,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:h0.2,lefttrigger:a2,x:b2,dpup:h0.4,back:b6,leftshoulder:b4,y:b3,a:b0,dpright:h0.8,righttrigger:a5,b:b1,",
"030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
diff --git a/methods.py b/methods.py
index 74c282b8cf..e29fd760ba 100755
--- a/methods.py
+++ b/methods.py
@@ -1213,7 +1213,9 @@ def detect_modules():
register_cpp=""
unregister_cpp=""
- for x in glob.glob("modules/*"):
+ files = glob.glob("modules/*")
+ files.sort() #so register_module_types does not change that often, and also plugins are registered in alphabetic order
+ for x in files:
if (not os.path.isdir(x)):
continue
x=x.replace("modules/","") # rest of world
diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp
index b02e55cf9d..2e5fb82f37 100644
--- a/modules/gdscript/gd_editor.cpp
+++ b/modules/gdscript/gd_editor.cpp
@@ -44,7 +44,7 @@ void GDScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const {
}
-String GDScriptLanguage::get_template(const String& p_class_name, const String& p_base_class_name) const {
+Ref<Script> GDScriptLanguage::get_template(const String& p_class_name, const String& p_base_class_name) const {
String _template = String()+
"\nextends %BASE%\n\n"+
@@ -58,7 +58,14 @@ String GDScriptLanguage::get_template(const String& p_class_name, const String&
"\n"+
"\n";
- return _template.replace("%BASE%",p_base_class_name);
+ _template = _template.replace("%BASE%",p_base_class_name);
+
+ Ref<GDScript> script;
+ script.instance();
+ script->set_source_code(_template);
+
+ return script;
+
}
@@ -328,7 +335,7 @@ String GDScriptLanguage::make_function(const String& p_class,const String& p_nam
for(int i=0;i<p_args.size();i++) {
if (i>0)
s+=", ";
- s+=p_args[i];
+ s+=p_args[i].get_slice(":",0);
}
s+=" ";
}
@@ -2382,7 +2389,24 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base
}
}
} break;
+ case GDParser::COMPLETION_YIELD: {
+
+ const GDParser::Node *node = p.get_completion_node();
+
+ GDCompletionIdentifier t;
+ if (!_guess_expression_type(context,node,p.get_completion_line(),t))
+ break;
+ if (t.type==Variant::OBJECT && t.obj_type!=StringName()) {
+
+ List<MethodInfo> sigs;
+ ObjectTypeDB::get_signal_list(t.obj_type,&sigs);
+ for (List<MethodInfo>::Element *E=sigs.front();E;E=E->next()) {
+ options.insert("\""+E->get().name+"\"");
+ }
+ }
+
+ } break;
}
diff --git a/modules/gdscript/gd_function.cpp b/modules/gdscript/gd_function.cpp
index de86eb2ab9..47d8f0b40f 100644
--- a/modules/gdscript/gd_function.cpp
+++ b/modules/gdscript/gd_function.cpp
@@ -372,8 +372,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language()==GDScriptLanguage::get_singleton()) {
- GDInstance *ins = static_cast<GDInstance*>(obj_A->get_script_instance());
- GDScript *cmp = ins->script.ptr();
+ GDScript *cmp = static_cast<GDScript*>(obj_A->get_script_instance()->get_script().ptr());
//bool found=false;
while(cmp) {
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index e829fa86b4..a6794564db 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -378,6 +378,21 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
tokenizer->advance();
+ if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) {
+
+
+ completion_cursor=StringName();
+ completion_node=object;
+ completion_type=COMPLETION_YIELD;
+ completion_class=current_class;
+ completion_function=current_function;
+ completion_line=tokenizer->get_token_line();
+ completion_argument=0;
+ completion_block=current_block;
+ completion_found=true;
+ tokenizer->advance();
+ }
+
Node *signal = _parse_and_reduce_expression(p_parent,p_static);
if (!signal)
return NULL;
diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h
index 4afc534a8c..2d6b52c473 100644
--- a/modules/gdscript/gd_parser.h
+++ b/modules/gdscript/gd_parser.h
@@ -375,7 +375,8 @@ public:
COMPLETION_METHOD,
COMPLETION_CALL_ARGUMENTS,
COMPLETION_INDEX,
- COMPLETION_VIRTUAL_FUNC
+ COMPLETION_VIRTUAL_FUNC,
+ COMPLETION_YIELD,
};
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index cc46d91a2d..2f5c7956d1 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -262,10 +262,37 @@ void GDScript::get_method_list(List<MethodInfo> *p_list) const {
mi.arguments.push_back(arg);
}
- mi.return_val.name="var";
+ mi.return_val.name="Variant";
p_list->push_back(mi);
}
}
+
+bool GDScript::has_method(const StringName& p_method) const {
+
+ return member_functions.has(p_method);
+}
+
+MethodInfo GDScript::get_method_info(const StringName& p_method) const {
+
+ const Map<StringName,GDFunction*>::Element *E=member_functions.find(p_method);
+ if (!E)
+ return MethodInfo();
+
+ MethodInfo mi;
+ mi.name=E->key();
+ for(int i=0;i<E->get()->get_argument_count();i++) {
+ PropertyInfo arg;
+ arg.type=Variant::NIL; //variant
+ arg.name=E->get()->get_argument_name(i);
+ mi.arguments.push_back(arg);
+ }
+
+ mi.return_val.name="Variant";
+ return mi;
+
+}
+
+
bool GDScript::get_property_default_value(const StringName& p_property, Variant &r_value) const {
#ifdef TOOLS_ENABLED
@@ -1239,6 +1266,8 @@ void GDInstance::call_multilevel_reversed(const StringName& p_method,const Varia
}
}
+
+
void GDInstance::notification(int p_notification) {
//notification is not virutal, it gets called at ALL levels just like in C.
diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h
index 41c5c32e49..28a0df1efd 100644
--- a/modules/gdscript/gd_script.h
+++ b/modules/gdscript/gd_script.h
@@ -182,6 +182,8 @@ public:
bool get_property_default_value(const StringName& p_property,Variant& r_value) const;
virtual void get_method_list(List<MethodInfo> *p_list) const;
+ virtual bool has_method(const StringName& p_method) const;
+ virtual MethodInfo get_method_info(const StringName& p_method) const;
virtual ScriptLanguage *get_language() const;
@@ -375,7 +377,7 @@ public:
virtual void get_reserved_words(List<String> *p_words) const;
virtual void get_comment_delimiters(List<String> *p_delimiters) const;
virtual void get_string_delimiters(List<String> *p_delimiters) const;
- virtual String get_template(const String& p_class_name, const String& p_base_class_name) const;
+ virtual Ref<Script> get_template(const String& p_class_name, const String& p_base_class_name) const;
virtual bool validate(const String& p_script,int &r_line_error,int &r_col_error,String& r_test_error, const String& p_path="",List<String> *r_functions=NULL) const;
virtual Script *create_script() const;
virtual bool has_named_classes() const;
diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp
index da767c8447..1360e546f3 100644
--- a/modules/visual_script/register_types.cpp
+++ b/modules/visual_script/register_types.cpp
@@ -35,6 +35,7 @@
#include "visual_script_func_nodes.h"
#include "visual_script_builtin_funcs.h"
#include "visual_script_flow_control.h"
+#include "visual_script_yield_nodes.h"
VisualScriptLanguage *visual_script_language=NULL;
@@ -44,9 +45,11 @@ void register_visual_script_types() {
ObjectTypeDB::register_type<VisualScript>();
ObjectTypeDB::register_virtual_type<VisualScriptNode>();
+ ObjectTypeDB::register_virtual_type<VisualScriptFunctionState>();
ObjectTypeDB::register_type<VisualScriptFunction>();
ObjectTypeDB::register_type<VisualScriptOperator>();
- ObjectTypeDB::register_type<VisualScriptVariable>();
+ ObjectTypeDB::register_type<VisualScriptVariableSet>();
+ ObjectTypeDB::register_type<VisualScriptVariableGet>();
ObjectTypeDB::register_type<VisualScriptConstant>();
ObjectTypeDB::register_type<VisualScriptIndexGet>();
ObjectTypeDB::register_type<VisualScriptIndexSet>();
@@ -56,6 +59,9 @@ void register_visual_script_types() {
ObjectTypeDB::register_type<VisualScriptSceneNode>();
ObjectTypeDB::register_type<VisualScriptSceneTree>();
ObjectTypeDB::register_type<VisualScriptResourcePath>();
+ ObjectTypeDB::register_type<VisualScriptSelf>();
+ ObjectTypeDB::register_type<VisualScriptCustomNode>();
+ ObjectTypeDB::register_type<VisualScriptSubCall>();
ObjectTypeDB::register_type<VisualScriptFunctionCall>();
ObjectTypeDB::register_type<VisualScriptPropertySet>();
@@ -68,6 +74,11 @@ void register_visual_script_types() {
ObjectTypeDB::register_type<VisualScriptWhile>();
ObjectTypeDB::register_type<VisualScriptIterator>();
ObjectTypeDB::register_type<VisualScriptSequence>();
+ ObjectTypeDB::register_type<VisualScriptInputFilter>();
+ ObjectTypeDB::register_type<VisualScriptInputSelector>();
+
+ ObjectTypeDB::register_type<VisualScriptYield>();
+ ObjectTypeDB::register_type<VisualScriptYieldSignal>();
ObjectTypeDB::register_type<VisualScriptBuiltinFunc>();
@@ -79,6 +90,7 @@ void register_visual_script_types() {
register_visual_script_func_nodes();
register_visual_script_builtin_func_node();
register_visual_script_flow_control_nodes();
+ register_visual_script_yield_nodes();
#ifdef TOOLS_ENABLED
VisualScriptEditor::register_editor();
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index 6f18bcfaee..425436d907 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -1,6 +1,20 @@
#include "visual_script.h"
#include "visual_script_nodes.h"
+#include "scene/main/node.h"
+#include "globals.h"
+#define SCRIPT_VARIABLES_PREFIX "script_variables/"
+
+
+//used by editor, this is not really saved
+void VisualScriptNode::set_breakpoint(bool p_breakpoint) {
+ breakpoint=p_breakpoint;
+}
+
+bool VisualScriptNode::is_breakpoint() const {
+
+ return breakpoint;
+}
void VisualScriptNode::_notification(int p_what) {
@@ -95,20 +109,44 @@ Ref<VisualScript> VisualScriptNode::get_visual_script() const {
}
+VisualScriptNode::VisualScriptNode() {
+ breakpoint=false;
+}
+
////////////////
/////////////////////
+VisualScriptNodeInstance::VisualScriptNodeInstance() {
+
+ sequence_outputs=NULL;
+ input_ports=NULL;
+}
+
VisualScriptNodeInstance::~VisualScriptNodeInstance() {
+ if (sequence_outputs) {
+ memdelete(sequence_outputs);
+ }
+
+ if (input_ports) {
+ memdelete(input_ports);
+ }
+
+ if (output_ports) {
+ memdelete(output_ports);
+ }
+
}
void VisualScript::add_function(const StringName& p_name) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!String(p_name).is_valid_identifier());
ERR_FAIL_COND(functions.has(p_name));
functions[p_name]=Function();
+ functions[p_name].scroll=Vector2(-50,-100);
}
bool VisualScript::has_function(const StringName& p_name) const {
@@ -118,6 +156,7 @@ bool VisualScript::has_function(const StringName& p_name) const {
}
void VisualScript::remove_function(const StringName& p_name) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!functions.has(p_name));
for (Map<int,Function::NodeData>::Element *E=functions[p_name].nodes.front();E;E=E->next()) {
@@ -132,6 +171,7 @@ void VisualScript::remove_function(const StringName& p_name) {
void VisualScript::rename_function(const StringName& p_name,const StringName& p_new_name) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!functions.has(p_name));
if (p_new_name==p_name)
return;
@@ -147,6 +187,21 @@ void VisualScript::rename_function(const StringName& p_name,const StringName& p_
}
+void VisualScript::set_function_scroll(const StringName& p_name, const Vector2& p_scroll) {
+
+ ERR_FAIL_COND(!functions.has(p_name));
+ functions[p_name].scroll=p_scroll;
+
+}
+
+Vector2 VisualScript::get_function_scroll(const StringName& p_name) const {
+
+ ERR_FAIL_COND_V(!functions.has(p_name),Vector2());
+ return functions[p_name].scroll;
+
+}
+
+
void VisualScript::get_function_list(List<StringName> *r_functions) const {
for (const Map<StringName,Function>::Element *E=functions.front();E;E=E->next()) {
@@ -226,11 +281,14 @@ void VisualScript::_node_ports_changed(int p_id) {
}
}
+ set_edited(true); //something changed, let's set as edited
emit_signal("node_ports_changed",function,p_id);
+
}
void VisualScript::add_node(const StringName& p_func,int p_id, const Ref<VisualScriptNode>& p_node, const Point2 &p_pos) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!functions.has(p_func));
@@ -265,6 +323,7 @@ void VisualScript::add_node(const StringName& p_func,int p_id, const Ref<VisualS
void VisualScript::remove_node(const StringName& p_func,int p_id){
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!functions.has(p_func));
Function &func = functions[p_func];
@@ -314,6 +373,13 @@ void VisualScript::remove_node(const StringName& p_func,int p_id){
}
+bool VisualScript::has_node(const StringName& p_func,int p_id) const {
+
+ ERR_FAIL_COND_V(!functions.has(p_func),false);
+ const Function &func = functions[p_func];
+
+ return func.nodes.has(p_id);
+}
Ref<VisualScriptNode> VisualScript::get_node(const StringName& p_func,int p_id) const{
@@ -327,6 +393,7 @@ Ref<VisualScriptNode> VisualScript::get_node(const StringName& p_func,int p_id)
void VisualScript::set_node_pos(const StringName& p_func,int p_id,const Point2& p_pos) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!functions.has(p_func));
Function &func = functions[p_func];
@@ -358,6 +425,7 @@ void VisualScript::get_node_list(const StringName& p_func,List<int> *r_nodes) co
void VisualScript::sequence_connect(const StringName& p_func,int p_from_node,int p_from_output,int p_to_node){
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!functions.has(p_func));
Function &func = functions[p_func];
@@ -413,6 +481,7 @@ void VisualScript::get_sequence_connection_list(const StringName& p_func,List<Se
void VisualScript::data_connect(const StringName& p_func,int p_from_node,int p_from_port,int p_to_node,int p_to_port) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!functions.has(p_func));
Function &func = functions[p_func];
@@ -484,6 +553,7 @@ void VisualScript::get_data_connection_list(const StringName& p_func,List<DataCo
void VisualScript::add_variable(const StringName& p_name,const Variant& p_default_value) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!String(p_name).is_valid_identifier());
ERR_FAIL_COND(variables.has(p_name));
@@ -494,6 +564,12 @@ void VisualScript::add_variable(const StringName& p_name,const Variant& p_defaul
v.info.hint=PROPERTY_HINT_NONE;
variables[p_name]=v;
+ script_variable_remap[SCRIPT_VARIABLES_PREFIX+String(p_name)]=p_name;
+
+
+#ifdef TOOLS_ENABLED
+ _update_placeholders();
+#endif
}
@@ -506,6 +582,11 @@ void VisualScript::remove_variable(const StringName& p_name) {
ERR_FAIL_COND(!variables.has(p_name));
variables.erase(p_name);
+ script_variable_remap.erase(SCRIPT_VARIABLES_PREFIX+String(p_name));
+
+#ifdef TOOLS_ENABLED
+ _update_placeholders();
+#endif
}
void VisualScript::set_variable_default_value(const StringName& p_name,const Variant& p_value){
@@ -514,6 +595,10 @@ void VisualScript::set_variable_default_value(const StringName& p_name,const Var
variables[p_name].default_value=p_value;
+#ifdef TOOLS_ENABLED
+ _update_placeholders();
+#endif
+
}
Variant VisualScript::get_variable_default_value(const StringName& p_name) const{
@@ -523,10 +608,15 @@ Variant VisualScript::get_variable_default_value(const StringName& p_name) const
}
void VisualScript::set_variable_info(const StringName& p_name,const PropertyInfo& p_info){
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!variables.has(p_name));
variables[p_name].info=p_info;
variables[p_name].info.name=p_name;
+#ifdef TOOLS_ENABLED
+ _update_placeholders();
+#endif
+
}
PropertyInfo VisualScript::get_variable_info(const StringName& p_name) const{
@@ -578,12 +668,14 @@ void VisualScript::get_variable_list(List<StringName> *r_variables){
void VisualScript::set_instance_base_type(const StringName& p_type) {
+ ERR_FAIL_COND( instances.size() );
base_type=p_type;
}
void VisualScript::rename_variable(const StringName& p_name,const StringName& p_new_name) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!variables.has(p_name));
if (p_new_name==p_name)
return;
@@ -601,6 +693,7 @@ void VisualScript::rename_variable(const StringName& p_name,const StringName& p_
void VisualScript::add_custom_signal(const StringName& p_name) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!String(p_name).is_valid_identifier());
ERR_FAIL_COND(custom_signals.has(p_name));
@@ -614,6 +707,7 @@ bool VisualScript::has_custom_signal(const StringName& p_name) const {
}
void VisualScript::custom_signal_add_argument(const StringName& p_func,Variant::Type p_type,const String& p_name,int p_index) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!custom_signals.has(p_func));
Argument arg;
arg.type=p_type;
@@ -626,6 +720,7 @@ void VisualScript::custom_signal_add_argument(const StringName& p_func,Variant::
}
void VisualScript::custom_signal_set_argument_type(const StringName& p_func,int p_argidx,Variant::Type p_type) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!custom_signals.has(p_func));
ERR_FAIL_INDEX(p_argidx,custom_signals[p_func].size());
custom_signals[p_func][p_argidx].type=p_type;
@@ -637,6 +732,7 @@ Variant::Type VisualScript::custom_signal_get_argument_type(const StringName& p_
return custom_signals[p_func][p_argidx].type;
}
void VisualScript::custom_signal_set_argument_name(const StringName& p_func,int p_argidx,const String& p_name) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!custom_signals.has(p_func));
ERR_FAIL_INDEX(p_argidx,custom_signals[p_func].size());
custom_signals[p_func][p_argidx].name=p_name;
@@ -651,6 +747,7 @@ String VisualScript::custom_signal_get_argument_name(const StringName& p_func,in
}
void VisualScript::custom_signal_remove_argument(const StringName& p_func,int p_argidx) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!custom_signals.has(p_func));
ERR_FAIL_INDEX(p_argidx,custom_signals[p_func].size());
custom_signals[p_func].remove(p_argidx);
@@ -665,6 +762,7 @@ int VisualScript::custom_signal_get_argument_count(const StringName& p_func) con
}
void VisualScript::custom_signal_swap_argument(const StringName& p_func,int p_argidx,int p_with_argidx) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!custom_signals.has(p_func));
ERR_FAIL_INDEX(p_argidx,custom_signals[p_func].size());
ERR_FAIL_INDEX(p_with_argidx,custom_signals[p_func].size());
@@ -674,6 +772,7 @@ void VisualScript::custom_signal_swap_argument(const StringName& p_func,int p_ar
}
void VisualScript::remove_custom_signal(const StringName& p_name) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!custom_signals.has(p_name));
custom_signals.erase(p_name);
@@ -681,6 +780,7 @@ void VisualScript::remove_custom_signal(const StringName& p_name) {
void VisualScript::rename_custom_signal(const StringName& p_name,const StringName& p_new_name) {
+ ERR_FAIL_COND( instances.size() );
ERR_FAIL_COND(!custom_signals.has(p_name));
if (p_new_name==p_name)
return;
@@ -725,7 +825,7 @@ int VisualScript::get_available_id() const {
bool VisualScript::can_instance() const {
- return ScriptServer::is_scripting_enabled();
+ return true;//ScriptServer::is_scripting_enabled();
}
@@ -735,14 +835,88 @@ StringName VisualScript::get_instance_base_type() const {
return base_type;
}
+
+#ifdef TOOLS_ENABLED
+void VisualScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) {
+
+
+ placeholders.erase(p_placeholder);
+}
+
+
+void VisualScript::_update_placeholders() {
+
+ if (placeholders.size()==0)
+ return; //no bother if no placeholders
+ List<PropertyInfo> pinfo;
+ Map<StringName,Variant> values;
+
+ for (Map<StringName,Variable>::Element *E=variables.front();E;E=E->next()) {
+
+ PropertyInfo p = E->get().info;
+ p.name=SCRIPT_VARIABLES_PREFIX+String(E->key());
+ pinfo.push_back(p);
+ values[p.name]=E->get().default_value;
+ }
+
+ for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) {
+
+ E->get()->update(pinfo,values);
+ }
+
+}
+
+#endif
+
+
ScriptInstance* VisualScript::instance_create(Object *p_this) {
- return NULL;
+
+
+#ifdef TOOLS_ENABLED
+
+ if (!ScriptServer::is_scripting_enabled()) {
+
+
+ PlaceHolderScriptInstance *sins = memnew( PlaceHolderScriptInstance(VisualScriptLanguage::singleton,Ref<Script>((Script*)this),p_this));
+ placeholders.insert(sins);
+
+ List<PropertyInfo> pinfo;
+ Map<StringName,Variant> values;
+
+ for (Map<StringName,Variable>::Element *E=variables.front();E;E=E->next()) {
+
+ PropertyInfo p = E->get().info;
+ p.name=SCRIPT_VARIABLES_PREFIX+String(E->key());
+ pinfo.push_back(p);
+ values[p.name]=E->get().default_value;
+ }
+
+ sins->update(pinfo,values);
+
+ return sins;
+ }
+#endif
+
+
+ VisualScriptInstance *instance=memnew( VisualScriptInstance );
+ instance->create(Ref<VisualScript>(this),p_this);
+
+
+ if (VisualScriptLanguage::singleton->lock)
+ VisualScriptLanguage::singleton->lock->lock();
+
+ instances[p_this]=instance;
+
+ if (VisualScriptLanguage::singleton->lock)
+ VisualScriptLanguage::singleton->lock->unlock();
+
+ return instance;
}
bool VisualScript::instance_has(const Object *p_this) const {
- return false;
+ return instances.has((Object*)p_this);
}
bool VisualScript::has_source_code() const {
@@ -785,17 +959,37 @@ ScriptLanguage *VisualScript::get_language() const {
bool VisualScript::has_script_signal(const StringName& p_signal) const {
- return false;
+ return custom_signals.has(p_signal);
}
void VisualScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
+ for (const Map<StringName,Vector<Argument> >::Element *E=custom_signals.front();E;E=E->next()) {
+
+ MethodInfo mi;
+ mi.name=E->key();
+ for(int i=0;i<E->get().size();i++) {
+ PropertyInfo arg;
+ arg.type=E->get()[i].type;
+ arg.name=E->get()[i].name;
+ mi.arguments.push_back(arg);
+ }
+
+
+ r_signals->push_back(mi);
+ }
+
+
}
bool VisualScript::get_property_default_value(const StringName& p_property,Variant& r_value) const {
- return false;
+ if (!script_variable_remap.has(p_property))
+ return false;
+
+ r_value=variables[ script_variable_remap[p_property] ].default_value;
+ return true;
}
void VisualScript::get_method_list(List<MethodInfo> *p_list) const {
@@ -821,6 +1015,36 @@ void VisualScript::get_method_list(List<MethodInfo> *p_list) const {
}
}
+bool VisualScript::has_method(const StringName& p_method) const {
+
+ return functions.has(p_method);
+}
+MethodInfo VisualScript::get_method_info(const StringName& p_method) const{
+
+ const Map<StringName,Function>::Element *E=functions.find(p_method);
+ if (!E)
+ return MethodInfo();
+
+ MethodInfo mi;
+ mi.name=E->key();
+ if (E->get().function_id>=0) {
+
+ Ref<VisualScriptFunction> func=E->get().nodes[E->get().function_id].node;
+ if (func.is_valid()) {
+
+ for(int i=0;i<func->get_argument_count();i++) {
+ PropertyInfo arg;
+ arg.name=func->get_argument_name(i);
+ arg.type=func->get_argument_type(i);
+ mi.arguments.push_back(arg);
+ }
+ }
+ }
+
+ return mi;
+}
+
+
void VisualScript::_set_data(const Dictionary& p_data) {
Dictionary d = p_data;
@@ -832,8 +1056,11 @@ void VisualScript::_set_data(const Dictionary& p_data) {
for (int i=0;i<vars.size();i++) {
Dictionary v=vars[i];
- add_variable(v["name"],v["default_value"]);
- _set_variable_info(v["name"],v);
+ StringName name = v["name"];
+ add_variable(name);
+ _set_variable_info(name,v);
+ set_variable_default_value(name,v["default_value"]);
+
}
@@ -857,10 +1084,13 @@ void VisualScript::_set_data(const Dictionary& p_data) {
Dictionary func=funcs[i];
+
StringName name=func["name"];
//int id=func["function_id"];
add_function(name);
+ set_function_scroll(name,func["scroll"]);
+
Array nodes = func["nodes"];
for(int i=0;i<nodes.size();i+=3) {
@@ -928,6 +1158,7 @@ Dictionary VisualScript::_get_data() const{
Dictionary func;
func["name"]=E->key();
func["function_id"]=E->get().function_id;
+ func["scroll"]=E->get().scroll;
Array nodes;
@@ -989,12 +1220,15 @@ void VisualScript::_bind_methods() {
ObjectTypeDB::bind_method(_MD("has_function","name"),&VisualScript::has_function);
ObjectTypeDB::bind_method(_MD("remove_function","name"),&VisualScript::remove_function);
ObjectTypeDB::bind_method(_MD("rename_function","name","new_name"),&VisualScript::rename_function);
+ ObjectTypeDB::bind_method(_MD("set_function_scroll","ofs"),&VisualScript::set_function_scroll);
+ ObjectTypeDB::bind_method(_MD("get_function_scroll"),&VisualScript::get_function_scroll);
ObjectTypeDB::bind_method(_MD("add_node","func","id","node","pos"),&VisualScript::add_node,DEFVAL(Point2()));
ObjectTypeDB::bind_method(_MD("remove_node","func","id"),&VisualScript::remove_node);
ObjectTypeDB::bind_method(_MD("get_function_node_id","name"),&VisualScript::get_function_node_id);
ObjectTypeDB::bind_method(_MD("get_node","func","id"),&VisualScript::get_node);
+ ObjectTypeDB::bind_method(_MD("has_node","func","id"),&VisualScript::has_node);
ObjectTypeDB::bind_method(_MD("set_node_pos","func","id","pos"),&VisualScript::set_node_pos);
ObjectTypeDB::bind_method(_MD("get_node_pos","func","id"),&VisualScript::get_node_pos);
@@ -1058,6 +1292,948 @@ VisualScript::~VisualScript() {
////////////////////////////////////////////
+
+bool VisualScriptInstance::set(const StringName& p_name, const Variant& p_value) {
+
+ const Map<StringName,StringName>::Element *remap = script->script_variable_remap.find(p_name);
+ if (!remap)
+ return false;
+
+ Map<StringName,Variant>::Element *E=variables.find(remap->get());
+ ERR_FAIL_COND_V(!E,false);
+
+ E->get()=p_value;
+
+ return true;
+}
+
+
+bool VisualScriptInstance::get(const StringName& p_name, Variant &r_ret) const {
+
+ const Map<StringName,StringName>::Element *remap = script->script_variable_remap.find(p_name);
+ if (!remap)
+ return false;
+
+ const Map<StringName,Variant>::Element *E=variables.find(remap->get());
+ ERR_FAIL_COND_V(!E,false);
+
+ return E->get();
+}
+void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const{
+
+ for (const Map<StringName,VisualScript::Variable>::Element *E=script->variables.front();E;E=E->next()) {
+
+ PropertyInfo p = E->get().info;
+ p.name=SCRIPT_VARIABLES_PREFIX+String(E->key());
+ p_properties->push_back(p);
+
+ }
+}
+Variant::Type VisualScriptInstance::get_property_type(const StringName& p_name,bool *r_is_valid) const{
+
+ const Map<StringName,StringName>::Element *remap = script->script_variable_remap.find(p_name);
+ if (!remap) {
+ if (r_is_valid)
+ *r_is_valid=false;
+ return Variant::NIL;
+ }
+
+ const Map<StringName,VisualScript::Variable>::Element *E=script->variables.find(remap->get());
+ if (!E) {
+ if (r_is_valid)
+ *r_is_valid=false;
+ ERR_FAIL_V(Variant::NIL);
+ }
+
+ if (r_is_valid)
+ *r_is_valid=true;
+
+ return E->get().info.type;
+
+}
+
+void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const{
+
+ for (const Map<StringName,VisualScript::Function>::Element *E=script->functions.front();E;E=E->next()) {
+
+ MethodInfo mi;
+ mi.name=E->key();
+ if (E->get().function_id>=0 && E->get().nodes.has(E->get().function_id)) {
+
+ Ref<VisualScriptFunction> vsf = E->get().nodes[E->get().function_id].node;
+ if (vsf.is_valid()) {
+
+ for(int i=0;i<vsf->get_argument_count();i++) {
+ PropertyInfo arg;
+ arg.name=vsf->get_argument_name(i);
+ arg.type=vsf->get_argument_type(i);
+
+ mi.arguments.push_back(arg);
+ }
+
+ //vsf->Get_ for now at least it does not return..
+ }
+ }
+
+ p_list->push_back(mi);
+ }
+
+}
+bool VisualScriptInstance::has_method(const StringName& p_method) const{
+
+ return script->functions.has(p_method);
+}
+
+
+//#define VSDEBUG(m_text) print_line(m_text)
+#define VSDEBUG(m_text)
+
+Variant VisualScriptInstance::_call_internal(const StringName& p_method, void* p_stack, int p_stack_size, VisualScriptNodeInstance* p_node, int p_flow_stack_pos, bool p_resuming_yield, Variant::CallError &r_error) {
+
+ Map<StringName,Function>::Element *F = functions.find(p_method);
+ ERR_FAIL_COND_V(!F,Variant());
+ Function *f=&F->get();
+
+ //this call goes separate, so it can e yielded and suspended
+ Variant *variant_stack=(Variant*)p_stack;
+ bool *sequence_bits = (bool*)(variant_stack + f->max_stack);
+ const Variant **input_args=(const Variant**)(sequence_bits+f->node_count);
+ Variant **output_args=(Variant**)(input_args + max_input_args);
+ int flow_max = f->flow_stack_size;
+ int* flow_stack = flow_max? (int*)(output_args + max_output_args) : (int*)NULL;
+
+ String error_str;
+
+ VisualScriptNodeInstance* node=p_node;
+ bool error=false;
+ int current_node_id=f->node;
+ Variant return_value;
+ Variant *working_mem=NULL;
+
+ int flow_stack_pos=p_flow_stack_pos;
+
+#ifdef DEBUG_ENABLED
+ if (ScriptDebugger::get_singleton()) {
+ VisualScriptLanguage::singleton->enter_function(this,&p_method,variant_stack,&working_mem,&current_node_id);
+ }
+#endif
+
+ while(true) {
+
+ current_node_id=node->get_id();
+
+ VSDEBUG("==========AT NODE: "+itos(current_node_id)+" base: "+node->get_base_node()->get_type());
+ VSDEBUG("AT STACK POS: "+itos(flow_stack_pos));
+
+
+ //setup working mem
+ working_mem=node->working_mem_idx>=0 ? &variant_stack[node->working_mem_idx] : (Variant*)NULL;
+
+ VSDEBUG("WORKING MEM: "+itos(node->working_mem_idx));
+
+ if (current_node_id==f->node) {
+ //if function node, set up function arguments from begining of stack
+
+ for(int i=0;i<f->argument_count;i++) {
+ input_args[i]=&variant_stack[i];
+ }
+ } else {
+ //setup input pointers normally
+ VSDEBUG("INPUT PORTS: "+itos(node->input_port_count));
+
+ for(int i=0 ; i<node->input_port_count ; i++) {
+
+
+ int index = node->input_ports[i] & VisualScriptNodeInstance::INPUT_MASK;
+
+ if (node->input_ports[i] & VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT) {
+ //is a default value (unassigned input port)
+ input_args[i]=&default_values[index];
+ VSDEBUG("\tPORT "+itos(i)+" DEFAULT VAL");
+ } else if (node->input_ports[i] & VisualScriptNodeInstance::INPUT_UNSEQUENCED_READ_BIT) {
+ //from a node that requires read
+ Function::UnsequencedGet *ug = &f->unsequenced_gets[index];
+
+ bool ok = ug->from->get_output_port_unsequenced(i,&variant_stack[ug->to_stack],working_mem,error_str);
+ if (!ok) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ current_node_id=ug->from->get_id();
+ error=true;
+ working_mem=NULL;
+ break;
+ }
+
+ VSDEBUG("\tPORT "+itos(i)+" UNSEQ READ TO STACK: " + itos(ug->to_stack));
+ input_args[i]=&variant_stack[ug->to_stack];
+ } else {
+ //regular temporary in stack
+ input_args[i]=&variant_stack[index];
+ VSDEBUG("PORT "+itos(i)+" AT STACK "+itos(index));
+
+ }
+ }
+ }
+
+ if (error)
+ break;
+
+ //setup output pointers
+
+ VSDEBUG("OUTPUT PORTS: "+itos(node->output_port_count));
+ for(int i=0 ; i<node->output_port_count ; i++) {
+ output_args[i] = &variant_stack[ node->output_ports[i] ];
+ VSDEBUG("PORT "+itos(i)+" AT STACK "+itos(node->output_ports[i]));
+ }
+
+ //do step
+
+ VisualScriptNodeInstance::StartMode start_mode;
+ {
+ if (p_resuming_yield)
+ start_mode=VisualScriptNodeInstance::START_MODE_RESUME_YIELD;
+ else if (flow_stack && !(flow_stack[flow_stack_pos] & VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT)) //if there is a push bit, it means we are continuing a sequence
+ start_mode=VisualScriptNodeInstance::START_MODE_BEGIN_SEQUENCE;
+ else
+ start_mode=VisualScriptNodeInstance::START_MODE_CONTINUE_SEQUENCE;
+ }
+
+ VSDEBUG("STEP - STARTSEQ: "+itos(start_sequence));
+
+ int ret = node->step(input_args,output_args,start_mode,working_mem,r_error,error_str);
+
+ if (r_error.error!=Variant::CallError::CALL_OK) {
+ //use error from step
+ error=true;
+ break;
+ }
+
+ if (ret&VisualScriptNodeInstance::STEP_YIELD_BIT) {
+ //yielded!
+ if (node->get_working_memory_size()==0) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ error_str=RTR("A node yielded without working memory, please read the docs on how to yield properly!");
+ error=true;
+ break;
+
+ } else {
+ Ref<VisualScriptFunctionState> state = *working_mem;
+ if (!state.is_valid()) {
+
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ error_str=RTR("Node yielded, but did not return a function state in the first working memory.");
+ error=true;
+ break;
+
+ }
+
+ //step 1, capture all state
+ state->instance_id=get_owner_ptr()->get_instance_ID();
+ state->script_id=get_script()->get_instance_ID();
+ state->instance=this;
+ state->function=p_method;
+ state->working_mem_index=node->working_mem_idx;
+ state->variant_stack_size=f->max_stack;
+ state->node=node;
+ state->flow_stack_pos=flow_stack_pos;
+ state->stack.resize(p_stack_size);
+ copymem(state->stack.ptr(),p_stack,p_stack_size);
+ //step 2, run away, return directly
+ r_error.error=Variant::CallError::CALL_OK;
+
+
+#ifdef DEBUG_ENABLED
+ //will re-enter later, so exiting
+ if (ScriptDebugger::get_singleton()) {
+ VisualScriptLanguage::singleton->exit_function();
+ }
+#endif
+
+ return state;
+
+ }
+ }
+
+#ifdef DEBUG_ENABLED
+ if (ScriptDebugger::get_singleton()) {
+ // line
+ bool do_break=false;
+
+ if (ScriptDebugger::get_singleton()->get_lines_left()>0) {
+
+ if (ScriptDebugger::get_singleton()->get_depth()<=0)
+ ScriptDebugger::get_singleton()->set_lines_left( ScriptDebugger::get_singleton()->get_lines_left() -1 );
+ if (ScriptDebugger::get_singleton()->get_lines_left()<=0)
+ do_break=true;
+ }
+
+ if (ScriptDebugger::get_singleton()->is_breakpoint(current_node_id,source))
+ do_break=true;
+
+ if (do_break) {
+ VisualScriptLanguage::singleton->debug_break("Breakpoint",true);
+ }
+
+ ScriptDebugger::get_singleton()->line_poll();
+
+ }
+#endif
+ int output = ret & VisualScriptNodeInstance::STEP_MASK;
+
+ VSDEBUG("STEP RETURN: "+itos(ret));
+
+ if (ret & VisualScriptNodeInstance::STEP_EXIT_FUNCTION_BIT) {
+ if (node->get_working_memory_size()==0) {
+
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ error_str=RTR("Return value must be assigned to first element of node working memory! Fix your node please.");
+ error=true;
+ } else {
+ //assign from working memory, first element
+ return_value=*working_mem;
+ }
+
+ VSDEBUG("EXITING FUNCTION - VALUE "+String(return_value));
+ break; //exit function requested, bye
+ }
+
+ VisualScriptNodeInstance *next=NULL; //next node
+
+ if ( (ret==output || ret&VisualScriptNodeInstance::STEP_FLAG_PUSH_STACK_BIT) && node->sequence_output_count) {
+ //if no exit bit was set, and has sequence outputs, guess next node
+ if (output<0 || output>=node->sequence_output_count) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ error_str=RTR("Node returned an invalid sequence output: ")+itos(output);
+ error=true;
+ break;
+ }
+
+ next = node->sequence_outputs[output];
+ if (next) {
+ VSDEBUG("GOT NEXT NODE - "+itos(next->get_id()));
+ } else {
+ VSDEBUG("GOT NEXT NODE - NULL");
+ }
+ }
+
+ if (flow_stack) {
+
+ //update flow stack pos (may have changed)
+ flow_stack[flow_stack_pos] = current_node_id;
+
+ //add stack push bit if requested
+ if (ret & VisualScriptNodeInstance::STEP_FLAG_PUSH_STACK_BIT) {
+
+ flow_stack[flow_stack_pos] |= VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT;
+ sequence_bits[ node ->sequence_index ]=true; //remember sequence bit
+ VSDEBUG("NEXT SEQ - FLAG BIT");
+ } else {
+ sequence_bits[ node ->sequence_index ]=false; //forget sequence bit
+ VSDEBUG("NEXT SEQ - NORMAL");
+ }
+
+
+ if (ret & VisualScriptNodeInstance::STEP_FLAG_GO_BACK_BIT) {
+ //go back request
+
+ if (flow_stack_pos>0) {
+ flow_stack_pos--;
+ node = instances[ flow_stack[flow_stack_pos] & VisualScriptNodeInstance::FLOW_STACK_MASK ];
+ VSDEBUG("NEXT IS GO BACK");
+ } else {
+ VSDEBUG("NEXT IS GO BACK, BUT NO NEXT SO EXIT");
+ break; //simply exit without value or error
+ }
+ } else if (next) {
+
+
+ if (sequence_bits[next->sequence_index]) {
+ // what happened here is that we are entering a node that is in the middle of doing a sequence (pushed stack) from the front
+ // because each node has a working memory, we can't really do a sub-sequence
+ // as a result, the sequence will be restarted and the stack will roll back to find where this node
+ // started the sequence
+
+ bool found = false;
+
+ for(int i=flow_stack_pos;i>=0;i--) {
+
+
+ if ( (flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_MASK ) == next->get_id() ) {
+ flow_stack_pos=i; //roll back and remove bit
+ flow_stack[i]=next->get_id();
+ sequence_bits[next->sequence_index]=false;
+ found=true;
+ }
+ }
+
+ if (!found) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ error_str=RTR("Found sequence bit but not the node in the stack, report bug!");
+ error=true;
+ break;
+ }
+
+ node=next;
+ VSDEBUG("RE-ENTERED A LOOP, RETURNED STACK POS TO - "+itos(flow_stack_pos));
+
+ } else {
+ // check for stack overflow
+ if (flow_stack_pos+1 >= flow_max) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ error_str=RTR("Stack overflow with stack depth: ")+itos(output);
+ error=true;
+ break;
+ }
+
+ node = next;
+
+ flow_stack_pos++;
+ flow_stack[flow_stack_pos]=node->get_id();
+
+ VSDEBUG("INCREASE FLOW STACK");
+
+ }
+
+ } else {
+ //no next node, try to go back in stack to pushed bit
+
+ bool found = false;
+
+ for(int i=flow_stack_pos;i>=0;i--) {
+
+ VSDEBUG("FS "+itos(i)+" - "+itos(flow_stack[i]));
+ if (flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT) {
+
+ node = instances[ flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_MASK ];
+ flow_stack_pos=i;
+ found=true;
+ }
+ }
+
+ if (!found) {
+ VSDEBUG("NO NEXT NODE, NO GO BACK, EXITING");
+ break; //done, couldn't find a push stack bit
+ }
+
+ VSDEBUG("NO NEXT NODE, GO BACK TO: "+itos(flow_stack_pos));
+
+ }
+ } else {
+
+ node=next; //stackless mode, simply assign next node
+ }
+
+ }
+
+
+
+ if (error) {
+
+ //error
+ // function, file, line, error, explanation
+ String err_file = script->get_path();
+ String err_func = p_method;
+ int err_line=current_node_id; //not a line but it works as one
+
+
+ //if (!GDScriptLanguage::get_singleton()->debug_break(err_text,false)) {
+ // debugger break did not happen
+
+ if (!VisualScriptLanguage::singleton->debug_break(error_str,false)) {
+
+ _err_print_error(err_func.utf8().get_data(),err_file.utf8().get_data(),err_line,error_str.utf8().get_data(),ERR_HANDLER_SCRIPT);
+ }
+
+ //}
+ } else {
+
+
+ //return_value=
+ }
+
+#ifdef DEBUG_ENABLED
+ if (ScriptDebugger::get_singleton()) {
+ VisualScriptLanguage::singleton->exit_function();
+ }
+#endif
+
+ //clean up variant stack
+ for(int i=0;i<f->max_stack;i++) {
+ variant_stack[i].~Variant();
+ }
+
+
+ return return_value;
+}
+
+
+Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error){
+
+ r_error.error=Variant::CallError::CALL_OK; //ok by default
+
+ Map<StringName,Function>::Element *F = functions.find(p_method);
+ if (!F) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ return Variant();
+ }
+
+ VSDEBUG("CALLING: "+String(p_method));
+
+ Function *f=&F->get();
+
+ int total_stack_size=0;
+
+ total_stack_size+=f->max_stack*sizeof(Variant); //variants
+ total_stack_size+=f->node_count*sizeof(bool);
+ total_stack_size+=(max_input_args+max_output_args)*sizeof(Variant*); //arguments
+ total_stack_size+=f->flow_stack_size*sizeof(int); //flow
+
+ VSDEBUG("STACK SIZE: "+itos(total_stack_size));
+ VSDEBUG("STACK VARIANTS: : "+itos(f->max_stack));
+ VSDEBUG("SEQBITS: : "+itos(f->node_count));
+ VSDEBUG("MAX INPUT: "+itos(max_input_args));
+ VSDEBUG("MAX OUTPUT: "+itos(max_output_args));
+ VSDEBUG("FLOW STACK SIZE: "+itos(f->flow_stack_size));
+
+ void *stack = alloca(total_stack_size);
+
+ Variant *variant_stack=(Variant*)stack;
+ bool *sequence_bits = (bool*)(variant_stack + f->max_stack);
+ const Variant **input_args=(const Variant**)(sequence_bits+f->node_count);
+ Variant **output_args=(Variant**)(input_args + max_input_args);
+ int flow_max = f->flow_stack_size;
+ int* flow_stack = flow_max? (int*)(output_args + max_output_args) : (int*)NULL;
+
+ for(int i=0;i<f->node_count;i++) {
+ sequence_bits[i]=false; //all starts as false
+ }
+
+
+ Map<int,VisualScriptNodeInstance*>::Element *E = instances.find(f->node);
+ if (!E) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+
+ ERR_EXPLAIN("No VisualScriptFunction node in function!");
+ ERR_FAIL_V(Variant());
+ }
+
+ VisualScriptNodeInstance *node = E->get();
+
+
+ if (flow_stack) {
+ flow_stack[0]=node->get_id();
+ }
+
+ VSDEBUG("ARGUMENTS: "+itos(f->argument_count)=" RECEIVED: "+itos(p_argcount));
+
+ if (p_argcount<f->argument_count) {
+ r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument=node->get_input_port_count();
+
+ return Variant();
+ }
+
+ if (p_argcount>f->argument_count) {
+ r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument=node->get_input_port_count();
+
+ return Variant();
+ }
+
+ //allocate variant stack
+ for(int i=0;i<f->max_stack;i++) {
+ memnew_placement(&variant_stack[i],Variant);
+ }
+
+ //allocate function arguments (must be copied for yield to work properly)
+ for(int i=0;i<p_argcount;i++) {
+ variant_stack[i]=*p_args[i];
+ }
+
+ return _call_internal(p_method,stack,total_stack_size,node,0,false,r_error);
+
+
+}
+
+void VisualScriptInstance::notification(int p_notification){
+
+ //do nothing as this is called using virtual
+
+ Variant what=p_notification;
+ const Variant*whatp=&what;
+ Variant::CallError ce;
+ call(VisualScriptLanguage::singleton->notification,&whatp,1,ce); //do as call
+
+}
+
+Ref<Script> VisualScriptInstance::get_script() const{
+
+ return script;
+}
+
+
+void VisualScriptInstance::create(const Ref<VisualScript>& p_script,Object *p_owner) {
+
+ script=p_script;
+ owner=p_owner;
+ source=p_script->get_path();
+
+ max_input_args = 0;
+ max_output_args = 0;
+
+ if (p_owner->cast_to<Node>()) {
+ //turn on these if they exist and base is a node
+ Node* node = p_owner->cast_to<Node>();
+ if (p_script->functions.has("_process"))
+ node->set_process(true);
+ if (p_script->functions.has("_fixed_process"))
+ node->set_fixed_process(true);
+ if (p_script->functions.has("_input"))
+ node->set_process_input(true);
+ if (p_script->functions.has("_unhandled_input"))
+ node->set_process_unhandled_input(true);
+ if (p_script->functions.has("_unhandled_key_input"))
+ node->set_process_unhandled_key_input(true);
+ }
+
+ for(const Map<StringName,VisualScript::Variable>::Element *E=script->variables.front();E;E=E->next()) {
+ variables[E->key()]=E->get().default_value;
+ }
+
+
+ for(const Map<StringName,VisualScript::Function>::Element *E=script->functions.front();E;E=E->next()) {
+
+ Function function;
+ function.node=E->get().function_id;
+ function.max_stack=0;
+ function.flow_stack_size=0;
+ function.node_count=0;
+
+ if (function.node<0) {
+ VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(),0,"No start node in function: "+String(E->key()));
+
+ ERR_CONTINUE( function.node < 0 );
+ }
+
+ {
+ Ref<VisualScriptFunction> func_node = script->get_node(E->key(),E->get().function_id);
+
+ if (func_node.is_null()) {
+ VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(),0,"No VisualScriptFunction typed start node in function: "+String(E->key()));
+ }
+
+ ERR_CONTINUE( !func_node.is_valid() );
+
+ function.argument_count=func_node->get_argument_count();
+ function.max_stack+=function.argument_count;
+ function.flow_stack_size= func_node->is_stack_less() ? 0 : func_node->get_stack_size();
+
+ }
+
+ //multiple passes are required to set up this complex thing..
+
+
+
+
+ //first create the nodes
+ for (const Map<int,VisualScript::Function::NodeData>::Element *F=E->get().nodes.front();F;F=F->next()) {
+
+ Ref<VisualScriptNode> node = F->get().node;
+ VisualScriptNodeInstance *instance = node->instance(this); //create instance
+ ERR_FAIL_COND(!instance);
+
+ instance->base=node.ptr();
+
+ instance->id=F->key();
+ instance->input_port_count = node->get_input_value_port_count();
+ instance->output_port_count = node->get_output_value_port_count();
+ instance->sequence_output_count = node->get_output_sequence_port_count();
+ instance->sequence_index=function.node_count++;
+
+ if (instance->input_port_count) {
+ instance->input_ports = memnew_arr(int,instance->input_port_count);
+ for(int i=0;i<instance->input_port_count;i++) {
+ instance->input_ports[i]=-1; //if not assigned, will become default value
+ }
+ }
+
+ if (instance->output_port_count) {
+ instance->output_ports = memnew_arr(int,instance->output_port_count);
+ for(int i=0;i<instance->output_port_count;i++) {
+ instance->output_ports[i]=-1; //if not assigned, will output to trash
+ }
+ }
+
+ if (instance->sequence_output_count) {
+ instance->sequence_outputs = memnew_arr(VisualScriptNodeInstance*,instance->sequence_output_count);
+ for(int i=0;i<instance->sequence_output_count;i++) {
+ instance->sequence_outputs[i]=NULL; //if it remains null, flow ends here
+ }
+ }
+
+ if (instance->get_working_memory_size()) {
+ instance->working_mem_idx = function.max_stack;
+ function.max_stack+=instance->get_working_memory_size();
+ } else {
+ instance->working_mem_idx=-1; //no working mem
+ }
+
+ max_input_args = MAX( max_input_args, instance->input_port_count );
+ max_output_args = MAX( max_output_args, instance->output_port_count );
+
+ instances[F->key()]=instance;
+
+
+ }
+
+ function.trash_pos = function.max_stack++; //create pos for trash
+
+ //second pass, do data connections
+
+ for(const Set<VisualScript::DataConnection>::Element *F=E->get().data_connections.front();F;F=F->next()) {
+
+ VisualScript::DataConnection dc = F->get();
+ ERR_CONTINUE(!instances.has(dc.from_node));
+ VisualScriptNodeInstance *from = instances[dc.from_node];
+ ERR_CONTINUE(!instances.has(dc.to_node));
+ VisualScriptNodeInstance *to = instances[dc.to_node];
+ ERR_CONTINUE(dc.from_port >= from->output_port_count);
+ ERR_CONTINUE(dc.to_port >= to->input_port_count);
+
+ if (from->output_ports[dc.from_port]==-1) {
+
+ int stack_pos = function.max_stack++;
+ from->output_ports[dc.from_port] = stack_pos;
+ }
+
+
+ if (from->is_output_port_unsequenced(dc.from_node)) {
+
+ //prepare an unsequenced read (must actually get the value from the output)
+ int stack_pos = function.max_stack++;
+
+ Function::UnsequencedGet uget;
+ uget.from=from;
+ uget.from_port=dc.from_port;
+ uget.to_stack=stack_pos;
+
+ to->input_ports[dc.to_port] = function.unsequenced_gets.size() | VisualScriptNodeInstance::INPUT_UNSEQUENCED_READ_BIT;
+ function.unsequenced_gets.push_back(uget);
+
+ } else {
+
+ to->input_ports[dc.to_port] = from->output_ports[dc.from_port]; //read from wherever the stack is
+ }
+
+ }
+
+ //third pass, do sequence connections
+
+ for(const Set<VisualScript::SequenceConnection>::Element *F=E->get().sequence_connections.front();F;F=F->next()) {
+
+ VisualScript::SequenceConnection sc = F->get();
+ ERR_CONTINUE(!instances.has(sc.from_node));
+ VisualScriptNodeInstance *from = instances[sc.from_node];
+ ERR_CONTINUE(!instances.has(sc.to_node));
+ VisualScriptNodeInstance *to = instances[sc.to_node];
+ ERR_CONTINUE(sc.from_output >= from->sequence_output_count);
+
+ from->sequence_outputs[sc.from_output]=to;
+
+ }
+
+ //fourth pass:
+ // 1) unassigned input ports to default values
+ // 2) connect unassigned output ports to trash
+
+
+ for (const Map<int,VisualScript::Function::NodeData>::Element *F=E->get().nodes.front();F;F=F->next()) {
+
+ ERR_CONTINUE(!instances.has(F->key()));
+
+ Ref<VisualScriptNode> node = F->get().node;
+ VisualScriptNodeInstance *instance = instances[F->key()];
+
+ // conect to default values
+ for(int i=0;i<instance->input_port_count;i++) {
+ if (instance->input_ports[i]==-1) {
+
+ //unassigned, connect to default val
+ instance->input_ports[i] = default_values.size() | VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT;
+ default_values.push_back( node->get_default_input_value(i) );
+ }
+ }
+
+ // conect to trash
+ for(int i=0;i<instance->output_port_count;i++) {
+ if (instance->output_ports[i]==-1) {
+ instance->output_ports[i] = function.trash_pos; //trash is same for all
+ }
+ }
+ }
+
+
+ functions[E->key()]=function;
+ }
+}
+
+ScriptLanguage *VisualScriptInstance::get_language(){
+
+ return VisualScriptLanguage::singleton;
+}
+
+
+VisualScriptInstance::VisualScriptInstance() {
+
+
+}
+
+VisualScriptInstance::~VisualScriptInstance() {
+
+ if (VisualScriptLanguage::singleton->lock)
+ VisualScriptLanguage::singleton->lock->lock();
+
+ script->instances.erase(owner);
+
+ if (VisualScriptLanguage::singleton->lock)
+ VisualScriptLanguage::singleton->lock->unlock();
+
+ for (Map<int,VisualScriptNodeInstance*>::Element *E=instances.front();E;E=E->next()) {
+ memdelete(E->get());
+ }
+}
+
+
+
+/////////////////////////////////////////////
+
+
+/////////////////////
+
+
+Variant VisualScriptFunctionState::_signal_callback(const Variant** p_args, int p_argcount, Variant::CallError& r_error) {
+
+ ERR_FAIL_COND_V(function==StringName(),Variant());
+
+#ifdef DEBUG_ENABLED
+ if (instance_id && !ObjectDB::get_instance(instance_id)) {
+ ERR_EXPLAIN("Resumed after yield, but class instance is gone");
+ ERR_FAIL_V(Variant());
+ }
+
+ if (script_id && !ObjectDB::get_instance(script_id)) {
+ ERR_EXPLAIN("Resumed after yield, but script is gone");
+ ERR_FAIL_V(Variant());
+ }
+#endif
+
+ r_error.error=Variant::CallError::CALL_OK;
+
+ Array args;
+
+ if (p_argcount==0) {
+ r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument=1;
+ return Variant();
+ } else if (p_argcount==1) {
+ //noooneee, reserved for me, me and only me.
+ } else {
+
+ for(int i=0;i<p_argcount-1;i++) {
+ args.push_back(*p_args[i]);
+ }
+ }
+
+ Ref<VisualScriptFunctionState> self = *p_args[p_argcount-1]; //hi, I'm myself, needed this to remain alive.
+
+ if (self.is_null()) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=p_argcount-1;
+ r_error.expected=Variant::OBJECT;
+ return Variant();
+ }
+
+ r_error.error=Variant::CallError::CALL_OK;
+
+ Variant *working_mem = ((Variant*)stack.ptr()) + working_mem_index;
+
+ *working_mem=args; //arguments go to working mem.
+
+ Variant ret = instance->_call_internal(function,stack.ptr(),stack.size(),node,flow_stack_pos,true,r_error);
+ function=StringName(); //invalidate
+ return ret;
+}
+
+void VisualScriptFunctionState::connect_to_signal(Object* p_obj, const String& p_signal, Array p_binds) {
+
+ Vector<Variant> binds;
+ for(int i=0;i<p_binds.size();i++) {
+ binds.push_back(p_binds[i]);
+ }
+ binds.push_back(Ref<VisualScriptFunctionState>(this)); //add myself on the back to avoid dying from unreferencing
+ p_obj->connect(p_signal,this,"_signal_callback",binds);
+}
+
+bool VisualScriptFunctionState::is_valid() const {
+
+ return function!=StringName();
+}
+
+Variant VisualScriptFunctionState::resume(Array p_args) {
+
+ ERR_FAIL_COND_V(function==StringName(),Variant());
+#ifdef DEBUG_ENABLED
+ if (instance_id && !ObjectDB::get_instance(instance_id)) {
+ ERR_EXPLAIN("Resumed after yield, but class instance is gone");
+ ERR_FAIL_V(Variant());
+ }
+
+ if (script_id && !ObjectDB::get_instance(script_id)) {
+ ERR_EXPLAIN("Resumed after yield, but script is gone");
+ ERR_FAIL_V(Variant());
+ }
+#endif
+
+ Variant::CallError r_error;
+ r_error.error=Variant::CallError::CALL_OK;
+
+ Variant *working_mem = ((Variant*)stack.ptr()) + working_mem_index;
+
+ *working_mem=p_args; //arguments go to working mem.
+
+ Variant ret= instance->_call_internal(function,stack.ptr(),stack.size(),node,flow_stack_pos,true,r_error);
+ function=StringName(); //invalidate
+ return ret;
+}
+
+
+void VisualScriptFunctionState::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("connect_to_signal","obj","signals","args"),&VisualScriptFunctionState::connect_to_signal);
+ ObjectTypeDB::bind_method(_MD("resume:Array","args"),&VisualScriptFunctionState::resume,DEFVAL(Variant()));
+ ObjectTypeDB::bind_method(_MD("is_valid"),&VisualScriptFunctionState::is_valid);
+ ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"_signal_callback",&VisualScriptFunctionState::_signal_callback,MethodInfo("_signal_callback"));
+}
+
+VisualScriptFunctionState::VisualScriptFunctionState() {
+
+}
+
+VisualScriptFunctionState::~VisualScriptFunctionState() {
+
+ if (function!=StringName()) {
+ Variant *s = ((Variant*)stack.ptr());
+ for(int i=0;i<variant_stack_size;i++) {
+ s[i].~Variant();
+ }
+ }
+}
+
+
+
+
+
+///////////////////////////////////////////////
+
String VisualScriptLanguage::get_name() const {
return "VisualScript";
@@ -1098,9 +2274,12 @@ void VisualScriptLanguage::get_string_delimiters(List<String> *p_delimiters) con
}
-String VisualScriptLanguage::get_template(const String& p_class_name, const String& p_base_class_name) const {
+Ref<Script> VisualScriptLanguage::get_template(const String& p_class_name, const String& p_base_class_name) const {
- return String();
+ Ref<VisualScript> script;
+ script.instance();
+ script->set_instance_base_type(p_base_class_name);
+ return script;
}
bool VisualScriptLanguage::validate(const String& p_script, int &r_line_error,int &r_col_error,String& r_test_error, const String& p_path,List<String> *r_functions) const {
@@ -1135,44 +2314,199 @@ void VisualScriptLanguage::add_global_constant(const StringName& p_variable,cons
/* DEBUGGER FUNCTIONS */
+
+
+bool VisualScriptLanguage::debug_break_parse(const String& p_file, int p_node,const String& p_error) {
+ //break because of parse error
+
+ if (ScriptDebugger::get_singleton() && Thread::get_caller_ID()==Thread::get_main_ID()) {
+
+ _debug_parse_err_node=p_node;
+ _debug_parse_err_file=p_file;
+ _debug_error=p_error;
+ ScriptDebugger::get_singleton()->debug(this,false);
+ return true;
+ } else {
+ return false;
+ }
+
+}
+
+bool VisualScriptLanguage::debug_break(const String& p_error,bool p_allow_continue) {
+
+ if (ScriptDebugger::get_singleton() && Thread::get_caller_ID()==Thread::get_main_ID()) {
+
+ _debug_parse_err_node=-1;
+ _debug_parse_err_file="";
+ _debug_error=p_error;
+ ScriptDebugger::get_singleton()->debug(this,p_allow_continue);
+ return true;
+ } else {
+ return false;
+ }
+
+}
+
+
String VisualScriptLanguage::debug_get_error() const {
- return String();
+ return _debug_error;
}
+
int VisualScriptLanguage::debug_get_stack_level_count() const {
- return 0;
+ if (_debug_parse_err_node>=0)
+ return 1;
+
+
+ return _debug_call_stack_pos;
}
int VisualScriptLanguage::debug_get_stack_level_line(int p_level) const {
- return 0;
+ if (_debug_parse_err_node>=0)
+ return _debug_parse_err_node;
+
+ ERR_FAIL_INDEX_V(p_level,_debug_call_stack_pos,-1);
+
+ int l = _debug_call_stack_pos - p_level -1;
+
+ return *(_call_stack[l].current_id);
+
}
String VisualScriptLanguage::debug_get_stack_level_function(int p_level) const {
- return String();
+ if (_debug_parse_err_node>=0)
+ return "";
+
+ ERR_FAIL_INDEX_V(p_level,_debug_call_stack_pos,"");
+ int l = _debug_call_stack_pos - p_level -1;
+ return *_call_stack[l].function;
}
String VisualScriptLanguage::debug_get_stack_level_source(int p_level) const {
- return String();
+ if (_debug_parse_err_node>=0)
+ return _debug_parse_err_file;
+
+ ERR_FAIL_INDEX_V(p_level,_debug_call_stack_pos,"");
+ int l = _debug_call_stack_pos - p_level -1;
+ return _call_stack[l].instance->get_script_ptr()->get_path();
+
}
void VisualScriptLanguage::debug_get_stack_level_locals(int p_level,List<String> *p_locals, List<Variant> *p_values, int p_max_subitems,int p_max_depth) {
+ if (_debug_parse_err_node>=0)
+ return;
+
+ ERR_FAIL_INDEX(p_level,_debug_call_stack_pos);
+
+ int l = _debug_call_stack_pos - p_level -1;
+ const StringName *f = _call_stack[l].function;
+
+ ERR_FAIL_COND(!_call_stack[l].instance->functions.has(*f));
+ VisualScriptInstance::Function *func = &_call_stack[l].instance->functions[*f];
+ VisualScriptNodeInstance *node =_call_stack[l].instance->instances[*_call_stack[l].current_id];
+ ERR_FAIL_COND(!node);
+
+ p_locals->push_back("node_name");
+ p_values->push_back(node->get_base_node()->get_text());
+
+ for(int i=0;i<node->input_port_count;i++) {
+ String name = node->get_base_node()->get_input_value_port_info(i).name;
+ if (name==String()) {
+ name="in_"+itos(i);
+ }
+
+ p_locals->push_back("input/"+name);
+
+ //value is trickier
+
+ int in_from = node->input_ports[i];
+ int in_value = in_from&VisualScriptNodeInstance::INPUT_MASK;
+
+ if (in_from&VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT) {
+ p_values->push_back(_call_stack[l].instance->default_values[in_value]);
+ } else if (in_from&VisualScriptNodeInstance::INPUT_UNSEQUENCED_READ_BIT) {
+ p_values->push_back( _call_stack[l].stack[ func->unsequenced_gets[ in_value ].to_stack ] );
+ } else {
+ p_values->push_back( _call_stack[l].stack[ in_value] );
+ }
+ }
+
+ for(int i=0;i<node->output_port_count;i++) {
+
+ String name = node->get_base_node()->get_output_value_port_info(i).name;
+ if (name==String()) {
+ name="out_"+itos(i);
+ }
+
+ p_locals->push_back("output/"+name);
+
+ //value is trickier
+
+ int in_from = node->output_ports[i];
+ p_values->push_back( _call_stack[l].stack[ in_from] );
+
+ }
+
+ for(int i=0;i<node->get_working_memory_size();i++) {
+ p_locals->push_back("working_mem/mem_"+itos(i));
+ p_values->push_back( (*_call_stack[l].work_mem)[i]);
+ }
+
+/*
+ ERR_FAIL_INDEX(p_level,_debug_call_stack_pos);
+
+
+ VisualFunction *f = _call_stack[l].function;
+
+ List<Pair<StringName,int> > locals;
+
+ f->debug_get_stack_member_state(*_call_stack[l].line,&locals);
+ for( List<Pair<StringName,int> >::Element *E = locals.front();E;E=E->next() ) {
+
+ p_locals->push_back(E->get().first);
+ p_values->push_back(_call_stack[l].stack[E->get().second]);
+ }
+*/
}
void VisualScriptLanguage::debug_get_stack_level_members(int p_level,List<String> *p_members, List<Variant> *p_values, int p_max_subitems,int p_max_depth) {
+ if (_debug_parse_err_node>=0)
+ return;
+ ERR_FAIL_INDEX(p_level,_debug_call_stack_pos);
+ int l = _debug_call_stack_pos - p_level -1;
+
+
+ Ref<VisualScript> vs = _call_stack[l].instance->get_script();
+ if (vs.is_null())
+ return;
+
+ List<StringName> vars;
+ vs->get_variable_list(&vars);
+ for (List<StringName>::Element *E=vars.front();E;E=E->next()) {
+ Variant v;
+ if (_call_stack[l].instance->get_variable(E->get(),&v)) {
+ p_members->push_back("variables/"+E->get());
+ p_values->push_back(v);
+ }
+ }
}
-void VisualScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems,int p_max_depth) {
+void VisualScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems,int p_max_depth) {
+ //no globals are really reachable in gdscript
}
String VisualScriptLanguage::debug_parse_stack_level_expression(int p_level,const String& p_expression,int p_max_subitems,int p_max_depth) {
- return String();
+ if (_debug_parse_err_node>=0)
+ return "";
+ return "";
}
+
void VisualScriptLanguage::reload_all_scripts() {
@@ -1243,5 +2577,41 @@ void VisualScriptLanguage::get_registered_node_names(List<String> *r_names) {
VisualScriptLanguage::VisualScriptLanguage() {
+ notification="_notification";
+ _get_output_port_unsequenced="_get_output_port_unsequenced";
+ _step="_step";
+ _subcall="_subcall";
singleton=this;
+#ifndef NO_THREADS
+ lock = Mutex::create();
+#endif
+
+
+ _debug_parse_err_node=-1;
+ _debug_parse_err_file="";
+ _debug_call_stack_pos=0;
+ int dmcs=GLOBAL_DEF("debug/script_max_call_stack",1024);
+ if (ScriptDebugger::get_singleton()) {
+ //debugging enabled!
+ _debug_max_call_stack = dmcs;
+ if (_debug_max_call_stack<1024)
+ _debug_max_call_stack=1024;
+ _call_stack = memnew_arr( CallLevel, _debug_max_call_stack+1 );
+
+ } else {
+ _debug_max_call_stack=0;
+ _call_stack=NULL;
+ }
+
+}
+
+VisualScriptLanguage::~VisualScriptLanguage() {
+
+ if (lock)
+ memdelete(lock);
+
+ if (_call_stack) {
+ memdelete_arr(_call_stack);
+ }
+ singleton=NULL;
}
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index 26daddbba6..786b9b873e 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -2,9 +2,9 @@
#define VSCRIPT_H
#include "script_language.h"
+#include "os/thread.h"
-
-class VScriptInstance;
+class VisualScriptInstance;
class VisualScriptNodeInstance;
class VisualScript;
@@ -16,11 +16,14 @@ friend class VisualScript;
Set<VisualScript*> scripts_used;
Array default_input_values;
+ bool breakpoint;
void _set_default_input_values(Array p_values);
Array _get_default_input_values() const;
protected:
+ virtual bool _use_builtin_script() const { return false; }
+
void _notification(int p_what);
void ports_changed_notify();
static void _bind_methods();
@@ -45,22 +48,82 @@ public:
virtual String get_caption() const=0;
virtual String get_text() const=0;
+ virtual String get_category() const=0;
+
+ //used by editor, this is not really saved
+ void set_breakpoint(bool p_breakpoint);
+ bool is_breakpoint() const;
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance)=0;
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance)=0;
+ VisualScriptNode();
};
class VisualScriptNodeInstance {
+friend class VisualScriptInstance;
+friend class VisualScriptLanguage; //for debugger
+
+
+ enum { //input argument addressing
+ INPUT_SHIFT=1<<24,
+ INPUT_MASK=INPUT_SHIFT-1,
+ INPUT_DEFAULT_VALUE_BIT=INPUT_SHIFT, // from unassigned input port, using default value (edited by user)
+ INPUT_UNSEQUENCED_READ_BIT=INPUT_SHIFT<<1, //from unsequenced read (requires calling a function, used for constants, variales, etc).
+ };
+
+
+ int id;
+ int sequence_index;
+ VisualScriptNodeInstance **sequence_outputs;
+ int sequence_output_count;
+ int *input_ports;
+ int input_port_count;
+ int *output_ports;
+ int output_port_count;
+ int working_mem_idx;
+
+ VisualScriptNode *base;
+
public:
- virtual int step()=0; //do a step, return which sequence port to go out
+ enum StartMode {
+ START_MODE_BEGIN_SEQUENCE,
+ START_MODE_CONTINUE_SEQUENCE,
+ START_MODE_RESUME_YIELD
+ };
+
+ enum {
+ STEP_SHIFT=1<<24,
+ STEP_MASK=STEP_SHIFT-1,
+ STEP_FLAG_PUSH_STACK_BIT=STEP_SHIFT, //push bit to stack
+ STEP_FLAG_GO_BACK_BIT=STEP_SHIFT<<1, //go back to previous node
+ STEP_NO_ADVANCE_BIT=STEP_SHIFT<<2, //do not advance past this node
+ STEP_EXIT_FUNCTION_BIT=STEP_SHIFT<<3, //return from function
+ STEP_YIELD_BIT=STEP_SHIFT<<4, //yield (will find VisualScriptFunctionState state in first working memory)
+
+ FLOW_STACK_PUSHED_BIT=1<<30, //in flow stack, means bit was pushed (must go back here if end of sequence)
+ FLOW_STACK_MASK=FLOW_STACK_PUSHED_BIT-1
+
+ };
+
+ _FORCE_INLINE_ int get_input_port_count() const { return input_port_count; }
+ _FORCE_INLINE_ int get_output_port_count() const { return output_port_count; }
+ _FORCE_INLINE_ int get_sequence_output_count() const { return sequence_output_count; }
+
+ _FORCE_INLINE_ int get_id() const { return id; }
- virtual Variant get_input_value(int p_idx)=0;
- virtual Variant get_output_value(int p_idx)=0;
+ virtual int get_working_memory_size() const { return 0; }
- virtual VisualScriptNode* get_node()=0;
+ //unsequenced ports are those that can return a value even if no sequence happened through them, used for constants, variables, etc.
+ virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+ 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)=0; //do a step, return which sequence port to go out
+
+ Ref<VisualScriptNode> get_base_node() { return Ref<VisualScriptNode>( base ); }
+
+ VisualScriptNodeInstance();
virtual ~VisualScriptNodeInstance();
};
@@ -112,6 +175,7 @@ public:
private:
+friend class VisualScriptInstance;
StringName base_type;
struct Argument {
@@ -133,6 +197,9 @@ private:
int function_id;
+ Vector2 scroll;
+
+
Function() { function_id=-1; }
};
@@ -146,8 +213,18 @@ private:
Map<StringName,Function> functions;
Map<StringName,Variable> variables;
+ Map<StringName,StringName> script_variable_remap;
Map<StringName,Vector<Argument> > custom_signals;
+ Map<Object*,VisualScriptInstance*> instances;
+
+#ifdef TOOLS_ENABLED
+ Set<PlaceHolderScriptInstance*> placeholders;
+ //void _update_placeholder(PlaceHolderScriptInstance *p_placeholder);
+ virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder);
+ void _update_placeholders();
+#endif
+
void _set_variable_info(const StringName& p_name,const Dictionary& p_info);
Dictionary _get_variable_info(const StringName& p_name) const;
@@ -166,12 +243,15 @@ public:
bool has_function(const StringName& p_name) const;
void remove_function(const StringName& p_name);
void rename_function(const StringName& p_name,const StringName& p_new_name);
+ void set_function_scroll(const StringName& p_name, const Vector2& p_scroll);
+ Vector2 get_function_scroll(const StringName& p_name) const;
void get_function_list(List<StringName> *r_functions) const;
int get_function_node_id(const StringName& p_name) const;
void add_node(const StringName& p_func,int p_id,const Ref<VisualScriptNode>& p_node,const Point2& p_pos=Point2());
void remove_node(const StringName& p_func,int p_id);
+ bool has_node(const StringName& p_func,int p_id) const;
Ref<VisualScriptNode> get_node(const StringName& p_func,int p_id) const;
void set_node_pos(const StringName& p_func,int p_id,const Point2& p_pos);
Point2 get_node_pos(const StringName& p_func,int p_id) const;
@@ -242,21 +322,210 @@ public:
virtual bool get_property_default_value(const StringName& p_property,Variant& r_value) const;
virtual void get_method_list(List<MethodInfo> *p_list) const;
+ virtual bool has_method(const StringName& p_method) const;
+ virtual MethodInfo get_method_info(const StringName& p_method) const;
+
+
VisualScript();
~VisualScript();
};
+class VisualScriptInstance : public ScriptInstance {
+ Object *owner;
+ Ref<VisualScript> script;
+
+ Map<StringName,Variant> variables; //using variable path, not script
+ Map<int,VisualScriptNodeInstance*> instances;
+
+ struct Function {
+ int node;
+ int max_stack;
+ int trash_pos;
+ int return_pos;
+ int flow_stack_size;
+ int node_count;
+ int argument_count;
+ bool valid;
+
+ struct UnsequencedGet {
+ VisualScriptNodeInstance* from;
+ int from_port;
+ int to_stack;
+ };
+
+ Vector<UnsequencedGet> unsequenced_gets;
+
+ };
+
+ Map<StringName,Function> functions;
+
+ Vector<Variant> default_values;
+ int max_input_args,max_output_args;
+
+ StringName source;
+
+ Variant _call_internal(const StringName& p_method, void* p_stack,int p_stack_size, VisualScriptNodeInstance* p_node, int p_flow_stack_pos, bool p_resuming_yield,Variant::CallError &r_error);
+
+
+ //Map<StringName,Function> functions;
+friend class VisualScriptFunctionState; //for yield
+friend class VisualScriptLanguage; //for debugger
+public:
+ virtual bool set(const StringName& p_name, const Variant& p_value);
+ virtual bool get(const StringName& p_name, Variant &r_ret) const;
+ virtual void get_property_list(List<PropertyInfo> *p_properties) const;
+ virtual Variant::Type get_property_type(const StringName& p_name,bool *r_is_valid=NULL) const;
+
+ virtual void get_method_list(List<MethodInfo> *p_list) const;
+ virtual bool has_method(const StringName& p_method) const;
+ virtual Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error);
+ virtual void notification(int p_notification);
+
+ bool set_variable(const StringName& p_variable,const Variant& p_value) {
+
+ Map<StringName,Variant>::Element *E=variables.find(p_variable);
+ if (!E)
+ return false;
+
+ E->get()=p_value;
+ return true;
+ }
+
+ bool get_variable(const StringName& p_variable,Variant* r_variable) const {
+
+ const Map<StringName,Variant>::Element *E=variables.find(p_variable);
+ if (!E)
+ return false;
+
+ *r_variable=E->get();
+ return true;
+
+ }
+
+ virtual Ref<Script> get_script() const;
+
+ _FORCE_INLINE_ VisualScript *get_script_ptr() { return script.ptr(); }
+ _FORCE_INLINE_ Object *get_owner_ptr() { return owner; }
+
+ void create(const Ref<VisualScript>& p_script,Object *p_owner);
+
+ virtual ScriptLanguage *get_language();
+
+ VisualScriptInstance();
+ ~VisualScriptInstance();
+};
+
+
+class VisualScriptFunctionState : public Reference {
+
+ OBJ_TYPE(VisualScriptFunctionState,Reference);
+friend class VisualScriptInstance;
+
+ ObjectID instance_id;
+ ObjectID script_id;
+ VisualScriptInstance *instance;
+ StringName function;
+ Vector<uint8_t> stack;
+ int working_mem_index;
+ int variant_stack_size;
+ VisualScriptNodeInstance *node;
+ int flow_stack_pos;
+
+ Variant _signal_callback(const Variant** p_args, int p_argcount, Variant::CallError& r_error);
+protected:
+ static void _bind_methods();
+public:
+
+ void connect_to_signal(Object* p_obj,const String& p_signal,Array p_binds);
+ bool is_valid() const;
+ Variant resume(Array p_args);
+ VisualScriptFunctionState();
+ ~VisualScriptFunctionState();
+};
+
+
typedef Ref<VisualScriptNode> (*VisualScriptNodeRegisterFunc)(const String& p_type);
class VisualScriptLanguage : public ScriptLanguage {
Map<String,VisualScriptNodeRegisterFunc> register_funcs;
+
+ struct CallLevel {
+
+ Variant *stack;
+ Variant **work_mem;
+ const StringName *function;
+ VisualScriptInstance *instance;
+ int *current_id;
+
+ };
+
+
+ int _debug_parse_err_node;
+ String _debug_parse_err_file;
+ String _debug_error;
+ int _debug_call_stack_pos;
+ int _debug_max_call_stack;
+ CallLevel *_call_stack;
+
public:
+ StringName notification;
+ StringName _get_output_port_unsequenced;
+ StringName _step;
+ StringName _subcall;
static VisualScriptLanguage* singleton;
+ Mutex *lock;
+
+ bool debug_break(const String& p_error,bool p_allow_continue=true);
+ bool debug_break_parse(const String& p_file, int p_node,const String& p_error);
+
+ _FORCE_INLINE_ void enter_function(VisualScriptInstance *p_instance,const StringName* p_function, Variant *p_stack, Variant **p_work_mem,int *current_id) {
+
+ if (Thread::get_main_ID()!=Thread::get_caller_ID())
+ return; //no support for other threads than main for now
+
+ if (ScriptDebugger::get_singleton()->get_lines_left()>0 && ScriptDebugger::get_singleton()->get_depth()>=0)
+ ScriptDebugger::get_singleton()->set_depth( ScriptDebugger::get_singleton()->get_depth() +1 );
+
+ if (_debug_call_stack_pos >= _debug_max_call_stack) {
+ //stack overflow
+ _debug_error="Stack Overflow (Stack Size: "+itos(_debug_max_call_stack)+")";
+ ScriptDebugger::get_singleton()->debug(this);
+ return;
+ }
+
+ _call_stack[_debug_call_stack_pos].stack=p_stack;
+ _call_stack[_debug_call_stack_pos].instance=p_instance;
+ _call_stack[_debug_call_stack_pos].function=p_function;
+ _call_stack[_debug_call_stack_pos].work_mem=p_work_mem;
+ _call_stack[_debug_call_stack_pos].current_id=current_id;
+ _debug_call_stack_pos++;
+ }
+
+ _FORCE_INLINE_ void exit_function() {
+
+ if (Thread::get_main_ID()!=Thread::get_caller_ID())
+ return; //no support for other threads than main for now
+
+ if (ScriptDebugger::get_singleton()->get_lines_left()>0 && ScriptDebugger::get_singleton()->get_depth()>=0)
+ ScriptDebugger::get_singleton()->set_depth( ScriptDebugger::get_singleton()->get_depth() -1 );
+
+ if (_debug_call_stack_pos==0) {
+
+ _debug_error="Stack Underflow (Engine Bug)";
+ ScriptDebugger::get_singleton()->debug(this);
+ return;
+ }
+
+ _debug_call_stack_pos--;
+ }
+
+ //////////////////////////////////////
+
virtual String get_name() const;
/* LANGUAGE FUNCTIONS */
@@ -270,7 +539,7 @@ public:
virtual void get_reserved_words(List<String> *p_words) const;
virtual void get_comment_delimiters(List<String> *p_delimiters) const;
virtual void get_string_delimiters(List<String> *p_delimiters) const;
- virtual String get_template(const String& p_class_name, const String& p_base_class_name) const;
+ virtual Ref<Script> get_template(const String& p_class_name, const String& p_base_class_name) const;
virtual bool validate(const String& p_script, int &r_line_error,int &r_col_error,String& r_test_error, const String& p_path="",List<String> *r_functions=NULL) const;
virtual Script *create_script() const;
virtual bool has_named_classes() const;
@@ -313,6 +582,7 @@ public:
VisualScriptLanguage();
+ ~VisualScriptLanguage();
};
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index 58edafd963..e813d9ea84 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -1,5 +1,11 @@
#include "visual_script_builtin_funcs.h"
-
+#include "math_funcs.h"
+#include "object_type_db.h"
+#include "reference.h"
+#include "func_ref.h"
+#include "os/os.h"
+#include "variant_parser.h"
+#include "io/marshalls.h"
const char* VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX]={
"sin",
@@ -538,12 +544,550 @@ VisualScriptBuiltinFunc::BuiltinFunc VisualScriptBuiltinFunc::get_func() {
}
+#define VALIDATE_ARG_NUM(m_arg) \
+ if (!p_inputs[m_arg]->is_num()) {\
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;\
+ r_error.argument=m_arg;\
+ r_error.expected=Variant::REAL;\
+ return 0;\
+ }
+
+class VisualScriptNodeInstanceBuiltinFunc : public VisualScriptNodeInstance {
+public:
+
+ VisualScriptBuiltinFunc *node;
+ VisualScriptInstance *instance;
+
+ VisualScriptBuiltinFunc::BuiltinFunc func;
+
+
+ //virtual int get_working_memory_size() const { return 0; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+
+ 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) {
+
+ switch(func) {
+ case VisualScriptBuiltinFunc::MATH_SIN: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::sin(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_COS: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::cos(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_TAN: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::tan(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_SINH: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::sinh(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_COSH: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::cosh(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_TANH: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::tanh(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_ASIN: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::asin(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_ACOS: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::acos(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_ATAN: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::atan(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_ATAN2: {
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ *p_outputs[0]=Math::atan2(*p_inputs[0],*p_inputs[1]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_SQRT: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::sqrt(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_FMOD: {
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ *p_outputs[0]=Math::fmod(*p_inputs[0],*p_inputs[1]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_FPOSMOD: {
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ *p_outputs[0]=Math::fposmod(*p_inputs[0],*p_inputs[1]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_FLOOR: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::floor(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_CEIL: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::ceil(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_ROUND: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::round(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_ABS: {
+
+ if (p_inputs[0]->get_type()==Variant::INT) {
+
+ int64_t i = *p_inputs[0];
+ *p_outputs[0]=ABS(i);
+ } else if (p_inputs[0]->get_type()==Variant::REAL) {
+
+ real_t r = *p_inputs[0];
+ *p_outputs[0]=Math::abs(r);
+ } else {
+
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::REAL;
+
+ }
+ } break;
+ case VisualScriptBuiltinFunc::MATH_SIGN: {
+
+ if (p_inputs[0]->get_type()==Variant::INT) {
+
+ int64_t i = *p_inputs[0];
+ *p_outputs[0]= i < 0 ? -1 : ( i > 0 ? +1 : 0);
+ } else if (p_inputs[0]->get_type()==Variant::REAL) {
+
+ real_t r = *p_inputs[0];
+ *p_outputs[0]= r < 0.0 ? -1.0 : ( r > 0.0 ? +1.0 : 0.0);
+ } else {
+
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::REAL;
+
+ }
+ } break;
+ case VisualScriptBuiltinFunc::MATH_POW: {
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ *p_outputs[0]=Math::pow(*p_inputs[0],*p_inputs[1]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_LOG: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::log(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_EXP: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::exp(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_ISNAN: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::is_nan(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_ISINF: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::is_inf(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_EASE: {
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ *p_outputs[0]=Math::ease(*p_inputs[0],*p_inputs[1]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_DECIMALS: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::step_decimals(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_STEPIFY: {
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ *p_outputs[0]=Math::stepify(*p_inputs[0],*p_inputs[1]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_LERP: {
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+ *p_outputs[0]=Math::lerp(*p_inputs[0],*p_inputs[1],*p_inputs[2]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_DECTIME: {
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+ *p_outputs[0]=Math::dectime(*p_inputs[0],*p_inputs[1],*p_inputs[2]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_RANDOMIZE: {
+ Math::randomize();
+
+ } break;
+ case VisualScriptBuiltinFunc::MATH_RAND: {
+ *p_outputs[0]=Math::rand();
+ } break;
+ case VisualScriptBuiltinFunc::MATH_RANDF: {
+ *p_outputs[0]=Math::randf();
+ } break;
+ case VisualScriptBuiltinFunc::MATH_RANDOM: {
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ *p_outputs[0]=Math::random(*p_inputs[0],*p_inputs[1]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_SEED: {
+
+ VALIDATE_ARG_NUM(0);
+ uint32_t seed=*p_inputs[0];
+ Math::seed(seed);
+
+ } break;
+ case VisualScriptBuiltinFunc::MATH_RANDSEED: {
+
+ VALIDATE_ARG_NUM(0);
+ uint32_t seed=*p_inputs[0];
+ int ret = Math::rand_from_seed(&seed);
+ Array reta;
+ reta.push_back(ret);
+ reta.push_back(seed);
+ *p_outputs[0]=reta;
+
+ } break;
+ case VisualScriptBuiltinFunc::MATH_DEG2RAD: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::deg2rad(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_RAD2DEG: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::rad2deg(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_LINEAR2DB: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::linear2db(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_DB2LINEAR: {
+
+ VALIDATE_ARG_NUM(0);
+ *p_outputs[0]=Math::db2linear(*p_inputs[0]);
+ } break;
+ case VisualScriptBuiltinFunc::LOGIC_MAX: {
+
+ if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT) {
+
+ int64_t a = *p_inputs[0];
+ int64_t b = *p_inputs[1];
+ *p_outputs[0]=MAX(a,b);
+ } else {
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+
+ real_t a = *p_inputs[0];
+ real_t b = *p_inputs[1];
+
+ *p_outputs[0]=MAX(a,b);
+ }
+
+ } break;
+ case VisualScriptBuiltinFunc::LOGIC_MIN: {
+
+ if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT) {
+
+ int64_t a = *p_inputs[0];
+ int64_t b = *p_inputs[1];
+ *p_outputs[0]=MIN(a,b);
+ } else {
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+
+ real_t a = *p_inputs[0];
+ real_t b = *p_inputs[1];
+
+ *p_outputs[0]=MIN(a,b);
+ }
+ } break;
+ case VisualScriptBuiltinFunc::LOGIC_CLAMP: {
+
+ if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT && p_inputs[2]->get_type()==Variant::INT) {
+
+ int64_t a = *p_inputs[0];
+ int64_t b = *p_inputs[1];
+ int64_t c = *p_inputs[2];
+ *p_outputs[0]=CLAMP(a,b,c);
+ } else {
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+
+ real_t a = *p_inputs[0];
+ real_t b = *p_inputs[1];
+ real_t c = *p_inputs[2];
+
+ *p_outputs[0]=CLAMP(a,b,c);
+ }
+ } break;
+ case VisualScriptBuiltinFunc::LOGIC_NEAREST_PO2: {
+
+ VALIDATE_ARG_NUM(0);
+ int64_t num = *p_inputs[0];
+ *p_outputs[0] = nearest_power_of_2(num);
+ } break;
+ case VisualScriptBuiltinFunc::OBJ_WEAKREF: {
+
+ if (p_inputs[0]->get_type()!=Variant::OBJECT) {
+
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::OBJECT;
+
+ return 0;
+
+ }
+
+ if (p_inputs[0]->is_ref()) {
+
+ REF r = *p_inputs[0];
+ if (!r.is_valid()) {
+
+ return 0;
+ }
+
+ Ref<WeakRef> wref = memnew( WeakRef );
+ wref->set_ref(r);
+ *p_outputs[0]=wref;
+ } else {
+ Object *obj = *p_inputs[0];
+ if (!obj) {
+
+ return 0;
+ }
+ Ref<WeakRef> wref = memnew( WeakRef );
+ wref->set_obj(obj);
+ *p_outputs[0]=wref;
+ }
+
+
+
+
+ } break;
+ case VisualScriptBuiltinFunc::FUNC_FUNCREF: {
+
+ if (p_inputs[0]->get_type()!=Variant::OBJECT) {
+
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::OBJECT;
+
+ return 0;
+
+ }
+ if (p_inputs[1]->get_type()!=Variant::STRING && p_inputs[1]->get_type()!=Variant::NODE_PATH) {
+
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=1;
+ r_error.expected=Variant::STRING;
+
+ return 0;
+
+ }
+
+ Ref<FuncRef> fr = memnew( FuncRef);
+
+ fr->set_instance(*p_inputs[0]);
+ fr->set_function(*p_inputs[1]);
+
+ *p_outputs[0]=fr;
+
+ } break;
+ case VisualScriptBuiltinFunc::TYPE_CONVERT: {
+
+ VALIDATE_ARG_NUM(1);
+ int type=*p_inputs[1];
+ if (type<0 || type>=Variant::VARIANT_MAX) {
+
+ *p_outputs[0]=RTR("Invalid type argument to convert(), use TYPE_* constants.");
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::INT;
+ return 0;
+
+ } else {
+
+
+ *p_outputs[0]=Variant::construct(Variant::Type(type),p_inputs,1,r_error);
+ }
+ } break;
+ case VisualScriptBuiltinFunc::TYPE_OF: {
-VisualScriptNodeInstance* VisualScriptBuiltinFunc::instance(VScriptInstance* p_instance) {
- return NULL;
+ *p_outputs[0] = p_inputs[0]->get_type();
+
+ } break;
+ case VisualScriptBuiltinFunc::TYPE_EXISTS: {
+
+
+ *p_outputs[0] = ObjectTypeDB::type_exists(*p_inputs[0]);
+
+ } break;
+ case VisualScriptBuiltinFunc::TEXT_STR: {
+
+ String str = *p_inputs[0];
+
+ *p_outputs[0]=str;
+
+ } break;
+ case VisualScriptBuiltinFunc::TEXT_PRINT: {
+
+ String str = *p_inputs[0];
+ print_line(str);
+
+
+ } break;
+
+ case VisualScriptBuiltinFunc::TEXT_PRINTERR: {
+
+ String str = *p_inputs[0];
+
+ //str+="\n";
+ OS::get_singleton()->printerr("%s\n",str.utf8().get_data());
+
+
+ } break;
+ case VisualScriptBuiltinFunc::TEXT_PRINTRAW: {
+ String str = *p_inputs[0];
+
+ //str+="\n";
+ OS::get_singleton()->print("%s",str.utf8().get_data());
+
+
+ } break;
+ case VisualScriptBuiltinFunc::VAR_TO_STR: {
+
+ String vars;
+ VariantWriter::write_to_string(*p_inputs[0],vars);
+ *p_outputs[0]=vars;
+ } break;
+ case VisualScriptBuiltinFunc::STR_TO_VAR: {
+
+ if (p_inputs[0]->get_type()!=Variant::STRING) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::STRING;
+
+ return 0;
+ }
+
+ VariantParser::StreamString ss;
+ ss.s=*p_inputs[0];
+
+ String errs;
+ int line;
+ Error err = VariantParser::parse(&ss,*p_outputs[0],errs,line);
+
+ if (err!=OK) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::STRING;
+ *p_outputs[0]="Parse error at line "+itos(line)+": "+errs;
+ return 0;
+ }
+
+ } break;
+ case VisualScriptBuiltinFunc::VAR_TO_BYTES: {
+
+
+ ByteArray barr;
+ int len;
+ Error err = encode_variant(*p_inputs[0],NULL,len);
+ if (err) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::NIL;
+ *p_outputs[0]="Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).";
+ return 0;
+ }
+
+ barr.resize(len);
+ {
+ ByteArray::Write w = barr.write();
+ encode_variant(*p_inputs[0],w.ptr(),len);
+
+ }
+ *p_outputs[0]=barr;
+ } break;
+ case VisualScriptBuiltinFunc::BYTES_TO_VAR: {
+
+ if (p_inputs[0]->get_type()!=Variant::RAW_ARRAY) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::RAW_ARRAY;
+
+ return 0;
+ }
+
+ ByteArray varr=*p_inputs[0];
+ Variant ret;
+ {
+ ByteArray::Read r=varr.read();
+ Error err = decode_variant(ret,r.ptr(),varr.size(),NULL);
+ if (err!=OK) {
+ *p_outputs[0]=RTR("Not enough bytes for decoding bytes, or invalid format.");
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::RAW_ARRAY;
+ return 0;
+ }
+
+ }
+
+ *p_outputs[0]=ret;
+
+ } break;
+ default: {}
+ }
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptBuiltinFunc::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceBuiltinFunc * instance = memnew(VisualScriptNodeInstanceBuiltinFunc );
+ instance->node=this;
+ instance->instance=p_instance;
+ instance->func=func;
+ return instance;
}
+
void VisualScriptBuiltinFunc::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_func","which"),&VisualScriptBuiltinFunc::set_func);
@@ -577,66 +1121,66 @@ static Ref<VisualScriptNode> create_builtin_func_node(const String& p_name) {
void register_visual_script_builtin_func_node() {
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/sin",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SIN>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/cos",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_COS>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/tan",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_TAN>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/sinh",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SINH>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/cosh",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_COSH>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/tanh",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_TANH>);
-
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/asin",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ASIN>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/acos",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ACOS>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/atan",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ATAN>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/atan2",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ATAN2>);
-
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/sqrt",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SQRT>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/fmod",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FMOD>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/fposmod",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FPOSMOD>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/floor",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FLOOR>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/ceil",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_CEIL>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/round",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ROUND>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/abs",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ABS>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/sign",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SIGN>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/pow",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_POW>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/log",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LOG>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/exp",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_EXP>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/isnan",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ISNAN>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/isinf",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ISINF>);
-
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/ease",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_EASE>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/decimals",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECIMALS>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/stepify",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_STEPIFY>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/lerp",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LERP>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/dectime",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECTIME>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/randomize",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOMIZE>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/rand",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAND>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/randf",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDF>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/random",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOM>);
-
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/seed",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SEED>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/randseed",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDSEED>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/deg2rad",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DEG2RAD>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/rad2deg",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAD2DEG>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/linear2db",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LINEAR2DB>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/db2linear",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DB2LINEAR>);
-
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/max",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MAX>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/min",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MIN>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/clamp",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_CLAMP>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/nearest_po2",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_NEAREST_PO2>);
-
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/weakref",create_builtin_func_node<VisualScriptBuiltinFunc::OBJ_WEAKREF>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/funcref",create_builtin_func_node<VisualScriptBuiltinFunc::FUNC_FUNCREF>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/convert",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_CONVERT>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/typeof",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_OF>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/type_exists",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_EXISTS>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/str",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_STR>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/print",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINT>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/printerr",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINTERR>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/printraw",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINTRAW>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/var2str",create_builtin_func_node<VisualScriptBuiltinFunc::VAR_TO_STR>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/str2var",create_builtin_func_node<VisualScriptBuiltinFunc::STR_TO_VAR>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/var2bytes",create_builtin_func_node<VisualScriptBuiltinFunc::VAR_TO_BYTES>);
- VisualScriptLanguage::singleton->add_register_func("functions/builtin/bytes2var",create_builtin_func_node<VisualScriptBuiltinFunc::BYTES_TO_VAR>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/sin",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SIN>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/cos",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_COS>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/tan",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_TAN>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/sinh",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SINH>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/cosh",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_COSH>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/tanh",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_TANH>);
+
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/asin",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ASIN>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/acos",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ACOS>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/atan",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ATAN>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/atan2",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ATAN2>);
+
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/sqrt",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SQRT>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/fmod",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FMOD>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/fposmod",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FPOSMOD>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/floor",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FLOOR>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/ceil",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_CEIL>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/round",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ROUND>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/abs",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ABS>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/sign",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SIGN>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/pow",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_POW>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/log",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LOG>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/exp",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_EXP>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/isnan",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ISNAN>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/isinf",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ISINF>);
+
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/ease",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_EASE>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/decimals",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECIMALS>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/stepify",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_STEPIFY>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/lerp",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LERP>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/dectime",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECTIME>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/randomize",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOMIZE>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/rand",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAND>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/randf",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDF>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/random",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOM>);
+
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/seed",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SEED>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/randseed",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDSEED>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/deg2rad",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DEG2RAD>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/rad2deg",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAD2DEG>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/linear2db",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LINEAR2DB>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/db2linear",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DB2LINEAR>);
+
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/max",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MAX>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/min",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MIN>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/clamp",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_CLAMP>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/nearest_po2",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_NEAREST_PO2>);
+
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/weakref",create_builtin_func_node<VisualScriptBuiltinFunc::OBJ_WEAKREF>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/funcref",create_builtin_func_node<VisualScriptBuiltinFunc::FUNC_FUNCREF>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/convert",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_CONVERT>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/typeof",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_OF>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/type_exists",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_EXISTS>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/str",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_STR>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/print",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINT>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/printerr",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINTERR>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/printraw",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINTRAW>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/var2str",create_builtin_func_node<VisualScriptBuiltinFunc::VAR_TO_STR>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/str2var",create_builtin_func_node<VisualScriptBuiltinFunc::STR_TO_VAR>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/var2bytes",create_builtin_func_node<VisualScriptBuiltinFunc::VAR_TO_BYTES>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/bytes2var",create_builtin_func_node<VisualScriptBuiltinFunc::BYTES_TO_VAR>);
}
diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h
index b4dbd4db39..ebf227a192 100644
--- a/modules/visual_script/visual_script_builtin_funcs.h
+++ b/modules/visual_script/visual_script_builtin_funcs.h
@@ -91,11 +91,12 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "functions"; }
void set_func(BuiltinFunc p_which);
BuiltinFunc get_func();
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptBuiltinFunc();
};
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index ad4f2be34c..0d97126e0a 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -347,6 +347,8 @@ void VisualScriptEditor::_update_graph_connections() {
void VisualScriptEditor::_update_graph(int p_only_id) {
+ updating_graph=true;
+
//byebye all nodes
if (p_only_id>=0) {
if (graph->has_node(itos(p_only_id))) {
@@ -368,6 +370,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
if (!script->has_function(edited_func)) {
graph->hide();
select_func_text->show();
+ updating_graph=false;
return;
}
@@ -424,6 +427,15 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
GraphNode *gnode = memnew( GraphNode );
gnode->set_title(node->get_caption());
+ if (error_line==E->get()) {
+ gnode->set_overlay(GraphNode::OVERLAY_POSITION);
+ } else if (node->is_breakpoint()) {
+ gnode->set_overlay(GraphNode::OVERLAY_BREAKPOINT);
+ }
+
+ if (EditorSettings::get_singleton()->has("visual_script_editor/color_"+node->get_category())) {
+ gnode->set_modulate(EditorSettings::get_singleton()->get("visual_script_editor/color_"+node->get_category()));
+ }
gnode->set_meta("__vnode",node);
gnode->set_name(itos(E->get()));
@@ -551,6 +563,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
}
_update_graph_connections();
+ graph->call_deferred("set_scroll_ofs",script->get_function_scroll(edited_func)*EDSCALE); //may need to adapt a bit, let it do so
+ updating_graph=false;
}
@@ -579,6 +593,10 @@ void VisualScriptEditor::_update_members() {
//ti->add_button(0,Control::get_icon("Edit","EditorIcons"),0); function arguments are in the node now
ti->add_button(0,Control::get_icon("Del","EditorIcons"),1);
ti->set_metadata(0,E->get());
+ if (E->get()==edited_func) {
+ ti->set_custom_bg_color(0,get_color("prop_category","Editor"));
+ ti->set_custom_color(0,Color(1,1,1,1));
+ }
if (selected==E->get())
ti->select(0);
}
@@ -656,6 +674,7 @@ void VisualScriptEditor::_member_selected() {
revert_on_drag=edited_func;
edited_func=selected;
+ _update_members();
_update_graph();
}
@@ -1377,6 +1396,16 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2& p_point,const Variant& p
const_cast<VisualScriptEditor*>(this)->_show_hint("Hold Ctrl to drop a Setter, Shift+Ctrl to drop a Setter and copy the value.");
#endif
}
+
+ if (String(d["type"])=="visual_script_variable_drag") {
+
+#ifdef OSX_ENABLED
+ const_cast<VisualScriptEditor*>(this)->_show_hint("Hold Meta to drop a Variable Setter.");
+#else
+ const_cast<VisualScriptEditor*>(this)->_show_hint("Hold Ctrl to drop a Variable Setter.");
+#endif
+ }
+
return true;
}
@@ -1448,6 +1477,11 @@ void VisualScriptEditor::drop_data_fw(const Point2& p_point,const Variant& p_dat
if (d.has("type") && String(d["type"])=="visual_script_variable_drag") {
+#ifdef OSX_ENABLED
+ bool use_set = Input::get_singleton()->is_key_pressed(KEY_META);
+#else
+ bool use_set = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+#endif
Vector2 ofs = graph->get_scroll_ofs() + p_point;
if (graph->is_using_snap()) {
int snap = graph->get_snap();
@@ -1456,9 +1490,19 @@ void VisualScriptEditor::drop_data_fw(const Point2& p_point,const Variant& p_dat
ofs/=EDSCALE;
- Ref<VisualScriptVariable> vnode;
- vnode.instance();
- vnode->set_variable(d["variable"]);
+ Ref<VisualScriptNode> vnode;
+ if (use_set) {
+ Ref<VisualScriptVariableSet> vnodes;
+ vnodes.instance();
+ vnodes->set_variable(d["variable"]);
+ vnode=vnodes;
+ } else {
+
+ Ref<VisualScriptVariableGet> vnodeg;
+ vnodeg.instance();
+ vnodeg->set_variable(d["variable"]);
+ vnode=vnodeg;
+ }
int new_id = script->get_available_id();
@@ -1775,23 +1819,91 @@ Ref<Texture> VisualScriptEditor::get_icon(){
}
bool VisualScriptEditor::is_unsaved(){
-
+#ifdef TOOLS_ENABLED
+ return script->is_edited();
+#else
return false;
+#endif
}
Variant VisualScriptEditor::get_edit_state(){
- return Variant();
+ Dictionary d;
+ d["function"]=edited_func;
+ d["scroll"]=graph->get_scroll_ofs();
+ d["zoom"]=graph->get_zoom();
+ d["using_snap"]=graph->is_using_snap();
+ d["snap"]=graph->get_snap();
+ return d;
}
void VisualScriptEditor::set_edit_state(const Variant& p_state){
+ Dictionary d = p_state;
+ if (d.has("function")) {
+ edited_func=p_state;
+ selected=edited_func;
+
+ }
+
+ _update_graph();
+ _update_members();
+
+ if (d.has("scroll")) {
+ graph->set_scroll_ofs(d["scroll"]);
+ }
+ if (d.has("zoom")) {
+ graph->set_zoom(d["zoom"]);
+ }
+ if (d.has("snap")) {
+ graph->set_snap(d["snap"]);
+ }
+ if (d.has("snap_enabled")) {
+ graph->set_use_snap(d["snap_enabled"]);
+ }
}
-void VisualScriptEditor::goto_line(int p_line){
+void VisualScriptEditor::_center_on_node(int p_id) {
+ Node *n = graph->get_node(itos(p_id));
+ if (!n)
+ return;
+ GraphNode *gn = n->cast_to<GraphNode>();
+ if (gn) {
+ gn->set_selected(true);
+ Vector2 new_scroll = gn->get_offset() - graph->get_size()*0.5 + gn->get_size()*0.5;
+ graph->set_scroll_ofs( new_scroll );
+ script->set_function_scroll(edited_func,new_scroll/EDSCALE);
+ script->set_edited(true); //so it's saved
+
+ }
+}
+
+void VisualScriptEditor::goto_line(int p_line, bool p_with_error){
+
+ p_line+=1; //add one because script lines begin from 0.
+
+ if (p_with_error)
+ error_line=p_line;
+
+ List<StringName> functions;
+ script->get_function_list(&functions);
+ for (List<StringName>::Element *E=functions.front();E;E=E->next()) {
+
+ if (script->has_node(E->get(),p_line)) {
+
+ edited_func=E->get();
+ selected=edited_func;
+ _update_graph();
+ _update_members();
+
+ call_deferred("_center_on_node",p_line); //editor might be just created and size might not exist yet
+
+ return;
+ }
+ }
}
void VisualScriptEditor::trim_trailing_whitespace(){
@@ -1801,7 +1913,7 @@ void VisualScriptEditor::trim_trailing_whitespace(){
void VisualScriptEditor::ensure_focus(){
-
+ graph->grab_focus();
}
void VisualScriptEditor::tag_saved_version(){
@@ -1816,24 +1928,92 @@ void VisualScriptEditor::reload(bool p_soft){
void VisualScriptEditor::get_breakpoints(List<int> *p_breakpoints){
+ List<StringName> functions;
+ script->get_function_list(&functions);
+ for (List<StringName>::Element *E=functions.front();E;E=E->next()) {
+ List<int> nodes;
+ script->get_node_list(E->get(),&nodes);
+ for (List<int>::Element *F=nodes.front();F;F=F->next()) {
+
+ Ref<VisualScriptNode> vsn = script->get_node(E->get(),F->get());
+ if (vsn->is_breakpoint()) {
+ p_breakpoints->push_back(F->get()-1); //subtract 1 because breakpoints in text start from zero
+ }
+ }
+ }
}
bool VisualScriptEditor::goto_method(const String& p_method){
- return false;
+ if (!script->has_function(p_method))
+ return false;
+
+ edited_func=p_method;
+ selected=edited_func;
+ _update_members();
+ _update_graph();
+ return true;
}
void VisualScriptEditor::add_callback(const String& p_function,StringArray p_args){
+ if (script->has_function(p_function)) {
+ edited_func=p_function;
+ selected=edited_func;
+ _update_members();
+ _update_graph();
+ return;
+ }
+
+ Ref<VisualScriptFunction> func;
+ func.instance();
+ for(int i=0;i<p_args.size();i++) {
+
+ String name = p_args[i];
+ Variant::Type type=Variant::NIL;
+
+ if (name.find(":")!=-1) {
+ String tt = name.get_slice(":",1);
+ name=name.get_slice(":",0);
+ for(int j=0;j<Variant::VARIANT_MAX;j++) {
+
+ String tname = Variant::get_type_name(Variant::Type(j));
+ if (tname==tt) {
+ type=Variant::Type(j);
+ break;
+ }
+ }
+ }
+
+ func->add_argument(type,name);
+ }
+
+ func->set_name(p_function);
+ script->add_function(p_function);
+ script->add_node(p_function,script->get_available_id(),func);
+
+ edited_func=p_function;
+ selected=edited_func;
+ _update_members();
+ _update_graph();
+ graph->call_deferred("set_scroll_ofs",script->get_function_scroll(edited_func)); //for first time it might need to be later
+
+ //undo_redo->clear_history();
}
void VisualScriptEditor::update_settings(){
-
+ _update_graph();
}
+void VisualScriptEditor::set_debugger_active(bool p_active) {
+ if (!p_active) {
+ error_line=-1;
+ _update_graph(); //clear line break
+ }
+}
void VisualScriptEditor::set_tooltip_request_func(String p_method,Object* p_obj){
@@ -1842,7 +2022,7 @@ void VisualScriptEditor::set_tooltip_request_func(String p_method,Object* p_obj)
Control *VisualScriptEditor::get_edit_menu(){
- return NULL;
+ return edit_menu;
}
void VisualScriptEditor::_change_base_type() {
@@ -2137,6 +2317,60 @@ void VisualScriptEditor::_notification(int p_what) {
}
}
+void VisualScriptEditor::_graph_ofs_changed(const Vector2& p_ofs) {
+
+ if (updating_graph)
+ return;
+
+ updating_graph=true;
+
+ if (script->has_function(edited_func)) {
+ script->set_function_scroll(edited_func,graph->get_scroll_ofs()/EDSCALE);
+ script->set_edited(true);
+ }
+ updating_graph=false;
+}
+
+void VisualScriptEditor::_menu_option(int p_what) {
+
+ switch(p_what) {
+ case EDIT_DELETE_NODES: {
+ _on_nodes_delete();
+ } break;
+ case EDIT_TOGGLE_BREAKPOINT: {
+
+ List<String> reselect;
+ for(int i=0;i<graph->get_child_count();i++) {
+ GraphNode *gn = graph->get_child(i)->cast_to<GraphNode>();
+ if (gn) {
+ if (gn->is_selected()) {
+ int id = String(gn->get_name()).to_int();
+ Ref<VisualScriptNode> vsn = script->get_node(edited_func,id);
+ if (vsn.is_valid()) {
+ vsn->set_breakpoint(!vsn->is_breakpoint());
+ reselect.push_back(gn->get_name());
+ }
+ }
+ }
+ }
+
+ _update_graph();
+
+ for(List<String>::Element *E=reselect.front();E;E=E->next()) {
+ GraphNode *gn = graph->get_node(E->get())->cast_to<GraphNode>();
+ gn->set_selected(true);
+ }
+
+ } break;
+ case EDIT_FIND_NODE_TYPE: {
+ //popup disappearing grabs focus to owner, so use call deferred
+ node_filter->call_deferred("grab_focus");
+ node_filter->call_deferred("select_all");
+ } break;
+
+ }
+}
+
void VisualScriptEditor::_bind_methods() {
ObjectTypeDB::bind_method("_member_button",&VisualScriptEditor::_member_button);
@@ -2157,6 +2391,9 @@ void VisualScriptEditor::_bind_methods() {
ObjectTypeDB::bind_method("_available_node_doubleclicked",&VisualScriptEditor::_available_node_doubleclicked);
ObjectTypeDB::bind_method("_default_value_edited",&VisualScriptEditor::_default_value_edited);
ObjectTypeDB::bind_method("_default_value_changed",&VisualScriptEditor::_default_value_changed);
+ ObjectTypeDB::bind_method("_menu_option",&VisualScriptEditor::_menu_option);
+ ObjectTypeDB::bind_method("_graph_ofs_changed",&VisualScriptEditor::_graph_ofs_changed);
+ ObjectTypeDB::bind_method("_center_on_node",&VisualScriptEditor::_center_on_node);
@@ -2182,6 +2419,15 @@ void VisualScriptEditor::_bind_methods() {
VisualScriptEditor::VisualScriptEditor() {
+ updating_graph=false;
+
+ edit_menu = memnew( MenuButton );
+ edit_menu->set_text(TTR("Edit"));
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/delete_selected"), EDIT_DELETE_NODES);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/toggle_breakpoint"), EDIT_TOGGLE_BREAKPOINT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/find_node_type"), EDIT_FIND_NODE_TYPE);
+ edit_menu->get_popup()->connect("item_pressed",this,"_menu_option");
+
main_hsplit = memnew( HSplitContainer );
add_child(main_hsplit);
main_hsplit->set_area_as_parent_rect();
@@ -2203,7 +2449,7 @@ VisualScriptEditor::VisualScriptEditor() {
members->set_hide_root(true);
members->connect("button_pressed",this,"_member_button");
members->connect("item_edited",this,"_member_edited");
- members->connect("cell_selected",this,"_member_selected");
+ members->connect("cell_selected",this,"_member_selected",varray(),CONNECT_DEFERRED);
members->set_single_select_cell_editing_only_when_already_selected(true);
members->set_hide_folding(true);
members->set_drag_forwarding(this);
@@ -2245,6 +2491,7 @@ VisualScriptEditor::VisualScriptEditor() {
graph->connect("duplicate_nodes_request",this,"_on_nodes_duplicate");
graph->set_drag_forwarding(this);
graph->hide();
+ graph->connect("scroll_offset_changed",this,"_graph_ofs_changed");
select_func_text = memnew( Label );
select_func_text->set_text(TTR("Select or create a function to edit graph"));
@@ -2329,6 +2576,7 @@ VisualScriptEditor::VisualScriptEditor() {
add_child(default_value_edit);
default_value_edit->connect("variant_changed",this,"_default_value_changed");
+ error_line=-1;
}
VisualScriptEditor::~VisualScriptEditor() {
@@ -2347,9 +2595,28 @@ static ScriptEditorBase * create_editor(const Ref<Script>& p_script) {
return NULL;
}
+static void register_editor_callback() {
+
+ ScriptEditor::register_create_script_editor_function(create_editor);
+ EditorSettings::get_singleton()->set("visual_script_editor/color_functions",Color(1,0.9,0.9));
+ EditorSettings::get_singleton()->set("visual_script_editor/color_data",Color(0.9,1.0,0.9));
+ EditorSettings::get_singleton()->set("visual_script_editor/color_operators",Color(0.9,0.9,1.0));
+ EditorSettings::get_singleton()->set("visual_script_editor/color_flow_control",Color(1.0,1.0,0.8));
+ EditorSettings::get_singleton()->set("visual_script_editor/color_custom",Color(0.8,1.0,1.0));
+
+
+ ED_SHORTCUT("visual_script_editor/delete_selected", TTR("Delete Selected"));
+ ED_SHORTCUT("visual_script_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9);
+ ED_SHORTCUT("visual_script_editor/find_node_type", TTR("Find Node Tyoe"), KEY_MASK_CMD+KEY_F);
+
+}
void VisualScriptEditor::register_editor() {
- ScriptEditor::register_create_script_editor_function(create_editor);
+ //too early to register stuff here, request a callback
+ EditorNode::add_plugin_init_callback(register_editor_callback);
+
+
+
}
diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h
index 61a486da02..bd33f35739 100644
--- a/modules/visual_script/visual_script_editor.h
+++ b/modules/visual_script/visual_script_editor.h
@@ -22,6 +22,14 @@ class VisualScriptEditor : public ScriptEditorBase {
};
+ enum {
+ EDIT_DELETE_NODES,
+ EDIT_TOGGLE_BREAKPOINT,
+ EDIT_FIND_NODE_TYPE,
+ };
+
+ MenuButton *edit_menu;
+
Ref<VisualScript> script;
Button *base_type_select;
@@ -57,6 +65,8 @@ class VisualScriptEditor : public ScriptEditorBase {
Label *select_func_text;
+ bool updating_graph;
+
void _show_hint(const String& p_hint);
void _hide_timer();
@@ -88,7 +98,10 @@ class VisualScriptEditor : public ScriptEditorBase {
String _validate_name(const String& p_name) const;
+ int error_line;
+
void _node_selected(Node* p_node);
+ void _center_on_node(int p_id);
void _node_filter_changed(const String& p_text);
void _change_base_type_callback();
@@ -129,6 +142,10 @@ class VisualScriptEditor : public ScriptEditorBase {
void _default_value_changed();
void _default_value_edited(Node * p_button,int p_id,int p_input_port);
+
+ void _menu_option(int p_what);
+
+ void _graph_ofs_changed(const Vector2& p_ofs);
protected:
void _notification(int p_what);
@@ -145,7 +162,7 @@ public:
virtual bool is_unsaved();
virtual Variant get_edit_state();
virtual void set_edit_state(const Variant& p_state);
- virtual void goto_line(int p_line);
+ virtual void goto_line(int p_line,bool p_with_error=false);
virtual void trim_trailing_whitespace();
virtual void ensure_focus();
virtual void tag_saved_version();
@@ -154,7 +171,7 @@ public:
virtual bool goto_method(const String& p_method);
virtual void add_callback(const String& p_function,StringArray p_args);
virtual void update_settings();
-
+ virtual void set_debugger_active(bool p_active);
virtual void set_tooltip_request_func(String p_method,Object* p_obj);
virtual Control *get_edit_menu();
diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp
index 83d975fbca..cb0ff4086c 100644
--- a/modules/visual_script/visual_script_flow_control.cpp
+++ b/modules/visual_script/visual_script_flow_control.cpp
@@ -1,4 +1,6 @@
#include "visual_script_flow_control.h"
+#include "os/keyboard.h"
+#include "globals.h"
//////////////////////////////////////////
////////////////RETURN////////////////////
@@ -93,9 +95,38 @@ void VisualScriptReturn::_bind_methods() {
}
-VisualScriptNodeInstance* VisualScriptReturn::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceReturn : public VisualScriptNodeInstance {
+public:
- return NULL;
+ VisualScriptReturn *node;
+ VisualScriptInstance *instance;
+ bool with_value;
+
+ virtual int get_working_memory_size() const { return 1; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+
+ 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) {
+
+ if (with_value) {
+ *p_working_mem = *p_inputs[0];
+ } else {
+ *p_working_mem = Variant();
+ }
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptReturn::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceReturn * instance = memnew(VisualScriptNodeInstanceReturn );
+ instance->node=this;
+ instance->instance=p_instance;
+ instance->with_value=with_value;
+ return instance;
}
VisualScriptReturn::VisualScriptReturn() {
@@ -174,9 +205,33 @@ void VisualScriptCondition::_bind_methods() {
}
-VisualScriptNodeInstance* VisualScriptCondition::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceCondition : public VisualScriptNodeInstance {
+public:
+
+ VisualScriptCondition *node;
+ VisualScriptInstance *instance;
+
+ //virtual int get_working_memory_size() const { return 1; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
- return NULL;
+ 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) {
+
+ if (p_inputs[0]->operator bool())
+ return 0;
+ else
+ return 1;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptCondition::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceCondition * instance = memnew(VisualScriptNodeInstanceCondition );
+ instance->node=this;
+ instance->instance=p_instance;
+ return instance;
}
VisualScriptCondition::VisualScriptCondition() {
@@ -244,11 +299,36 @@ void VisualScriptWhile::_bind_methods() {
}
-VisualScriptNodeInstance* VisualScriptWhile::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceWhile : public VisualScriptNodeInstance {
+public:
- return NULL;
-}
+ VisualScriptWhile *node;
+ VisualScriptInstance *instance;
+
+ //virtual int get_working_memory_size() const { return 1; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+
+ 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) {
+ bool keep_going = p_inputs[0]->operator bool();
+
+ if (keep_going)
+ return 0|STEP_FLAG_PUSH_STACK_BIT;
+ else
+ return 1;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptWhile::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceWhile * instance = memnew(VisualScriptNodeInstanceWhile );
+ instance->node=this;
+ instance->instance=p_instance;
+ return instance;
+}
VisualScriptWhile::VisualScriptWhile() {
}
@@ -316,9 +396,79 @@ void VisualScriptIterator::_bind_methods() {
}
-VisualScriptNodeInstance* VisualScriptIterator::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceIterator : public VisualScriptNodeInstance {
+public:
+
+ VisualScriptIterator *node;
+ VisualScriptInstance *instance;
+
+ virtual int get_working_memory_size() const { return 2; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+
+ 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) {
+
+ if (p_start_mode==START_MODE_BEGIN_SEQUENCE) {
+ p_working_mem[0]=*p_inputs[0];
+ bool valid;
+ bool can_iter = p_inputs[0]->iter_init(p_working_mem[1],valid);
+
+ if (!valid) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str=RTR("Input type not iterable: ")+Variant::get_type_name(p_inputs[0]->get_type());
+ return 0;
+ }
+
+ if (!can_iter)
+ return 1; //nothing to iterate
+
+
+ *p_outputs[0]=p_working_mem[0].iter_get( p_working_mem[1],valid);
+
+ if (!valid) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str=RTR("Iterator became invalid");
+ return 0;
+ }
+
+
+ } else { //continue sequence
+
+ bool valid;
+ bool can_iter = p_working_mem[0].iter_next(p_working_mem[1],valid);
+
+ if (!valid) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str=RTR("Iterator became invalid: ")+Variant::get_type_name(p_inputs[0]->get_type());
+ return 0;
+ }
+
+ if (!can_iter)
+ return 1; //nothing to iterate
+
+
+ *p_outputs[0]=p_working_mem[0].iter_get( p_working_mem[1],valid);
- return NULL;
+ if (!valid) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str=RTR("Iterator became invalid");
+ return 0;
+ }
+
+ }
+
+ return 0|STEP_FLAG_PUSH_STACK_BIT; //go around
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptIterator::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceIterator * instance = memnew(VisualScriptNodeInstanceIterator );
+ instance->node=this;
+ instance->instance=p_instance;
+ return instance;
}
VisualScriptIterator::VisualScriptIterator() {
@@ -396,16 +546,1122 @@ void VisualScriptSequence::_bind_methods() {
}
-VisualScriptNodeInstance* VisualScriptSequence::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceSequence : public VisualScriptNodeInstance {
+public:
- return NULL;
-}
+ VisualScriptSequence *node;
+ VisualScriptInstance *instance;
+ int steps;
+
+ virtual int get_working_memory_size() const { return 1; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+
+ 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) {
+
+ if (p_start_mode==START_MODE_BEGIN_SEQUENCE) {
+ p_working_mem[0]=0;
+ }
+
+ int step = p_working_mem[0];
+
+ *p_outputs[0]=step;
+
+ if (step+1==steps)
+ return step;
+ else {
+ p_working_mem[0]=step+1;
+ return step|STEP_FLAG_PUSH_STACK_BIT;
+ }
+
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptSequence::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceSequence * instance = memnew(VisualScriptNodeInstanceSequence );
+ instance->node=this;
+ instance->instance=p_instance;
+ instance->steps=steps;
+ return instance;
+}
VisualScriptSequence::VisualScriptSequence() {
steps=1;
}
+
+//////////////////////////////////////////
+////////////////EVENT TYPE FILTER///////////
+//////////////////////////////////////////
+
+static const char* event_type_names[InputEvent::TYPE_MAX]={
+ "None",
+ "Key",
+ "MouseMotion",
+ "MouseButton",
+ "JoystickMotion",
+ "JoystickButton",
+ "ScreenTouch",
+ "ScreenDrag",
+ "Action"
+};
+
+int VisualScriptInputSelector::get_output_sequence_port_count() const {
+
+ return InputEvent::TYPE_MAX;
+}
+
+bool VisualScriptInputSelector::has_input_sequence_port() const{
+
+ return true;
+}
+
+int VisualScriptInputSelector::get_input_value_port_count() const{
+
+
+ return 1;
+}
+int VisualScriptInputSelector::get_output_value_port_count() const{
+
+ return 1;
+}
+
+String VisualScriptInputSelector::get_output_sequence_port_text(int p_port) const {
+
+ return event_type_names[p_port];
+}
+
+PropertyInfo VisualScriptInputSelector::get_input_value_port_info(int p_idx) const{
+
+ return PropertyInfo(Variant::INPUT_EVENT,"event");
+}
+
+PropertyInfo VisualScriptInputSelector::get_output_value_port_info(int p_idx) const{
+
+ return PropertyInfo(Variant::INPUT_EVENT,"");
+}
+
+
+String VisualScriptInputSelector::get_caption() const {
+
+ return "InputSelector";
+}
+
+String VisualScriptInputSelector::get_text() const {
+
+ return "";
+}
+
+
+class VisualScriptNodeInstanceInputSelector : public VisualScriptNodeInstance {
+public:
+
+ VisualScriptInstance* instance;
+ InputEvent::Type type;
+
+ //virtual int get_working_memory_size() const { return 0; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
+
+ 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) {
+
+ if (p_inputs[0]->get_type()!=Variant::INPUT_EVENT) {
+ r_error_str="Input value not of type event";
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ return 0;
+ }
+
+ InputEvent event = *p_inputs[0];
+
+ *p_outputs[0] = event;
+
+ return event.type;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptInputSelector::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceInputSelector * instance = memnew(VisualScriptNodeInstanceInputSelector );
+ instance->instance=p_instance;
+ return instance;
+}
+
+
+
+void VisualScriptInputSelector::_bind_methods() {
+
+
+}
+
+VisualScriptInputSelector::VisualScriptInputSelector() {
+
+
+}
+
+//////////////////////////////////////////
+////////////////EVENT ACTION FILTER///////////
+//////////////////////////////////////////
+
+
+int VisualScriptInputFilter::get_output_sequence_port_count() const {
+
+ return filters.size();
+}
+
+bool VisualScriptInputFilter::has_input_sequence_port() const{
+
+ return true;
+}
+
+int VisualScriptInputFilter::get_input_value_port_count() const{
+
+
+ return 1;
+}
+int VisualScriptInputFilter::get_output_value_port_count() const{
+
+ return 1;
+}
+
+String VisualScriptInputFilter::get_output_sequence_port_text(int p_port) const {
+
+ String text;
+
+ switch(filters[p_port].type) {
+ case InputEvent::NONE: {
+ text="None";
+ } break;
+ case InputEvent::KEY: {
+
+ InputEventKey k = filters[p_port].key;
+
+ if (k.scancode==0 && k.unicode==0) {
+ text="No Key";
+ } else {
+ if (k.scancode!=0) {
+ text="KeyCode: "+keycode_get_string(k.scancode);
+ } else if (k.unicode!=0) {
+ text="Uniode: "+String::chr(k.unicode);
+ }
+
+ if (k.pressed)
+ text+=", Pressed";
+ else
+ text+=", Released";
+
+ if (k.echo)
+ text+=", Echo";
+ if (k.mod.alt)
+ text="Alt+"+text;
+ if (k.mod.shift)
+ text="Shift+"+text;
+ if (k.mod.control)
+ text="Ctrl+"+text;
+ if (k.mod.meta)
+ text="Meta+"+text;
+ }
+
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+ InputEventMouseMotion mm = filters[p_port].mouse_motion;
+ text="Mouse Motion";
+
+ String b = "Left,Right,Middle,WheelUp,WheelDown,WheelLeft,WheelRight";
+
+ for(int i=0;i<7;i++) {
+ if (mm.button_mask&(1<<i)) {
+ text=b.get_slice(",",i)+"+"+text;
+ }
+ }
+ if (mm.mod.alt)
+ text="Alt+"+text;
+ if (mm.mod.shift)
+ text="Shift+"+text;
+ if (mm.mod.control)
+ text="Ctrl+"+text;
+ if (mm.mod.meta)
+ text="Meta+"+text;
+ } break;
+ case InputEvent::MOUSE_BUTTON: {
+
+ InputEventMouseButton mb = filters[p_port].mouse_button;
+
+ String b = "Any,Left,Right,Middle,WheelUp,WheelDown,WheelLeft,WheelRight";
+
+ text=b.get_slice(",",mb.button_index)+" Mouse Button";
+
+ if (mb.pressed)
+ text+=", Pressed";
+ else
+ text+=", Released";
+
+ if (mb.doubleclick)
+ text+=", DblClick";
+ if (mb.mod.alt)
+ text="Alt+"+text;
+ if (mb.mod.shift)
+ text="Shift+"+text;
+ if (mb.mod.control)
+ text="Ctrl+"+text;
+ if (mb.mod.meta)
+ text="Meta+"+text;
+
+
+ } break;
+ case InputEvent::JOYSTICK_MOTION: {
+
+ InputEventJoystickMotion jm = filters[p_port].joy_motion;
+
+ text="JoyMotion Axis "+itos(jm.axis>>1);
+ if (jm.axis&1)
+ text+=" > "+rtos(jm.axis_value);
+ else
+ text+=" < "+rtos(-jm.axis_value);
+
+ } break;
+ case InputEvent::JOYSTICK_BUTTON: {
+ InputEventJoystickButton jb = filters[p_port].joy_button;
+
+ text="JoyButton "+itos(jb.button_index);
+ if (jb.pressed)
+ text+=", Pressed";
+ else
+ text+=", Released";
+ } break;
+ case InputEvent::SCREEN_TOUCH: {
+ InputEventScreenTouch sd = filters[p_port].screen_touch;
+
+ text="Touch Finger "+itos(sd.index);
+ if (sd.pressed)
+ text+=", Pressed";
+ else
+ text+=", Released";
+ } break;
+ case InputEvent::SCREEN_DRAG: {
+ InputEventScreenDrag sd = filters[p_port].screen_drag;
+ text="Drag Finger "+itos(sd.index);
+ } break;
+ case InputEvent::ACTION: {
+
+
+ List<PropertyInfo> pinfo;
+ Globals::get_singleton()->get_property_list(&pinfo);
+ int index=1;
+
+ text="No Action";
+ for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+ const PropertyInfo &pi=E->get();
+
+ if (!pi.name.begins_with("input/"))
+ continue;
+
+
+ if (filters[p_port].action.action==index) {
+ text="Action "+pi.name.substr(pi.name.find("/")+1,pi.name.length());
+ break;
+ }
+ index++;
+ }
+
+ if (filters[p_port].action.pressed)
+ text+=", Pressed";
+ else
+ text+=", Released";
+
+
+ } break;
+ }
+
+
+
+ return text+" - "+itos(p_port);
+}
+
+PropertyInfo VisualScriptInputFilter::get_input_value_port_info(int p_idx) const{
+
+ return PropertyInfo(Variant::INPUT_EVENT,"event");
+}
+
+PropertyInfo VisualScriptInputFilter::get_output_value_port_info(int p_idx) const{
+
+ return PropertyInfo(Variant::INPUT_EVENT,"");
+}
+
+
+String VisualScriptInputFilter::get_caption() const {
+
+ return "InputFilter";
+}
+
+String VisualScriptInputFilter::get_text() const {
+
+ return "";
+}
+
+
+
+bool VisualScriptInputFilter::_set(const StringName& p_name, const Variant& p_value) {
+
+ if (p_name=="filter_count") {
+ filters.resize(p_value);
+ _change_notify();
+ ports_changed_notify();
+ return true;
+ }
+
+
+ if (String(p_name).begins_with("filter_")) {
+
+ int idx = String(p_name).replace_first("filters_","").get_slice("/",0).to_int();
+
+ ERR_FAIL_INDEX_V(idx,filters.size(),false);
+
+ String what = String(p_name).get_slice("/",1);
+
+
+ if (what=="type") {
+ filters[idx]=InputEvent();
+ filters[idx].type=InputEvent::Type(int(p_value));
+ if (filters[idx].type==InputEvent::JOYSTICK_MOTION) {
+ filters[idx].joy_motion.axis_value=0.5; //for treshold
+ } else if (filters[idx].type==InputEvent::KEY) {
+ filters[idx].key.pressed=true; //put these as true to make it more user friendly
+ } else if (filters[idx].type==InputEvent::MOUSE_BUTTON) {
+ filters[idx].mouse_button.pressed=true;
+ } else if (filters[idx].type==InputEvent::JOYSTICK_BUTTON) {
+ filters[idx].joy_button.pressed=true;
+ } else if (filters[idx].type==InputEvent::SCREEN_TOUCH) {
+ filters[idx].screen_touch.pressed=true;
+ } else if (filters[idx].type==InputEvent::ACTION) {
+ filters[idx].action.pressed=true;
+ }
+ _change_notify();
+ ports_changed_notify();
+
+ return true;
+ }
+ if (what=="device") {
+ filters[idx].device=p_value;
+ ports_changed_notify();
+ return true;
+ }
+
+ switch(filters[idx].type) {
+
+ case InputEvent::KEY: {
+
+ if (what=="scancode") {
+ String sc = p_value;
+ if (sc==String()) {
+ filters[idx].key.scancode=0;
+ } else {
+ filters[idx].key.scancode=find_keycode(p_value);
+ }
+
+ } else if (what=="unicode") {
+
+ String uc = p_value;
+
+ if (uc==String()) {
+ filters[idx].key.unicode=0;
+ } else {
+ filters[idx].key.unicode=uc[0];
+ }
+
+ } else if (what=="pressed") {
+
+ filters[idx].key.pressed=p_value;
+ } else if (what=="echo") {
+
+ filters[idx].key.echo=p_value;
+
+ } else if (what=="mod_alt") {
+ filters[idx].key.mod.alt=p_value;
+
+ } else if (what=="mod_shift") {
+ filters[idx].key.mod.shift=p_value;
+
+ } else if (what=="mod_ctrl") {
+ filters[idx].key.mod.control=p_value;
+
+ } else if (what=="mod_meta") {
+ filters[idx].key.mod.meta=p_value;
+ } else {
+ return false;
+ }
+ ports_changed_notify();
+
+ return true;
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+
+ if (what=="button_mask") {
+ filters[idx].mouse_motion.button_mask=p_value;
+
+ } else if (what=="mod_alt") {
+ filters[idx].mouse_motion.mod.alt=p_value;
+
+ } else if (what=="mod_shift") {
+ filters[idx].mouse_motion.mod.shift=p_value;
+
+ } else if (what=="mod_ctrl") {
+ filters[idx].mouse_motion.mod.control=p_value;
+
+ } else if (what=="mod_meta") {
+ filters[idx].mouse_motion.mod.meta=p_value;
+ } else {
+ return false;
+ }
+
+ ports_changed_notify();
+ return true;
+
+ } break;
+ case InputEvent::MOUSE_BUTTON: {
+
+ if (what=="button_index") {
+ filters[idx].mouse_button.button_index=p_value;
+ } else if (what=="pressed") {
+ filters[idx].mouse_button.pressed=p_value;
+ } else if (what=="doubleclicked") {
+ filters[idx].mouse_button.doubleclick=p_value;
+
+ } else if (what=="mod_alt") {
+ filters[idx].mouse_button.mod.alt=p_value;
+
+ } else if (what=="mod_shift") {
+ filters[idx].mouse_button.mod.shift=p_value;
+
+ } else if (what=="mod_ctrl") {
+ filters[idx].mouse_button.mod.control=p_value;
+
+ } else if (what=="mod_meta") {
+ filters[idx].mouse_button.mod.meta=p_value;
+ } else {
+ return false;
+ }
+ ports_changed_notify();
+ return true;
+
+ } break;
+ case InputEvent::JOYSTICK_MOTION: {
+
+ if (what=="axis") {
+ filters[idx].joy_motion.axis=int(p_value)<<1|filters[idx].joy_motion.axis;
+ } else if (what=="mode") {
+ filters[idx].joy_motion.axis|=int(p_value);
+ } else if (what=="treshold") {
+ filters[idx].joy_motion.axis_value=p_value;
+ } else {
+ return false;
+ }
+ ports_changed_notify();
+ return true;
+
+
+ } break;
+ case InputEvent::JOYSTICK_BUTTON: {
+
+ if (what=="button_index") {
+ filters[idx].joy_button.button_index=p_value;
+ } else if (what=="pressed") {
+ filters[idx].joy_button.pressed=p_value;
+ } else {
+ return false;
+ }
+ ports_changed_notify();
+ return true;
+
+ } break;
+ case InputEvent::SCREEN_TOUCH: {
+
+ if (what=="finger_index") {
+ filters[idx].screen_touch.index=p_value;
+ } else if (what=="pressed") {
+ filters[idx].screen_touch.pressed=p_value;
+ } else {
+ return false;
+ }
+ ports_changed_notify();
+ return true;
+ } break;
+ case InputEvent::SCREEN_DRAG: {
+ if (what=="finger_index") {
+ filters[idx].screen_drag.index=p_value;
+ } else {
+ return false;
+ }
+ ports_changed_notify();
+ return true;
+ } break;
+ case InputEvent::ACTION: {
+
+
+ if (what=="action_name") {
+
+ List<PropertyInfo> pinfo;
+ Globals::get_singleton()->get_property_list(&pinfo);
+ int index=1;
+
+ for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+ const PropertyInfo &pi=E->get();
+
+ if (!pi.name.begins_with("input/"))
+ continue;
+
+ String name = pi.name.substr(pi.name.find("/")+1,pi.name.length());
+ if (name==String(p_value)) {
+
+ filters[idx].action.action=index;
+ ports_changed_notify();
+ return true;
+ }
+
+ index++;
+ }
+
+ filters[idx].action.action=0;
+ ports_changed_notify();
+
+ return false;
+
+ } else if (what=="pressed") {
+
+ filters[idx].action.pressed=p_value;
+ ports_changed_notify();
+ return true;
+ }
+
+
+ } break;
+
+ }
+ }
+ return false;
+}
+
+bool VisualScriptInputFilter::_get(const StringName& p_name,Variant &r_ret) const{
+
+ if (p_name=="filter_count") {
+ r_ret=filters.size();
+ return true;
+ }
+
+
+ if (String(p_name).begins_with("filter_")) {
+
+ int idx = String(p_name).replace_first("filters_","").get_slice("/",0).to_int();
+
+ ERR_FAIL_INDEX_V(idx,filters.size(),false);
+
+ String what = String(p_name).get_slice("/",1);
+
+
+ if (what=="type") {
+ r_ret=filters[idx].type;
+ return true;
+ }
+ if (what=="device") {
+ r_ret=filters[idx].device;
+ return true;
+ }
+
+ switch(filters[idx].type) {
+
+ case InputEvent::KEY: {
+
+ if (what=="scancode") {
+ if (filters[idx].key.scancode==0)
+ r_ret=String();
+ else {
+
+ r_ret=keycode_get_string(filters[idx].key.scancode);
+ }
+
+ } else if (what=="unicode") {
+
+
+ if (filters[idx].key.unicode==0) {
+ r_ret=String();
+ } else {
+ CharType str[2]={ (CharType)filters[idx].key.unicode, 0};
+ r_ret=String(str);
+ }
+
+ } else if (what=="pressed") {
+
+ r_ret=filters[idx].key.pressed;
+ } else if (what=="echo") {
+
+ r_ret=filters[idx].key.echo;
+
+ } else if (what=="mod_alt") {
+ r_ret=filters[idx].key.mod.alt;
+
+ } else if (what=="mod_shift") {
+ r_ret=filters[idx].key.mod.shift;
+
+ } else if (what=="mod_ctrl") {
+ r_ret=filters[idx].key.mod.control;
+
+ } else if (what=="mod_meta") {
+ r_ret=filters[idx].key.mod.meta;
+ } else {
+ return false;
+ }
+
+ return true;
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+
+ if (what=="button_mask") {
+ r_ret=filters[idx].mouse_motion.button_mask;
+
+ } else if (what=="mod_alt") {
+ r_ret=filters[idx].mouse_motion.mod.alt;
+
+ } else if (what=="mod_shift") {
+ r_ret=filters[idx].mouse_motion.mod.shift;
+
+ } else if (what=="mod_ctrl") {
+ r_ret=filters[idx].mouse_motion.mod.control;
+
+ } else if (what=="mod_meta") {
+ r_ret=filters[idx].mouse_motion.mod.meta;
+ } else {
+ return false;
+ }
+
+ return true;
+
+ } break;
+ case InputEvent::MOUSE_BUTTON: {
+
+ if (what=="button_index") {
+ r_ret=filters[idx].mouse_button.button_index;
+ } else if (what=="pressed") {
+ r_ret=filters[idx].mouse_button.pressed;
+ } else if (what=="doubleclicked") {
+ r_ret=filters[idx].mouse_button.doubleclick;
+
+ } else if (what=="mod_alt") {
+ r_ret=filters[idx].mouse_button.mod.alt;
+
+ } else if (what=="mod_shift") {
+ r_ret=filters[idx].mouse_button.mod.shift;
+
+ } else if (what=="mod_ctrl") {
+ r_ret=filters[idx].mouse_button.mod.control;
+
+ } else if (what=="mod_meta") {
+ r_ret=filters[idx].mouse_button.mod.meta;
+ } else {
+ return false;
+ }
+ return true;
+
+ } break;
+ case InputEvent::JOYSTICK_MOTION: {
+
+ if (what=="axis_index") {
+ r_ret=filters[idx].joy_motion.axis>>1;
+ } else if (what=="mode") {
+ r_ret=filters[idx].joy_motion.axis&1;
+ } else if (what=="treshold") {
+ r_ret=filters[idx].joy_motion.axis_value;
+ } else {
+ return false;
+ }
+ return true;
+
+
+ } break;
+ case InputEvent::JOYSTICK_BUTTON: {
+
+ if (what=="button_index") {
+ r_ret=filters[idx].joy_button.button_index;
+ } else if (what=="pressed") {
+ r_ret=filters[idx].joy_button.pressed;
+ } else {
+ return false;
+ }
+ return true;
+
+ } break;
+ case InputEvent::SCREEN_TOUCH: {
+
+ if (what=="finger_index") {
+ r_ret=filters[idx].screen_touch.index;
+ } else if (what=="pressed") {
+ r_ret=filters[idx].screen_touch.pressed;
+ } else {
+ return false;
+ }
+ return true;
+ } break;
+ case InputEvent::SCREEN_DRAG: {
+ if (what=="finger_index") {
+ r_ret=filters[idx].screen_drag.index;
+ } else {
+ return false;
+ }
+ return true;
+ } break;
+ case InputEvent::ACTION: {
+
+
+ if (what=="action_name") {
+
+ List<PropertyInfo> pinfo;
+ Globals::get_singleton()->get_property_list(&pinfo);
+ int index=1;
+
+ for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+ const PropertyInfo &pi=E->get();
+
+ if (!pi.name.begins_with("input/"))
+ continue;
+
+
+ if (filters[idx].action.action==index) {
+ r_ret=pi.name.substr(pi.name.find("/")+1,pi.name.length());
+ return true;
+ }
+ index++;
+ }
+
+ r_ret="None"; //no index
+ return false;
+
+ } else if (what=="pressed") {
+
+ r_ret=filters[idx].action.pressed;
+ return true;
+ }
+
+
+ } break;
+
+ }
+ }
+ return false;
+}
+void VisualScriptInputFilter::_get_property_list( List<PropertyInfo> *p_list) const {
+
+ p_list->push_back(PropertyInfo(Variant::INT,"filter_count",PROPERTY_HINT_RANGE,"0,64"));
+
+ String et;
+ for(int i=0;i<InputEvent::TYPE_MAX;i++) {
+ if (i>0)
+ et+=",";
+
+ et+=event_type_names[i];
+ }
+
+ String kc;
+ String actions;
+
+
+
+ for(int i=0;i<filters.size();i++) {
+
+ String base = "filter_"+itos(i)+"/";
+ p_list->push_back(PropertyInfo(Variant::INT,base+"type",PROPERTY_HINT_ENUM,et));
+ p_list->push_back(PropertyInfo(Variant::INT,base+"device"));
+ switch(filters[i].type) {
+
+ case InputEvent::NONE: {
+
+ } break;
+ case InputEvent::KEY: {
+ if (kc==String()) {
+ int kcc = keycode_get_count();
+ kc="None";
+ for(int i=0;i<kcc;i++) {
+ kc+=",";
+ kc+=String(keycode_get_name_by_index(i));
+ }
+ }
+ p_list->push_back(PropertyInfo(Variant::STRING,base+"scancode",PROPERTY_HINT_ENUM,kc));
+ p_list->push_back(PropertyInfo(Variant::STRING,base+"unicode"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"pressed"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"echo"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_alt"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_shift"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_ctrl"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_meta"));
+
+
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+ p_list->push_back(PropertyInfo(Variant::INT,base+"button_mask",PROPERTY_HINT_FLAGS,"Left,Right,Middle,WheelUp,WheelDown,WheelLeft,WheelRight"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_alt"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_shift"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_ctrl"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_meta"));
+
+ } break;
+ case InputEvent::MOUSE_BUTTON: {
+ p_list->push_back(PropertyInfo(Variant::INT,base+"button_index",PROPERTY_HINT_ENUM,"Any,Left,Right,Middle,WheelUp,WheelDown,WheelLeft,WheelRight"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"pressed"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"doubleclicked"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_alt"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_shift"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_ctrl"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_meta"));
+
+ } break;
+ case InputEvent::JOYSTICK_MOTION: {
+
+ p_list->push_back(PropertyInfo(Variant::INT,base+"axis_index"));
+ p_list->push_back(PropertyInfo(Variant::INT,base+"mode",PROPERTY_HINT_ENUM,"Min,Max"));
+ p_list->push_back(PropertyInfo(Variant::REAL,base+"treshold",PROPERTY_HINT_RANGE,"0,1,0.01"));
+ } break;
+ case InputEvent::JOYSTICK_BUTTON: {
+ p_list->push_back(PropertyInfo(Variant::INT,base+"button_index"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"pressed"));
+
+ } break;
+ case InputEvent::SCREEN_TOUCH: {
+ p_list->push_back(PropertyInfo(Variant::INT,base+"finger_index"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"pressed"));
+
+ } break;
+ case InputEvent::SCREEN_DRAG: {
+ p_list->push_back(PropertyInfo(Variant::INT,base+"finger_index"));
+ } break;
+ case InputEvent::ACTION: {
+
+
+
+ if (actions==String()) {
+
+ actions="None";
+
+ List<PropertyInfo> pinfo;
+ Globals::get_singleton()->get_property_list(&pinfo);
+ Vector<String> al;
+
+ for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+ const PropertyInfo &pi=E->get();
+
+ if (!pi.name.begins_with("input/"))
+ continue;
+
+ String name = pi.name.substr(pi.name.find("/")+1,pi.name.length());
+
+
+ al.push_back(name);
+ }
+
+ for(int i=0;i<al.size();i++) {
+ actions+=",";
+ actions+=al[i];
+ }
+ }
+
+ p_list->push_back(PropertyInfo(Variant::STRING,base+"action_name",PROPERTY_HINT_ENUM,actions));
+ p_list->push_back(PropertyInfo(Variant::BOOL,base+"pressed"));
+
+ } break;
+
+ }
+ }
+}
+
+class VisualScriptNodeInstanceInputFilter : public VisualScriptNodeInstance {
+public:
+
+ VisualScriptInstance* instance;
+ Vector<InputEvent> filters;
+
+ //virtual int get_working_memory_size() const { return 0; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
+
+ 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) {
+
+ if (p_inputs[0]->get_type()!=Variant::INPUT_EVENT) {
+ r_error_str="Input value not of type event";
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ return 0;
+ }
+
+ InputEvent event = *p_inputs[0];
+
+
+ for(int i=0;i<filters.size();i++) {
+
+ const InputEvent &ie = filters[i];
+ if (ie.type!=event.type)
+ continue;
+
+ bool match=false;
+
+ switch(ie.type) {
+
+ case InputEvent::NONE: {
+
+ match=true;
+ } break;
+ case InputEvent::KEY: {
+
+ InputEventKey k = ie.key;
+ InputEventKey k2 = event.key;
+
+ if (k.scancode==0 && k.unicode==0 && k2.scancode==0 && k2.unicode==0) {
+ match=true;
+
+ } else {
+
+ if ( (k.scancode!=0 && k.scancode==k2.scancode) || (k.unicode!=0 && k.unicode==k2.unicode)) {
+ //key valid
+
+ if (
+ k.pressed==k2.pressed &&
+ k.echo==k2.echo &&
+ k.mod == k2.mod
+ ) {
+ match=true;
+ }
+ }
+
+ }
+
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+ InputEventMouseMotion mm = ie.mouse_motion;
+ InputEventMouseMotion mm2 = event.mouse_motion;
+
+ if ( mm.button_mask==mm2.button_mask &&
+ mm.mod==mm2.mod
+ ) {
+ match=true;
+ }
+
+ } break;
+ case InputEvent::MOUSE_BUTTON: {
+
+ InputEventMouseButton mb = ie.mouse_button;
+ InputEventMouseButton mb2 = event.mouse_button;
+
+ if ( mb.button_index==mb2.button_index &&
+ mb.pressed==mb2.pressed &&
+ mb.doubleclick==mb2.doubleclick &&
+ mb.mod==mb2.mod) {
+ match=true;
+ }
+
+
+ } break;
+ case InputEvent::JOYSTICK_MOTION: {
+
+ InputEventJoystickMotion jm = ie.joy_motion;
+ InputEventJoystickMotion jm2 = event.joy_motion;
+
+ int axis = jm.axis>>1;
+
+ if (axis==jm2.axis) {
+
+ if (jm.axis&1) {
+ //greater
+ if (jm2.axis_value > jm.axis_value) {
+ match=true;
+ }
+ } else {
+ //less
+ if (jm2.axis_value < -jm.axis_value) {
+ match=true;
+ }
+ }
+ }
+
+
+ } break;
+ case InputEvent::JOYSTICK_BUTTON: {
+ InputEventJoystickButton jb = ie.joy_button;
+ InputEventJoystickButton jb2 = event.joy_button;
+
+ if ( jb.button_index==jb2.button_index &&
+ jb.pressed == jb2.pressed
+ ) {
+ match=true;
+ }
+ } break;
+ case InputEvent::SCREEN_TOUCH: {
+ InputEventScreenTouch st = ie.screen_touch;
+ InputEventScreenTouch st2 = event.screen_touch;
+
+ if ( st.index==st2.index &&
+ st.pressed==st2.pressed) {
+ match=true;
+ }
+
+ } break;
+ case InputEvent::SCREEN_DRAG: {
+ InputEventScreenDrag sd = ie.screen_drag;
+ InputEventScreenDrag sd2 = event.screen_drag;
+
+ if (sd.index==sd2.index) {
+ match=true;
+ }
+ } break;
+ case InputEvent::ACTION: {
+
+ InputEventAction ia = ie.action;
+ InputEventAction ia2 = event.action;
+
+ if ( ia.action==ia2.action &&
+ ia.pressed==ia2.pressed) {
+ match=true;
+ }
+ } break;
+
+ }
+
+ *p_outputs[0] = event;
+
+ if (match)
+ return i; //go through match output
+
+ }
+
+ return STEP_NO_ADVANCE_BIT; //none found, don't advance
+
+
+ }
+
+
+};
+
+
+VisualScriptNodeInstance* VisualScriptInputFilter::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceInputFilter * instance = memnew(VisualScriptNodeInstanceInputFilter );
+ instance->instance=p_instance;
+ instance->filters=filters;
+ return instance;
+}
+
+
+
+
+VisualScriptInputFilter::VisualScriptInputFilter() {
+
+
+}
+
+
+
+
void register_visual_script_flow_control_nodes() {
VisualScriptLanguage::singleton->add_register_func("flow_control/return",create_return_node<false>);
@@ -414,5 +1670,9 @@ void register_visual_script_flow_control_nodes() {
VisualScriptLanguage::singleton->add_register_func("flow_control/while",create_node_generic<VisualScriptWhile>);
VisualScriptLanguage::singleton->add_register_func("flow_control/iterator",create_node_generic<VisualScriptIterator>);
VisualScriptLanguage::singleton->add_register_func("flow_control/sequence",create_node_generic<VisualScriptSequence>);
+ VisualScriptLanguage::singleton->add_register_func("flow_control/input_select",create_node_generic<VisualScriptInputSelector>);
+ VisualScriptLanguage::singleton->add_register_func("flow_control/input_filter",create_node_generic<VisualScriptInputFilter>);
+
+
}
diff --git a/modules/visual_script/visual_script_flow_control.h b/modules/visual_script/visual_script_flow_control.h
index 557654b080..ed0e328629 100644
--- a/modules/visual_script/visual_script_flow_control.h
+++ b/modules/visual_script/visual_script_flow_control.h
@@ -31,6 +31,7 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "flow_control"; }
void set_return_type(Variant::Type);
Variant::Type get_return_type() const;
@@ -39,7 +40,7 @@ public:
bool is_return_value_enabled() const;
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptReturn();
};
@@ -72,9 +73,10 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "flow_control"; }
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptCondition();
};
@@ -107,9 +109,10 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "flow_control"; }
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptWhile();
};
@@ -143,9 +146,10 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "flow_control"; }
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptIterator();
};
@@ -180,15 +184,95 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "flow_control"; }
void set_steps(int p_steps);
int get_steps() const;
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptSequence();
};
+
+
+
+class VisualScriptInputSelector : public VisualScriptNode {
+
+ OBJ_TYPE(VisualScriptInputSelector,VisualScriptNode)
+
+
+
+protected:
+
+ static void _bind_methods();
+public:
+
+ virtual int get_output_sequence_port_count() const;
+ virtual bool has_input_sequence_port() const;
+
+
+ virtual String get_output_sequence_port_text(int p_port) const;
+
+
+ virtual int get_input_value_port_count() const;
+ virtual int get_output_value_port_count() const;
+
+
+ virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+ virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+ virtual String get_caption() const;
+ virtual String get_text() const;
+ virtual String get_category() const { return "flow_control"; }
+
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
+
+
+ VisualScriptInputSelector();
+};
+
+
+
+
+class VisualScriptInputFilter : public VisualScriptNode {
+
+ OBJ_TYPE(VisualScriptInputFilter,VisualScriptNode)
+
+ Vector<InputEvent> filters;
+
+
+protected:
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list( List<PropertyInfo> *p_list) const;
+
+public:
+
+ virtual int get_output_sequence_port_count() const;
+ virtual bool has_input_sequence_port() const;
+
+
+ virtual String get_output_sequence_port_text(int p_port) const;
+
+
+ virtual int get_input_value_port_count() const;
+ virtual int get_output_value_port_count() const;
+
+
+ virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+ virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+ virtual String get_caption() const;
+ virtual String get_text() const;
+ virtual String get_category() const { return "flow_control"; }
+
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
+
+
+ VisualScriptInputFilter();
+};
+
void register_visual_script_flow_control_nodes();
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index 750ad00a56..4006dab4a5 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -485,11 +485,96 @@ void VisualScriptFunctionCall::_bind_methods() {
BIND_CONSTANT( CALL_MODE_BASIC_TYPE );
}
-VisualScriptNodeInstance* VisualScriptFunctionCall::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceFunctionCall : public VisualScriptNodeInstance {
+public:
- return NULL;
-}
+ VisualScriptFunctionCall::CallMode call_mode;
+ NodePath node_path;
+ int input_args;
+ bool returns;
+ StringName function;
+
+ VisualScriptFunctionCall *node;
+ VisualScriptInstance *instance;
+
+
+
+ //virtual int get_working_memory_size() const { return 0; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+
+ 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) {
+
+
+ switch(call_mode) {
+
+ case VisualScriptFunctionCall::CALL_MODE_SELF: {
+
+ Object *object=instance->get_owner_ptr();
+
+ if (returns) {
+ *p_outputs[0] = object->call(function,p_inputs,input_args,r_error);
+ } else {
+ object->call(function,p_inputs,input_args,r_error);
+ }
+ } break;
+ case VisualScriptFunctionCall::CALL_MODE_NODE_PATH: {
+
+ Node* node = instance->get_owner_ptr()->cast_to<Node>();
+ if (!node) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Base object is not a Node!";
+ return 0;
+ }
+
+ Node* another = node->get_node(node_path);
+ if (!node) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Path does not lead Node!";
+ return 0;
+ }
+
+ if (returns) {
+ *p_outputs[0] = another->call(function,p_inputs,input_args,r_error);
+ } else {
+ another->call(function,p_inputs,input_args,r_error);
+ }
+
+ } break;
+ case VisualScriptFunctionCall::CALL_MODE_INSTANCE:
+ case VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE: {
+
+ Variant v = *p_inputs[0];
+
+ if (returns) {
+ *p_outputs[0] = v.call(function,p_inputs+1,input_args,r_error);
+ } else {
+ v.call(function,p_inputs+1,input_args,r_error);
+ }
+
+ } break;
+
+ }
+ return 0;
+
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptFunctionCall::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceFunctionCall * instance = memnew(VisualScriptNodeInstanceFunctionCall );
+ instance->node=this;
+ instance->instance=p_instance;
+ instance->function=function;
+ instance->call_mode=call_mode;
+ instance->returns=get_output_value_port_count();
+ instance->node_path=base_path;
+ instance->input_args = get_input_value_port_count() - ( (call_mode==CALL_MODE_BASIC_TYPE || call_mode==CALL_MODE_INSTANCE) ? 1: 0 );
+ return instance;
+}
VisualScriptFunctionCall::VisualScriptFunctionCall() {
call_mode=CALL_MODE_INSTANCE;
@@ -513,6 +598,19 @@ static Ref<VisualScriptNode> create_function_call_node(const String& p_name) {
////////////////SET//////////////////////
//////////////////////////////////////////
+static const char* event_type_names[InputEvent::TYPE_MAX]={
+ "None",
+ "Key",
+ "MouseMotion",
+ "MouseButton",
+ "JoystickMotion",
+ "JoystickButton",
+ "ScreenTouch",
+ "ScreenDrag",
+ "Action"
+};
+
+
int VisualScriptPropertySet::get_output_sequence_port_count() const {
return 1;
@@ -586,7 +684,7 @@ int VisualScriptPropertySet::get_input_value_port_count() const{
}
int VisualScriptPropertySet::get_output_value_port_count() const{
- return 0;
+ return call_mode==CALL_MODE_BASIC_TYPE? 1 : 0;
}
String VisualScriptPropertySet::get_output_sequence_port_text(int p_port) const {
@@ -617,9 +715,17 @@ PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const
if (call_mode==CALL_MODE_BASIC_TYPE) {
- Variant::CallError ce;
- Variant v = Variant::construct(basic_type,NULL,0,ce);
+ Variant v;
+ if (basic_type==Variant::INPUT_EVENT) {
+ InputEvent ev;
+ ev.type=event_type;
+ v=ev;
+ } else {
+ Variant::CallError ce;
+ v = Variant::construct(basic_type,NULL,0,ce);
+ }
v.get_property_list(&pinfo);
+
} else if (call_mode==CALL_MODE_NODE_PATH) {
Node *n = _get_base_node();
@@ -651,8 +757,11 @@ PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const
}
PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) const{
-
- return PropertyInfo();
+ if (call_mode==CALL_MODE_BASIC_TYPE) {
+ return PropertyInfo(basic_type,"out");
+ } else {
+ return PropertyInfo();
+ }
}
@@ -725,6 +834,21 @@ Variant::Type VisualScriptPropertySet::get_basic_type() const{
return basic_type;
}
+void VisualScriptPropertySet::set_event_type(InputEvent::Type p_type) {
+
+ if (event_type==p_type)
+ return;
+ event_type=p_type;
+ _change_notify();
+ _update_base_type();
+ ports_changed_notify();
+}
+
+InputEvent::Type VisualScriptPropertySet::get_event_type() const{
+
+ return event_type;
+}
+
void VisualScriptPropertySet::set_base_type(const StringName& p_type) {
@@ -833,6 +957,12 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo& property) const {
}
}
+ if (property.name=="property/event_type") {
+ if (call_mode!=CALL_MODE_BASIC_TYPE || basic_type!=Variant::INPUT_EVENT) {
+ property.usage=0;
+ }
+ }
+
if (property.name=="property/node_path") {
if (call_mode!=CALL_MODE_NODE_PATH) {
property.usage=0;
@@ -856,7 +986,14 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo& property) const {
if (call_mode==CALL_MODE_BASIC_TYPE) {
Variant::CallError ce;
- Variant v = Variant::construct(basic_type,NULL,0,ce);
+ Variant v;
+ if (basic_type==Variant::INPUT_EVENT) {
+ InputEvent ev;
+ ev.type=event_type;
+ v=ev;
+ } else {
+ v = Variant::construct(basic_type,NULL,0,ce);
+ }
v.get_property_list(&pinfo);
} else if (call_mode==CALL_MODE_NODE_PATH) {
@@ -945,6 +1082,8 @@ void VisualScriptPropertySet::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_basic_type","basic_type"),&VisualScriptPropertySet::set_basic_type);
ObjectTypeDB::bind_method(_MD("get_basic_type"),&VisualScriptPropertySet::get_basic_type);
+ ObjectTypeDB::bind_method(_MD("set_event_type","event_type"),&VisualScriptPropertySet::set_event_type);
+ ObjectTypeDB::bind_method(_MD("get_event_type"),&VisualScriptPropertySet::get_event_type);
ObjectTypeDB::bind_method(_MD("set_property","property"),&VisualScriptPropertySet::set_property);
ObjectTypeDB::bind_method(_MD("get_property"),&VisualScriptPropertySet::get_property);
@@ -969,9 +1108,19 @@ void VisualScriptPropertySet::_bind_methods() {
bt+=Variant::get_type_name(Variant::Type(i));
}
+ String et;
+ for(int i=0;i<InputEvent::TYPE_MAX;i++) {
+ if (i>0)
+ et+=",";
+
+ et+=event_type_names[i];
+ }
+
+
ADD_PROPERTY(PropertyInfo(Variant::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type",PROPERTY_USAGE_NOEDITOR),_SCS("set_call_mode"),_SCS("get_call_mode"));
ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
ADD_PROPERTY(PropertyInfo(Variant::INT,"property/basic_type",PROPERTY_HINT_ENUM,bt),_SCS("set_basic_type"),_SCS("get_basic_type"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"property/event_type",PROPERTY_HINT_ENUM,et),_SCS("set_event_type"),_SCS("get_event_type"));
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path"));
ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/property"),_SCS("set_property"),_SCS("get_property"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"value/use_builtin"),_SCS("set_use_builtin_value"),_SCS("is_using_builtin_value"));
@@ -983,9 +1132,120 @@ void VisualScriptPropertySet::_bind_methods() {
}
-VisualScriptNodeInstance* VisualScriptPropertySet::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstancePropertySet : public VisualScriptNodeInstance {
+public:
- return NULL;
+
+ VisualScriptPropertySet::CallMode call_mode;
+ NodePath node_path;
+ StringName property;
+ bool use_builtin;
+ Variant builtin_val;
+
+ VisualScriptPropertySet *node;
+ VisualScriptInstance *instance;
+
+
+
+ //virtual int get_working_memory_size() const { return 0; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+
+ 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) {
+
+
+ switch(call_mode) {
+
+ case VisualScriptPropertySet::CALL_MODE_SELF: {
+
+ Object *object=instance->get_owner_ptr();
+
+ bool valid;
+
+ if (use_builtin) {
+ object->set(property,builtin_val,&valid);
+ } else {
+ object->set(property,*p_inputs[0],&valid);
+ }
+
+ if (!valid) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Invalid index property name.";
+ }
+ } break;
+ case VisualScriptPropertySet::CALL_MODE_NODE_PATH: {
+
+ Node* node = instance->get_owner_ptr()->cast_to<Node>();
+ if (!node) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Base object is not a Node!";
+ return 0;
+ }
+
+ Node* another = node->get_node(node_path);
+ if (!node) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Path does not lead Node!";
+ return 0;
+ }
+
+ bool valid;
+
+ if (use_builtin) {
+ another->set(property,builtin_val,&valid);
+ } else {
+ another->set(property,*p_inputs[0],&valid);
+ }
+
+ if (!valid) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Invalid index property name.";
+ }
+
+ } break;
+ case VisualScriptPropertySet::CALL_MODE_INSTANCE:
+ case VisualScriptPropertySet::CALL_MODE_BASIC_TYPE: {
+
+ Variant v = *p_inputs[0];
+
+ bool valid;
+
+ if (use_builtin) {
+ v.set(property,builtin_val,&valid);
+ } else {
+ v.set(property,p_inputs[1],&valid);
+ }
+
+ if (!valid) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Invalid index property name.";
+ }
+
+ if (call_mode==VisualScriptPropertySet::CALL_MODE_BASIC_TYPE) {
+ *p_outputs[0]=v;
+ }
+
+ } break;
+
+ }
+ return 0;
+
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptPropertySet::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstancePropertySet * instance = memnew(VisualScriptNodeInstancePropertySet );
+ instance->node=this;
+ instance->instance=p_instance;
+ instance->property=property;
+ instance->call_mode=call_mode;
+ instance->node_path=base_path;
+ instance->use_builtin=use_builtin_value;
+ instance->builtin_val=builtin_value;
+ return instance;
}
VisualScriptPropertySet::VisualScriptPropertySet() {
@@ -993,6 +1253,7 @@ VisualScriptPropertySet::VisualScriptPropertySet() {
call_mode=CALL_MODE_INSTANCE;
base_type="Object";
basic_type=Variant::NIL;
+ event_type=InputEvent::NONE;
}
@@ -1012,12 +1273,12 @@ static Ref<VisualScriptNode> create_property_set_node(const String& p_name) {
int VisualScriptPropertyGet::get_output_sequence_port_count() const {
- return 1;
+ return (call_mode==CALL_MODE_SELF || call_mode==CALL_MODE_NODE_PATH)?0:1;
}
bool VisualScriptPropertyGet::has_input_sequence_port() const{
- return true;
+ return (call_mode==CALL_MODE_SELF || call_mode==CALL_MODE_NODE_PATH)?false:true;
}
void VisualScriptPropertyGet::_update_base_type() {
//cache it because this information may not be available on load
@@ -1132,8 +1393,15 @@ PropertyInfo VisualScriptPropertyGet::get_output_value_port_info(int p_idx) cons
if (call_mode==CALL_MODE_BASIC_TYPE) {
- Variant::CallError ce;
- Variant v = Variant::construct(basic_type,NULL,0,ce);
+ Variant v;
+ if (basic_type==Variant::INPUT_EVENT) {
+ InputEvent ev;
+ ev.type=event_type;
+ v=ev;
+ } else {
+ Variant::CallError ce;
+ v = Variant::construct(basic_type,NULL,0,ce);
+ }
v.get_property_list(&pinfo);
} else if (call_mode==CALL_MODE_NODE_PATH) {
@@ -1268,6 +1536,21 @@ Variant::Type VisualScriptPropertyGet::get_basic_type() const{
}
+void VisualScriptPropertyGet::set_event_type(InputEvent::Type p_type) {
+
+ if (event_type==p_type)
+ return;
+ event_type=p_type;
+ _change_notify();
+ _update_base_type();
+ ports_changed_notify();
+}
+
+InputEvent::Type VisualScriptPropertyGet::get_event_type() const{
+
+ return event_type;
+}
+
void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const {
if (property.name=="property/base_type") {
@@ -1282,6 +1565,11 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const {
property.usage=0;
}
}
+ if (property.name=="property/event_type") {
+ if (call_mode!=CALL_MODE_BASIC_TYPE || basic_type!=Variant::INPUT_EVENT) {
+ property.usage=0;
+ }
+ }
if (property.name=="property/node_path") {
if (call_mode!=CALL_MODE_NODE_PATH) {
@@ -1305,7 +1593,14 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const {
if (call_mode==CALL_MODE_BASIC_TYPE) {
Variant::CallError ce;
- Variant v = Variant::construct(basic_type,NULL,0,ce);
+ Variant v;
+ if (basic_type==Variant::INPUT_EVENT) {
+ InputEvent ev;
+ ev.type=event_type;
+ v=ev;
+ } else {
+ v = Variant::construct(basic_type,NULL,0,ce);
+ }
v.get_property_list(&pinfo);
} else if (call_mode==CALL_MODE_NODE_PATH) {
@@ -1355,6 +1650,9 @@ void VisualScriptPropertyGet::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_basic_type","basic_type"),&VisualScriptPropertyGet::set_basic_type);
ObjectTypeDB::bind_method(_MD("get_basic_type"),&VisualScriptPropertyGet::get_basic_type);
+ ObjectTypeDB::bind_method(_MD("set_event_type","event_type"),&VisualScriptPropertyGet::set_event_type);
+ ObjectTypeDB::bind_method(_MD("get_event_type"),&VisualScriptPropertyGet::get_event_type);
+
ObjectTypeDB::bind_method(_MD("set_property","property"),&VisualScriptPropertyGet::set_property);
ObjectTypeDB::bind_method(_MD("get_property"),&VisualScriptPropertyGet::get_property);
@@ -1373,10 +1671,19 @@ void VisualScriptPropertyGet::_bind_methods() {
bt+=Variant::get_type_name(Variant::Type(i));
}
+ String et;
+ for(int i=0;i<InputEvent::TYPE_MAX;i++) {
+ if (i>0)
+ et+=",";
+
+ et+=event_type_names[i];
+ }
+
ADD_PROPERTY(PropertyInfo(Variant::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance",PROPERTY_USAGE_NOEDITOR),_SCS("set_call_mode"),_SCS("get_call_mode"));
ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
ADD_PROPERTY(PropertyInfo(Variant::INT,"property/basic_type",PROPERTY_HINT_ENUM,bt),_SCS("set_basic_type"),_SCS("get_basic_type"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"property/event_type",PROPERTY_HINT_ENUM,et),_SCS("set_event_type"),_SCS("get_event_type"));
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path"));
ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/property"),_SCS("set_property"),_SCS("get_property"));
@@ -1385,9 +1692,107 @@ void VisualScriptPropertyGet::_bind_methods() {
BIND_CONSTANT( CALL_MODE_INSTANCE);
}
-VisualScriptNodeInstance* VisualScriptPropertyGet::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstancePropertyGet : public VisualScriptNodeInstance {
+public:
- return NULL;
+
+ VisualScriptPropertyGet::CallMode call_mode;
+ NodePath node_path;
+ StringName property;
+
+ VisualScriptPropertyGet *node;
+ VisualScriptInstance *instance;
+
+
+
+ //virtual int get_working_memory_size() const { return 0; }
+ virtual bool is_output_port_unsequenced(int p_idx) const { return (call_mode==VisualScriptPropertyGet::CALL_MODE_SELF || call_mode==VisualScriptPropertyGet::CALL_MODE_NODE_PATH); }
+ virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
+
+ //these two modes can be get directly, so they use unsequenced mode
+ switch(call_mode) {
+
+ case VisualScriptPropertyGet::CALL_MODE_SELF: {
+
+ Object *object=instance->get_owner_ptr();
+
+ bool valid;
+
+ *r_value = object->get(property,&valid);
+
+ if (!valid) {
+ //r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error=RTR("Invalid index property name.");
+ return false;
+ }
+ } break;
+ case VisualScriptPropertyGet::CALL_MODE_NODE_PATH: {
+
+ Node* node = instance->get_owner_ptr()->cast_to<Node>();
+ if (!node) {
+ //r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error=RTR("Base object is not a Node!");
+ return false;
+ }
+
+ Node* another = node->get_node(node_path);
+ if (!node) {
+ //r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error=RTR("Path does not lead Node!");
+ return false;
+ }
+
+ bool valid;
+
+
+ *r_value = another->get(property,&valid);
+
+ if (!valid) {
+ //r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error=vformat(RTR("Invalid index property name '%s' in node %s."),String(property),another->get_name());
+ return false;
+ }
+
+ } break;
+ default: {};
+ }
+ return true;
+
+ }
+
+ 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) {
+
+
+ bool valid;
+ Variant v = *p_inputs[0];
+
+ *p_outputs[0] = v.get(property,&valid);
+
+ if (!valid) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str=RTR("Invalid index property name.");
+
+ }
+
+
+ return 0;
+ }
+
+
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptPropertyGet::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstancePropertyGet * instance = memnew(VisualScriptNodeInstancePropertyGet );
+ instance->node=this;
+ instance->instance=p_instance;
+ instance->property=property;
+ instance->call_mode=call_mode;
+ instance->node_path=base_path;
+
+ return instance;
}
VisualScriptPropertyGet::VisualScriptPropertyGet() {
@@ -1395,6 +1800,7 @@ VisualScriptPropertyGet::VisualScriptPropertyGet() {
call_mode=CALL_MODE_INSTANCE;
base_type="Object";
basic_type=Variant::NIL;
+ event_type=InputEvent::NONE;
}
@@ -1463,7 +1869,9 @@ Node *VisualScriptScriptCall::_get_base_node() const {
int VisualScriptScriptCall::get_input_value_port_count() const{
-
+#if 1
+ return argument_count;
+#else
if (call_mode==CALL_MODE_SELF) {
Ref<VisualScript> vs = get_visual_script();
@@ -1501,6 +1909,7 @@ int VisualScriptScriptCall::get_input_value_port_count() const{
return 0;
+#endif
}
int VisualScriptScriptCall::get_output_value_port_count() const{
@@ -1573,6 +1982,48 @@ String VisualScriptScriptCall::get_text() const {
return " "+String(function)+"()";
}
+void VisualScriptScriptCall::_update_argument_count() {
+
+ //try to remember the amount of arguments in the function, because if loaded from scratch
+ //this information will not be available
+
+ if (call_mode==CALL_MODE_SELF) {
+
+ Ref<VisualScript> vs = get_visual_script();
+ if (vs.is_valid()) {
+
+ if (!vs->has_function(function))
+ return ;
+
+ int id = vs->get_function_node_id(function);
+ if (id<0)
+ return;
+
+ Ref<VisualScriptFunction> func = vs->get_node(function,id);
+
+ argument_count=func->get_argument_count();
+ }
+ } else {
+
+ Node*base = _get_base_node();
+ if (!base)
+ return;
+
+ Ref<Script> script = base->get_script();
+ if (!script.is_valid())
+ return ;
+
+ List<MethodInfo> functions;
+ script->get_method_list(&functions);
+ for (List<MethodInfo>::Element *E=functions.front();E;E=E->next()) {
+ if (E->get().name==function) {
+ argument_count=E->get().arguments.size();
+ return;
+ }
+ }
+
+ }
+}
void VisualScriptScriptCall::set_function(const StringName& p_type){
@@ -1581,7 +2032,7 @@ void VisualScriptScriptCall::set_function(const StringName& p_type){
return;
function=p_type;
-
+ _update_argument_count();
_change_notify();
ports_changed_notify();
}
@@ -1597,7 +2048,7 @@ void VisualScriptScriptCall::set_base_path(const NodePath& p_type) {
return;
base_path=p_type;
-
+ _update_argument_count();
_change_notify();
ports_changed_notify();
}
@@ -1614,11 +2065,25 @@ void VisualScriptScriptCall::set_call_mode(CallMode p_mode) {
return;
call_mode=p_mode;
+ _update_argument_count();
+ _change_notify();
+ ports_changed_notify();
+}
+
+void VisualScriptScriptCall::set_argument_count(int p_count) {
+
+ argument_count=p_count;
_change_notify();
ports_changed_notify();
}
+
+int VisualScriptScriptCall::get_argument_count() const {
+
+ return argument_count;
+}
+
VisualScriptScriptCall::CallMode VisualScriptScriptCall::get_call_mode() const {
return call_mode;
@@ -1703,24 +2168,95 @@ void VisualScriptScriptCall::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_base_path","base_path"),&VisualScriptScriptCall::set_base_path);
ObjectTypeDB::bind_method(_MD("get_base_path"),&VisualScriptScriptCall::get_base_path);
+ ObjectTypeDB::bind_method(_MD("set_argument_count","argument_count"),&VisualScriptScriptCall::set_argument_count);
+ ObjectTypeDB::bind_method(_MD("get_argument_count"),&VisualScriptScriptCall::get_argument_count);
ADD_PROPERTY(PropertyInfo(Variant::INT,"function/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path"),_SCS("set_call_mode"),_SCS("get_call_mode"));
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"function/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path"));
ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/function"),_SCS("set_function"),_SCS("get_function"));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/argument_count"),_SCS("set_argument_count"),_SCS("get_argument_count"));
BIND_CONSTANT( CALL_MODE_SELF );
BIND_CONSTANT( CALL_MODE_NODE_PATH);
}
-VisualScriptNodeInstance* VisualScriptScriptCall::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceScriptCall : public VisualScriptNodeInstance {
+public:
- return NULL;
+
+ VisualScriptScriptCall::CallMode call_mode;
+ NodePath node_path;
+ int input_args;
+ bool returns;
+ StringName function;
+
+ VisualScriptScriptCall *node;
+ VisualScriptInstance *instance;
+
+
+
+ //virtual int get_working_memory_size() const { return 0; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+
+ 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) {
+
+
+ switch(call_mode) {
+
+ case VisualScriptScriptCall::CALL_MODE_SELF: {
+
+ Object *object=instance->get_owner_ptr();
+
+ *p_outputs[0] = object->call(function,p_inputs,input_args,r_error);
+
+ } break;
+ case VisualScriptScriptCall::CALL_MODE_NODE_PATH: {
+
+ Node* node = instance->get_owner_ptr()->cast_to<Node>();
+ if (!node) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Base object is not a Node!";
+ return 0;
+ }
+
+ Node* another = node->get_node(node_path);
+ if (!node) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Path does not lead Node!";
+ return 0;
+ }
+
+
+ *p_outputs[0] = another->call(function,p_inputs,input_args,r_error);
+
+ } break;
+
+ }
+ return 0;
+
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptScriptCall::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceScriptCall * instance = memnew(VisualScriptNodeInstanceScriptCall );
+ instance->node=this;
+ instance->instance=p_instance;
+ instance->function=function;
+ instance->call_mode=call_mode;
+ instance->node_path=base_path;
+ instance->input_args = argument_count;
+ return instance;
}
VisualScriptScriptCall::VisualScriptScriptCall() {
call_mode=CALL_MODE_SELF;
+ argument_count=0;
}
@@ -1736,7 +2272,7 @@ static Ref<VisualScriptNode> create_script_call_node(const String& p_name) {
//////////////////////////////////////////
-////////////////SCRIPT CALL//////////////////////
+////////////////EMIT//////////////////////
//////////////////////////////////////////
int VisualScriptEmitSignal::get_output_sequence_port_count() const {
@@ -1865,34 +2401,111 @@ void VisualScriptEmitSignal::_bind_methods() {
}
-VisualScriptNodeInstance* VisualScriptEmitSignal::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceEmitSignal : public VisualScriptNodeInstance {
+public:
- return NULL;
+ VisualScriptEmitSignal *node;
+ VisualScriptInstance *instance;
+ int argcount;
+ StringName name;
+
+ //virtual int get_working_memory_size() const { return 0; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+
+ 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) {
+
+
+ Object *obj = instance->get_owner_ptr();
+
+ obj->emit_signal(name,p_inputs,argcount);
+
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptEmitSignal::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceEmitSignal * instance = memnew(VisualScriptNodeInstanceEmitSignal );
+ instance->node=this;
+ instance->instance=p_instance;
+ instance->name=name;
+ instance->argcount=get_input_value_port_count();
+ return instance;
}
VisualScriptEmitSignal::VisualScriptEmitSignal() {
}
+
+
+static Ref<VisualScriptNode> create_basic_type_call_node(const String& p_name) {
+
+ Vector<String> path = p_name.split("/");
+ ERR_FAIL_COND_V(path.size()<4,Ref<VisualScriptNode>());
+ String base_type = path[2];
+ String method = path[3];
+
+ Ref<VisualScriptFunctionCall> node;
+ node.instance();
+
+ Variant::Type type=Variant::VARIANT_MAX;
+
+ for(int i=0;i<Variant::VARIANT_MAX;i++) {
+
+ if (Variant::get_type_name(Variant::Type(i))==base_type) {
+ type=Variant::Type(i);
+ break;
+ }
+ }
+
+ ERR_FAIL_COND_V(type==Variant::VARIANT_MAX,Ref<VisualScriptNode>());
+
+
+ node->set_call_mode(VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE);
+ node->set_basic_type(type);
+ node->set_function(method);
+
+ return node;
+}
+
+
void register_visual_script_func_nodes() {
- VisualScriptLanguage::singleton->add_register_func("functions/call_method/instance_call",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_INSTANCE>);
- VisualScriptLanguage::singleton->add_register_func("functions/call_method/basic_type_call",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE>);
- VisualScriptLanguage::singleton->add_register_func("functions/call_method/self_call",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_SELF>);
- VisualScriptLanguage::singleton->add_register_func("functions/call_method/node_call",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_NODE_PATH>);
+ VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_instance",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_INSTANCE>);
+ VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_basic_type",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE>);
+ VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_self",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_SELF>);
+ VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_node",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_NODE_PATH>);
- VisualScriptLanguage::singleton->add_register_func("functions/set_property/instace_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_INSTANCE>);
- VisualScriptLanguage::singleton->add_register_func("functions/set_property/basic_type_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_BASIC_TYPE>);
- VisualScriptLanguage::singleton->add_register_func("functions/set_property/self_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_SELF>);
- VisualScriptLanguage::singleton->add_register_func("functions/set_property/node_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_NODE_PATH>);
+ VisualScriptLanguage::singleton->add_register_func("functions/property_set/instace_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_INSTANCE>);
+ VisualScriptLanguage::singleton->add_register_func("functions/property_set/basic_type_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_BASIC_TYPE>);
+ VisualScriptLanguage::singleton->add_register_func("functions/property_set/self_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_SELF>);
+ VisualScriptLanguage::singleton->add_register_func("functions/property_set/node_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_NODE_PATH>);
- VisualScriptLanguage::singleton->add_register_func("functions/get_property/instance_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_INSTANCE>);
- VisualScriptLanguage::singleton->add_register_func("functions/get_property/basic_type_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_BASIC_TYPE>);
- VisualScriptLanguage::singleton->add_register_func("functions/get_property/self_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_SELF>);
- VisualScriptLanguage::singleton->add_register_func("functions/get_property/node_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_NODE_PATH>);
+ VisualScriptLanguage::singleton->add_register_func("functions/property_get/instance_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_INSTANCE>);
+ VisualScriptLanguage::singleton->add_register_func("functions/property_get/basic_type_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_BASIC_TYPE>);
+ VisualScriptLanguage::singleton->add_register_func("functions/property_get/self_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_SELF>);
+ VisualScriptLanguage::singleton->add_register_func("functions/property_get/node_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_NODE_PATH>);
- VisualScriptLanguage::singleton->add_register_func("functions/script/script_call",create_script_call_node<VisualScriptScriptCall::CALL_MODE_SELF>);
- VisualScriptLanguage::singleton->add_register_func("functions/script/script_call_in_node",create_script_call_node<VisualScriptScriptCall::CALL_MODE_NODE_PATH>);
- VisualScriptLanguage::singleton->add_register_func("functions/script/emit_signal",create_node_generic<VisualScriptEmitSignal>);
+ VisualScriptLanguage::singleton->add_register_func("functions/call_script/call_self",create_script_call_node<VisualScriptScriptCall::CALL_MODE_SELF>);
+ VisualScriptLanguage::singleton->add_register_func("functions/call_script/call_node",create_script_call_node<VisualScriptScriptCall::CALL_MODE_NODE_PATH>);
+ VisualScriptLanguage::singleton->add_register_func("functions/call_script/emit_signal",create_node_generic<VisualScriptEmitSignal>);
+ for(int i=0;i<Variant::VARIANT_MAX;i++) {
+
+ Variant::Type t = Variant::Type(i);
+ String type_name = Variant::get_type_name(t);
+ Variant::CallError ce;
+ Variant vt = Variant::construct(t,NULL,0,ce);
+ List<MethodInfo> ml;
+ vt.get_method_list(&ml);
+
+ for (List<MethodInfo>::Element *E=ml.front();E;E=E->next()) {
+ VisualScriptLanguage::singleton->add_register_func("functions/by_type/"+type_name+"/"+E->get().name,create_basic_type_call_node);
+ }
+ }
}
diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h
index 940a133d63..2ccc61242a 100644
--- a/modules/visual_script/visual_script_func_nodes.h
+++ b/modules/visual_script/visual_script_func_nodes.h
@@ -50,6 +50,7 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "functions"; }
void set_basic_type(Variant::Type p_type);
Variant::Type get_basic_type() const;
@@ -69,7 +70,7 @@ public:
void set_use_default_args(int p_amount);
int get_use_default_args() const;
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptFunctionCall();
};
@@ -92,12 +93,13 @@ public:
private:
CallMode call_mode;
- Variant::Type basic_type;
+ Variant::Type basic_type;
StringName base_type;
NodePath base_path;
StringName property;
bool use_builtin_value;
Variant builtin_value;
+ InputEvent::Type event_type;
Node *_get_base_node() const;
StringName _get_base_type() const;
@@ -127,6 +129,7 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "functions"; }
void set_base_type(const StringName& p_type);
StringName get_base_type() const;
@@ -134,6 +137,9 @@ public:
void set_basic_type(Variant::Type p_type);
Variant::Type get_basic_type() const;
+ void set_event_type(InputEvent::Type p_type);
+ InputEvent::Type get_event_type() const;
+
void set_property(const StringName& p_type);
StringName get_property() const;
@@ -149,7 +155,7 @@ public:
void set_builtin_value(const Variant &p_value);
Variant get_builtin_value() const;
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptPropertySet();
};
@@ -175,6 +181,7 @@ private:
StringName base_type;
NodePath base_path;
StringName property;
+ InputEvent::Type event_type;
void _update_base_type();
Node *_get_base_node() const;
@@ -204,6 +211,7 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "functions"; }
void set_base_type(const StringName& p_type);
StringName get_base_type() const;
@@ -211,6 +219,9 @@ public:
void set_basic_type(Variant::Type p_type);
Variant::Type get_basic_type() const;
+ void set_event_type(InputEvent::Type p_type);
+ InputEvent::Type get_event_type() const;
+
void set_property(const StringName& p_type);
StringName get_property() const;
@@ -220,7 +231,7 @@ public:
void set_call_mode(CallMode p_mode);
CallMode get_call_mode() const;
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptPropertyGet();
};
@@ -246,11 +257,13 @@ private:
CallMode call_mode;
NodePath base_path;
StringName function;
+ int argument_count;
Node *_get_base_node() const;
+ void _update_argument_count();
protected:
virtual void _validate_property(PropertyInfo& property) const;
@@ -274,6 +287,7 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "functions"; }
void set_function(const StringName& p_type);
StringName get_function() const;
@@ -284,9 +298,11 @@ public:
void set_call_mode(CallMode p_mode);
CallMode get_call_mode() const;
+ void set_argument_count(int p_count);
+ int get_argument_count() const;
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptScriptCall();
};
@@ -328,11 +344,12 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "functions"; }
void set_signal(const StringName& p_type);
StringName get_signal() const;
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptEmitSignal();
};
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index 1e898675d3..d205a40f76 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -53,7 +53,15 @@ bool VisualScriptFunction::_set(const StringName& p_name, const Variant& p_valu
}
+ if (p_name=="stack/stackless") {
+ set_stack_less(p_value);
+ return true;
+ }
+ if (p_name=="stack/size") {
+ stack_size=p_value;
+ return true;
+ }
return false;
}
@@ -81,6 +89,16 @@ bool VisualScriptFunction::_get(const StringName& p_name,Variant &r_ret) const
}
+ if (p_name=="stack/stackless") {
+ r_ret=stack_less;
+ return true;
+ }
+
+ if (p_name=="stack/size") {
+ r_ret=stack_size;
+ return true;
+ }
+
return false;
}
void VisualScriptFunction::_get_property_list( List<PropertyInfo> *p_list) const {
@@ -96,6 +114,11 @@ void VisualScriptFunction::_get_property_list( List<PropertyInfo> *p_list) cons
p_list->push_back(PropertyInfo(Variant::INT,"argument/"+itos(i+1)+"/type",PROPERTY_HINT_ENUM,argt));
p_list->push_back(PropertyInfo(Variant::STRING,"argument/"+itos(i+1)+"/name"));
}
+ if (!stack_less) {
+ p_list->push_back(PropertyInfo(Variant::INT,"stack/size",PROPERTY_HINT_RANGE,"1,100000"));
+ }
+ p_list->push_back(PropertyInfo(Variant::BOOL,"stack/stackless"));
+
}
@@ -201,15 +224,75 @@ int VisualScriptFunction::get_argument_count() const {
return arguments.size();
}
+class VisualScriptNodeInstanceFunction : public VisualScriptNodeInstance {
+public:
-VisualScriptNodeInstance* VisualScriptFunction::instance(VScriptInstance* p_instance) {
+ VisualScriptFunction *node;
+ VisualScriptInstance *instance;
- return NULL;
+ //virtual int get_working_memory_size() const { return 0; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+
+ 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) {
+
+ int ac = node->get_argument_count();
+
+ for(int i=0;i<ac;i++) {
+#ifdef DEBUG_ENABLED
+ Variant::Type expected = node->get_argument_type(i);
+ if (expected!=Variant::NIL) {
+ if (!Variant::can_convert_strict(p_inputs[i]->get_type(),expected)) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.expected=expected;
+ r_error.argument=i;
+ return 0;
+ }
+ }
+#endif
+
+ *p_outputs[i]=*p_inputs[i];
+ }
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptFunction::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceFunction * instance = memnew(VisualScriptNodeInstanceFunction );
+ instance->node=this;
+ instance->instance=p_instance;
+ return instance;
}
VisualScriptFunction::VisualScriptFunction() {
+ stack_size=256;
+ stack_less=false;
+}
+
+
+void VisualScriptFunction::set_stack_less(bool p_enable) {
+ stack_less=p_enable;
+ _change_notify();
+}
+
+bool VisualScriptFunction::is_stack_less() const {
+ return stack_less;
+}
+
+void VisualScriptFunction::set_stack_size(int p_size) {
+
+ ERR_FAIL_COND(p_size <1 || p_size>100000);
+ stack_size=p_size;
+}
+
+int VisualScriptFunction::get_stack_size() const {
+ return stack_size;
}
@@ -425,9 +508,51 @@ void VisualScriptOperator::_bind_methods() {
}
-VisualScriptNodeInstance* VisualScriptOperator::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceOperator : public VisualScriptNodeInstance {
+public:
- return NULL;
+ bool unary;
+ Variant::Operator op;
+
+ //virtual int get_working_memory_size() const { return 0; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+
+ 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) {
+
+ bool valid;
+ if (unary) {
+
+ Variant::evaluate(op,*p_inputs[0],Variant(),*p_outputs[0],valid);
+ } else {
+ Variant::evaluate(op,*p_inputs[0],*p_inputs[1],*p_outputs[0],valid);
+ }
+
+ if (!valid) {
+
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ if (p_outputs[0]->get_type()==Variant::STRING) {
+ r_error_str=*p_outputs[0];
+ } else {
+ if (unary)
+ r_error_str=String(op_names[op])+RTR(": Invalid argument of type: ")+Variant::get_type_name(p_inputs[0]->get_type());
+ else
+ r_error_str=String(op_names[op])+RTR(": Invalid arguments: ")+"A: "+Variant::get_type_name(p_inputs[0]->get_type())+" B: "+Variant::get_type_name(p_inputs[1]->get_type());
+ }
+ }
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptOperator::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceOperator * instance = memnew(VisualScriptNodeInstanceOperator );
+ instance->unary=get_input_value_port_count()==1;
+ instance->op=op;
+ return instance;
}
VisualScriptOperator::VisualScriptOperator() {
@@ -447,37 +572,42 @@ static Ref<VisualScriptNode> create_op_node(const String& p_name) {
}
//////////////////////////////////////////
-////////////////VARIABLE//////////////////
+////////////////VARIABLE GET//////////////////
//////////////////////////////////////////
-int VisualScriptVariable::get_output_sequence_port_count() const {
+int VisualScriptVariableGet::get_output_sequence_port_count() const {
- return 1;
+ return 0;
}
-bool VisualScriptVariable::has_input_sequence_port() const{
+bool VisualScriptVariableGet::has_input_sequence_port() const{
- return true;
+ return false;
}
-int VisualScriptVariable::get_input_value_port_count() const{
+int VisualScriptVariableGet::get_input_value_port_count() const{
- return 1;
+ return 0;
}
-int VisualScriptVariable::get_output_value_port_count() const{
+int VisualScriptVariableGet::get_output_value_port_count() const{
return 1;
}
-String VisualScriptVariable::get_output_sequence_port_text(int p_port) const {
+String VisualScriptVariableGet::get_output_sequence_port_text(int p_port) const {
return String();
}
-PropertyInfo VisualScriptVariable::get_input_value_port_info(int p_idx) const{
+PropertyInfo VisualScriptVariableGet::get_input_value_port_info(int p_idx) const{
+
+ return PropertyInfo();
+}
+
+PropertyInfo VisualScriptVariableGet::get_output_value_port_info(int p_idx) const{
PropertyInfo pinfo;
- pinfo.name="set";
+ pinfo.name="value";
if (get_visual_script().is_valid() && get_visual_script()->has_variable(variable)) {
PropertyInfo vinfo = get_visual_script()->get_variable_info(variable);
pinfo.type=vinfo.type;
@@ -487,10 +617,134 @@ PropertyInfo VisualScriptVariable::get_input_value_port_info(int p_idx) const{
return pinfo;
}
-PropertyInfo VisualScriptVariable::get_output_value_port_info(int p_idx) const{
+
+String VisualScriptVariableGet::get_caption() const {
+
+ return "Variable";
+}
+
+String VisualScriptVariableGet::get_text() const {
+
+ return variable;
+}
+
+void VisualScriptVariableGet::set_variable(StringName p_variable) {
+
+ if (variable==p_variable)
+ return;
+ variable=p_variable;
+ ports_changed_notify();
+
+}
+
+StringName VisualScriptVariableGet::get_variable() const{
+
+ return variable;
+}
+
+void VisualScriptVariableGet::_validate_property(PropertyInfo& property) const {
+
+ if (property.name=="variable/name" && get_visual_script().is_valid()) {
+ Ref<VisualScript> vs = get_visual_script();
+ List<StringName> vars;
+ vs->get_variable_list(&vars);
+
+ String vhint;
+ for (List<StringName>::Element *E=vars.front();E;E=E->next()) {
+ if (vhint!=String())
+ vhint+=",";
+
+ vhint+=E->get().operator String();
+ }
+
+ property.hint=PROPERTY_HINT_ENUM;
+ property.hint_string=vhint;
+ }
+}
+
+void VisualScriptVariableGet::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_variable","name"),&VisualScriptVariableGet::set_variable);
+ ObjectTypeDB::bind_method(_MD("get_variable"),&VisualScriptVariableGet::get_variable);
+
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"variable/name"),_SCS("set_variable"),_SCS("get_variable"));
+
+}
+
+class VisualScriptNodeInstanceVariableGet : public VisualScriptNodeInstance {
+public:
+
+ VisualScriptVariableGet *node;
+ VisualScriptInstance *instance;
+ StringName variable;
+
+ //virtual int get_working_memory_size() const { return 0; }
+ virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
+ virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
+
+ if (instance->get_variable(variable,r_value)==false) {
+ r_error=RTR("VariableGet not found in script: ")+"'"+String(variable)+"'";
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ 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) {
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptVariableGet::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceVariableGet * instance = memnew(VisualScriptNodeInstanceVariableGet );
+ instance->node=this;
+ instance->instance=p_instance;
+ instance->variable=variable;
+ return instance;
+}
+VisualScriptVariableGet::VisualScriptVariableGet() {
+
+
+}
+
+
+//////////////////////////////////////////
+////////////////VARIABLE GET//////////////////
+//////////////////////////////////////////
+
+int VisualScriptVariableSet::get_output_sequence_port_count() const {
+
+ return 1;
+}
+
+bool VisualScriptVariableSet::has_input_sequence_port() const{
+
+ return true;
+}
+
+int VisualScriptVariableSet::get_input_value_port_count() const{
+
+ return 1;
+}
+int VisualScriptVariableSet::get_output_value_port_count() const{
+
+ return 0;
+}
+
+String VisualScriptVariableSet::get_output_sequence_port_text(int p_port) const {
+
+ return String();
+}
+
+PropertyInfo VisualScriptVariableSet::get_input_value_port_info(int p_idx) const{
PropertyInfo pinfo;
- pinfo.name="get";
+ pinfo.name="set";
if (get_visual_script().is_valid() && get_visual_script()->has_variable(variable)) {
PropertyInfo vinfo = get_visual_script()->get_variable_info(variable);
pinfo.type=vinfo.type;
@@ -500,18 +754,23 @@ PropertyInfo VisualScriptVariable::get_output_value_port_info(int p_idx) const{
return pinfo;
}
+PropertyInfo VisualScriptVariableSet::get_output_value_port_info(int p_idx) const{
-String VisualScriptVariable::get_caption() const {
+ return PropertyInfo();
+}
- return "Variable";
+
+String VisualScriptVariableSet::get_caption() const {
+
+ return "VariableSet";
}
-String VisualScriptVariable::get_text() const {
+String VisualScriptVariableSet::get_text() const {
return variable;
}
-void VisualScriptVariable::set_variable(StringName p_variable) {
+void VisualScriptVariableSet::set_variable(StringName p_variable) {
if (variable==p_variable)
return;
@@ -520,12 +779,12 @@ void VisualScriptVariable::set_variable(StringName p_variable) {
}
-StringName VisualScriptVariable::get_variable() const{
+StringName VisualScriptVariableSet::get_variable() const{
return variable;
}
-void VisualScriptVariable::_validate_property(PropertyInfo& property) const {
+void VisualScriptVariableSet::_validate_property(PropertyInfo& property) const {
if (property.name=="variable/name" && get_visual_script().is_valid()) {
Ref<VisualScript> vs = get_visual_script();
@@ -545,22 +804,50 @@ void VisualScriptVariable::_validate_property(PropertyInfo& property) const {
}
}
-void VisualScriptVariable::_bind_methods() {
+void VisualScriptVariableSet::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("set_variable","name"),&VisualScriptVariable::set_variable);
- ObjectTypeDB::bind_method(_MD("get_variable"),&VisualScriptVariable::get_variable);
+ ObjectTypeDB::bind_method(_MD("set_variable","name"),&VisualScriptVariableSet::set_variable);
+ ObjectTypeDB::bind_method(_MD("get_variable"),&VisualScriptVariableSet::get_variable);
ADD_PROPERTY(PropertyInfo(Variant::STRING,"variable/name"),_SCS("set_variable"),_SCS("get_variable"));
}
-VisualScriptNodeInstance* VisualScriptVariable::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceVariableSet : public VisualScriptNodeInstance {
+public:
- return NULL;
-}
+ VisualScriptVariableSet *node;
+ VisualScriptInstance *instance;
+ StringName variable;
+
+ //virtual int get_working_memory_size() const { return 0; }
+ virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
+
+ 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) {
+
+ if (instance->set_variable(variable,*p_inputs[0])==false) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD ;
+ r_error_str=RTR("VariableSet not found in script: ")+"'"+String(variable)+"'";
+ }
-VisualScriptVariable::VisualScriptVariable() {
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptVariableSet::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceVariableSet * instance = memnew(VisualScriptNodeInstanceVariableSet );
+ instance->node=this;
+ instance->instance=p_instance;
+ instance->variable=variable;
+ return instance;
+}
+VisualScriptVariableSet::VisualScriptVariableSet() {
}
@@ -679,9 +966,33 @@ void VisualScriptConstant::_bind_methods() {
}
-VisualScriptNodeInstance* VisualScriptConstant::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceConstant : public VisualScriptNodeInstance {
+public:
- return NULL;
+ Variant constant;
+ //virtual int get_working_memory_size() const { return 0; }
+ virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
+ virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
+
+ *r_value=constant;
+
+ return true;
+
+ }
+
+ 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) {
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptConstant::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceConstant * instance = memnew(VisualScriptNodeInstanceConstant );
+ instance->constant=value;
+ return instance;
}
VisualScriptConstant::VisualScriptConstant() {
@@ -747,11 +1058,34 @@ String VisualScriptIndexGet::get_text() const {
}
-VisualScriptNodeInstance* VisualScriptIndexGet::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceIndexGet : public VisualScriptNodeInstance {
+public:
- return NULL;
-}
+ //virtual int get_working_memory_size() const { return 0; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
+
+ 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) {
+
+ bool valid;
+ *p_outputs[0] = p_inputs[0]->get(*p_inputs[1],&valid);
+
+ if (!valid) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Invalid get: "+p_inputs[0]->get_construct_string();
+ }
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptIndexGet::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceIndexGet * instance = memnew(VisualScriptNodeInstanceIndexGet );
+ return instance;
+}
VisualScriptIndexGet::VisualScriptIndexGet() {
@@ -816,11 +1150,35 @@ String VisualScriptIndexSet::get_text() const {
}
-VisualScriptNodeInstance* VisualScriptIndexSet::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceIndexSet : public VisualScriptNodeInstance {
+public:
- return NULL;
-}
+ //virtual int get_working_memory_size() const { return 0; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
+
+ 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) {
+
+ bool valid;
+ *p_outputs[0]=*p_inputs[0];
+ p_outputs[0]->set(*p_inputs[1],*p_inputs[2],&valid);
+
+ if (!valid) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Invalid set: "+p_inputs[1]->get_construct_string();
+ }
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptIndexSet::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceIndexSet * instance = memnew(VisualScriptNodeInstanceIndexSet );
+ return instance;
+}
VisualScriptIndexSet::VisualScriptIndexSet() {
@@ -889,10 +1247,33 @@ int VisualScriptGlobalConstant::get_global_constant() {
}
+class VisualScriptNodeInstanceGlobalConstant : public VisualScriptNodeInstance {
+public:
-VisualScriptNodeInstance* VisualScriptGlobalConstant::instance(VScriptInstance* p_instance) {
+ int index;
+ //virtual int get_working_memory_size() const { return 0; }
+ virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
+ virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
- return NULL;
+ *r_value = GlobalConstants::get_global_constant_value(index);
+ return true;
+
+ }
+
+ 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) {
+
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptGlobalConstant::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceGlobalConstant * instance = memnew(VisualScriptNodeInstanceGlobalConstant );
+ instance->index=index;
+ return instance;
}
void VisualScriptGlobalConstant::_bind_methods() {
@@ -931,6 +1312,17 @@ const char* VisualScriptMathConstant::const_name[MATH_CONSTANT_MAX]={
"E",
"Sqrt2",
};
+
+double VisualScriptMathConstant::const_value[MATH_CONSTANT_MAX]={
+ 1.0,
+ Math_PI,
+ Math_PI*2,
+ Math_PI*0.5,
+ 2.71828182845904523536,
+ Math::sqrt(2.0)
+};
+
+
int VisualScriptMathConstant::get_output_sequence_port_count() const {
return 0;
@@ -962,7 +1354,7 @@ PropertyInfo VisualScriptMathConstant::get_input_value_port_info(int p_idx) cons
PropertyInfo VisualScriptMathConstant::get_output_value_port_info(int p_idx) const{
- return PropertyInfo(Variant::INT,"value");
+ return PropertyInfo(Variant::REAL,"value");
}
@@ -987,13 +1379,36 @@ VisualScriptMathConstant::MathConstant VisualScriptMathConstant::get_math_consta
return constant;
}
+class VisualScriptNodeInstanceMathConstant : public VisualScriptNodeInstance {
+public:
+ float value;
+ //virtual int get_working_memory_size() const { return 0; }
+ virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
+ virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
-VisualScriptNodeInstance* VisualScriptMathConstant::instance(VScriptInstance* p_instance) {
+ *r_value = value;
+ return true;
- return NULL;
+ }
+
+ 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) {
+
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptMathConstant::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceMathConstant * instance = memnew(VisualScriptNodeInstanceMathConstant );
+ instance->value=const_value[constant];
+ return instance;
}
+
void VisualScriptMathConstant::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_math_constant","which"),&VisualScriptMathConstant::set_math_constant);
@@ -1080,11 +1495,35 @@ String VisualScriptEngineSingleton::get_singleton() {
-VisualScriptNodeInstance* VisualScriptEngineSingleton::instance(VScriptInstance* p_instance) {
+class VisualScriptNodeInstanceEngineSingleton : public VisualScriptNodeInstance {
+public:
- return NULL;
+ Object* singleton;
+
+ //virtual int get_working_memory_size() const { return 0; }
+ virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
+ virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
+
+ *r_value=singleton;
+ return true;
+ }
+
+ 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) {
+
+
+ return 0;
+ }
+
+};
+
+VisualScriptNodeInstance* VisualScriptEngineSingleton::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceEngineSingleton * instance = memnew(VisualScriptNodeInstanceEngineSingleton );
+ instance->singleton=Globals::get_singleton()->get_singleton_object(singleton);
+ return instance;
}
+
void VisualScriptEngineSingleton::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_singleton","name"),&VisualScriptEngineSingleton::set_singleton);
@@ -1176,12 +1615,53 @@ NodePath VisualScriptSceneNode::get_node_path() {
}
+class VisualScriptNodeInstanceSceneNode : public VisualScriptNodeInstance {
+public:
-VisualScriptNodeInstance* VisualScriptSceneNode::instance(VScriptInstance* p_instance) {
+ VisualScriptSceneNode *node;
+ VisualScriptInstance *instance;
+ NodePath path;
- return NULL;
+ //virtual int get_working_memory_size() const { return 0; }
+ virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
+ virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
+
+ Node* node = instance->get_owner_ptr()->cast_to<Node>();
+ if (!node) {
+ r_error="Base object is not a Node!";
+ return false;
+ }
+
+
+
+ Node* another = node->get_node(path);
+ if (!node) {
+ r_error="Path does not lead Node!";
+ return false;
+ }
+
+ *r_value=another;
+ return true;
+ }
+
+ 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) {
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptSceneNode::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceSceneNode * instance = memnew(VisualScriptNodeInstanceSceneNode );
+ instance->node=this;
+ instance->instance=p_instance;
+ instance->path=path;
+ return instance;
}
+
#ifdef TOOLS_ENABLED
static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) {
@@ -1302,12 +1782,51 @@ String VisualScriptSceneTree::get_text() const {
}
+class VisualScriptNodeInstanceSceneTree : public VisualScriptNodeInstance {
+public:
-VisualScriptNodeInstance* VisualScriptSceneTree::instance(VScriptInstance* p_instance) {
+ VisualScriptSceneTree *node;
+ VisualScriptInstance *instance;
- return NULL;
+ //virtual int get_working_memory_size() const { return 0; }
+ virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
+ virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
+
+ Node* node = instance->get_owner_ptr()->cast_to<Node>();
+ if (!node) {
+ r_error="Base object is not a Node!";
+ return false;
+ }
+
+ SceneTree* tree = node->get_tree();
+ if (!tree) {
+ r_error="Attempt to get SceneTree while node is not in the active tree.";
+ return false;
+ }
+
+ *r_value=tree;
+ return true;
+
+ }
+
+ 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) {
+
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptSceneTree::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceSceneTree * instance = memnew(VisualScriptNodeInstanceSceneTree );
+ instance->node=this;
+ instance->instance=p_instance;
+ return instance;
}
+
void VisualScriptSceneTree::_validate_property(PropertyInfo& property) const {
}
@@ -1382,10 +1901,31 @@ String VisualScriptResourcePath::get_resource_path() {
}
+class VisualScriptNodeInstanceResourcePath : public VisualScriptNodeInstance {
+public:
-VisualScriptNodeInstance* VisualScriptResourcePath::instance(VScriptInstance* p_instance) {
+ String path;
- return NULL;
+ //virtual int get_working_memory_size() const { return 0; }
+ virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
+ virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
+ *r_value = path;
+ return true;
+ }
+
+ 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) {
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptResourcePath::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceResourcePath * instance = memnew(VisualScriptNodeInstanceResourcePath );
+ instance->path=path;
+ return instance;
}
@@ -1404,9 +1944,499 @@ VisualScriptResourcePath::VisualScriptResourcePath() {
}
+
+//////////////////////////////////////////
+////////////////SELF///////////
+//////////////////////////////////////////
+
+int VisualScriptSelf::get_output_sequence_port_count() const {
+
+ return 0;
+}
+
+bool VisualScriptSelf::has_input_sequence_port() const{
+
+ return false;
+}
+
+int VisualScriptSelf::get_input_value_port_count() const{
+
+ return 0;
+}
+int VisualScriptSelf::get_output_value_port_count() const{
+
+ return 1;
+}
+
+String VisualScriptSelf::get_output_sequence_port_text(int p_port) const {
+
+ return String();
+}
+
+PropertyInfo VisualScriptSelf::get_input_value_port_info(int p_idx) const{
+
+ return PropertyInfo();
+}
+
+PropertyInfo VisualScriptSelf::get_output_value_port_info(int p_idx) const{
+
+ return PropertyInfo(Variant::OBJECT,"instance");
+}
+
+
+String VisualScriptSelf::get_caption() const {
+
+ return "Self";
+}
+
+String VisualScriptSelf::get_text() const {
+
+ if (get_visual_script().is_valid())
+ return get_visual_script()->get_instance_base_type();
+ else
+ return "";
+}
+
+
+class VisualScriptNodeInstanceSelf : public VisualScriptNodeInstance {
+public:
+
+ VisualScriptInstance* instance;
+
+ //virtual int get_working_memory_size() const { return 0; }
+ virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
+ virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
+
+ *r_value = instance->get_owner_ptr();
+ return true;
+ }
+
+ 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) {
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptSelf::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceSelf * instance = memnew(VisualScriptNodeInstanceSelf );
+ instance->instance=p_instance;
+ return instance;
+}
+
+
+
+void VisualScriptSelf::_bind_methods() {
+
+}
+
+VisualScriptSelf::VisualScriptSelf() {
+
+
+}
+
+//////////////////////////////////////////
+////////////////CUSTOM (SCRIPTED)///////////
+//////////////////////////////////////////
+
+int VisualScriptCustomNode::get_output_sequence_port_count() const {
+
+ if (get_script_instance() && get_script_instance()->has_method("_get_output_sequence_port_count")) {
+ return get_script_instance()->call("_get_output_sequence_port_count");
+ }
+ return 0;
+}
+
+bool VisualScriptCustomNode::has_input_sequence_port() const{
+
+ if (get_script_instance() && get_script_instance()->has_method("_has_input_sequence_port")) {
+ return get_script_instance()->call("_has_input_sequence_port");
+ }
+ return false;
+}
+
+int VisualScriptCustomNode::get_input_value_port_count() const{
+
+ if (get_script_instance() && get_script_instance()->has_method("_get_input_value_port_count")) {
+ return get_script_instance()->call("_get_input_value_port_count");
+ }
+ return 0;
+}
+int VisualScriptCustomNode::get_output_value_port_count() const{
+
+ if (get_script_instance() && get_script_instance()->has_method("_get_output_value_port_count")) {
+ return get_script_instance()->call("_get_output_value_port_count");
+ }
+ return 0;
+}
+
+String VisualScriptCustomNode::get_output_sequence_port_text(int p_port) const {
+
+ if (get_script_instance() && get_script_instance()->has_method("_get_output_sequence_port_text")) {
+ return get_script_instance()->call("_get_output_sequence_port_text",p_port);
+ }
+
+ return String();
+}
+
+PropertyInfo VisualScriptCustomNode::get_input_value_port_info(int p_idx) const{
+
+ PropertyInfo info;
+ if (get_script_instance() && get_script_instance()->has_method("_get_input_value_port_type")) {
+ info.type=Variant::Type(int(get_script_instance()->call("_get_input_value_port_type",p_idx)));
+ }
+ if (get_script_instance() && get_script_instance()->has_method("_get_input_value_port_name")) {
+ info.name=get_script_instance()->call("_get_input_value_port_name",p_idx);
+ }
+ return info;
+}
+
+PropertyInfo VisualScriptCustomNode::get_output_value_port_info(int p_idx) const{
+
+ PropertyInfo info;
+ if (get_script_instance() && get_script_instance()->has_method("_get_output_value_port_type")) {
+ info.type=Variant::Type(int(get_script_instance()->call("_get_output_value_port_type",p_idx)));
+ }
+ if (get_script_instance() && get_script_instance()->has_method("_get_output_value_port_name")) {
+ info.name=get_script_instance()->call("_get_output_value_port_name",p_idx);
+ }
+ return info;
+}
+
+
+String VisualScriptCustomNode::get_caption() const {
+
+ if (get_script_instance() && get_script_instance()->has_method("_get_caption")) {
+ return get_script_instance()->call("_get_caption");
+ }
+ return "CustomNode";
+}
+
+String VisualScriptCustomNode::get_text() const {
+
+ if (get_script_instance() && get_script_instance()->has_method("_get_text")) {
+ return get_script_instance()->call("_get_text");
+ }
+ return "";
+}
+
+String VisualScriptCustomNode::get_category() const {
+
+ if (get_script_instance() && get_script_instance()->has_method("_get_category")) {
+ return get_script_instance()->call("_get_category");
+ }
+ return "custom";
+}
+
+class VisualScriptNodeInstanceCustomNode : public VisualScriptNodeInstance {
+public:
+
+ VisualScriptInstance* instance;
+ VisualScriptCustomNode *node;
+ int in_count;
+ int out_count;
+ int work_mem_size;
+ Vector<bool> out_unsequenced;
+
+ virtual int get_working_memory_size() const { return work_mem_size; }
+ virtual bool is_output_port_unsequenced(int p_idx) const { return out_unsequenced[p_idx]; }
+ virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
+
+ if (!node->get_script_instance() || !node->get_script_instance()->has_method(VisualScriptLanguage::singleton->_get_output_port_unsequenced)) {
+#ifdef DEBUG_ENABLED
+ r_error=RTR("Custom node has no _get_output_port_unsequenced(idx,wmem), but unsequenced ports were specified.");
+ return false;
+ }
+#endif
+
+ Array work_mem(true);
+ work_mem.resize(work_mem_size);
+
+ *r_value = node->get_script_instance()->call(VisualScriptLanguage::singleton->_get_output_port_unsequenced,p_idx,work_mem);
+
+
+ for(int i=0;i<work_mem_size;i++) {
+ if (i<work_mem.size()) {
+ p_working_mem[i]=work_mem[i];
+ }
+ }
+
+ return true;
+
+ }
+
+ 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) {
+
+ if (node->get_script_instance()) {
+#ifdef DEBUG_ENABLED
+ if (!node->get_script_instance()->has_method(VisualScriptLanguage::singleton->_step)) {
+ r_error_str=RTR("Custom node has no _step() method, can't process graph.");
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ return 0;
+ }
+#endif
+ Array in_values(true);
+ Array out_values(true);
+ Array work_mem(true);
+
+ in_values.resize(in_count);
+
+ for(int i=0;i<in_count;i++) {
+ in_values[i]=p_inputs[i];
+ }
+
+ out_values.resize(in_count);
+
+ work_mem.resize(work_mem_size);
+
+ for(int i=0;i<work_mem_size;i++) {
+ work_mem[i]=p_working_mem[i];
+ }
+
+ int ret_out;
+
+ Variant ret = node->get_script_instance()->call(VisualScriptLanguage::singleton->_step,in_values,out_values,p_start_mode,work_mem);
+ if (ret.get_type()==Variant::STRING) {
+ r_error_str=ret;
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ return 0;
+ } else if (ret.is_num()) {
+ ret_out=ret;
+ } else {
+ r_error_str=RTR("Invalid return value from _step(), must be integer (seq out), or string (error).");
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ return 0;
+ }
+
+ for(int i=0;i<out_count;i++) {
+ if (i<out_values.size()) {
+ *p_outputs[i]=out_values[i];
+ }
+ }
+
+ for(int i=0;i<work_mem_size;i++) {
+ if (i<work_mem.size()) {
+ p_working_mem[i]=work_mem[i];
+ }
+ }
+
+ return ret_out;
+
+ }
+
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptCustomNode::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceCustomNode * instance = memnew(VisualScriptNodeInstanceCustomNode );
+ instance->instance=p_instance;
+ instance->in_count=get_input_value_port_count();
+ instance->out_count=get_output_value_port_count();
+
+ for(int i=0;i<instance->out_count;i++) {
+ bool unseq = get_script_instance() && get_script_instance()->has_method("_is_output_port_unsequenced") && bool(get_script_instance()->call("_is_output_port_unsequenced",i));
+ instance->out_unsequenced.push_back(unseq);
+ }
+
+ if (get_script_instance() && get_script_instance()->has_method("_get_working_memory_size")) {
+ instance->work_mem_size = get_script_instance()->call("_get_working_memory_size");
+ } else {
+ instance->work_mem_size=0;
+ }
+
+ return instance;
+}
+
+
+
+void VisualScriptCustomNode::_bind_methods() {
+
+ BIND_VMETHOD( MethodInfo(Variant::INT,"_get_output_sequence_port_count") );
+ BIND_VMETHOD( MethodInfo(Variant::BOOL,"_has_input_sequence_port") );
+
+ BIND_VMETHOD( MethodInfo(Variant::STRING,"_get_output_sequence_port_text",PropertyInfo(Variant::INT,"idx")) );
+ BIND_VMETHOD( MethodInfo(Variant::INT,"_get_input_value_port_count") );
+ BIND_VMETHOD( MethodInfo(Variant::INT,"_get_output_value_port_count") );
+
+ BIND_VMETHOD( MethodInfo(Variant::INT,"_get_input_value_port_type",PropertyInfo(Variant::INT,"idx")) );
+ BIND_VMETHOD( MethodInfo(Variant::STRING,"_get_input_value_port_name",PropertyInfo(Variant::INT,"idx")) );
+
+ BIND_VMETHOD( MethodInfo(Variant::INT,"_get_output_value_port_type",PropertyInfo(Variant::INT,"idx")) );
+ BIND_VMETHOD( MethodInfo(Variant::STRING,"_get_output_value_port_name",PropertyInfo(Variant::INT,"idx")) );
+
+ BIND_VMETHOD( MethodInfo(Variant::STRING,"_get_caption") );
+ BIND_VMETHOD( MethodInfo(Variant::STRING,"_get_text") );
+ BIND_VMETHOD( MethodInfo(Variant::STRING,"_get_category") );
+
+ BIND_VMETHOD( MethodInfo(Variant::INT,"_get_working_memory_size") );
+ BIND_VMETHOD( MethodInfo(Variant::INT,"_is_output_port_unsequenced",PropertyInfo(Variant::INT,"idx")) );
+ BIND_VMETHOD( MethodInfo(Variant::INT,"_get_output_port_unsequenced",PropertyInfo(Variant::INT,"idx"),PropertyInfo(Variant::ARRAY,"work_mem")) );
+ BIND_VMETHOD( MethodInfo(Variant::NIL,"_step:Variant",PropertyInfo(Variant::ARRAY,"inputs"),PropertyInfo(Variant::ARRAY,"outputs"),PropertyInfo(Variant::INT,"start_mode"),PropertyInfo(Variant::ARRAY,"working_mem")) );
+
+ BIND_CONSTANT( START_MODE_BEGIN_SEQUENCE );
+ BIND_CONSTANT( START_MODE_CONTINUE_SEQUENCE );
+ BIND_CONSTANT( START_MODE_RESUME_YIELD );
+
+ BIND_CONSTANT( STEP_PUSH_STACK_BIT );
+ BIND_CONSTANT( STEP_GO_BACK_BIT );
+ BIND_CONSTANT( STEP_NO_ADVANCE_BIT );
+ BIND_CONSTANT( STEP_EXIT_FUNCTION_BIT );
+ BIND_CONSTANT( STEP_YIELD_BIT );
+
+}
+
+VisualScriptCustomNode::VisualScriptCustomNode() {
+
+
+}
+
+//////////////////////////////////////////
+////////////////SUBCALL///////////
+//////////////////////////////////////////
+
+int VisualScriptSubCall::get_output_sequence_port_count() const {
+
+ return 1;
+}
+
+bool VisualScriptSubCall::has_input_sequence_port() const{
+
+ return true;
+}
+
+int VisualScriptSubCall::get_input_value_port_count() const{
+
+ Ref<Script> script = get_script();
+
+ if (script.is_valid() && script->has_method(VisualScriptLanguage::singleton->_subcall)) {
+
+ MethodInfo mi = script->get_method_info(VisualScriptLanguage::singleton->_subcall);
+ return mi.arguments.size();
+ }
+
+ return 0;
+}
+int VisualScriptSubCall::get_output_value_port_count() const{
+
+ return 1;
+}
+
+String VisualScriptSubCall::get_output_sequence_port_text(int p_port) const {
+
+ return String();
+}
+
+PropertyInfo VisualScriptSubCall::get_input_value_port_info(int p_idx) const{
+
+ Ref<Script> script = get_script();
+ if (script.is_valid() && script->has_method(VisualScriptLanguage::singleton->_subcall)) {
+
+ MethodInfo mi = script->get_method_info(VisualScriptLanguage::singleton->_subcall);
+ return mi.arguments[p_idx];
+ }
+
+ return PropertyInfo();
+}
+
+PropertyInfo VisualScriptSubCall::get_output_value_port_info(int p_idx) const{
+
+ Ref<Script> script = get_script();
+ if (script.is_valid() && script->has_method(VisualScriptLanguage::singleton->_subcall)) {
+ MethodInfo mi = script->get_method_info(VisualScriptLanguage::singleton->_subcall);
+ return mi.return_val;
+ }
+ return PropertyInfo();
+}
+
+
+String VisualScriptSubCall::get_caption() const {
+
+ return "SubCall";
+}
+
+
+String VisualScriptSubCall::get_text() const {
+
+ Ref<Script> script = get_script();
+ if (script.is_valid()) {
+ if (script->get_name()!=String())
+ return script->get_name();
+ if (script->get_path().is_resource_file())
+ return script->get_path().get_file();
+ return script->get_type();
+ }
+ return "";
+}
+
+String VisualScriptSubCall::get_category() const {
+
+ return "custom";
+}
+
+class VisualScriptNodeInstanceSubCall : public VisualScriptNodeInstance {
+public:
+
+ VisualScriptInstance* instance;
+ VisualScriptSubCall *subcall;
+ int input_args;
+ bool valid;
+
+ //virtual int get_working_memory_size() const { return 0; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; };
+
+ 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) {
+
+ if (!valid) {
+ r_error_str="Node requires a script with a _subcall(<args>) method to work.";
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ return 0;
+ }
+ *p_outputs[0]=subcall->call(VisualScriptLanguage::singleton->_subcall,p_inputs,input_args,r_error_str);
+ return 0;
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptSubCall::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceSubCall * instance = memnew(VisualScriptNodeInstanceSubCall );
+ instance->instance=p_instance;
+ Ref<Script> script = get_script();
+ if (script.is_valid() && script->has_method(VisualScriptLanguage::singleton->_subcall)) {
+ instance->valid=true;
+ instance->input_args=get_input_value_port_count();
+ } else {
+ instance->valid=false;
+ }
+ return instance;
+}
+
+
+
+void VisualScriptSubCall::_bind_methods() {
+
+ BIND_VMETHOD( MethodInfo(Variant::NIL,"_subcall",PropertyInfo(Variant::NIL,"arguments:Variant")) );
+
+}
+
+VisualScriptSubCall::VisualScriptSubCall() {
+
+
+}
+
+
void register_visual_script_nodes() {
- VisualScriptLanguage::singleton->add_register_func("data/variable",create_node_generic<VisualScriptVariable>);
+ VisualScriptLanguage::singleton->add_register_func("data/set_variable",create_node_generic<VisualScriptVariableGet>);
+ VisualScriptLanguage::singleton->add_register_func("data/get_variable",create_node_generic<VisualScriptVariableSet>);
VisualScriptLanguage::singleton->add_register_func("data/constant",create_node_generic<VisualScriptConstant>);
VisualScriptLanguage::singleton->add_register_func("data/global_constant",create_node_generic<VisualScriptGlobalConstant>);
VisualScriptLanguage::singleton->add_register_func("data/math_constant",create_node_generic<VisualScriptMathConstant>);
@@ -1414,6 +2444,9 @@ void register_visual_script_nodes() {
VisualScriptLanguage::singleton->add_register_func("data/scene_node",create_node_generic<VisualScriptSceneNode>);
VisualScriptLanguage::singleton->add_register_func("data/scene_tree",create_node_generic<VisualScriptSceneTree>);
VisualScriptLanguage::singleton->add_register_func("data/resource_path",create_node_generic<VisualScriptResourcePath>);
+ VisualScriptLanguage::singleton->add_register_func("data/self",create_node_generic<VisualScriptSelf>);
+ VisualScriptLanguage::singleton->add_register_func("custom/custom_node",create_node_generic<VisualScriptCustomNode>);
+ VisualScriptLanguage::singleton->add_register_func("custom/sub_call",create_node_generic<VisualScriptSubCall>);
VisualScriptLanguage::singleton->add_register_func("index/get_index",create_node_generic<VisualScriptIndexGet>);
@@ -1448,4 +2481,5 @@ void register_visual_script_nodes() {
VisualScriptLanguage::singleton->add_register_func("operators/logic/not",create_op_node<Variant::OP_NOT>);
VisualScriptLanguage::singleton->add_register_func("operators/logic/in",create_op_node<Variant::OP_IN>);
+
}
diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h
index 6080050d78..50f61ecfcc 100644
--- a/modules/visual_script/visual_script_nodes.h
+++ b/modules/visual_script/visual_script_nodes.h
@@ -14,6 +14,11 @@ class VisualScriptFunction : public VisualScriptNode {
};
Vector<Argument> arguments;
+
+ bool stack_less;
+ int stack_size;
+
+
protected:
bool _set(const StringName& p_name, const Variant& p_value);
@@ -38,6 +43,7 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "flow_control"; }
void add_argument(Variant::Type p_type,const String& p_name,int p_index=-1);
void set_argument_type(int p_argidx,Variant::Type p_type);
@@ -47,7 +53,14 @@ public:
void remove_argument(int p_argidx);
int get_argument_count() const;
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+
+ void set_stack_less(bool p_enable);
+ bool is_stack_less() const;
+
+ void set_stack_size(int p_size);
+ int get_stack_size() const;
+
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptFunction();
};
@@ -80,19 +93,20 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "operators"; }
void set_operator(Variant::Operator p_op);
Variant::Operator get_operator() const;
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptOperator();
};
-class VisualScriptVariable : public VisualScriptNode {
+class VisualScriptVariableGet : public VisualScriptNode {
- OBJ_TYPE(VisualScriptVariable,VisualScriptNode)
+ OBJ_TYPE(VisualScriptVariableGet,VisualScriptNode)
StringName variable;
@@ -118,15 +132,56 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "data"; }
void set_variable(StringName p_var);
StringName get_variable() const;
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
- VisualScriptVariable();
+ VisualScriptVariableGet();
};
+
+class VisualScriptVariableSet : public VisualScriptNode {
+
+ OBJ_TYPE(VisualScriptVariableSet,VisualScriptNode)
+
+
+ StringName variable;
+protected:
+
+ virtual void _validate_property(PropertyInfo& property) const;
+ static void _bind_methods();
+public:
+
+ virtual int get_output_sequence_port_count() const;
+ virtual bool has_input_sequence_port() const;
+
+
+ virtual String get_output_sequence_port_text(int p_port) const;
+
+
+ virtual int get_input_value_port_count() const;
+ virtual int get_output_value_port_count() const;
+
+
+ virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+ virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+ virtual String get_caption() const;
+ virtual String get_text() const;
+ virtual String get_category() const { return "data"; }
+
+ void set_variable(StringName p_var);
+ StringName get_variable() const;
+
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
+
+ VisualScriptVariableSet();
+};
+
+
class VisualScriptConstant : public VisualScriptNode {
OBJ_TYPE(VisualScriptConstant,VisualScriptNode)
@@ -156,6 +211,7 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "data"; }
void set_constant_type(Variant::Type p_type);
Variant::Type get_constant_type() const;
@@ -163,7 +219,7 @@ public:
void set_constant_value(Variant p_value);
Variant get_constant_value() const;
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptConstant();
};
@@ -192,8 +248,9 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "operators"; }
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptIndexGet();
};
@@ -222,8 +279,9 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "operators"; }
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptIndexSet();
};
@@ -255,11 +313,12 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "data"; }
void set_global_constant(int p_which);
int get_global_constant();
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptGlobalConstant();
};
@@ -283,6 +342,7 @@ public:
private:
static const char* const_name[MATH_CONSTANT_MAX];
+ static double const_value[MATH_CONSTANT_MAX];
MathConstant constant;
protected:
static void _bind_methods();
@@ -304,11 +364,12 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "data"; }
void set_math_constant(MathConstant p_which);
MathConstant get_math_constant();
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptMathConstant();
};
@@ -340,11 +401,12 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "data"; }
void set_singleton(const String &p_string);
String get_singleton();
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptEngineSingleton();
};
@@ -378,11 +440,12 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "data"; }
void set_node_path(const NodePath &p_path);
NodePath get_node_path();
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptSceneNode();
};
@@ -416,8 +479,9 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "data"; }
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptSceneTree();
};
@@ -450,16 +514,138 @@ public:
virtual String get_caption() const;
virtual String get_text() const;
+ virtual String get_category() const { return "data"; }
void set_resource_path(const String &p_path);
String get_resource_path();
- virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance);
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
VisualScriptResourcePath();
};
+class VisualScriptSelf : public VisualScriptNode {
+
+ OBJ_TYPE(VisualScriptSelf,VisualScriptNode)
+
+
+protected:
+
+ static void _bind_methods();
+public:
+
+ virtual int get_output_sequence_port_count() const;
+ virtual bool has_input_sequence_port() const;
+
+
+ virtual String get_output_sequence_port_text(int p_port) const;
+
+
+ virtual int get_input_value_port_count() const;
+ virtual int get_output_value_port_count() const;
+
+
+ virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+ virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+ virtual String get_caption() const;
+ virtual String get_text() const;
+ virtual String get_category() const { return "data"; }
+
+
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
+
+ VisualScriptSelf();
+};
+
+
+class VisualScriptCustomNode: public VisualScriptNode {
+
+ OBJ_TYPE(VisualScriptCustomNode,VisualScriptNode)
+
+
+protected:
+
+ virtual bool _use_builtin_script() const { return true; }
+
+ static void _bind_methods();
+public:
+
+ enum StartMode { //replicated for step
+ START_MODE_BEGIN_SEQUENCE,
+ START_MODE_CONTINUE_SEQUENCE,
+ START_MODE_RESUME_YIELD
+ };
+
+ enum { //replicated for step
+ STEP_SHIFT=1<<24,
+ STEP_MASK=STEP_SHIFT-1,
+ STEP_PUSH_STACK_BIT=STEP_SHIFT, //push bit to stack
+ STEP_GO_BACK_BIT=STEP_SHIFT<<1, //go back to previous node
+ STEP_NO_ADVANCE_BIT=STEP_SHIFT<<2, //do not advance past this node
+ STEP_EXIT_FUNCTION_BIT=STEP_SHIFT<<3, //return from function
+ STEP_YIELD_BIT=STEP_SHIFT<<4, //yield (will find VisualScriptFunctionState state in first working memory)
+ };
+
+ virtual int get_output_sequence_port_count() const;
+ virtual bool has_input_sequence_port() const;
+
+
+ virtual String get_output_sequence_port_text(int p_port) const;
+
+
+ virtual int get_input_value_port_count() const;
+ virtual int get_output_value_port_count() const;
+
+
+ virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+ virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+ virtual String get_caption() const;
+ virtual String get_text() const;
+ virtual String get_category() const;
+
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
+
+ VisualScriptCustomNode();
+};
+
+class VisualScriptSubCall: public VisualScriptNode {
+
+ OBJ_TYPE(VisualScriptSubCall,VisualScriptNode)
+
+
+protected:
+
+ virtual bool _use_builtin_script() const { return true; }
+
+ static void _bind_methods();
+public:
+ virtual int get_output_sequence_port_count() const;
+ virtual bool has_input_sequence_port() const;
+
+
+ virtual String get_output_sequence_port_text(int p_port) const;
+
+
+ virtual int get_input_value_port_count() const;
+ virtual int get_output_value_port_count() const;
+
+
+ virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+ virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+ virtual String get_caption() const;
+ virtual String get_text() const;
+ virtual String get_category() const;
+
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
+
+ VisualScriptSubCall();
+};
+
+
void register_visual_script_nodes();
#endif // VISUAL_SCRIPT_NODES_H
diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp
new file mode 100644
index 0000000000..a6f84a97d9
--- /dev/null
+++ b/modules/visual_script/visual_script_yield_nodes.cpp
@@ -0,0 +1,622 @@
+#include "visual_script_yield_nodes.h"
+#include "scene/main/scene_main_loop.h"
+#include "os/os.h"
+#include "scene/main/node.h"
+#include "visual_script_nodes.h"
+
+//////////////////////////////////////////
+////////////////YIELD///////////
+//////////////////////////////////////////
+
+int VisualScriptYield::get_output_sequence_port_count() const {
+
+ return 1;
+}
+
+bool VisualScriptYield::has_input_sequence_port() const{
+
+ return true;
+}
+
+int VisualScriptYield::get_input_value_port_count() const{
+
+ return 0;
+}
+int VisualScriptYield::get_output_value_port_count() const{
+
+ return 0;
+}
+
+String VisualScriptYield::get_output_sequence_port_text(int p_port) const {
+
+ return String();
+}
+
+PropertyInfo VisualScriptYield::get_input_value_port_info(int p_idx) const{
+
+ return PropertyInfo();
+}
+
+PropertyInfo VisualScriptYield::get_output_value_port_info(int p_idx) const{
+
+ return PropertyInfo();
+}
+
+
+String VisualScriptYield::get_caption() const {
+
+ return "Wait";
+}
+
+String VisualScriptYield::get_text() const {
+
+ switch (yield_mode) {
+ case YIELD_FRAME: return "Next Frame"; break;
+ case YIELD_FIXED_FRAME: return "Next Fixed Frame"; break;
+ case YIELD_WAIT: return rtos(wait_time)+" sec(s)"; break;
+ }
+
+ return String();
+}
+
+
+class VisualScriptNodeInstanceYield : public VisualScriptNodeInstance {
+public:
+
+ VisualScriptYield::YieldMode mode;
+ float wait_time;
+
+ virtual int get_working_memory_size() const { return 1; } //yield needs at least 1
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
+
+ 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) {
+
+ if (p_start_mode==START_MODE_RESUME_YIELD) {
+ return 0; //resuming yield
+ } else {
+ //yield
+
+
+ SceneTree *tree = OS::get_singleton()->get_main_loop()->cast_to<SceneTree>();
+ if (!tree) {
+ r_error_str="Main Loop is not SceneTree";
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ return 0;
+ }
+
+ Ref<VisualScriptFunctionState> state;
+ state.instance();
+
+ switch(mode) {
+
+ case VisualScriptYield::YIELD_FRAME: state->connect_to_signal(tree,"idle_frame",Array()); break;
+ case VisualScriptYield::YIELD_FIXED_FRAME: state->connect_to_signal(tree,"fixed_frame",Array()); break;
+ case VisualScriptYield::YIELD_WAIT: state->connect_to_signal(tree->create_timer(wait_time).ptr(),"timeout",Array()); break;
+
+ }
+
+ *p_working_mem=state;
+
+ return STEP_YIELD_BIT;
+ }
+ }
+
+};
+
+VisualScriptNodeInstance* VisualScriptYield::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceYield * instance = memnew(VisualScriptNodeInstanceYield );
+ //instance->instance=p_instance;
+ instance->mode=yield_mode;
+ instance->wait_time=wait_time;
+ return instance;
+}
+
+void VisualScriptYield::set_yield_mode(YieldMode p_mode) {
+
+ if (yield_mode==p_mode)
+ return;
+ yield_mode=p_mode;
+ ports_changed_notify();
+ _change_notify();
+}
+
+VisualScriptYield::YieldMode VisualScriptYield::get_yield_mode(){
+
+ return yield_mode;
+}
+
+void VisualScriptYield::set_wait_time(float p_time) {
+
+ if (wait_time==p_time)
+ return;
+ wait_time=p_time;
+ ports_changed_notify();
+
+}
+
+float VisualScriptYield::get_wait_time(){
+
+ return wait_time;
+}
+
+
+void VisualScriptYield::_validate_property(PropertyInfo& property) const {
+
+
+ if (property.name=="wait_time") {
+ if (yield_mode!=YIELD_WAIT) {
+ property.usage=0;
+ }
+ }
+}
+
+void VisualScriptYield::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_yield_mode","mode"),&VisualScriptYield::set_yield_mode);
+ ObjectTypeDB::bind_method(_MD("get_yield_mode"),&VisualScriptYield::get_yield_mode);
+
+ ObjectTypeDB::bind_method(_MD("set_wait_time","sec"),&VisualScriptYield::set_wait_time);
+ ObjectTypeDB::bind_method(_MD("get_wait_time"),&VisualScriptYield::get_wait_time);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Frame,FixedFrame,Time",PROPERTY_USAGE_NOEDITOR),_SCS("set_yield_mode"),_SCS("get_yield_mode"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"wait_time"),_SCS("set_wait_time"),_SCS("get_wait_time"));
+
+
+ BIND_CONSTANT( YIELD_FRAME );
+ BIND_CONSTANT( YIELD_FIXED_FRAME );
+ BIND_CONSTANT( YIELD_WAIT );
+
+}
+
+VisualScriptYield::VisualScriptYield() {
+
+ yield_mode=YIELD_FRAME;
+ wait_time=1;
+
+}
+
+
+template<VisualScriptYield::YieldMode MODE>
+static Ref<VisualScriptNode> create_yield_node(const String& p_name) {
+
+ Ref<VisualScriptYield> node;
+ node.instance();
+ node->set_yield_mode(MODE);
+ return node;
+}
+
+///////////////////////////////////////////////////
+////////////////YIELD SIGNAL//////////////////////
+//////////////////////////////////////////////////
+
+int VisualScriptYieldSignal::get_output_sequence_port_count() const {
+
+ return 1;
+}
+
+bool VisualScriptYieldSignal::has_input_sequence_port() const{
+
+ return true;
+}
+#ifdef TOOLS_ENABLED
+
+static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) {
+
+ if (p_edited_scene!=p_current_node && p_current_node->get_owner()!=p_edited_scene)
+ return NULL;
+
+ Ref<Script> scr = p_current_node->get_script();
+
+ if (scr.is_valid() && scr==script)
+ return p_current_node;
+
+ for(int i=0;i<p_current_node->get_child_count();i++) {
+ Node *n = _find_script_node(p_edited_scene,p_current_node->get_child(i),script);
+ if (n)
+ return n;
+ }
+
+ return NULL;
+}
+
+#endif
+Node *VisualScriptYieldSignal::_get_base_node() const {
+
+#ifdef TOOLS_ENABLED
+ Ref<Script> script = get_visual_script();
+ if (!script.is_valid())
+ return NULL;
+
+ MainLoop * main_loop = OS::get_singleton()->get_main_loop();
+ if (!main_loop)
+ return NULL;
+
+ SceneTree *scene_tree = main_loop->cast_to<SceneTree>();
+
+ if (!scene_tree)
+ return NULL;
+
+ Node *edited_scene = scene_tree->get_edited_scene_root();
+
+ if (!edited_scene)
+ return NULL;
+
+ Node* script_node = _find_script_node(edited_scene,edited_scene,script);
+
+ if (!script_node)
+ return NULL;
+
+ if (!script_node->has_node(base_path))
+ return NULL;
+
+ Node *path_to = script_node->get_node(base_path);
+
+ return path_to;
+#else
+
+ return NULL;
+#endif
+}
+
+StringName VisualScriptYieldSignal::_get_base_type() const {
+
+ if (call_mode==CALL_MODE_SELF && get_visual_script().is_valid())
+ return get_visual_script()->get_instance_base_type();
+ else if (call_mode==CALL_MODE_NODE_PATH && get_visual_script().is_valid()) {
+ Node *path = _get_base_node();
+ if (path)
+ return path->get_type();
+
+ }
+
+ return base_type;
+}
+
+int VisualScriptYieldSignal::get_input_value_port_count() const{
+
+ if (call_mode==CALL_MODE_INSTANCE)
+ return 1;
+ else
+ return 0;
+
+}
+int VisualScriptYieldSignal::get_output_value_port_count() const{
+
+
+ MethodInfo sr;
+
+ if (!ObjectTypeDB::get_signal(_get_base_type(),signal,&sr))
+ return 0;
+
+ return sr.arguments.size();
+
+}
+
+String VisualScriptYieldSignal::get_output_sequence_port_text(int p_port) const {
+
+ return String();
+}
+
+PropertyInfo VisualScriptYieldSignal::get_input_value_port_info(int p_idx) const{
+
+ if (call_mode==CALL_MODE_INSTANCE)
+ return PropertyInfo(Variant::OBJECT,"instance");
+ else
+ return PropertyInfo();
+
+}
+
+PropertyInfo VisualScriptYieldSignal::get_output_value_port_info(int p_idx) const{
+
+ MethodInfo sr;
+
+ if (!ObjectTypeDB::get_signal(_get_base_type(),signal,&sr))
+ return PropertyInfo(); //no signal
+ ERR_FAIL_INDEX_V(p_idx,sr.arguments.size(),PropertyInfo());
+ return sr.arguments[p_idx];
+
+}
+
+
+String VisualScriptYieldSignal::get_caption() const {
+
+ static const char*cname[3]= {
+ "WaitSignal",
+ "WaitNodeSignal",
+ "WaitInstanceSigna;",
+ };
+
+ return cname[call_mode];
+}
+
+String VisualScriptYieldSignal::get_text() const {
+
+ if (call_mode==CALL_MODE_SELF)
+ return " "+String(signal)+"()";
+ else
+ return " "+_get_base_type()+"."+String(signal)+"()";
+
+}
+
+
+void VisualScriptYieldSignal::set_base_type(const StringName& p_type) {
+
+ if (base_type==p_type)
+ return;
+
+ base_type=p_type;
+
+ _change_notify();
+ ports_changed_notify();
+}
+
+StringName VisualScriptYieldSignal::get_base_type() const{
+
+ return base_type;
+}
+
+void VisualScriptYieldSignal::set_signal(const StringName& p_type){
+
+ if (signal==p_type)
+ return;
+
+ signal=p_type;
+
+ _change_notify();
+ ports_changed_notify();
+}
+StringName VisualScriptYieldSignal::get_signal() const {
+
+
+ return signal;
+}
+
+void VisualScriptYieldSignal::set_base_path(const NodePath& p_type) {
+
+ if (base_path==p_type)
+ return;
+
+ base_path=p_type;
+
+ _change_notify();
+ ports_changed_notify();
+}
+
+NodePath VisualScriptYieldSignal::get_base_path() const {
+
+ return base_path;
+}
+
+
+void VisualScriptYieldSignal::set_call_mode(CallMode p_mode) {
+
+ if (call_mode==p_mode)
+ return;
+
+ call_mode=p_mode;
+
+ _change_notify();
+ ports_changed_notify();
+
+}
+
+VisualScriptYieldSignal::CallMode VisualScriptYieldSignal::get_call_mode() const {
+
+ return call_mode;
+}
+
+
+void VisualScriptYieldSignal::_validate_property(PropertyInfo& property) const {
+
+ if (property.name=="signal/base_type") {
+ if (call_mode!=CALL_MODE_INSTANCE) {
+ property.usage=PROPERTY_USAGE_NOEDITOR;
+ }
+ }
+
+
+ if (property.name=="signal/node_path") {
+ if (call_mode!=CALL_MODE_NODE_PATH) {
+ property.usage=0;
+ } else {
+
+ Node *bnode = _get_base_node();
+ if (bnode) {
+ property.hint_string=bnode->get_path(); //convert to loong string
+ } else {
+
+ }
+ }
+ }
+
+ if (property.name=="signal/signal") {
+ property.hint=PROPERTY_HINT_ENUM;
+
+
+ List<MethodInfo> methods;
+
+ ObjectTypeDB::get_signal_list(_get_base_type(),&methods);
+
+ List<String> mstring;
+ for (List<MethodInfo>::Element *E=methods.front();E;E=E->next()) {
+ if (E->get().name.begins_with("_"))
+ continue;
+ mstring.push_back(E->get().name.get_slice(":",0));
+ }
+
+ mstring.sort();
+
+ String ml;
+ for (List<String>::Element *E=mstring.front();E;E=E->next()) {
+
+ if (ml!=String())
+ ml+=",";
+ ml+=E->get();
+ }
+
+ property.hint_string=ml;
+ }
+
+
+}
+
+
+void VisualScriptYieldSignal::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_base_type","base_type"),&VisualScriptYieldSignal::set_base_type);
+ ObjectTypeDB::bind_method(_MD("get_base_type"),&VisualScriptYieldSignal::get_base_type);
+
+ ObjectTypeDB::bind_method(_MD("set_signal","signal"),&VisualScriptYieldSignal::set_signal);
+ ObjectTypeDB::bind_method(_MD("get_signal"),&VisualScriptYieldSignal::get_signal);
+
+ ObjectTypeDB::bind_method(_MD("set_call_mode","mode"),&VisualScriptYieldSignal::set_call_mode);
+ ObjectTypeDB::bind_method(_MD("get_call_mode"),&VisualScriptYieldSignal::get_call_mode);
+
+ ObjectTypeDB::bind_method(_MD("set_base_path","base_path"),&VisualScriptYieldSignal::set_base_path);
+ ObjectTypeDB::bind_method(_MD("get_base_path"),&VisualScriptYieldSignal::get_base_path);
+
+
+
+ String bt;
+ for(int i=0;i<Variant::VARIANT_MAX;i++) {
+ if (i>0)
+ bt+=",";
+
+ bt+=Variant::get_type_name(Variant::Type(i));
+ }
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"signal/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance",PROPERTY_USAGE_NOEDITOR),_SCS("set_call_mode"),_SCS("get_call_mode"));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"signal/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"signal/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path"));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"signal/signal"),_SCS("set_signal"),_SCS("get_signal"));
+
+
+ BIND_CONSTANT( CALL_MODE_SELF );
+ BIND_CONSTANT( CALL_MODE_NODE_PATH);
+ BIND_CONSTANT( CALL_MODE_INSTANCE);
+
+}
+
+class VisualScriptNodeInstanceYieldSignal : public VisualScriptNodeInstance {
+public:
+
+
+ VisualScriptYieldSignal::CallMode call_mode;
+ NodePath node_path;
+ int output_args;
+ StringName signal;
+
+ VisualScriptYieldSignal *node;
+ VisualScriptInstance *instance;
+
+
+
+ virtual int get_working_memory_size() const { return 1; }
+ //virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+ //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+
+ 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) {
+
+ if (p_start_mode==START_MODE_RESUME_YIELD) {
+ return 0; //resuming yield
+ } else {
+ //yield
+
+ Object * object;
+
+ switch(call_mode) {
+
+ case VisualScriptYieldSignal::CALL_MODE_SELF: {
+
+ object=instance->get_owner_ptr();
+
+ } break;
+ case VisualScriptYieldSignal::CALL_MODE_NODE_PATH: {
+
+ Node* node = instance->get_owner_ptr()->cast_to<Node>();
+ if (!node) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Base object is not a Node!";
+ return 0;
+ }
+
+ Node* another = node->get_node(node_path);
+ if (!node) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Path does not lead Node!";
+ return 0;
+ }
+
+ object=another;
+
+ } break;
+ case VisualScriptYieldSignal::CALL_MODE_INSTANCE: {
+
+ object = *p_inputs[0];
+ if (!object) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str="Supplied instance input is null.";
+ return 0;
+
+ }
+
+ } break;
+
+ }
+
+ Ref<VisualScriptFunctionState> state;
+ state.instance();
+
+ state->connect_to_signal(object,signal,Array());
+
+ *p_working_mem=state;
+
+ return STEP_YIELD_BIT;
+ }
+
+
+ }
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptYieldSignal::instance(VisualScriptInstance* p_instance) {
+
+ VisualScriptNodeInstanceYieldSignal * instance = memnew(VisualScriptNodeInstanceYieldSignal );
+ instance->node=this;
+ instance->instance=p_instance;
+ instance->signal=signal;
+ instance->call_mode=call_mode;
+ instance->node_path=base_path;
+ instance->output_args = get_output_value_port_count();
+ return instance;
+}
+VisualScriptYieldSignal::VisualScriptYieldSignal() {
+
+ call_mode=CALL_MODE_INSTANCE;
+ base_type="Object";
+
+}
+
+template<VisualScriptYieldSignal::CallMode cmode>
+static Ref<VisualScriptNode> create_yield_signal_node(const String& p_name) {
+
+ Ref<VisualScriptYieldSignal> node;
+ node.instance();
+ node->set_call_mode(cmode);
+ return node;
+}
+
+void register_visual_script_yield_nodes() {
+
+ VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_frame",create_yield_node<VisualScriptYield::YIELD_FRAME>);
+ VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_fixed_frame",create_yield_node<VisualScriptYield::YIELD_FIXED_FRAME>);
+ VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_time",create_yield_node<VisualScriptYield::YIELD_WAIT>);
+
+ VisualScriptLanguage::singleton->add_register_func("functions/yield/instance_signal",create_yield_signal_node<VisualScriptYieldSignal::CALL_MODE_INSTANCE>);
+ VisualScriptLanguage::singleton->add_register_func("functions/yield/self_signal",create_yield_signal_node<VisualScriptYieldSignal::CALL_MODE_SELF>);
+ VisualScriptLanguage::singleton->add_register_func("functions/yield/node_signal",create_yield_signal_node<VisualScriptYieldSignal::CALL_MODE_NODE_PATH>);
+
+}
diff --git a/modules/visual_script/visual_script_yield_nodes.h b/modules/visual_script/visual_script_yield_nodes.h
new file mode 100644
index 0000000000..a7e200305d
--- /dev/null
+++ b/modules/visual_script/visual_script_yield_nodes.h
@@ -0,0 +1,127 @@
+#ifndef VISUAL_SCRIPT_YIELD_NODES_H
+#define VISUAL_SCRIPT_YIELD_NODES_H
+
+#include "visual_script.h"
+
+class VisualScriptYield : public VisualScriptNode {
+
+ OBJ_TYPE(VisualScriptYield,VisualScriptNode)
+public:
+
+ enum YieldMode {
+ YIELD_FRAME,
+ YIELD_FIXED_FRAME,
+ YIELD_WAIT
+
+ };
+private:
+
+ YieldMode yield_mode;
+ float wait_time;
+
+
+protected:
+
+ virtual void _validate_property(PropertyInfo& property) const;
+
+ static void _bind_methods();
+public:
+
+ virtual int get_output_sequence_port_count() const;
+ virtual bool has_input_sequence_port() const;
+
+
+ virtual String get_output_sequence_port_text(int p_port) const;
+
+
+ virtual int get_input_value_port_count() const;
+ virtual int get_output_value_port_count() const;
+
+
+ virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+ virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+ virtual String get_caption() const;
+ virtual String get_text() const;
+ virtual String get_category() const { return "functions"; }
+
+ void set_yield_mode(YieldMode p_mode);
+ YieldMode get_yield_mode();
+
+ void set_wait_time(float p_time);
+ float get_wait_time();
+
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
+
+ VisualScriptYield();
+};
+VARIANT_ENUM_CAST( VisualScriptYield::YieldMode )
+
+class VisualScriptYieldSignal : public VisualScriptNode {
+
+ OBJ_TYPE(VisualScriptYieldSignal,VisualScriptNode)
+public:
+ enum CallMode {
+ CALL_MODE_SELF,
+ CALL_MODE_NODE_PATH,
+ CALL_MODE_INSTANCE,
+
+ };
+private:
+
+ CallMode call_mode;
+ StringName base_type;
+ NodePath base_path;
+ StringName signal;
+
+ Node *_get_base_node() const;
+ StringName _get_base_type() const;
+
+
+protected:
+ virtual void _validate_property(PropertyInfo& property) const;
+
+ static void _bind_methods();
+
+public:
+
+ virtual int get_output_sequence_port_count() const;
+ virtual bool has_input_sequence_port() const;
+
+
+ virtual String get_output_sequence_port_text(int p_port) const;
+
+
+ virtual int get_input_value_port_count() const;
+ virtual int get_output_value_port_count() const;
+
+
+ virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+ virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+ virtual String get_caption() const;
+ virtual String get_text() const;
+ virtual String get_category() const { return "functions"; }
+
+ void set_base_type(const StringName& p_type);
+ StringName get_base_type() const;
+
+ void set_signal(const StringName& p_type);
+ StringName get_signal() const;
+
+ void set_base_path(const NodePath& p_type);
+ NodePath get_base_path() const;
+
+ void set_call_mode(CallMode p_mode);
+ CallMode get_call_mode() const;
+
+ virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
+
+ VisualScriptYieldSignal();
+};
+
+VARIANT_ENUM_CAST(VisualScriptYieldSignal::CallMode );
+
+void register_visual_script_yield_nodes();
+
+#endif // VISUAL_SCRIPT_YIELD_NODES_H
diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp
index 920c6bf1e6..feaf516f42 100644
--- a/scene/gui/container.cpp
+++ b/scene/gui/container.cpp
@@ -41,6 +41,8 @@ void Container::_child_minsize_changed() {
void Container::add_child_notify(Node *p_child) {
+ Control::add_child_notify(p_child);
+
Control *control = p_child->cast_to<Control>();
if (!control)
return;
@@ -50,18 +52,24 @@ void Container::add_child_notify(Node *p_child) {
control->connect("visibility_changed",this,"_child_minsize_changed");
queue_sort();
+
}
void Container::move_child_notify(Node *p_child) {
+ Control::move_child_notify(p_child);
+
if (!p_child->cast_to<Control>())
return;
queue_sort();
+
+
}
void Container::remove_child_notify(Node *p_child) {
+ Control::remove_child_notify(p_child);
Control *control = p_child->cast_to<Control>();
if (!control)
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index c08e10b9ff..71ec508c81 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -422,6 +422,32 @@ void Control::_resize(const Size2& p_size) {
_size_changed();
}
+//moved theme configuration here, so controls can set up even if still not inside active scene
+
+void Control::add_child_notify(Node *p_child) {
+
+ Control *child_c=p_child->cast_to<Control>();
+ if (!child_c)
+ return;
+
+ if (child_c->data.theme.is_null() && data.theme_owner) {
+ child_c->data.theme_owner=data.theme_owner;
+ child_c->notification(NOTIFICATION_THEME_CHANGED);
+ }
+}
+
+void Control::remove_child_notify(Node *p_child) {
+
+ Control *child_c=p_child->cast_to<Control>();
+ if (!child_c)
+ return;
+
+ if (child_c->data.theme_owner && child_c->data.theme.is_null()) {
+ child_c->data.theme_owner=NULL;
+ //notification(NOTIFICATION_THEME_CHANGED);
+ }
+
+}
void Control::_notification(int p_notification) {
@@ -512,10 +538,10 @@ void Control::_notification(int p_notification) {
}
- if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) {
- data.theme_owner=data.parent->data.theme_owner;
- notification(NOTIFICATION_THEME_CHANGED);
- }
+ //if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) {
+ // data.theme_owner=data.parent->data.theme_owner;
+ // notification(NOTIFICATION_THEME_CHANGED);
+ //}
} break;
case NOTIFICATION_EXIT_CANVAS: {
@@ -547,10 +573,10 @@ void Control::_notification(int p_notification) {
data.parent=NULL;
data.parent_canvas_item=NULL;
- if (data.theme_owner && data.theme.is_null()) {
- data.theme_owner=NULL;
+ //if (data.theme_owner && data.theme.is_null()) {
+ // data.theme_owner=NULL;
//notification(NOTIFICATION_THEME_CHANGED);
- }
+ //}
} break;
case NOTIFICATION_MOVED_IN_PARENT: {
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 1337cbc4b9..b9ac53067a 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -194,12 +194,16 @@ private:
void _font_changed();
+
friend class Viewport;
void _modal_stack_remove();
void _modal_set_prev_focus_owner(ObjectID p_prev);
protected:
+ virtual void add_child_notify(Node *p_child);
+ virtual void remove_child_notify(Node *p_child);
+
//virtual void _window_input_event(InputEvent p_event);
bool _set(const StringName& p_name, const Variant& p_value);
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index c488dd0d16..458e51b4fd 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -100,6 +100,15 @@ void GraphEdit::get_connection_list(List<Connection> *r_connections) const {
*r_connections=connections;
}
+void GraphEdit::set_scroll_ofs(const Vector2& p_ofs) {
+
+ setting_scroll_ofs=true;
+ h_scroll->set_val(p_ofs.x);
+ v_scroll->set_val(p_ofs.y);
+ _update_scroll();
+ setting_scroll_ofs=false;
+}
+
Vector2 GraphEdit::get_scroll_ofs() const{
return Vector2(h_scroll->get_val(),v_scroll->get_val());
@@ -113,6 +122,10 @@ void GraphEdit::_scroll_moved(double) {
//must redraw grid
update();
}
+
+ if (!setting_scroll_ofs) {//in godot, signals on change value are avoided as a convention
+ emit_signal("scroll_offset_changed",get_scroll_ofs());
+ }
}
void GraphEdit::_update_scroll_offset() {
@@ -196,6 +209,8 @@ void GraphEdit::_graph_node_moved(Node *p_gn) {
void GraphEdit::add_child_notify(Node *p_child) {
+ Control::add_child_notify(p_child);
+
top_layer->call_deferred("raise"); //top layer always on top!
GraphNode *gn = p_child->cast_to<GraphNode>();
if (gn) {
@@ -205,10 +220,14 @@ void GraphEdit::add_child_notify(Node *p_child) {
_graph_node_moved(gn);
gn->set_stop_mouse(false);
}
+
+
}
void GraphEdit::remove_child_notify(Node *p_child) {
+ Control::remove_child_notify(p_child);
+
top_layer->call_deferred("raise"); //top layer always on top!
GraphNode *gn = p_child->cast_to<GraphNode>();
if (gn) {
@@ -1036,6 +1055,7 @@ void GraphEdit::_bind_methods() {
ObjectTypeDB::bind_method(_MD("disconnect_node","from","from_port","to","to_port"),&GraphEdit::disconnect_node);
ObjectTypeDB::bind_method(_MD("get_connection_list"),&GraphEdit::_get_connection_list);
ObjectTypeDB::bind_method(_MD("get_scroll_ofs"),&GraphEdit::get_scroll_ofs);
+ ObjectTypeDB::bind_method(_MD("set_scroll_ofs","ofs"),&GraphEdit::set_scroll_ofs);
ObjectTypeDB::bind_method(_MD("set_zoom","p_zoom"),&GraphEdit::set_zoom);
ObjectTypeDB::bind_method(_MD("get_zoom"),&GraphEdit::get_zoom);
@@ -1073,6 +1093,7 @@ void GraphEdit::_bind_methods() {
ADD_SIGNAL(MethodInfo("delete_nodes_request"));
ADD_SIGNAL(MethodInfo("_begin_node_move"));
ADD_SIGNAL(MethodInfo("_end_node_move"));
+ ADD_SIGNAL(MethodInfo("scroll_offset_changed",PropertyInfo(Variant::VECTOR2,"ofs")));
}
@@ -1103,6 +1124,13 @@ GraphEdit::GraphEdit() {
box_selecting = false;
dragging = false;
+ //set large minmax so it can scroll even if not resized yet
+ h_scroll->set_min(-10000);
+ h_scroll->set_max(10000);
+
+ v_scroll->set_min(-10000);
+ v_scroll->set_max(10000);
+
h_scroll->connect("value_changed", this,"_scroll_moved");
v_scroll->connect("value_changed", this,"_scroll_moved");
@@ -1143,6 +1171,6 @@ GraphEdit::GraphEdit() {
snap_amount->connect("value_changed",this,"_snap_value_changed");
zoom_hb->add_child(snap_amount);
-
+ setting_scroll_ofs=false;
}
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index ad20fbefce..6d35e1518f 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -107,6 +107,7 @@ private:
Rect2 box_selecting_rect;
List<GraphNode*> previus_selected;
+ bool setting_scroll_ofs;
bool right_disconnects;
bool updating;
List<Connection> connections;
@@ -188,6 +189,7 @@ public:
void add_valid_left_disconnect_type(int p_type);
void remove_valid_left_disconnect_type(int p_type);
+ void set_scroll_ofs(const Vector2& p_ofs);
Vector2 get_scroll_ofs() const;
void set_selected(Node* p_child);
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 1efc9a1ceb..66d2725ad2 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -189,6 +189,8 @@ void GraphNode::_notification(int p_what) {
if (p_what==NOTIFICATION_DRAW) {
Ref<StyleBox> sb=get_stylebox(selected ? "selectedframe" : "frame");
+ sb=sb->duplicate();
+ sb->call("set_modulate",modulate);
Ref<Texture> port =get_icon("port");
Ref<Texture> close =get_icon("close");
int close_offset = get_constant("close_offset");
@@ -198,8 +200,25 @@ void GraphNode::_notification(int p_what) {
Point2i icofs = -port->get_size()*0.5;
int edgeofs=get_constant("port_offset");
icofs.y+=sb->get_margin(MARGIN_TOP);
+
+
+
draw_style_box(sb,Rect2(Point2(),get_size()));
+ switch(overlay) {
+ case OVERLAY_DISABLED: {
+
+ } break;
+ case OVERLAY_BREAKPOINT: {
+
+ draw_style_box(get_stylebox("breakpoint"),Rect2(Point2(),get_size()));
+ } break;
+ case OVERLAY_POSITION: {
+ draw_style_box(get_stylebox("position"),Rect2(Point2(),get_size()));
+
+ } break;
+ }
+
int w = get_size().width-sb->get_minimum_size().x;
if (show_close)
@@ -590,6 +609,26 @@ void GraphNode::_input_event(const InputEvent& p_ev) {
}
+void GraphNode::set_modulate(const Color &p_color) {
+
+ modulate=p_color;
+ update();
+}
+
+Color GraphNode::get_modulate() const{
+
+ return modulate;
+}
+void GraphNode::set_overlay(Overlay p_overlay) {
+
+ overlay=p_overlay;
+ update();
+}
+
+GraphNode::Overlay GraphNode::get_overlay() const{
+
+ return overlay;
+}
void GraphNode::_bind_methods() {
@@ -620,10 +659,15 @@ void GraphNode::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_connection_input_type","idx"),&GraphNode::get_connection_input_type);
ObjectTypeDB::bind_method(_MD("get_connection_input_color","idx"),&GraphNode::get_connection_input_color);
+ ObjectTypeDB::bind_method(_MD("set_modulate","color"),&GraphNode::set_modulate);
+ ObjectTypeDB::bind_method(_MD("get_modulate"),&GraphNode::get_modulate);
ObjectTypeDB::bind_method(_MD("set_show_close_button","show"),&GraphNode::set_show_close_button);
ObjectTypeDB::bind_method(_MD("is_close_button_visible"),&GraphNode::is_close_button_visible);
+ ObjectTypeDB::bind_method(_MD("set_overlay","overlay"),&GraphNode::set_overlay);
+ ObjectTypeDB::bind_method(_MD("get_overlay"),&GraphNode::get_overlay);
+
ADD_PROPERTY( PropertyInfo(Variant::STRING,"title"),_SCS("set_title"),_SCS("get_title"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"show_close"),_SCS("set_show_close_button"),_SCS("is_close_button_visible"));
@@ -631,10 +675,17 @@ void GraphNode::_bind_methods() {
ADD_SIGNAL(MethodInfo("dragged",PropertyInfo(Variant::VECTOR2,"from"),PropertyInfo(Variant::VECTOR2,"to")));
ADD_SIGNAL(MethodInfo("raise_request"));
ADD_SIGNAL(MethodInfo("close_request"));
+
+ BIND_CONSTANT( OVERLAY_DISABLED );
+ BIND_CONSTANT( OVERLAY_BREAKPOINT );
+ BIND_CONSTANT( OVERLAY_POSITION );
}
GraphNode::GraphNode() {
+
+ overlay=OVERLAY_DISABLED;
show_close=false;
connpos_dirty=true;
set_stop_mouse(false);
+ modulate=Color(1,1,1,1);
}
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index f308f30b81..e87fb15b93 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -34,8 +34,14 @@
class GraphNode : public Container {
OBJ_TYPE(GraphNode,Container);
+public:
-
+ enum Overlay {
+ OVERLAY_DISABLED,
+ OVERLAY_BREAKPOINT,
+ OVERLAY_POSITION
+ };
+private:
struct Slot {
bool enable_left;
@@ -77,6 +83,10 @@ class GraphNode : public Container {
Vector2 drag_from;
bool selected;
+
+ Overlay overlay;
+
+ Color modulate;
protected:
@@ -128,10 +138,17 @@ public:
Color get_connection_output_color(int p_idx);
+ void set_modulate(const Color& p_color);
+ Color get_modulate() const;
+
+ void set_overlay(Overlay p_overlay);
+ Overlay get_overlay() const;
+
virtual Size2 get_minimum_size() const;
GraphNode();
};
+VARIANT_ENUM_CAST( GraphNode::Overlay )
#endif // GRAPH_NODE_H
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 0e0339c488..8557500488 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -400,6 +400,7 @@ void TabContainer::_child_renamed_callback() {
void TabContainer::add_child_notify(Node *p_child) {
+ Control::add_child_notify(p_child);
Control *c = p_child->cast_to<Control>();
if (!c)
@@ -532,6 +533,8 @@ Control* TabContainer::get_current_tab_control() const {
void TabContainer::remove_child_notify(Node *p_child) {
+ Control::remove_child_notify(p_child);
+
int tc = get_tab_count();
if (current==tc-1) {
current--;
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index c3bdf7c856..f0301fc250 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -438,7 +438,7 @@ public:
bool is_highlight_all_occurrences_enabled() const;
bool is_selection_active() const;
int get_selection_from_line() const;
- int get_selection_from_column() const;
+ int get_selection_from_column() const;
int get_selection_to_line() const;
int get_selection_to_column() const;
String get_selection_text() const;
@@ -496,7 +496,7 @@ public:
String get_text_for_completion();
- virtual bool is_text_field() const;
+ virtual bool is_text_field() const;
TextEdit();
~TextEdit();
};
diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp
index a7ef7ca7c1..77156203b8 100644
--- a/scene/main/scene_main_loop.cpp
+++ b/scene/main/scene_main_loop.cpp
@@ -45,6 +45,30 @@
#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
+
+void SceneTreeTimer::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_time_left","time"),&SceneTreeTimer::set_time_left);
+ ObjectTypeDB::bind_method(_MD("get_time_left"),&SceneTreeTimer::get_time_left);
+
+ ADD_SIGNAL(MethodInfo("timeout"));
+}
+
+
+void SceneTreeTimer::set_time_left(float p_time) {
+ time_left=p_time;
+}
+
+float SceneTreeTimer::get_time_left() const {
+ return time_left;
+}
+
+
+SceneTreeTimer::SceneTreeTimer() {
+ time_left=0;
+}
+
+
void SceneTree::tree_changed() {
tree_version++;
@@ -547,6 +571,23 @@ bool SceneTree::idle(float p_time){
_flush_delete_queue();
+ //go through timers
+
+ for (List<Ref<SceneTreeTimer> >::Element *E=timers.front();E;) {
+
+ List<Ref<SceneTreeTimer> >::Element *N = E->next();
+
+ float time_left = E->get()->get_time_left();
+ time_left-=p_time;
+ E->get()->set_time_left(time_left);
+
+ if (time_left<0) {
+ E->get()->emit_signal("timeout");
+ timers.erase(E);
+ }
+ E=N;
+ }
+
return _quit;
}
@@ -1604,6 +1645,16 @@ void SceneTree::drop_files(const Vector<String>& p_files,int p_from_screen) {
MainLoop::drop_files(p_files,p_from_screen);
}
+
+Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec) {
+
+ Ref<SceneTreeTimer> stt;
+ stt.instance();
+ stt->set_time_left(p_delay_sec);
+ timers.push_back(stt);
+ return stt;
+}
+
void SceneTree::_bind_methods() {
@@ -1634,6 +1685,8 @@ void SceneTree::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_paused"),&SceneTree::is_paused);
ObjectTypeDB::bind_method(_MD("set_input_as_handled"),&SceneTree::set_input_as_handled);
+ ObjectTypeDB::bind_method(_MD("create_timer:SceneTreeTimer","time_sec"),&SceneTree::create_timer);
+
ObjectTypeDB::bind_method(_MD("get_node_count"),&SceneTree::get_node_count);
ObjectTypeDB::bind_method(_MD("get_frame"),&SceneTree::get_frame);
diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h
index 38d13c0447..6129a12446 100644
--- a/scene/main/scene_main_loop.h
+++ b/scene/main/scene_main_loop.h
@@ -47,6 +47,22 @@ class Viewport;
class Material;
class Mesh;
+
+
+class SceneTreeTimer : public Reference {
+ OBJ_TYPE(SceneTreeTimer,Reference);
+
+ float time_left;
+protected:
+ static void _bind_methods();
+public:
+
+ void set_time_left(float p_time);
+ float get_time_left() const;
+
+ SceneTreeTimer();
+};
+
class SceneTree : public MainLoop {
_THREAD_SAFE_CLASS_
@@ -155,6 +171,8 @@ private:
void _change_scene(Node* p_to);
//void _call_group(uint32_t p_call_flags,const StringName& p_group,const StringName& p_function,const Variant& p_arg1,const Variant& p_arg2);
+ List<Ref<SceneTreeTimer> > timers;
+
static SceneTree *singleton;
friend class Node;
@@ -339,6 +357,8 @@ public:
Error change_scene_to(const Ref<PackedScene>& p_scene);
Error reload_current_scene();
+ Ref<SceneTreeTimer> create_timer(float p_delay_sec);
+
//used by Main::start, don't use otherwise
void add_current_scene(Node * p_current);
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index bc0951e436..be2c12d63a 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -632,6 +632,7 @@ void register_scene_types() {
ObjectTypeDB::register_type<PackedScene>();
ObjectTypeDB::register_type<SceneTree>();
+ ObjectTypeDB::register_virtual_type<SceneTreeTimer>(); //sorry, you can't create it
OS::get_singleton()->yield(); //may take time to init
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 30c2262ac6..2033599307 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -630,12 +630,17 @@ void fill_default_theme(Ref<Theme>& t,const Ref<Font> & default_font,const Ref<F
Ref<StyleBoxTexture> graphsbselected = make_stylebox(graph_node_selected_png,6,24,6,5,16,24,16,5);
Ref<StyleBoxTexture> graphsbdefault = make_stylebox(graph_node_default_png,4,4,4,4,6,4,4,4);
Ref<StyleBoxTexture> graphsbdeffocus = make_stylebox(graph_node_default_focus_png,4,4,4,4,6,4,4,4);
+ Ref<StyleBoxTexture> graph_bpoint = make_stylebox(graph_node_breakpoint_png,6,24,6,5,16,24,16,5);
+ Ref<StyleBoxTexture> graph_position = make_stylebox(graph_node_position_png,6,24,6,5,16,24,16,5);
+
//graphsb->set_expand_margin_size(MARGIN_LEFT,10);
//graphsb->set_expand_margin_size(MARGIN_RIGHT,10);
t->set_stylebox("frame","GraphNode", graphsb );
t->set_stylebox("selectedframe","GraphNode", graphsbselected );
t->set_stylebox("defaultframe", "GraphNode", graphsbdefault );
t->set_stylebox("defaultfocus", "GraphNode", graphsbdeffocus );
+ t->set_stylebox("breakpoint", "GraphNode", graph_bpoint );
+ t->set_stylebox("position", "GraphNode", graph_position );
t->set_constant("separation","GraphNode", 1 *scale);
t->set_icon("port","GraphNode", make_icon( graph_port_png ) );
t->set_icon("close","GraphNode", make_icon( graph_node_close_png ) );
diff --git a/scene/resources/default_theme/graph_node_breakpoint.png b/scene/resources/default_theme/graph_node_breakpoint.png
new file mode 100644
index 0000000000..0e36f31bd4
--- /dev/null
+++ b/scene/resources/default_theme/graph_node_breakpoint.png
Binary files differ
diff --git a/scene/resources/default_theme/graph_node_position.png b/scene/resources/default_theme/graph_node_position.png
new file mode 100644
index 0000000000..7ec15e2ff4
--- /dev/null
+++ b/scene/resources/default_theme/graph_node_position.png
Binary files differ
diff --git a/scene/resources/default_theme/graph_node_selected.png b/scene/resources/default_theme/graph_node_selected.png
index 051cc32f7c..33c4d06128 100644
--- a/scene/resources/default_theme/graph_node_selected.png
+++ b/scene/resources/default_theme/graph_node_selected.png
Binary files differ
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index 215818da49..2286973bf2 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -104,6 +104,11 @@ static const unsigned char graph_node_png[]={
};
+static const unsigned char graph_node_breakpoint_png[]={
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x6,0xf,0x3b,0x1c,0xec,0x64,0x51,0x75,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x8f,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0xd7,0xbd,0x9,0xc0,0x20,0x10,0x5,0xe0,0x53,0x2c,0x5d,0x40,0x74,0x4,0xf7,0x9f,0xc4,0x11,0x22,0x2e,0x60,0x6f,0x9a,0x13,0x4e,0x21,0x41,0x50,0x48,0x91,0x77,0x95,0xf8,0xf3,0x79,0x62,0xf5,0x88,0x36,0x4b,0xf5,0x41,0x2d,0xf1,0x22,0x22,0xbf,0x78,0x2e,0x5b,0x97,0x2,0xc9,0xc3,0xc,0x2c,0x95,0xdc,0x6f,0x78,0xce,0x5b,0x97,0xd4,0x42,0x27,0xd9,0xba,0x14,0xac,0x4b,0xa1,0x96,0xd8,0x24,0x20,0x9f,0x41,0x1d,0x7b,0xba,0x59,0xb6,0xaf,0xa7,0x3d,0x7e,0x78,0xdb,0x54,0xbc,0x36,0x74,0xa7,0x77,0x7f,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7e,0x4,0xe4,0xb7,0xfc,0xc8,0x6b,0x59,0xce,0x99,0x39,0x95,0x71,0xb4,0x6b,0x4b,0x89,0xf5,0x44,0x72,0x3d,0x93,0x9d,0x3f,0xad,0x1b,0x54,0xed,0x49,0xd3,0x36,0x45,0x4f,0x1f,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+};
+
+
static const unsigned char graph_node_close_png[]={
0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x93,0x49,0x44,0x41,0x54,0x28,0x91,0x95,0x92,0x31,0xe,0xc2,0x30,0x10,0x4,0x17,0xaa,0x3d,0x7b,0xdb,0x58,0xa4,0xa7,0xe1,0x47,0xfe,0x2c,0x3c,0x82,0x48,0x44,0x22,0x6f,0xb1,0x4d,0x15,0xc9,0x20,0x1f,0x52,0xae,0xdd,0xd9,0x2b,0xe6,0xe,0x0,0x60,0x66,0x59,0x52,0x82,0x33,0x92,0x92,0x99,0x65,0xec,0x30,0xc9,0x4a,0x72,0x19,0x95,0x24,0x25,0x92,0xb,0xc9,0x6a,0x66,0x19,0x92,0x26,0x33,0x7b,0x92,0x6c,0x24,0xd7,0x10,0xc2,0xdc,0xc1,0x5f,0x59,0x8c,0xf1,0x32,0xc,0x42,0x8,0xb3,0xb,0x3b,0xdb,0xde,0x24,0x5f,0x2e,0xdc,0x97,0x3a,0xb0,0x91,0xdc,0x7e,0xe1,0xb3,0x67,0x66,0x9f,0xd6,0xda,0x69,0x58,0x90,0x34,0x95,0x52,0xee,0x0,0x6e,0x0,0x36,0x0,0x2b,0x80,0x6b,0xad,0xf5,0xd1,0x8b,0x70,0x6d,0xb8,0xf6,0xfe,0xd9,0x18,0x96,0xe,0x1f,0xe,0x38,0xf6,0x1a,0x1f,0x9f,0xec,0x40,0x47,0x56,0x51,0x84,0x77,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};
@@ -119,8 +124,13 @@ static const unsigned char graph_node_default_focus_png[]={
};
+static const unsigned char graph_node_position_png[]={
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x6,0xf,0x3b,0x3b,0x49,0x6e,0xe4,0x1e,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x90,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0xd7,0xbd,0x9,0xc0,0x20,0x10,0x5,0xe0,0x53,0x2c,0xdd,0x40,0x47,0x70,0x7,0x67,0x77,0x7,0x47,0x88,0x1b,0xd8,0x9b,0xe6,0x84,0x53,0x48,0x10,0x14,0x52,0xe4,0x5d,0x25,0xfe,0x7c,0x9e,0x58,0x3d,0xa2,0xcd,0x52,0x7d,0x50,0x63,0xb8,0x88,0xc8,0x2d,0x9e,0x2b,0x36,0x65,0x4f,0xf2,0x30,0x3,0x4b,0x25,0xf7,0x1b,0x9e,0x73,0x36,0x65,0xb5,0xd0,0x49,0xb1,0x29,0x7b,0x9b,0xb2,0xaf,0x31,0x34,0x9,0xc8,0x67,0x50,0xc7,0x9e,0x6e,0x96,0xed,0xeb,0x69,0x8f,0x1b,0xde,0x36,0x15,0xaf,0xd,0xdd,0xe9,0xdd,0x5f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x1f,0x1,0xe5,0x2d,0x3f,0xf2,0x5a,0x91,0x73,0x66,0x4e,0x65,0x1c,0xed,0xda,0x52,0x62,0x3d,0x91,0x5c,0xcf,0x64,0xe7,0x4f,0xeb,0x6,0x80,0xff,0x44,0x93,0xd4,0xd9,0xea,0x7e,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+};
+
+
static const unsigned char graph_node_selected_png[]={
-0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x7,0x1d,0x1,0x17,0x2a,0x15,0x39,0xc5,0x7,0x0,0x0,0x3,0x63,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x97,0xcd,0x6f,0x1b,0x55,0x14,0xc5,0xcf,0x7d,0xf3,0xe5,0x19,0xbb,0xf1,0x47,0xe5,0xa4,0xd0,0x36,0x81,0x48,0x14,0x9,0xca,0x2a,0xa6,0x5d,0x50,0xb1,0x64,0x45,0xa5,0x2c,0xc8,0xaa,0xaa,0xc4,0x16,0xf6,0x48,0x48,0x48,0xed,0x22,0x1b,0xfe,0x2,0xd6,0xa8,0x55,0x57,0xd9,0x54,0xea,0xa,0x96,0x6c,0x23,0x96,0x20,0x91,0x45,0x20,0xa1,0x95,0x70,0x8d,0xfc,0x11,0x7b,0xc6,0xf6,0xbc,0x79,0xf7,0xb2,0xf0,0x38,0x19,0xdb,0xd1,0x18,0x89,0x1d,0xf2,0x93,0x6c,0xcf,0x78,0xe6,0xfe,0xce,0xb9,0xe7,0xbd,0x91,0xe6,0x91,0x88,0x10,0x0,0xf5,0xe2,0xc5,0xcf,0x5e,0xd2,0xee,0xf8,0xed,0xb3,0x96,0xc7,0xc2,0x4a,0xeb,0x98,0x90,0x19,0x8e,0xe3,0x8a,0x22,0xc5,0xb5,0xb5,0xfa,0xd8,0xae,0x55,0x87,0xf7,0xef,0xef,0x8c,0x1,0x30,0x89,0x88,0xf5,0xfc,0xfb,0xe7,0x57,0x7a,0x61,0x74,0xbd,0xdd,0xed,0x6e,0xf7,0x7a,0x9d,0x8d,0x41,0x38,0x8,0xe2,0x38,0xb6,0xb3,0x0,0xd7,0x75,0x93,0x52,0xb1,0x14,0x95,0xcb,0xd5,0x66,0xad,0x52,0x39,0x2e,0x17,0x83,0x57,0xbb,0x9f,0xef,0xf6,0xe9,0xc9,0x93,0x1f,0x8a,0x71,0xbb,0xf9,0x76,0xa7,0xd7,0xfe,0x78,0xf3,0xfa,0xe6,0xd7,0xe1,0x30,0xaa,0xc7,0x5a,0x17,0x44,0x4,0x90,0xb4,0x9a,0x0,0x22,0x82,0xeb,0x38,0xa3,0xa2,0x1f,0xb4,0x4e,0x5f,0x9d,0x7e,0x5b,0x2d,0xd7,0x7e,0x72,0x6b,0x1b,0xbf,0xdb,0xba,0xd3,0xd,0x9a,0x7f,0xbf,0xbe,0xb5,0x75,0x63,0xf3,0x71,0x62,0xcc,0xfa,0xbd,0x8f,0xee,0xc1,0xf6,0x2c,0x10,0xcd,0x74,0x0,0x11,0x41,0x32,0x36,0x85,0xc3,0xc3,0xc3,0x9b,0x6f,0x6c,0xbc,0xf9,0xf8,0xe4,0xe5,0xe9,0x17,0xd7,0xc8,0x6b,0xaa,0x38,0x19,0xba,0xe1,0xa0,0xbf,0x3e,0x1a,0x8f,0xae,0xde,0xb9,0xdb,0x0,0x29,0x42,0xa2,0x19,0x49,0x6c,0x66,0x3f,0x9a,0x41,0x8a,0x70,0xe7,0x6e,0x3,0xa3,0xf1,0xe8,0x6a,0x38,0xe8,0xaf,0xc7,0xc9,0xd0,0x55,0x2c,0xac,0xa2,0x61,0xe4,0x27,0xc6,0x58,0x46,0xb,0x44,0x18,0x4,0x0,0x9c,0x95,0x7,0x8,0x2,0x11,0x81,0x49,0x4,0x89,0x31,0x56,0x34,0x8c,0x7c,0x16,0x56,0x4a,0x6b,0x4d,0x6,0x86,0x44,0x18,0x92,0xda,0x16,0x11,0x40,0x61,0x26,0x3,0x61,0x0,0x22,0x80,0x10,0x44,0x18,0x6,0x86,0xb4,0xd6,0x64,0x3b,0x8e,0x23,0x30,0x0,0x84,0x0,0x16,0x8,0x8,0x20,0x1,0xe8,0x42,0xfd,0x1c,0x3a,0xfd,0x15,0x2,0xcc,0xe4,0x7f,0x7b,0x3e,0x28,0x10,0x1,0x10,0x88,0xe0,0xd2,0x21,0x73,0x17,0xec,0xb9,0xab,0x10,0x4e,0x6f,0x20,0xb9,0x70,0x90,0x75,0x93,0x7,0x90,0x89,0x76,0xf6,0x64,0x52,0xcc,0x17,0x90,0x79,0x67,0x33,0x0,0xe6,0x4c,0xef,0x69,0x7a,0x24,0x69,0x2e,0x22,0xa0,0xe5,0x2d,0x64,0x25,0x28,0xe3,0x67,0xf2,0xcd,0xcb,0x1c,0x40,0x18,0xc2,0x73,0xf1,0x2f,0xa6,0x98,0x93,0x41,0xda,0x77,0x6a,0x1a,0xe9,0xf2,0x99,0x36,0x33,0x39,0xca,0x73,0x30,0x1,0x70,0x5a,0x98,0x51,0xa3,0x8b,0xde,0x39,0x1f,0xc0,0x93,0xfa,0x19,0xed,0xac,0x2a,0x2d,0x9f,0x46,0x9a,0xae,0x7,0x9a,0x2e,0x26,0x9a,0xe6,0x99,0x3e,0xf,0x79,0xe,0x78,0x52,0xb8,0xa0,0xc4,0x38,0x9f,0x91,0xf9,0x68,0x17,0x97,0xb2,0xcc,0x3f,0x8a,0xf9,0x63,0x31,0xc4,0x79,0x8d,0x4c,0x90,0x73,0x7,0x8b,0x80,0x6f,0xf6,0xbf,0xc2,0xaf,0x47,0xbf,0xe4,0x2a,0xbe,0x77,0xeb,0x7d,0xec,0x7e,0xfa,0xd9,0x22,0x40,0x98,0xb1,0xbd,0xf5,0xe,0x2c,0xe5,0xe4,0x2,0xb6,0x6e,0xbe,0x5,0x61,0xbe,0xdc,0x41,0x18,0xe,0xd0,0x3b,0xeb,0xe6,0x2,0xc2,0x70,0x30,0x73,0xae,0xf0,0x1f,0xc7,0xa,0xb0,0x2,0xac,0x0,0x2b,0xc0,0xa,0xb0,0x2,0xac,0x0,0xff,0x3f,0x80,0xd6,0x9a,0x60,0xa5,0xdb,0x4,0xfa,0x17,0x15,0x94,0xde,0x6b,0x65,0x1c,0x58,0xb0,0x84,0x48,0xc1,0xb1,0xed,0xa5,0xf5,0x8e,0x6d,0x83,0x48,0xc1,0x82,0x25,0x0,0xa0,0x3c,0xd7,0x33,0x9e,0xeb,0xc6,0xca,0xb2,0x38,0xf0,0x4b,0x4b,0x1,0x81,0x5f,0x82,0xb2,0x2c,0xf6,0x5c,0x37,0xf6,0x5c,0xcf,0xd8,0xae,0xed,0xc7,0x5,0x3f,0x68,0x39,0xb6,0x3d,0x68,0xec,0x7c,0xb8,0x6,0x10,0xa2,0x61,0x1f,0x3a,0x49,0x66,0x36,0x5d,0x8e,0x6d,0x23,0xf0,0xaf,0xa0,0xb1,0xd3,0x0,0xb3,0x19,0x14,0xfc,0xa0,0xe5,0xda,0x7e,0x6c,0x3b,0xd5,0x4a,0x54,0xe9,0x97,0x8f,0xfe,0xf8,0xf3,0x78,0x7f,0xeb,0xc6,0xf6,0xa3,0xf,0x6e,0xdf,0x2e,0x31,0x33,0x89,0xc8,0xf9,0xb,0x36,0x11,0x81,0x88,0xa0,0x94,0x12,0x63,0xcc,0xe0,0xe4,0xe5,0xf1,0x7e,0x65,0xad,0x7a,0xe4,0x54,0x2b,0x11,0x89,0x88,0xf5,0xec,0xbb,0x67,0x6b,0xad,0x4e,0x77,0xab,0xd3,0xed,0xbe,0x1b,0xd,0xc3,0x75,0xad,0xb5,0xc3,0x3c,0xfb,0xb6,0xaa,0x94,0x82,0xe3,0x38,0x3a,0xf0,0x8b,0xaf,0xab,0x95,0xca,0x6f,0xf5,0x6a,0xe5,0xe4,0xc1,0x97,0xf,0xce,0x68,0xba,0x7b,0x7f,0xfa,0xf4,0xc7,0xc2,0xe0,0xaf,0x66,0x51,0xf3,0xd8,0x15,0xe1,0x4b,0xa7,0x97,0x48,0xb1,0xa3,0xbc,0xb8,0x74,0x6d,0x23,0x7c,0xf8,0xf0,0x93,0x11,0x80,0xf3,0xed,0x9,0x44,0x84,0xe,0xe,0xe,0x54,0xbd,0x5e,0xcf,0x9d,0xcc,0x56,0xab,0x25,0x7b,0x7b,0x7b,0x4c,0x34,0xd9,0xd6,0xfd,0x3,0xa,0x8,0xcf,0xdd,0x9c,0xab,0x42,0x7c,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x6,0xc,0x29,0x12,0x71,0x6e,0xb2,0xf8,0x0,0x0,0x3,0x37,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x97,0x4f,0x88,0xdc,0x74,0x14,0xc7,0xbf,0xef,0x97,0x7f,0x9b,0xcc,0xee,0xec,0x64,0x64,0x76,0x5,0xd1,0xd5,0xc2,0x6e,0x41,0x8f,0xbd,0xef,0x49,0x7a,0x10,0xa,0xeb,0x61,0xa1,0xb5,0x16,0xc4,0xa3,0x87,0xbd,0xb9,0x17,0x8f,0x5e,0xa4,0xc7,0x16,0xbc,0x8,0xa2,0xdb,0x16,0xf,0x7b,0xb0,0x50,0x28,0x54,0x7a,0xea,0xdd,0xa3,0x82,0x16,0x14,0x5,0xc1,0xd9,0xe9,0x4e,0x32,0x3b,0xc9,0x64,0x26,0xbf,0xe4,0xf7,0x3c,0x24,0xd9,0x26,0x99,0x35,0x73,0xf0,0x26,0xf3,0x60,0x66,0x12,0xe6,0xbd,0xcf,0xf7,0xbd,0xef,0xef,0x17,0xc8,0x8f,0x98,0x99,0x0,0x88,0x47,0x8f,0x7e,0xb4,0x92,0xa1,0x67,0xf,0xcf,0x6,0x96,0x62,0x25,0xa4,0x8c,0x9,0xa5,0x30,0xc,0x93,0x5,0x9,0xd5,0x6d,0xf7,0x66,0x7a,0xd7,0x8d,0xae,0x5d,0xbb,0x32,0x3,0xa0,0x88,0x99,0xb5,0x87,0xdf,0x3c,0x5c,0x1b,0x85,0x93,0xd7,0x86,0xbe,0x7f,0x69,0x34,0xf2,0x36,0x83,0x30,0x70,0xe2,0x38,0xd6,0xcb,0x0,0xd3,0x34,0x93,0xd5,0xd6,0xea,0x64,0x7d,0xdd,0xed,0x77,0x3b,0x9d,0xdf,0xd6,0x5b,0xce,0x5f,0x7b,0x1f,0xed,0x8d,0xe9,0xe8,0xe8,0x49,0x2b,0x1e,0xf6,0xdf,0xf2,0x46,0xc3,0xdd,0xf7,0x6f,0xec,0xde,0x31,0x2d,0x5d,0x43,0x43,0xc4,0xb3,0x24,0xfd,0xfe,0xbb,0x67,0x7,0xee,0x7a,0xf7,0x99,0xd9,0xdd,0xfc,0x5d,0x48,0xcf,0x77,0xfa,0x2f,0x4e,0x76,0xf6,0xae,0xef,0xde,0x65,0x66,0x6d,0x7a,0xda,0x46,0x12,0xb8,0x48,0xc3,0x6e,0xe5,0x93,0x4,0x2e,0xa6,0xa7,0x6d,0x30,0xb3,0xb6,0x77,0x7d,0xf7,0x6e,0xff,0xc5,0xc9,0x8e,0xf4,0x7c,0x47,0x8f,0x93,0xc8,0xc,0x83,0xf1,0x86,0xb5,0xa2,0x8b,0x99,0xb7,0x6,0x12,0x84,0x44,0x2a,0x50,0x4d,0x99,0x1,0x90,0x20,0x20,0xea,0xc2,0x72,0xc7,0x22,0xc,0xc6,0x1b,0xb1,0x1b,0x99,0x42,0xb1,0x12,0x93,0x68,0x62,0x3,0x40,0x2a,0x19,0xcc,0x79,0xb1,0xaa,0x56,0x13,0x18,0xcc,0x8c,0x34,0x61,0x0,0xc0,0x24,0x9a,0xd8,0x8a,0x95,0x10,0x52,0x4a,0x4a,0x91,0x12,0x0,0x30,0x65,0xba,0xcc,0xc,0x88,0x5c,0x16,0x0,0x8,0x60,0x5,0x80,0x19,0xe0,0x2c,0x27,0x45,0x4a,0x52,0x4a,0xd2,0xd,0xc3,0x60,0xa4,0x79,0xa2,0x62,0x30,0x8,0x20,0xc6,0xf9,0xc,0x39,0x84,0x99,0x2b,0xbf,0x45,0x4d,0x65,0xa9,0x98,0x19,0x20,0x2,0xc0,0x28,0xf2,0xea,0xc1,0xb5,0x3f,0xf4,0xda,0xbf,0x60,0x95,0x27,0x10,0x97,0xdc,0x2b,0x75,0xd3,0x4,0xe0,0x4c,0xbb,0x7c,0x93,0x15,0xab,0x97,0x90,0x7a,0x67,0x15,0x80,0x52,0xa5,0xd9,0x73,0xf7,0x88,0x73,0x5f,0x98,0x41,0x8b,0x47,0x28,0x4b,0x50,0xa9,0x9f,0xec,0x5b,0x2d,0xea,0x0,0xac,0xc0,0xaa,0x66,0xff,0xbc,0x8b,0xd,0x1e,0xe4,0x73,0xe7,0x4d,0x23,0xdf,0x3e,0xc5,0x30,0xd9,0x55,0x53,0x7,0x19,0x40,0xe5,0x85,0x25,0x35,0x7a,0x39,0xbb,0x6a,0x6,0xa8,0xac,0xbe,0xa2,0x5d,0x56,0xa5,0xc5,0xcb,0x48,0xc5,0x7e,0xa0,0x62,0x33,0x51,0xe1,0x67,0xfe,0x3c,0x34,0x75,0xa0,0xb2,0xc2,0x39,0x25,0x85,0xf3,0x15,0xa9,0x5b,0x3b,0xbf,0x95,0xb9,0xfe,0x28,0x36,0xc7,0xbc,0x89,0x75,0x8d,0x92,0x91,0xb5,0x8b,0x79,0xc0,0x67,0x9f,0x7f,0x8a,0x9f,0x7f,0xfd,0xa9,0x51,0xf1,0xed,0x9d,0x77,0xf0,0xd5,0xb7,0x5f,0x5c,0xc,0xb8,0xb4,0xb5,0xd,0x4d,0x18,0x8d,0x80,0xad,0xd7,0xdf,0xfc,0xf7,0xe,0xc2,0x30,0xc0,0xe8,0xcc,0x6f,0x4,0x84,0x61,0x50,0xb9,0x17,0xf8,0x8f,0xb1,0x4,0x2c,0x1,0x4b,0xc0,0x12,0xb0,0x4,0x2c,0x1,0x4b,0xc0,0xff,0xf,0x20,0xa5,0x24,0x68,0x17,0xbe,0xfe,0x5c,0x1c,0x45,0x8e,0x56,0xea,0x40,0x83,0xc6,0x0,0x60,0xe8,0xfa,0xc2,0xfa,0x22,0xa7,0xa8,0x11,0x96,0x69,0xa5,0x96,0x69,0xc6,0x0,0xe0,0xd8,0xab,0xb,0x1,0x45,0x8e,0x65,0x9a,0xb1,0x65,0x5a,0xa9,0x6e,0xea,0x76,0xbc,0x62,0x3b,0x83,0xd9,0x54,0xf2,0xc1,0xe1,0x7,0x74,0xe7,0x36,0x61,0x12,0x8d,0x21,0x93,0xa4,0x72,0xe8,0x32,0x74,0x1d,0x8e,0xbd,0x86,0x83,0xc3,0x1b,0x98,0x4d,0x25,0xaf,0xd8,0xce,0xc0,0xd4,0xed,0x98,0x8e,0x8e,0x9e,0xb4,0x4e,0xff,0x7c,0xbe,0xed,0x9f,0x79,0xef,0x7e,0xf8,0xf1,0x7b,0xb7,0x2d,0xdb,0x68,0x74,0x62,0x16,0x49,0xbe,0xff,0xf5,0xe3,0xc3,0x4e,0xdb,0x7d,0xfa,0xca,0x1b,0xdb,0xcf,0x89,0x99,0xb5,0x7,0x5f,0x3e,0x68,0xf,0x3c,0x7f,0xcb,0xf3,0xfd,0xcb,0x93,0x28,0xdc,0x90,0x52,0x1a,0x4a,0x55,0xdf,0x56,0x85,0x10,0x30,0xc,0x43,0x3a,0x76,0xeb,0xc4,0xed,0x74,0x7e,0xe9,0xb9,0x9d,0x3f,0x6e,0x7e,0x72,0xf3,0x8c,0x8a,0xd3,0xfb,0xbd,0x7b,0x3f,0xac,0x4,0x7f,0xf7,0x5b,0x52,0xcd,0x4c,0x66,0x75,0xe1,0xf2,0x12,0x9,0x65,0x8,0x2b,0x5e,0x7d,0x75,0x33,0xbc,0x75,0xeb,0xea,0x14,0xc0,0xf9,0xf1,0x4,0xcc,0x4c,0xc7,0xc7,0xc7,0xa2,0xd7,0xeb,0x35,0x8e,0x30,0x18,0xc,0x78,0x7f,0x7f,0x5f,0x11,0x65,0xc7,0xba,0x7f,0x0,0xff,0xc4,0xaa,0x19,0xfd,0xaf,0x1e,0xb7,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index 8580ffdc5a..59246dfabe 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -141,7 +141,7 @@ void StyleBoxTexture::draw(RID p_canvas_item,const Rect2& p_rect) const {
r.pos.y-=expand_margin[MARGIN_TOP];
r.size.x+=expand_margin[MARGIN_LEFT]+expand_margin[MARGIN_RIGHT];
r.size.y+=expand_margin[MARGIN_TOP]+expand_margin[MARGIN_BOTTOM];
- VisualServer::get_singleton()->canvas_item_add_style_box( p_canvas_item,r,region_rect,texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center);
+ VisualServer::get_singleton()->canvas_item_add_style_box( p_canvas_item,r,region_rect,texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center,modulate);
}
void StyleBoxTexture::set_draw_center(bool p_draw) {
@@ -193,6 +193,19 @@ Rect2 StyleBoxTexture::get_region_rect() const {
}
+void StyleBoxTexture::set_modulate(const Color& p_modulate) {
+ if (modulate==p_modulate)
+ return;
+ modulate=p_modulate;
+ emit_changed();
+}
+
+Color StyleBoxTexture::get_modulate() const {
+
+ return modulate;
+}
+
+
void StyleBoxTexture::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_texture","texture:Texture"),&StyleBoxTexture::set_texture);
@@ -210,6 +223,10 @@ void StyleBoxTexture::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_draw_center","enable"),&StyleBoxTexture::set_draw_center);
ObjectTypeDB::bind_method(_MD("get_draw_center"),&StyleBoxTexture::get_draw_center);
+ ObjectTypeDB::bind_method(_MD("set_modulate","color"),&StyleBoxTexture::set_modulate);
+ ObjectTypeDB::bind_method(_MD("get_modulate"),&StyleBoxTexture::get_modulate);
+
+
ADD_SIGNAL(MethodInfo("texture_changed"));
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture" ), _SCS("set_texture"),_SCS("get_texture") );
@@ -222,6 +239,7 @@ void StyleBoxTexture::_bind_methods() {
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin/right", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_expand_margin_size"),_SCS("get_expand_margin_size"), MARGIN_RIGHT );
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin/top", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_expand_margin_size"),_SCS("get_expand_margin_size"), MARGIN_TOP );
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin/bottom", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_expand_margin_size"),_SCS("get_expand_margin_size"), MARGIN_BOTTOM );
+ ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate/color" ), _SCS("set_modulate"),_SCS("get_modulate"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "draw_center" ) , _SCS("set_draw_center"),_SCS("get_draw_center"));
}
@@ -234,6 +252,7 @@ StyleBoxTexture::StyleBoxTexture() {
expand_margin[i]=0;
}
draw_center=true;
+ modulate=Color(1,1,1,1);
}
StyleBoxTexture::~StyleBoxTexture() {
diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h
index 98aaee754b..f667318e24 100644
--- a/scene/resources/style_box.h
+++ b/scene/resources/style_box.h
@@ -84,6 +84,7 @@ class StyleBoxTexture : public StyleBox {
Rect2 region_rect;
Ref<Texture> texture;
bool draw_center;
+ Color modulate;
protected:
@@ -109,6 +110,9 @@ public:
bool get_draw_center() const;
virtual Size2 get_center_size() const;
+ void set_modulate(const Color& p_modulate);
+ Color get_modulate() const;
+
virtual void draw(RID p_canvas_item,const Rect2& p_rect) const;
diff --git a/tools/editor/connections_dialog.cpp b/tools/editor/connections_dialog.cpp
index bdc420c70f..c4f2435675 100644
--- a/tools/editor/connections_dialog.cpp
+++ b/tools/editor/connections_dialog.cpp
@@ -674,7 +674,7 @@ void ConnectionsDock::update_tree() {
tname=Variant::get_type_name(pi.type);
}
signaldesc+=tname+" "+(pi.name==""?String("arg "+itos(i)):pi.name);
- argnames.push_back(pi.name);
+ argnames.push_back(pi.name+":"+tname);
}
signaldesc+=" ";
diff --git a/tools/editor/create_dialog.cpp b/tools/editor/create_dialog.cpp
index 3ab2e35242..b0cdd79798 100644
--- a/tools/editor/create_dialog.cpp
+++ b/tools/editor/create_dialog.cpp
@@ -292,9 +292,12 @@ String CreateDialog::get_selected_type() {
Object *CreateDialog::instance_selected() {
TreeItem *selected = search_options->get_selected();
+
if (selected) {
String custom = selected->get_metadata(0);
+
+
if (custom!=String()) {
if (EditorNode::get_editor_data().get_custom_types().has(custom)) {
@@ -323,6 +326,7 @@ Object *CreateDialog::instance_selected() {
}
}
+
return NULL;
}
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index 6f70eedcb3..85c560bf9d 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -5220,6 +5220,17 @@ void EditorNode::reload_scene(const String& p_path) {
_scene_tab_changed(current_tab);
}
+int EditorNode::plugin_init_callback_count=0;
+
+void EditorNode::add_plugin_init_callback(EditorPluginInitializeCallback p_callback) {
+
+ ERR_FAIL_COND(plugin_init_callback_count==MAX_INIT_CALLBACKS);
+
+ plugin_init_callbacks[plugin_init_callback_count++]=p_callback;
+}
+
+EditorPluginInitializeCallback EditorNode::plugin_init_callbacks[EditorNode::MAX_INIT_CALLBACKS];
+
void EditorNode::_bind_methods() {
@@ -6499,6 +6510,9 @@ EditorNode::EditorNode() {
for(int i=0;i<EditorPlugins::get_plugin_count();i++)
add_editor_plugin( EditorPlugins::create(i,this) );
+ for(int i=0;i<plugin_init_callback_count;i++) {
+ plugin_init_callbacks[i]();
+ }
resource_preview->add_preview_generator( Ref<EditorTexturePreviewPlugin>( memnew(EditorTexturePreviewPlugin )));
resource_preview->add_preview_generator( Ref<EditorPackedScenePreviewPlugin>( memnew(EditorPackedScenePreviewPlugin )));
@@ -6508,6 +6522,8 @@ EditorNode::EditorNode() {
resource_preview->add_preview_generator( Ref<EditorMeshPreviewPlugin>( memnew(EditorMeshPreviewPlugin )));
resource_preview->add_preview_generator( Ref<EditorBitmapPreviewPlugin>( memnew(EditorBitmapPreviewPlugin )));
+
+
circle_step_msec=OS::get_singleton()->get_ticks_msec();
circle_step_frame=OS::get_singleton()->get_frames_drawn();
circle_step=0;
diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h
index 09c42c6cd0..e6119cf577 100644
--- a/tools/editor/editor_node.h
+++ b/tools/editor/editor_node.h
@@ -94,6 +94,7 @@
typedef void (*EditorNodeInitCallback)();
+typedef void (*EditorPluginInitializeCallback)();
class EditorPluginList;
@@ -575,11 +576,20 @@ private:
static void _file_access_close_error_notify(const String& p_str);
+
+ enum {
+ MAX_INIT_CALLBACKS=128
+ };
+
+ static int plugin_init_callback_count;
+ static EditorPluginInitializeCallback plugin_init_callbacks[MAX_INIT_CALLBACKS];
protected:
void _notification(int p_what);
static void _bind_methods();
public:
+ static void add_plugin_init_callback(EditorPluginInitializeCallback p_callback);
+
enum EditorTable {
EDITOR_2D = 0,
EDITOR_3D,
@@ -741,6 +751,8 @@ public:
static void add_init_callback(EditorNodeInitCallback p_callback) { _init_callbacks.push_back(p_callback); }
+
+
};
diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp
index 9dcf71e256..582462aa19 100644
--- a/tools/editor/editor_settings.cpp
+++ b/tools/editor/editor_settings.cpp
@@ -945,6 +945,8 @@ bool EditorSettings::_save_text_editor_theme(String p_file) {
cf->set_value(theme_section, "word_highlighted_color", ((Color)get("text_editor/word_highlighted_color")).to_html());
cf->set_value(theme_section, "search_result_color", ((Color)get("text_editor/search_result_color")).to_html());
cf->set_value(theme_section, "search_result_border_color", ((Color)get("text_editor/search_result_border_color")).to_html());
+
+
Error err = cf->save(p_file);
if (err == OK) {
diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp
index 376c0daa68..74c8ac9766 100644
--- a/tools/editor/plugins/script_editor_plugin.cpp
+++ b/tools/editor/plugins/script_editor_plugin.cpp
@@ -285,6 +285,17 @@ void ScriptEditor::_breaked(bool p_breaked,bool p_can_debug) {
debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_BREAK), p_breaked );
debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), !p_breaked );
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (!se) {
+
+ continue;
+ }
+
+ se->set_debugger_active(p_breaked);
+ }
+
}
void ScriptEditor::_show_debugger(bool p_show) {
@@ -315,7 +326,16 @@ void ScriptEditor::_goto_script_line(REF p_script,int p_line) {
editor->push_item(p_script.ptr());
- _goto_script_line2(p_line);
+
+ int selected = tab_container->get_current_tab();
+ if (selected<0 || selected>=tab_container->get_child_count())
+ return;
+
+ ScriptEditorBase *current = tab_container->get_child(selected)->cast_to<ScriptEditorBase>();
+ if (!current)
+ return;
+
+ current->goto_line(p_line,true);
}
@@ -1133,6 +1153,7 @@ void ScriptEditor::clear() {
void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) {
+
for(int i=0;i<tab_container->get_child_count();i++) {
ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
@@ -1500,6 +1521,8 @@ void ScriptEditor::save_all_scripts() {
}
+ _update_script_names();
+
}
void ScriptEditor::apply_scripts() const {
@@ -1536,6 +1559,17 @@ void ScriptEditor::_editor_stop() {
debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_STEP), true );
debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_BREAK), true );
debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), true );
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (!se) {
+
+ continue;
+ }
+
+ se->set_debugger_active(false);
+ }
}
diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h
index 03176545ac..5cb70e13d7 100644
--- a/tools/editor/plugins/script_editor_plugin.h
+++ b/tools/editor/plugins/script_editor_plugin.h
@@ -91,7 +91,7 @@ public:
virtual bool is_unsaved()=0;
virtual Variant get_edit_state()=0;
virtual void set_edit_state(const Variant& p_state)=0;
- virtual void goto_line(int p_line)=0;
+ virtual void goto_line(int p_line,bool p_with_error=false)=0;
virtual void trim_trailing_whitespace()=0;
virtual void ensure_focus()=0;
virtual void tag_saved_version()=0;
@@ -100,6 +100,7 @@ public:
virtual bool goto_method(const String& p_method)=0;
virtual void add_callback(const String& p_function,StringArray p_args)=0;
virtual void update_settings()=0;
+ virtual void set_debugger_active(bool p_active)=0;
virtual void set_tooltip_request_func(String p_method,Object* p_obj)=0;
virtual Control *get_edit_menu()=0;
diff --git a/tools/editor/plugins/script_text_editor.cpp b/tools/editor/plugins/script_text_editor.cpp
index 92f1148435..57cf8cbea3 100644
--- a/tools/editor/plugins/script_text_editor.cpp
+++ b/tools/editor/plugins/script_text_editor.cpp
@@ -312,7 +312,7 @@ void ScriptTextEditor::tag_saved_version() {
code_editor->get_text_edit()->tag_saved_version();
}
-void ScriptTextEditor::goto_line(int p_line) {
+void ScriptTextEditor::goto_line(int p_line, bool p_with_error) {
code_editor->get_text_edit()->cursor_set_line(p_line);
}
@@ -952,6 +952,11 @@ void ScriptTextEditor::set_tooltip_request_func(String p_method,Object* p_obj) {
code_editor->get_text_edit()->set_tooltip_request_func(p_obj,p_method,this);
}
+void ScriptTextEditor::set_debugger_active(bool p_active) {
+
+
+}
+
ScriptTextEditor::ScriptTextEditor() {
code_editor = memnew( CodeTextEditor );
diff --git a/tools/editor/plugins/script_text_editor.h b/tools/editor/plugins/script_text_editor.h
index ad927c5725..247fd97e81 100644
--- a/tools/editor/plugins/script_text_editor.h
+++ b/tools/editor/plugins/script_text_editor.h
@@ -115,7 +115,7 @@ public:
virtual void trim_trailing_whitespace();
virtual void tag_saved_version();
- virtual void goto_line(int p_line);
+ virtual void goto_line(int p_line,bool p_with_error=false);
virtual void reload(bool p_soft);
virtual void get_breakpoints(List<int> *p_breakpoints);
@@ -126,6 +126,8 @@ public:
virtual void set_tooltip_request_func(String p_method,Object* p_obj);
+ virtual void set_debugger_active(bool p_active);
+
Control *get_edit_menu();
static void register_editor();
diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp
index f66cdd7cae..0518018e5a 100644
--- a/tools/editor/property_editor.cpp
+++ b/tools/editor/property_editor.cpp
@@ -211,6 +211,10 @@ void CustomPropertyEditor::_menu_option(int p_which) {
ERR_BREAK( !obj );
Resource *res=obj->cast_to<Resource>();
ERR_BREAK( !res );
+ if (owner && hint==PROPERTY_HINT_RESOURCE_TYPE && hint_text=="Script") {
+ //make visual script the right type
+ res->call("set_instance_base_type",owner->get_type());
+ }
v=Ref<Resource>(res).get_ref_ptr();
emit_signal("variant_changed");
diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp
index c4718a19a1..94587456f1 100644
--- a/tools/editor/scene_tree_dock.cpp
+++ b/tools/editor/scene_tree_dock.cpp
@@ -683,6 +683,8 @@ void SceneTreeDock::_notification(int p_what) {
}
button_add->set_icon(get_icon("Add","EditorIcons"));
button_instance->set_icon(get_icon("Instance","EditorIcons"));
+ button_create_script->set_icon(get_icon("Script","EditorIcons"));
+
filter_icon->set_texture(get_icon("Zoom","EditorIcons"));
@@ -1302,11 +1304,18 @@ void SceneTreeDock::_delete_confirm() {
void SceneTreeDock::_selection_changed() {
- if (EditorNode::get_singleton()->get_editor_selection()->get_selection().size()>1) {
+ int selection_size = EditorNode::get_singleton()->get_editor_selection()->get_selection().size();
+ if (selection_size>1) {
//automatically turn on multi-edit
_tool_selected(TOOL_MULTI_EDIT);
}
+ if (selection_size==1 && EditorNode::get_singleton()->get_editor_selection()->get_selection().front()->key()->get_script().is_null()) {
+ button_create_script->show();
+ } else {
+ button_create_script->hide();
+ }
+
//tool_buttons[TOOL_MULTI_EDIT]->set_disabled(EditorNode::get_singleton()->get_editor_selection()->get_selection().size()<2);
}
@@ -1899,6 +1908,12 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec
filter->connect("text_changed",this,"_filter_changed");
+ tb = memnew( ToolButton );
+ tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_SCRIPT, false));
+ tb->set_tooltip(TTR("Create a new script for the selected node."));
+ tb->set_shortcut(ED_GET_SHORTCUT("scene_tree/add_script"));
+ filter_hbc->add_child(tb);
+ button_create_script=tb;
scene_tree = memnew( SceneTreeEditor(false,true,true ));
diff --git a/tools/editor/scene_tree_dock.h b/tools/editor/scene_tree_dock.h
index bcf7ff7173..af612cbc77 100644
--- a/tools/editor/scene_tree_dock.h
+++ b/tools/editor/scene_tree_dock.h
@@ -78,6 +78,7 @@ class SceneTreeDock : public VBoxContainer {
ToolButton *button_add;
ToolButton *button_instance;
+ ToolButton *button_create_script;
SceneTreeEditor *scene_tree;
diff --git a/tools/editor/script_create_dialog.cpp b/tools/editor/script_create_dialog.cpp
index e93a40efbc..749198314a 100644
--- a/tools/editor/script_create_dialog.cpp
+++ b/tools/editor/script_create_dialog.cpp
@@ -117,20 +117,20 @@ void ScriptCreateDialog::ok_pressed() {
- String text = ScriptServer::get_language( language_menu->get_selected() )->get_template(cname,parent_name->get_text());
- Script *script = ScriptServer::get_language( language_menu->get_selected() )->create_script();
- script->set_source_code(text);
- if (cname!="")
- script->set_name(cname);
+ Ref<Script> scr = ScriptServer::get_language( language_menu->get_selected() )->get_template(cname,parent_name->get_text());
+ //scr->set_source_code(text);
+
+
+ if (cname!="")
+ scr->set_name(cname);
- Ref<Script> scr(script);
if (!internal->is_pressed()) {
String lpath = Globals::get_singleton()->localize_path(file_path->get_text());
- script->set_path(lpath);
+ scr->set_path(lpath);
if (!path_valid) {
alert->set_text(TTR("Invalid path!"));
@@ -145,7 +145,7 @@ void ScriptCreateDialog::ok_pressed() {
alert->popup_centered_minsize();
return;
}
- scr->set_path(lpath);
+ //scr->set_path(lpath);
//EditorFileSystem::get_singleton()->update_file(lpath,scr->get_type());
diff --git a/tools/editor/script_editor_debugger.cpp b/tools/editor/script_editor_debugger.cpp
index b6390e5aae..da42f54095 100644
--- a/tools/editor/script_editor_debugger.cpp
+++ b/tools/editor/script_editor_debugger.cpp
@@ -220,6 +220,7 @@ void ScriptEditorDebugger::debug_continue() {
msg.push_back("continue");
ppeer->put_var(msg);
+
}
void ScriptEditorDebugger::_scene_tree_folded(Object* obj) {
@@ -360,7 +361,7 @@ void ScriptEditorDebugger::_parse_message(const String& p_msg,const Array& p_dat
forward->set_disabled(true);
dobreak->set_disabled(false);
docontinue->set_disabled(true);
- emit_signal("breaked",false,false);
+ emit_signal("breaked",false,false,Variant());
//tabs->set_current_tab(0);
profiler->set_enabled(true);
profiler->disable_seeking();