Added a simpler way to do sub-functions in both visual and gdscript with the subcall node.

With this, visual script is almost done (missing registering custom nodes from addon).
All this is probably pretty broken, too and needs a lot of testing.
This commit is contained in:
Juan Linietsky 2016-08-08 01:21:22 -03:00
parent cfbdeeffec
commit 9865650b43
10 changed files with 241 additions and 2 deletions

View file

@ -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;

View file

@ -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.

View file

@ -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;

View file

@ -61,6 +61,7 @@ void register_visual_script_types() {
ObjectTypeDB::register_type<VisualScriptResourcePath>();
ObjectTypeDB::register_type<VisualScriptSelf>();
ObjectTypeDB::register_type<VisualScriptCustomNode>();
ObjectTypeDB::register_type<VisualScriptSubCall>();
ObjectTypeDB::register_type<VisualScriptFunctionCall>();
ObjectTypeDB::register_type<VisualScriptPropertySet>();

View file

@ -1015,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;
@ -2550,7 +2580,7 @@ VisualScriptLanguage::VisualScriptLanguage() {
notification="_notification";
_get_output_port_unsequenced="_get_output_port_unsequenced";
_step="_step";
_subcall="_subcall";
singleton=this;
#ifndef NO_THREADS
lock = Mutex::create();

View file

@ -322,6 +322,10 @@ 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();
@ -470,6 +474,7 @@ public:
StringName notification;
StringName _get_output_port_unsequenced;
StringName _step;
StringName _subcall;
static VisualScriptLanguage* singleton;

View file

@ -2596,6 +2596,7 @@ static void register_editor_callback() {
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"));

View file

@ -2296,6 +2296,133 @@ 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 {
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() {
@ -2311,6 +2438,7 @@ void register_visual_script_nodes() {
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>);
@ -2345,4 +2473,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>);
}

View file

@ -18,6 +18,7 @@ class VisualScriptFunction : public VisualScriptNode {
bool stack_less;
int stack_size;
protected:
bool _set(const StringName& p_name, const Variant& p_value);
@ -610,6 +611,40 @@ public:
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();

View file

@ -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");