#include "visual_script_builtin_funcs.h" #include "math_funcs.h" #include "class_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", "cos", "tan", "sinh", "cosh", "tanh", "asin", "acos", "atan", "atan2", "sqrt", "fmod", "fposmod", "floor", "ceil", "round", "abs", "sign", "pow", "log", "exp", "is_nan", "is_inf", "ease", "decimals", "stepify", "lerp", "dectime", "randomize", "randi", "randf", "rand_range", "seed", "rand_seed", "deg2rad", "rad2deg", "linear2db", "db2linear", "max", "min", "clamp", "nearest_po2", "weakref", "funcref", "convert", "typeof", "type_exists", "char", "str", "print", "printerr", "printraw", "var2str", "str2var", "var2bytes", "bytes2var", "color_named", }; VisualScriptBuiltinFunc::BuiltinFunc VisualScriptBuiltinFunc::find_function(const String& p_string) { for(int i=0;iis_num()) {\ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;\ r_error.argument=m_arg;\ r_error.expected=Variant::REAL;\ return;\ } void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func,const Variant** p_inputs,Variant* r_return,Variant::CallError& r_error,String& r_error_str) { switch(p_func) { case VisualScriptBuiltinFunc::MATH_SIN: { VALIDATE_ARG_NUM(0); *r_return=Math::sin((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_COS: { VALIDATE_ARG_NUM(0); *r_return=Math::cos((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_TAN: { VALIDATE_ARG_NUM(0); *r_return=Math::tan((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_SINH: { VALIDATE_ARG_NUM(0); *r_return=Math::sinh((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_COSH: { VALIDATE_ARG_NUM(0); *r_return=Math::cosh((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_TANH: { VALIDATE_ARG_NUM(0); *r_return=Math::tanh((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ASIN: { VALIDATE_ARG_NUM(0); *r_return=Math::asin((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ACOS: { VALIDATE_ARG_NUM(0); *r_return=Math::acos((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ATAN: { VALIDATE_ARG_NUM(0); *r_return=Math::atan((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ATAN2: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return=Math::atan2((double)*p_inputs[0],(double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_SQRT: { VALIDATE_ARG_NUM(0); *r_return=Math::sqrt((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_FMOD: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return=Math::fmod((double)*p_inputs[0],(double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_FPOSMOD: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return=Math::fposmod((double)*p_inputs[0],(double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_FLOOR: { VALIDATE_ARG_NUM(0); *r_return=Math::floor((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_CEIL: { VALIDATE_ARG_NUM(0); *r_return=Math::ceil((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ROUND: { VALIDATE_ARG_NUM(0); *r_return=Math::round((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ABS: { if (p_inputs[0]->get_type()==Variant::INT) { int64_t i = *p_inputs[0]; *r_return=ABS(i); } else if (p_inputs[0]->get_type()==Variant::REAL) { real_t r = *p_inputs[0]; *r_return=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]; *r_return= i < 0 ? -1 : ( i > 0 ? +1 : 0); } else if (p_inputs[0]->get_type()==Variant::REAL) { real_t r = *p_inputs[0]; *r_return= 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); *r_return=Math::pow((double)*p_inputs[0],(double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_LOG: { VALIDATE_ARG_NUM(0); *r_return=Math::log((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_EXP: { VALIDATE_ARG_NUM(0); *r_return=Math::exp((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ISNAN: { VALIDATE_ARG_NUM(0); *r_return=Math::is_nan((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ISINF: { VALIDATE_ARG_NUM(0); *r_return=Math::is_inf((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_EASE: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return=Math::ease((double)*p_inputs[0],(double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_DECIMALS: { VALIDATE_ARG_NUM(0); *r_return=Math::step_decimals((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_STEPIFY: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return=Math::stepify((double)*p_inputs[0],(double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_LERP: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return=Math::lerp((double)*p_inputs[0],(double)*p_inputs[1],(double)*p_inputs[2]); } break; case VisualScriptBuiltinFunc::MATH_DECTIME: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return=Math::dectime((double)*p_inputs[0],(double)*p_inputs[1],(double)*p_inputs[2]); } break; case VisualScriptBuiltinFunc::MATH_RANDOMIZE: { Math::randomize(); } break; case VisualScriptBuiltinFunc::MATH_RAND: { *r_return=Math::rand(); } break; case VisualScriptBuiltinFunc::MATH_RANDF: { *r_return=Math::randf(); } break; case VisualScriptBuiltinFunc::MATH_RANDOM: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return=Math::random((double)*p_inputs[0],(double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_SEED: { VALIDATE_ARG_NUM(0); uint64_t seed=*p_inputs[0]; Math::seed(seed); } break; case VisualScriptBuiltinFunc::MATH_RANDSEED: { VALIDATE_ARG_NUM(0); uint64_t seed=*p_inputs[0]; int ret = Math::rand_from_seed(&seed); Array reta; reta.push_back(ret); reta.push_back(seed); *r_return=reta; } break; case VisualScriptBuiltinFunc::MATH_DEG2RAD: { VALIDATE_ARG_NUM(0); *r_return=Math::deg2rad((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_RAD2DEG: { VALIDATE_ARG_NUM(0); *r_return=Math::rad2deg((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_LINEAR2DB: { VALIDATE_ARG_NUM(0); *r_return=Math::linear2db((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_DB2LINEAR: { VALIDATE_ARG_NUM(0); *r_return=Math::db2linear((double)*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]; *r_return=MAX(a,b); } else { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); real_t a = *p_inputs[0]; real_t b = *p_inputs[1]; *r_return=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]; *r_return=MIN(a,b); } else { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); real_t a = *p_inputs[0]; real_t b = *p_inputs[1]; *r_return=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]; *r_return=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]; *r_return=CLAMP(a,b,c); } } break; case VisualScriptBuiltinFunc::LOGIC_NEAREST_PO2: { VALIDATE_ARG_NUM(0); int64_t num = *p_inputs[0]; *r_return = 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; } if (p_inputs[0]->is_ref()) { REF r = *p_inputs[0]; if (!r.is_valid()) { return; } Ref wref = memnew( WeakRef ); wref->set_ref(r); *r_return=wref; } else { Object *obj = *p_inputs[0]; if (!obj) { return; } Ref wref = memnew( WeakRef ); wref->set_obj(obj); *r_return=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; } 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; } Ref fr = memnew( FuncRef); fr->set_instance(*p_inputs[0]); fr->set_function(*p_inputs[1]); *r_return=fr; } break; case VisualScriptBuiltinFunc::TYPE_CONVERT: { VALIDATE_ARG_NUM(1); int type=*p_inputs[1]; if (type<0 || type>=Variant::VARIANT_MAX) { r_error_str=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; } else { *r_return=Variant::construct(Variant::Type(type),p_inputs,1,r_error); } } break; case VisualScriptBuiltinFunc::TYPE_OF: { *r_return = p_inputs[0]->get_type(); } break; case VisualScriptBuiltinFunc::TYPE_EXISTS: { *r_return = ClassDB::class_exists(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::TEXT_CHAR: { CharType result[2] = {*p_inputs[0], 0}; *r_return=String(result); } break; case VisualScriptBuiltinFunc::TEXT_STR: { String str = *p_inputs[0]; *r_return=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); *r_return=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; } VariantParser::StreamString ss; ss.s=*p_inputs[0]; String errs; int line; Error err = VariantParser::parse(&ss,*r_return,errs,line); if (err!=OK) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::STRING; *r_return="Parse error at line "+itos(line)+": "+errs; return; } } break; case VisualScriptBuiltinFunc::VAR_TO_BYTES: { PoolByteArray 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; r_error_str="Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID)."; return; } barr.resize(len); { PoolByteArray::Write w = barr.write(); encode_variant(*p_inputs[0],w.ptr(),len); } *r_return=barr; } break; case VisualScriptBuiltinFunc::BYTES_TO_VAR: { if (p_inputs[0]->get_type()!=Variant::POOL_BYTE_ARRAY) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::POOL_BYTE_ARRAY; return; } PoolByteArray varr=*p_inputs[0]; Variant ret; { PoolByteArray::Read r=varr.read(); Error err = decode_variant(ret,r.ptr(),varr.size(),NULL); if (err!=OK) { r_error_str=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::POOL_BYTE_ARRAY; return; } } *r_return=ret; } break; case VisualScriptBuiltinFunc::COLORN: { VALIDATE_ARG_NUM(1); Color color = Color::named(*p_inputs[0]); color.a=*p_inputs[1]; *r_return=String(color); } break; default: {} } } 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) { VisualScriptBuiltinFunc::exec_func(func,p_inputs,p_outputs[0],r_error,r_error_str); 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() { ClassDB::bind_method(D_METHOD("set_func","which"),&VisualScriptBuiltinFunc::set_func); ClassDB::bind_method(D_METHOD("get_func"),&VisualScriptBuiltinFunc::get_func); String cc; for(int i=0;i0) cc+=","; cc+=func_name[i]; } ADD_PROPERTY(PropertyInfo(Variant::INT,"function",PROPERTY_HINT_ENUM,cc),"set_func","get_func"); } VisualScriptBuiltinFunc::VisualScriptBuiltinFunc() { func=MATH_SIN; } template static Ref create_builtin_func_node(const String& p_name) { Ref node; node.instance(); node->set_func(func); return node; } void register_visual_script_builtin_func_node() { VisualScriptLanguage::singleton->add_register_func("functions/built_in/sin",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/cos",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/tan",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/sinh",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/cosh",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/tanh",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/asin",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/acos",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/atan",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/atan2",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/sqrt",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/fmod",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/fposmod",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/floor",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/ceil",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/round",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/abs",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/sign",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/pow",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/log",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/exp",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/isnan",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/isinf",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/ease",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/decimals",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/stepify",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/lerp",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/dectime",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/randomize",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/rand",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/randf",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/random",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/seed",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/randseed",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/deg2rad",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/rad2deg",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/linear2db",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/db2linear",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/max",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/min",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/clamp",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/nearest_po2",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/weakref",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/funcref",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/convert",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/typeof",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/type_exists",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/char",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/str",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/print",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/printerr",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/printraw",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/var2str",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/str2var",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/var2bytes",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/bytes2var",create_builtin_func_node); VisualScriptLanguage::singleton->add_register_func("functions/built_in/color_named",create_builtin_func_node); }