From 748836e0b373a0139c11473f862c8071bed244b7 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 28 Aug 2016 20:57:27 -0300 Subject: [PATCH] Several all around fixes to visual scripting (in the process of creating demos) --- core/globals.cpp | 13 +- core/globals.h | 1 + modules/visual_script/register_types.cpp | 4 + modules/visual_script/visual_script.cpp | 42 +- .../visual_script/visual_script_editor.cpp | 105 ++- .../visual_script_flow_control.cpp | 18 +- .../visual_script_flow_control.h | 3 + .../visual_script_func_nodes.cpp | 267 ++++--- .../visual_script/visual_script_func_nodes.h | 13 +- modules/visual_script/visual_script_nodes.cpp | 670 +++++++++++++++++- modules/visual_script/visual_script_nodes.h | 187 ++++- scene/2d/physics_body_2d.cpp | 77 ++ scene/2d/physics_body_2d.h | 13 + 13 files changed, 1275 insertions(+), 138 deletions(-) diff --git a/core/globals.cpp b/core/globals.cpp index 3f0edd68f44..b822f52f157 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -1332,17 +1332,18 @@ Variant _GLOBAL_DEF( const String& p_var, const Variant& p_default) { void Globals::add_singleton(const Singleton &p_singleton) { singletons.push_back(p_singleton); + singleton_ptrs[p_singleton.name]=p_singleton.ptr; } Object* Globals::get_singleton_object(const String& p_name) const { - for(const List::Element *E=singletons.front();E;E=E->next()) { - if (E->get().name == p_name) { - return E->get().ptr; - }; - }; - return NULL; + const Map::Element *E=singleton_ptrs.find(p_name); + if (!E) + return NULL; + else + return E->get(); + }; bool Globals::has_singleton(const String& p_name) const { diff --git a/core/globals.h b/core/globals.h index f24b2daf798..5e0bdb0e545 100644 --- a/core/globals.h +++ b/core/globals.h @@ -91,6 +91,7 @@ protected: Error _save_settings_binary(const String& p_file,const Map > &props,const CustomMap& p_custom=CustomMap()); List singletons; + Map singleton_ptrs; Error _save_custom_bnd(const String& p_file); diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index dad1c751d54..50c3a4075f0 100644 --- a/modules/visual_script/register_types.cpp +++ b/modules/visual_script/register_types.cpp @@ -68,6 +68,10 @@ void register_visual_script_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 61e5d45d8ff..f2fb371d6b4 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -1482,7 +1482,10 @@ Variant VisualScriptInstance::_call_internal(const StringName& p_method, void* p //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); + Variant* ug_working_mem=ug->from->working_mem_idx>=0 ? &variant_stack[ug->from->working_mem_idx] : (Variant*)NULL; + + + bool ok = ug->from->get_output_port_unsequenced(i,&variant_stack[ug->to_stack],ug_working_mem,error_str); if (!ok) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; current_node_id=ug->from->get_id(); @@ -1519,13 +1522,13 @@ Variant VisualScriptInstance::_call_internal(const StringName& p_method, void* p { 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 + 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)); + VSDEBUG("STEP - STARTSEQ: "+itos(start_mode)); int ret = node->step(input_args,output_args,start_mode,working_mem,r_error,error_str); @@ -1734,6 +1737,7 @@ Variant VisualScriptInstance::_call_internal(const StringName& p_method, void* p node = instances[ flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_MASK ]; flow_stack_pos=i; found=true; + break; } } @@ -1762,6 +1766,22 @@ Variant VisualScriptInstance::_call_internal(const StringName& p_method, void* p String err_func = p_method; int err_line=current_node_id; //not a line but it works as one + if (node && (r_error.error!=Variant::CallError::CALL_ERROR_INVALID_METHOD || error_str==String())) { + + if (r_error.error==Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) { + int errorarg=r_error.argument; + error_str="Cannot convert argument "+itos(errorarg+1)+" to "+Variant::get_type_name(r_error.expected)+"."; + } else if (r_error.error==Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) { + error_str="Expected "+itos(r_error.argument)+" arguments."; + } else if (r_error.error==Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) { + error_str="Expected "+itos(r_error.argument)+" arguments."; + } else if (r_error.error==Variant::CallError::CALL_ERROR_INVALID_METHOD) { + error_str="Invalid Call."; + } else if (r_error.error==Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL) { + error_str="Instance is null"; + } + } + //if (!GDScriptLanguage::get_singleton()->debug_break(err_text,false)) { // debugger break did not happen @@ -1959,6 +1979,7 @@ void VisualScriptInstance::create(const Ref& p_script,Object *p_ow function.max_stack=0; function.flow_stack_size=0; function.node_count=0; + Map local_var_indices; if (function.node<0) { VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(),0,"No start node in function: "+String(E->key())); @@ -2022,7 +2043,20 @@ void VisualScriptInstance::create(const Ref& p_script,Object *p_ow } } - if (instance->get_working_memory_size()) { + if (node->cast_to()) { + //working memory is shared only for this node, for the same variables + Ref vslv = node; + + StringName var_name = String(vslv->get_var_name()).strip_edges(); + + if (!local_var_indices.has(var_name)) { + local_var_indices[var_name]=function.max_stack; + function.max_stack++; + } + + instance->working_mem_idx=local_var_indices[var_name]; + + } else if (instance->get_working_memory_size()) { instance->working_mem_idx = function.max_stack; function.max_stack+=instance->get_working_memory_size(); } else { diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 329c3fc1bb0..b8883726460 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -1426,6 +1426,8 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2& p_point,const Variant& p String(d["type"])=="visual_script_variable_drag" || String(d["type"])=="visual_script_signal_drag" || String(d["type"])=="obj_property" || + String(d["type"])=="resource" || + String(d["type"])=="files" || String(d["type"])=="nodes" ) ) { @@ -1586,13 +1588,14 @@ void VisualScriptEditor::drop_data_fw(const Point2& p_point,const Variant& p_dat Ref vnode; vnode.instance(); vnode->set_call_mode(VisualScriptFunctionCall::CALL_MODE_SELF); - vnode->set_base_type(script->get_instance_base_type()); - vnode->set_function(d["function"]); int new_id = script->get_available_id(); undo_redo->create_action(TTR("Add Node")); undo_redo->add_do_method(script.ptr(),"add_node",edited_func,new_id,vnode,ofs); + undo_redo->add_do_method(vnode.ptr(),"set_base_type",script->get_instance_base_type()); + undo_redo->add_do_method(vnode.ptr(),"set_function",d["function"]); + undo_redo->add_undo_method(script.ptr(),"remove_node",edited_func,new_id); undo_redo->add_do_method(this,"_update_graph"); undo_redo->add_undo_method(this,"_update_graph"); @@ -1630,12 +1633,94 @@ void VisualScriptEditor::drop_data_fw(const Point2& p_point,const Variant& p_dat undo_redo->add_undo_method(this,"_update_graph"); undo_redo->commit_action(); + Node* node = graph->get_node(itos(new_id)); + if (node) { + graph->set_selected(node); + _node_selected(node); + } + } + + if (d.has("type") && String(d["type"])=="resource") { + + Vector2 ofs = graph->get_scroll_ofs() + p_point; + if (graph->is_using_snap()) { + int snap = graph->get_snap(); + ofs = ofs.snapped(Vector2(snap,snap)); + } + + ofs/=EDSCALE; + + Ref prnode; + prnode.instance(); + prnode->set_preload(d["resource"]); + + int new_id = script->get_available_id(); + + undo_redo->create_action(TTR("Add Preload Node")); + undo_redo->add_do_method(script.ptr(),"add_node",edited_func,new_id,prnode,ofs); + undo_redo->add_undo_method(script.ptr(),"remove_node",edited_func,new_id); + undo_redo->add_do_method(this,"_update_graph"); + undo_redo->add_undo_method(this,"_update_graph"); + undo_redo->commit_action(); + Node* node = graph->get_node(itos(new_id)); if (node) { graph->set_selected(node); _node_selected(node); } } + + if (d.has("type") && String(d["type"])=="files") { + + Vector2 ofs = graph->get_scroll_ofs() + p_point; + if (graph->is_using_snap()) { + int snap = graph->get_snap(); + ofs = ofs.snapped(Vector2(snap,snap)); + } + + ofs/=EDSCALE; + + Array files = d["files"]; + + List new_ids; + int new_id = script->get_available_id(); + + if (files.size()) { + undo_redo->create_action(TTR("Add Preload Node")); + + for(int i=0;i res = ResourceLoader::load(files[i]); + if (!res.is_valid()) + continue; + + Ref prnode; + prnode.instance(); + prnode->set_preload(res); + + undo_redo->add_do_method(script.ptr(),"add_node",edited_func,new_id,prnode,ofs); + undo_redo->add_undo_method(script.ptr(),"remove_node",edited_func,new_id); + new_ids.push_back(new_id); + new_id++; + ofs+=Vector2(20,20)*EDSCALE; + } + + + undo_redo->add_do_method(this,"_update_graph"); + undo_redo->add_undo_method(this,"_update_graph"); + undo_redo->commit_action(); + } + + for(List::Element *E=new_ids.front();E;E=E->next()) { + + Node* node = graph->get_node(itos(E->get())); + if (node) { + graph->set_selected(node); + _node_selected(node); + } + } + } + if (d.has("type") && String(d["type"])=="nodes") { Node* sn = _find_script_node(get_tree()->get_edited_scene_root(),get_tree()->get_edited_scene_root(),script); @@ -1808,16 +1893,24 @@ void VisualScriptEditor::drop_data_fw(const Point2& p_point,const Variant& p_dat Ref pset; pset.instance(); - pset->set_call_mode(VisualScriptPropertySet::CALL_MODE_NODE_PATH); - pset->set_base_path(sn->get_path_to(node)); + if (sn==node) { + pset->set_call_mode(VisualScriptPropertySet::CALL_MODE_SELF); + } else { + pset->set_call_mode(VisualScriptPropertySet::CALL_MODE_NODE_PATH); + pset->set_base_path(sn->get_path_to(node)); + } vnode=pset; } else { Ref pget; pget.instance(); - pget->set_call_mode(VisualScriptPropertyGet::CALL_MODE_NODE_PATH); - pget->set_base_path(sn->get_path_to(node)); + if (sn==node) { + pget->set_call_mode(VisualScriptPropertyGet::CALL_MODE_SELF); + } else { + pget->set_call_mode(VisualScriptPropertyGet::CALL_MODE_NODE_PATH); + pget->set_base_path(sn->get_path_to(node)); + } vnode=pget; } diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index 78b3f76590e..700d5d57ff1 100644 --- a/modules/visual_script/visual_script_flow_control.cpp +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -86,7 +86,7 @@ void VisualScriptReturn::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_enable_return_value","enable"),&VisualScriptReturn::set_enable_return_value); ObjectTypeDB::bind_method(_MD("is_return_value_enabled"),&VisualScriptReturn::is_return_value_enabled); - String argt="Variant"; + String argt="Any"; for(int i=1;i create_return_node(const String& p_name) { int VisualScriptCondition::get_output_sequence_port_count() const { - return 2; + return 3; } bool VisualScriptCondition::has_input_sequence_port() const{ @@ -174,8 +174,10 @@ String VisualScriptCondition::get_output_sequence_port_text(int p_port) const { if (p_port==0) return "true"; - else + else if (p_port==1) return "false"; + else + return "done"; } PropertyInfo VisualScriptCondition::get_input_value_port_info(int p_idx) const{ @@ -218,10 +220,12 @@ public: 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; + if (p_start_mode==START_MODE_CONTINUE_SEQUENCE) + return 2; + else if (p_inputs[0]->operator bool()) + return 0 | STEP_FLAG_PUSH_STACK_BIT; else - return 1; + return 1 | STEP_FLAG_PUSH_STACK_BIT; } @@ -1662,7 +1666,7 @@ VisualScriptInputFilter::VisualScriptInputFilter() { ////////////////////////////////////////// -////////////////EVENT TYPE FILTER/////////// +////////////////TYPE CAST/////////// ////////////////////////////////////////// diff --git a/modules/visual_script/visual_script_flow_control.h b/modules/visual_script/visual_script_flow_control.h index 879d3ceab1d..42fab2e44d6 100644 --- a/modules/visual_script/visual_script_flow_control.h +++ b/modules/visual_script/visual_script_flow_control.h @@ -320,6 +320,9 @@ public: VisualScriptTypeCast(); }; + + + 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 7cd91c7d507..7414447279e 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -4,6 +4,7 @@ #include "scene/main/node.h" #include "visual_script_nodes.h" #include "io/resource_loader.h" +#include "globals.h" ////////////////////////////////////////// ////////////////CALL////////////////////// @@ -121,12 +122,18 @@ int VisualScriptFunctionCall::get_output_value_port_count() const{ return returns?1:0; } else { + int ret; MethodBind *mb = ObjectTypeDB::get_method(_get_base_type(),function); if (mb) { - return mb->has_return() ? 1 : 0; + ret = mb->has_return() ? 1 : 0; + } else + ret = 1; //it is assumed that script always returns something + + if (call_mode==CALL_MODE_INSTANCE) { + ret++; } - return 1; //it is assumed that script always returns something + return ret; } } @@ -197,15 +204,34 @@ PropertyInfo VisualScriptFunctionCall::get_output_value_port_info(int p_idx) con return PropertyInfo(Variant::get_method_return_type(basic_type,function),""); } else { - MethodBind *mb = ObjectTypeDB::get_method(_get_base_type(),function); - if (mb) { - - PropertyInfo pi = mb->get_argument_info(-1); - pi.name=""; - return pi; + if (call_mode==CALL_MODE_INSTANCE) { + if (p_idx==0) { + return PropertyInfo(Variant::OBJECT,"pass"); + } else { + p_idx--; + } } - return method_cache.return_val; + PropertyInfo ret; + + /*MethodBind *mb = ObjectTypeDB::get_method(_get_base_type(),function); + if (mb) { + + ret = mb->get_argument_info(-1); + } else {*/ + + ret = method_cache.return_val; + + //} + + if (call_mode==CALL_MODE_INSTANCE) { + ret.name="return"; + } else { + ret.name=""; + } + return ret; + + } #else return PropertyInfo(); @@ -215,11 +241,12 @@ PropertyInfo VisualScriptFunctionCall::get_output_value_port_info(int p_idx) con String VisualScriptFunctionCall::get_caption() const { - static const char*cname[4]= { + static const char*cname[5]= { "CallSelf", "CallNode", "CallInstance", - "CallBasic" + "CallBasic", + "CallSingleton" }; String caption = cname[call_mode]; @@ -235,8 +262,12 @@ String VisualScriptFunctionCall::get_text() const { if (call_mode==CALL_MODE_SELF) return " "+String(function)+"()"; + if (call_mode==CALL_MODE_SINGLETON) + return String(singleton)+":"+String(function)+"()"; else if (call_mode==CALL_MODE_BASIC_TYPE) return Variant::get_type_name(basic_type)+"."+String(function)+"()"; + else if (call_mode==CALL_MODE_NODE_PATH) + return " ["+String(base_path.simplified())+"]."+String(function)+"()"; else return " "+base_type+"."+String(function)+"()"; @@ -289,6 +320,27 @@ String VisualScriptFunctionCall::get_base_script() const { return base_script; } +void VisualScriptFunctionCall::set_singleton(const StringName& p_path) { + + if (singleton==p_path) + return; + + singleton=p_path; + Object *obj = Globals::get_singleton()->get_singleton_object(singleton); + if (obj) { + base_type=obj->get_type(); + } + + _change_notify(); + ports_changed_notify(); +} + +StringName VisualScriptFunctionCall::get_singleton() const { + + return singleton; +} + + void VisualScriptFunctionCall::_update_method_cache() { StringName type; @@ -309,6 +361,15 @@ void VisualScriptFunctionCall::_update_method_cache() { base_type=type; //cache, too script=get_visual_script(); } + + } else if (call_mode==CALL_MODE_SINGLETON) { + + Object *obj = Globals::get_singleton()->get_singleton_object(singleton); + if (obj) { + type=obj->get_type(); + script=obj->get_script(); + } + } else if (call_mode==CALL_MODE_INSTANCE) { type=base_type; @@ -475,6 +536,24 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo& property) const } } + if (property.name=="function/singleton") { + if (call_mode!=CALL_MODE_SINGLETON) { + property.usage=0; + } else { + List names; + Globals::get_singleton()->get_singletons(&names); + property.hint=PROPERTY_HINT_ENUM; + String sl; + for (List::Element *E=names.front();E;E=E->next()) { + if (sl!=String()) + sl+=","; + sl+=E->get().name; + } + property.hint_string=sl; + + } + } + if (property.name=="function/node_path") { if (call_mode!=CALL_MODE_NODE_PATH) { property.usage=0; @@ -499,6 +578,17 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo& property) const } else if (call_mode==CALL_MODE_SELF && get_visual_script().is_valid()) { property.hint=PROPERTY_HINT_METHOD_OF_SCRIPT; property.hint_string=itos(get_visual_script()->get_instance_ID()); + } else if (call_mode==CALL_MODE_SINGLETON) { + + Object *obj = Globals::get_singleton()->get_singleton_object(singleton); + if (obj) { + property.hint=PROPERTY_HINT_METHOD_OF_INSTANCE; + property.hint_string=itos(obj->get_instance_ID()); + } else { + + property.hint=PROPERTY_HINT_METHOD_OF_BASE_TYPE; + property.hint_string=base_type;//should be cached + } } else if (call_mode==CALL_MODE_INSTANCE) { property.hint=PROPERTY_HINT_METHOD_OF_BASE_TYPE; property.hint_string=base_type; @@ -579,6 +669,9 @@ void VisualScriptFunctionCall::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_basic_type","basic_type"),&VisualScriptFunctionCall::set_basic_type); ObjectTypeDB::bind_method(_MD("get_basic_type"),&VisualScriptFunctionCall::get_basic_type); + ObjectTypeDB::bind_method(_MD("set_singleton","singleton"),&VisualScriptFunctionCall::set_singleton); + ObjectTypeDB::bind_method(_MD("get_singleton"),&VisualScriptFunctionCall::get_singleton); + ObjectTypeDB::bind_method(_MD("set_function","function"),&VisualScriptFunctionCall::set_function); ObjectTypeDB::bind_method(_MD("get_function"),&VisualScriptFunctionCall::get_function); @@ -618,9 +711,12 @@ void VisualScriptFunctionCall::_bind_methods() { script_ext_hint+="*."+E->get(); } - ADD_PROPERTY(PropertyInfo(Variant::INT,"function/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type"),_SCS("set_call_mode"),_SCS("get_call_mode")); + + + ADD_PROPERTY(PropertyInfo(Variant::INT,"function/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type,Singleton"),_SCS("set_call_mode"),_SCS("get_call_mode")); ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type")); ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/base_script",PROPERTY_HINT_FILE,script_ext_hint),_SCS("set_base_script"),_SCS("get_base_script")); + ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/singleton"),_SCS("set_singleton"),_SCS("get_singleton")); ADD_PROPERTY(PropertyInfo(Variant::INT,"function/basic_type",PROPERTY_HINT_ENUM,bt),_SCS("set_basic_type"),_SCS("get_basic_type")); 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::DICTIONARY,"function/argument_cache",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_argument_cache"),_SCS("_get_argument_cache")); @@ -644,6 +740,7 @@ public: bool returns; VisualScriptFunctionCall::RPCCallMode rpc_mode; StringName function; + StringName singleton; VisualScriptFunctionCall *node; VisualScriptInstance *instance; @@ -736,13 +833,37 @@ public: call_rpc(obj,p_inputs+1,input_args-1); } } else if (returns) { - *p_outputs[0] = v.call(function,p_inputs+1,input_args,r_error); + if (call_mode==VisualScriptFunctionCall::CALL_MODE_INSTANCE) { + *p_outputs[1] = v.call(function,p_inputs+1,input_args,r_error); + } else { + *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; + if (call_mode==VisualScriptFunctionCall::CALL_MODE_INSTANCE) { + *p_outputs[0]=*p_inputs[0]; + } + } break; + case VisualScriptFunctionCall::CALL_MODE_SINGLETON: { + + Object *object=Globals::get_singleton()->get_singleton_object(singleton); + if (!object) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str="Invalid singleton name: '"+String(singleton)+"'"; + return 0; + } + + if (rpc_mode) { + call_rpc(object,p_inputs,input_args); + } else 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; } return 0; @@ -756,6 +877,7 @@ VisualScriptNodeInstance* VisualScriptFunctionCall::instance(VisualScriptInstanc VisualScriptNodeInstanceFunctionCall * instance = memnew(VisualScriptNodeInstanceFunctionCall ); instance->node=this; instance->instance=p_instance; + instance->singleton=singleton; instance->function=function; instance->call_mode=call_mode; instance->returns=get_output_value_port_count(); @@ -866,16 +988,13 @@ StringName VisualScriptPropertySet::_get_base_type() const { int VisualScriptPropertySet::get_input_value_port_count() const{ - int pc = (call_mode==CALL_MODE_BASIC_TYPE || call_mode==CALL_MODE_INSTANCE)?1:0; - - if (!use_builtin_value) - pc++; + int pc = (call_mode==CALL_MODE_BASIC_TYPE || call_mode==CALL_MODE_INSTANCE)?2:1; return pc; } int VisualScriptPropertySet::get_output_value_port_count() const{ - return call_mode==CALL_MODE_BASIC_TYPE? 1 : 0; + return (call_mode==CALL_MODE_BASIC_TYPE || call_mode==CALL_MODE_INSTANCE) ? 1 : 0; } String VisualScriptPropertySet::get_output_sequence_port_text(int p_port) const { @@ -904,6 +1023,8 @@ PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) const{ if (call_mode==CALL_MODE_BASIC_TYPE) { return PropertyInfo(basic_type,"out"); + } else if (call_mode==CALL_MODE_INSTANCE) { + return PropertyInfo(Variant::OBJECT,"pass"); } else { return PropertyInfo(); } @@ -929,18 +1050,12 @@ String VisualScriptPropertySet::get_text() const { if (call_mode==CALL_MODE_BASIC_TYPE) prop=Variant::get_type_name(basic_type)+"."+property; - else + else if (call_mode==CALL_MODE_NODE_PATH) + prop=String(base_path)+":"+property; + else if (call_mode==CALL_MODE_SELF) prop=property; - - if (use_builtin_value) { - String bit = builtin_value.get_construct_string(); - if (bit.length()>40) { - bit=bit.substr(0,40); - bit+="..."; - } - - prop+="\n "+bit; - } + else if (call_mode==CALL_MODE_INSTANCE) + prop=String(base_type)+":"+property; return prop; @@ -1183,35 +1298,6 @@ VisualScriptPropertySet::CallMode VisualScriptPropertySet::get_call_mode() const } -void VisualScriptPropertySet::set_use_builtin_value(bool p_use) { - - if (use_builtin_value==p_use) - return; - - use_builtin_value=p_use; - _change_notify(); - ports_changed_notify(); - -} - -bool VisualScriptPropertySet::is_using_builtin_value() const{ - - return use_builtin_value; -} - -void VisualScriptPropertySet::set_builtin_value(const Variant& p_value){ - - if (builtin_value==p_value) - return; - - builtin_value=p_value; - ports_changed_notify(); - -} -Variant VisualScriptPropertySet::get_builtin_value() const{ - - return builtin_value; -} void VisualScriptPropertySet::_set_type_cache(const Dictionary &p_type) { @@ -1308,17 +1394,6 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo& property) const { } - if (property.name=="value/builtin") { - - if (!use_builtin_value) { - property.usage=0; - } else { - property.type=type_cache.type; - property.hint=type_cache.hint; - property.hint_string=type_cache.hint_string; - } - - } } void VisualScriptPropertySet::_bind_methods() { @@ -1347,11 +1422,7 @@ void VisualScriptPropertySet::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_base_path","base_path"),&VisualScriptPropertySet::set_base_path); ObjectTypeDB::bind_method(_MD("get_base_path"),&VisualScriptPropertySet::get_base_path); - ObjectTypeDB::bind_method(_MD("set_builtin_value","value"),&VisualScriptPropertySet::set_builtin_value); - ObjectTypeDB::bind_method(_MD("get_builtin_value"),&VisualScriptPropertySet::get_builtin_value); - ObjectTypeDB::bind_method(_MD("set_use_builtin_value","enable"),&VisualScriptPropertySet::set_use_builtin_value); - ObjectTypeDB::bind_method(_MD("is_using_builtin_value"),&VisualScriptPropertySet::is_using_builtin_value); String bt; for(int i=0;iset(property,builtin_val,&valid); - } else { - object->set(property,*p_inputs[0],&valid); - } + 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."; + r_error_str="Invalid set value '"+String(*p_inputs[0])+"' on property '"+String(property)+"' of type "+object->get_type(); } } break; case VisualScriptPropertySet::CALL_MODE_NODE_PATH: { @@ -1457,15 +1520,11 @@ public: bool valid; - if (use_builtin) { - another->set(property,builtin_val,&valid); - } else { - another->set(property,*p_inputs[0],&valid); - } + 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."; + r_error_str="Invalid set value '"+String(*p_inputs[0])+"' on property '"+String(property)+"' of type "+another->get_type(); } } break; @@ -1476,20 +1535,14 @@ public: bool valid; - if (use_builtin) { - v.set(property,builtin_val,&valid); - } else { - v.set(property,p_inputs[1],&valid); - } + 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."; + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str="Invalid set value '"+String(*p_inputs[1])+"' ("+Variant::get_type_name(p_inputs[1]->get_type())+") on property '"+String(property)+"' of type "+Variant::get_type_name(v.get_type()); } - if (call_mode==VisualScriptPropertySet::CALL_MODE_BASIC_TYPE) { - *p_outputs[0]=v; - } + *p_outputs[0]=v; } break; @@ -1509,8 +1562,6 @@ VisualScriptNodeInstance* VisualScriptPropertySet::instance(VisualScriptInstance 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; } @@ -1666,12 +1717,18 @@ String VisualScriptPropertyGet::get_caption() const { String VisualScriptPropertyGet::get_text() const { + String prop; if (call_mode==CALL_MODE_BASIC_TYPE) - return Variant::get_type_name(basic_type)+"."+property; - else - return property; + prop=Variant::get_type_name(basic_type)+"."+property; + else if (call_mode==CALL_MODE_NODE_PATH) + prop=String(base_path)+":"+property; + else if (call_mode==CALL_MODE_SELF) + prop=property; + else if (call_mode==CALL_MODE_INSTANCE) + prop=String(base_type)+":"+property; + return prop; } void VisualScriptPropertyGet::set_base_type(const StringName& p_type) { diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h index 9d2c26faf04..f958da82225 100644 --- a/modules/visual_script/visual_script_func_nodes.h +++ b/modules/visual_script/visual_script_func_nodes.h @@ -13,6 +13,7 @@ public: CALL_MODE_NODE_PATH, CALL_MODE_INSTANCE, CALL_MODE_BASIC_TYPE, + CALL_MODE_SINGLETON, }; enum RPCCallMode { @@ -33,6 +34,7 @@ private: StringName function; int use_default_args; RPCCallMode rpc_call_mode; + StringName singleton; Node *_get_base_node() const; @@ -78,12 +80,16 @@ public: void set_base_script(const String& p_path); String get_base_script() const; + void set_singleton(const StringName& p_type); + StringName get_singleton() const; + void set_function(const StringName& p_type); StringName get_function() 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; @@ -124,8 +130,6 @@ private: String base_script; NodePath base_path; StringName property; - bool use_builtin_value; - Variant builtin_value; InputEvent::Type event_type; Node *_get_base_node() const; @@ -185,11 +189,6 @@ public: void set_call_mode(CallMode p_mode); CallMode get_call_mode() const; - void set_use_builtin_value(bool p_use); - bool is_using_builtin_value() const; - - void set_builtin_value(const Variant &p_value); - Variant get_builtin_value() const; virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index f8071cbf60d..21a27b91a36 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -4,6 +4,7 @@ #include "scene/main/scene_main_loop.h" #include "os/os.h" #include "scene/main/node.h" +#include "os/input.h" ////////////////////////////////////////// ////////////////FUNCTION////////////////// @@ -116,7 +117,7 @@ void VisualScriptFunction::_get_property_list( List *p_list) cons p_list->push_back(PropertyInfo(Variant::INT,"argument_count",PROPERTY_HINT_RANGE,"0,256")); - String argt="Variant"; + String argt="Any"; for(int i=1;i0) types+=","; types+=op_names[i]; } - ADD_PROPERTY(PropertyInfo(Variant::INT,"operator_value/type",PROPERTY_HINT_ENUM,types),_SCS("set_operator"),_SCS("get_operator")); + + String argt="Any"; + for(int i=1;iget_path().is_resource_file()) { + return preload->get_path(); + } else if (preload->get_name()!=String()) { + return preload->get_name(); + } else { + return preload->get_type(); + } + } else { + return ""; + } +} + + +void VisualScriptPreload::set_preload(const Ref& p_preload){ + + if (preload==p_preload) + return; + + preload=p_preload; + ports_changed_notify(); +} +Ref VisualScriptPreload::get_preload() const{ + + return preload; +} + + +void VisualScriptPreload::_bind_methods() { + + + ObjectTypeDB::bind_method(_MD("set_preload","resource"),&VisualScriptPreload::set_preload); + ObjectTypeDB::bind_method(_MD("get_preload"),&VisualScriptPreload::get_preload); + + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"resource",PROPERTY_HINT_RESOURCE_TYPE,"Resource"),_SCS("set_preload"),_SCS("get_preload")); + +} + +class VisualScriptNodeInstancePreload : public VisualScriptNodeInstance { +public: + + Ref preload; + //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=preload; + + 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* VisualScriptPreload::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstancePreload * instance = memnew(VisualScriptNodeInstancePreload ); + instance->preload=preload; + return instance; +} + +VisualScriptPreload::VisualScriptPreload() { + +} + + ////////////////////////////////////////// @@ -2751,6 +2900,519 @@ static Ref create_constructor_node(const String& p_name) { return vsc; } +////////////////////////////////////////// +////////////////LocalVar/////////// +////////////////////////////////////////// + +int VisualScriptLocalVar::get_output_sequence_port_count() const { + + return 1; +} + +bool VisualScriptLocalVar::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptLocalVar::get_input_value_port_count() const{ + return 1; +} +int VisualScriptLocalVar::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptLocalVar::get_output_sequence_port_text(int p_port) const { + + return ""; +} + +PropertyInfo VisualScriptLocalVar::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(type,"set"); +} +PropertyInfo VisualScriptLocalVar::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(type,"get"); +} + + +String VisualScriptLocalVar::get_caption() const { + + return "LocalVar"; +} + + +String VisualScriptLocalVar::get_text() const { + + return name; +} + + +String VisualScriptLocalVar::get_category() const { + + return "data"; +} + + +void VisualScriptLocalVar::set_var_name(const StringName& p_name) { + + if (name==p_name) + return; + + name=p_name; + ports_changed_notify(); + +} + +StringName VisualScriptLocalVar::get_var_name() const { + + return name; +} + +void VisualScriptLocalVar::set_var_type(Variant::Type p_type) { + + type=p_type; + ports_changed_notify(); +} + +Variant::Type VisualScriptLocalVar::get_var_type() const { + + return type; +} + + +class VisualScriptNodeInstanceLocalVar : public VisualScriptNodeInstance { +public: + + VisualScriptInstance* instance; + StringName name; + + + virtual int get_working_memory_size() const { return 1; } + 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=*p_working_mem; + 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) { + + *p_working_mem=*p_inputs[0]; + *p_outputs[0]=*p_working_mem; + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptLocalVar::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceLocalVar * instance = memnew(VisualScriptNodeInstanceLocalVar ); + instance->instance=p_instance; + instance->name=name; + + return instance; +} + + + +void VisualScriptLocalVar::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_var_name","name"),&VisualScriptLocalVar::set_var_name); + ObjectTypeDB::bind_method(_MD("get_var_name"),&VisualScriptLocalVar::get_var_name); + + ObjectTypeDB::bind_method(_MD("set_var_type","type"),&VisualScriptLocalVar::set_var_type); + ObjectTypeDB::bind_method(_MD("get_var_type"),&VisualScriptLocalVar::get_var_type); + + String argt="Any"; + for(int i=1;iis_action_pressed(action); + 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* VisualScriptInputAction::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceInputAction * instance = memnew(VisualScriptNodeInstanceInputAction ); + instance->instance=p_instance; + instance->action=name; + + return instance; +} + +void VisualScriptInputAction::_validate_property(PropertyInfo& property) const { + + + if (property.name=="action") { + + property.hint=PROPERTY_HINT_ENUM; + String actions; + + List pinfo; + Globals::get_singleton()->get_property_list(&pinfo); + Vector al; + + for(List::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); + } + + al.sort();; + + for(int i=0;i pinfo; + v.get_property_list(&pinfo); + + for (List::Element *E=pinfo.front();E;E=E->next()) { + + Element e; + e.name=E->get().name; + e.type=E->get().type; + elements.push_back(e); + } +} + +void VisualScriptDeconstruct::set_deconstruct_type(Variant::Type p_type) { + + if (type==p_type) + return; + + type=p_type; + _update_elements(); + ports_changed_notify(); + _change_notify(); //to make input appear/disappear +} + +Variant::Type VisualScriptDeconstruct::get_deconstruct_type() const { + + return type; +} + +void VisualScriptDeconstruct::set_deconstruct_input_type(InputEvent::Type p_input_type) { + + if (input_type==p_input_type) + return; + + input_type=p_input_type; + _update_elements(); + ports_changed_notify(); +} + +InputEvent::Type VisualScriptDeconstruct::get_deconstruct_input_type() const { + + return input_type; +} + +void VisualScriptDeconstruct::_set_elem_cache(const Array& p_elements) { + + ERR_FAIL_COND(p_elements.size()%2==1); + elements.resize(p_elements.size()/2); + for(int i=0;i outputs; + + //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) { + + Variant in=*p_inputs[0]; + + for(int i=0;iinstance=p_instance; + instance->outputs.resize(elements.size()); + for(int i=0;ioutputs[i]=elements[i].name; + } + + return instance; +} + + + +void VisualScriptDeconstruct::_validate_property(PropertyInfo& property) const { + + if (property.name=="input_type") { + if (type!=Variant::INPUT_EVENT) { + property.usage=0; + } + } +} + + +void VisualScriptDeconstruct::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_deconstruct_type","type"),&VisualScriptDeconstruct::set_deconstruct_type); + ObjectTypeDB::bind_method(_MD("get_deconstruct_type"),&VisualScriptDeconstruct::get_deconstruct_type); + + ObjectTypeDB::bind_method(_MD("set_deconstruct_input_type","input_type"),&VisualScriptDeconstruct::set_deconstruct_input_type); + ObjectTypeDB::bind_method(_MD("get_deconstruct_input_type"),&VisualScriptDeconstruct::get_deconstruct_input_type); + + ObjectTypeDB::bind_method(_MD("_set_elem_cache","_cache"),&VisualScriptDeconstruct::_set_elem_cache); + ObjectTypeDB::bind_method(_MD("_get_elem_cache"),&VisualScriptDeconstruct::_get_elem_cache); + + String argt="Any"; + for(int i=1;iadd_register_func("custom/custom_node",create_node_generic); VisualScriptLanguage::singleton->add_register_func("custom/sub_call",create_node_generic); VisualScriptLanguage::singleton->add_register_func("data/comment",create_node_generic); + VisualScriptLanguage::singleton->add_register_func("data/local_var",create_node_generic); + VisualScriptLanguage::singleton->add_register_func("data/preload",create_node_generic); + VisualScriptLanguage::singleton->add_register_func("data/action",create_node_generic); VisualScriptLanguage::singleton->add_register_func("index/get_index",create_node_generic); @@ -2802,6 +3467,7 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("operators/logic/not",create_op_node); VisualScriptLanguage::singleton->add_register_func("operators/logic/in",create_op_node); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct",create_node_generic); for(int i=1;i preload; +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"; } + + void set_preload(const Ref& p_value); + Ref get_preload() const; + + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + + VisualScriptPreload(); +}; + class VisualScriptIndexGet : public VisualScriptNode { OBJ_TYPE(VisualScriptIndexGet,VisualScriptNode) @@ -702,7 +745,6 @@ class VisualScriptConstructor: public VisualScriptNode { protected: - virtual bool _use_builtin_script() const { return true; } static void _bind_methods(); public: @@ -735,6 +777,149 @@ public: VisualScriptConstructor(); }; + + + +class VisualScriptLocalVar: public VisualScriptNode { + + OBJ_TYPE(VisualScriptLocalVar,VisualScriptNode) + + StringName name; + Variant::Type type; + +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; + + void set_var_name(const StringName& p_name); + StringName get_var_name() const; + + void set_var_type(Variant::Type p_type); + Variant::Type get_var_type() const; + + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + + VisualScriptLocalVar(); +}; + + + + +class VisualScriptInputAction: public VisualScriptNode { + + OBJ_TYPE(VisualScriptInputAction,VisualScriptNode) + + StringName name; + +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; + + void set_action_name(const StringName& p_name); + StringName get_action_name() const; + + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + + VisualScriptInputAction(); +}; + + + +class VisualScriptDeconstruct: public VisualScriptNode { + + OBJ_TYPE(VisualScriptDeconstruct,VisualScriptNode) + + + struct Element { + StringName name; + Variant::Type type; + }; + + + Vector elements; + + void _update_elements(); + Variant::Type type; + InputEvent::Type input_type; + + void _set_elem_cache(const Array& p_elements); + Array _get_elem_cache() const; + + virtual void _validate_property(PropertyInfo& property) const; + +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; + + void set_deconstruct_type(Variant::Type p_type); + Variant::Type get_deconstruct_type() const; + + void set_deconstruct_input_type(InputEvent::Type p_input_type); + InputEvent::Type get_deconstruct_input_type() const; + + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + + VisualScriptDeconstruct(); +}; + + void register_visual_script_nodes(); void unregister_visual_script_nodes(); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 26c4ea385f1..75fa6054ad1 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1226,6 +1226,73 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { #endif } + + +Vector2 KinematicBody2D::move_and_slide(const Vector2& p_linear_velocity,const Vector2& p_floor_direction,int p_max_bounces) { + + Vector2 motion = p_linear_velocity*get_fixed_process_delta_time(); + Vector2 lv = p_linear_velocity; + + move_and_slide_on_floor=false; + move_and_slide_on_ceiling=false; + move_and_slide_on_wall=false; + move_and_slide_colliders.clear(); + + while(motion!=Vector2() && p_max_bounces) { + + motion=move(motion); + + if (is_colliding()) { + + if (p_floor_direction==Vector2()) { + //all is a wall + move_and_slide_on_wall=true; + } else { + if ( get_collision_normal().dot(p_floor_direction) > Math::cos(Math::deg2rad(45))) { //floor + move_and_slide_on_floor=true; + move_and_slide_floor_velocity=get_collider_velocity(); + } else if ( get_collision_normal().dot(p_floor_direction) < Math::cos(Math::deg2rad(45))) { //ceiling + move_and_slide_on_ceiling=true; + } else { + move_and_slide_on_wall=true; + } + + } + + motion=get_collision_normal().slide(motion); + lv=get_collision_normal().slide(lv); + Variant collider = _get_collider(); + if (collider.get_type()!=Variant::NIL) { + move_and_slide_colliders.push_back(collider); + } + + } else { + break; + } + + p_max_bounces--; + } + + return lv; +} + +bool KinematicBody2D::is_move_and_slide_on_floor() const { + + return move_and_slide_on_floor; +} +bool KinematicBody2D::is_move_and_slide_on_wall() const{ + + return move_and_slide_on_wall; +} +bool KinematicBody2D::is_move_and_slide_on_ceiling() const{ + + return move_and_slide_on_ceiling; +} +Array KinematicBody2D::get_move_and_slide_colliders() const{ + + return move_and_slide_colliders; +} + Vector2 KinematicBody2D::move_to(const Vector2& p_position) { return move(p_position-get_global_pos()); @@ -1300,6 +1367,7 @@ void KinematicBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("move","rel_vec"),&KinematicBody2D::move); ObjectTypeDB::bind_method(_MD("move_to","position"),&KinematicBody2D::move_to); + ObjectTypeDB::bind_method(_MD("move_and_slide","linear_velocity","floor_normal","max_bounces"),&KinematicBody2D::move_and_slide,DEFVAL(Vector2(0,0)),DEFVAL(4)); ObjectTypeDB::bind_method(_MD("test_move","rel_vec"),&KinematicBody2D::test_move); ObjectTypeDB::bind_method(_MD("get_travel"),&KinematicBody2D::get_travel); @@ -1313,6 +1381,10 @@ void KinematicBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_collider:Object"),&KinematicBody2D::_get_collider); ObjectTypeDB::bind_method(_MD("get_collider_shape"),&KinematicBody2D::get_collider_shape); ObjectTypeDB::bind_method(_MD("get_collider_metadata:Variant"),&KinematicBody2D::get_collider_metadata); + ObjectTypeDB::bind_method(_MD("get_move_and_slide_colliders"),&KinematicBody2D::get_move_and_slide_colliders); + ObjectTypeDB::bind_method(_MD("is_move_and_slide_on_floor"),&KinematicBody2D::is_move_and_slide_on_floor); + ObjectTypeDB::bind_method(_MD("is_move_and_slide_on_ceiling"),&KinematicBody2D::is_move_and_slide_on_ceiling); + ObjectTypeDB::bind_method(_MD("is_move_and_slide_on_wall"),&KinematicBody2D::is_move_and_slide_on_wall); ObjectTypeDB::bind_method(_MD("set_collision_margin","pixels"),&KinematicBody2D::set_collision_margin); ObjectTypeDB::bind_method(_MD("get_collision_margin","pixels"),&KinematicBody2D::get_collision_margin); @@ -1330,6 +1402,11 @@ KinematicBody2D::KinematicBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_KI collider_shape=0; margin=0.08; + + move_and_slide_on_floor=false; + move_and_slide_on_ceiling=false; + move_and_slide_on_wall=false; + } KinematicBody2D::~KinematicBody2D() { diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 5af65bff33c..387267cd090 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -302,6 +302,12 @@ class KinematicBody2D : public PhysicsBody2D { Variant collider_metadata; Vector2 travel; + Vector2 move_and_slide_floor_velocity; + bool move_and_slide_on_floor; + bool move_and_slide_on_ceiling; + bool move_and_slide_on_wall; + Array move_and_slide_colliders; + Variant _get_collider() const; _FORCE_INLINE_ bool _ignores_mode(Physics2DServer::BodyMode) const; @@ -329,6 +335,13 @@ public: void set_collision_margin(float p_margin); float get_collision_margin() const; + Vector2 move_and_slide(const Vector2& p_linear_velocity,const Vector2& p_floor_direction=Vector2(0,0),int p_max_bounces=4); + bool is_move_and_slide_on_floor() const; + bool is_move_and_slide_on_wall() const; + bool is_move_and_slide_on_ceiling() const; + Array get_move_and_slide_colliders() const; + + KinematicBody2D(); ~KinematicBody2D();