Changed Vector3.snap from fmod to stepify, which makes more sense, fixes #6399

This commit is contained in:
Juan Linietsky 2016-09-06 19:12:28 -03:00
parent 78275aad87
commit 23ababdcd5
6 changed files with 640 additions and 516 deletions

View file

@ -65,13 +65,9 @@ int Vector3::max_axis() const {
void Vector3::snap(float p_val) {
x+=p_val/2.0;
x-=Math::fmod(x,p_val);
y+=p_val/2.0;
y-=Math::fmod(y,p_val);
z+=p_val/2.0;
z-=Math::fmod(z,p_val);
x=Math::stepify(x,p_val);
y=Math::stepify(y,p_val);
z=Math::stepify(z,p_val);
}
Vector3 Vector3::snapped(float p_val) const {

View file

@ -1417,7 +1417,8 @@ bool VisualScriptInstance::get(const StringName& p_name, Variant &r_ret) const {
if (!E)
return false;
return E->get();
r_ret=E->get();
return true;
}
void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const{

View file

@ -65,6 +65,21 @@ const char* VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX
"bytes2var",
};
VisualScriptBuiltinFunc::BuiltinFunc VisualScriptBuiltinFunc::find_function(const String& p_string) {
for(int i=0;i<FUNC_MAX;i++) {
if (p_string==func_name[i])
return BuiltinFunc(i);
}
return FUNC_MAX;
}
String VisualScriptBuiltinFunc::get_func_name(BuiltinFunc p_func) {
ERR_FAIL_INDEX_V(p_func,FUNC_MAX,String());
return func_name[p_func];
}
int VisualScriptBuiltinFunc::get_output_sequence_port_count() const {
@ -88,10 +103,10 @@ bool VisualScriptBuiltinFunc::has_input_sequence_port() const{
}
int VisualScriptBuiltinFunc::get_input_value_port_count() const{
int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) {
switch(func) {
switch(p_func) {
case MATH_RANDOMIZE:
case MATH_RAND:
@ -157,6 +172,11 @@ int VisualScriptBuiltinFunc::get_input_value_port_count() const{
}
return 0;
}
int VisualScriptBuiltinFunc::get_input_value_port_count() const{
return get_func_argument_count(func);
}
int VisualScriptBuiltinFunc::get_output_value_port_count() const{
switch(func) {
@ -560,118 +580,106 @@ VisualScriptBuiltinFunc::BuiltinFunc VisualScriptBuiltinFunc::get_func() {
r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;\
r_error.argument=m_arg;\
r_error.expected=Variant::REAL;\
return 0;\
return;\
}
class VisualScriptNodeInstanceBuiltinFunc : public VisualScriptNodeInstance {
public:
VisualScriptBuiltinFunc *node;
VisualScriptInstance *instance;
void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func,const Variant** p_inputs,Variant* r_return,Variant::CallError& r_error,String& r_error_str) {
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) {
switch(p_func) {
case VisualScriptBuiltinFunc::MATH_SIN: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::sin(*p_inputs[0]);
*r_return=Math::sin(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_COS: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::cos(*p_inputs[0]);
*r_return=Math::cos(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_TAN: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::tan(*p_inputs[0]);
*r_return=Math::tan(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_SINH: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::sinh(*p_inputs[0]);
*r_return=Math::sinh(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_COSH: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::cosh(*p_inputs[0]);
*r_return=Math::cosh(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_TANH: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::tanh(*p_inputs[0]);
*r_return=Math::tanh(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ASIN: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::asin(*p_inputs[0]);
*r_return=Math::asin(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ACOS: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::acos(*p_inputs[0]);
*r_return=Math::acos(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ATAN: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::atan(*p_inputs[0]);
*r_return=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]);
*r_return=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]);
*r_return=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]);
*r_return=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]);
*r_return=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]);
*r_return=Math::floor(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_CEIL: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::ceil(*p_inputs[0]);
*r_return=Math::ceil(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ROUND: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::round(*p_inputs[0]);
*r_return=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);
*r_return=ABS(i);
} else if (p_inputs[0]->get_type()==Variant::REAL) {
real_t r = *p_inputs[0];
*p_outputs[0]=Math::abs(r);
*r_return=Math::abs(r);
} else {
r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
@ -685,11 +693,11 @@ public:
if (p_inputs[0]->get_type()==Variant::INT) {
int64_t i = *p_inputs[0];
*p_outputs[0]= i < 0 ? -1 : ( i > 0 ? +1 : 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];
*p_outputs[0]= r < 0.0 ? -1.0 : ( r > 0.0 ? +1.0 : 0.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;
@ -702,74 +710,74 @@ public:
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
*p_outputs[0]=Math::pow(*p_inputs[0],*p_inputs[1]);
*r_return=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]);
*r_return=Math::log(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_EXP: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::exp(*p_inputs[0]);
*r_return=Math::exp(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ISNAN: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::is_nan(*p_inputs[0]);
*r_return=Math::is_nan(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_ISINF: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::is_inf(*p_inputs[0]);
*r_return=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]);
*r_return=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]);
*r_return=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]);
*r_return=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]);
*r_return=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]);
*r_return=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();
*r_return=Math::rand();
} break;
case VisualScriptBuiltinFunc::MATH_RANDF: {
*p_outputs[0]=Math::randf();
*r_return=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]);
*r_return=Math::random(*p_inputs[0],*p_inputs[1]);
} break;
case VisualScriptBuiltinFunc::MATH_SEED: {
@ -786,28 +794,28 @@ public:
Array reta;
reta.push_back(ret);
reta.push_back(seed);
*p_outputs[0]=reta;
*r_return=reta;
} break;
case VisualScriptBuiltinFunc::MATH_DEG2RAD: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::deg2rad(*p_inputs[0]);
*r_return=Math::deg2rad(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_RAD2DEG: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::rad2deg(*p_inputs[0]);
*r_return=Math::rad2deg(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_LINEAR2DB: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::linear2db(*p_inputs[0]);
*r_return=Math::linear2db(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::MATH_DB2LINEAR: {
VALIDATE_ARG_NUM(0);
*p_outputs[0]=Math::db2linear(*p_inputs[0]);
*r_return=Math::db2linear(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::LOGIC_MAX: {
@ -815,7 +823,7 @@ public:
int64_t a = *p_inputs[0];
int64_t b = *p_inputs[1];
*p_outputs[0]=MAX(a,b);
*r_return=MAX(a,b);
} else {
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
@ -823,7 +831,7 @@ public:
real_t a = *p_inputs[0];
real_t b = *p_inputs[1];
*p_outputs[0]=MAX(a,b);
*r_return=MAX(a,b);
}
} break;
@ -833,7 +841,7 @@ public:
int64_t a = *p_inputs[0];
int64_t b = *p_inputs[1];
*p_outputs[0]=MIN(a,b);
*r_return=MIN(a,b);
} else {
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
@ -841,7 +849,7 @@ public:
real_t a = *p_inputs[0];
real_t b = *p_inputs[1];
*p_outputs[0]=MIN(a,b);
*r_return=MIN(a,b);
}
} break;
case VisualScriptBuiltinFunc::LOGIC_CLAMP: {
@ -851,7 +859,7 @@ public:
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);
*r_return=CLAMP(a,b,c);
} else {
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
@ -861,14 +869,14 @@ public:
real_t b = *p_inputs[1];
real_t c = *p_inputs[2];
*p_outputs[0]=CLAMP(a,b,c);
*r_return=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);
*r_return = nearest_power_of_2(num);
} break;
case VisualScriptBuiltinFunc::OBJ_WEAKREF: {
@ -878,7 +886,7 @@ public:
r_error.argument=0;
r_error.expected=Variant::OBJECT;
return 0;
return;
}
@ -887,21 +895,21 @@ public:
REF r = *p_inputs[0];
if (!r.is_valid()) {
return 0;
return;
}
Ref<WeakRef> wref = memnew( WeakRef );
wref->set_ref(r);
*p_outputs[0]=wref;
*r_return=wref;
} else {
Object *obj = *p_inputs[0];
if (!obj) {
return 0;
return;
}
Ref<WeakRef> wref = memnew( WeakRef );
wref->set_obj(obj);
*p_outputs[0]=wref;
*r_return=wref;
}
@ -916,7 +924,7 @@ public:
r_error.argument=0;
r_error.expected=Variant::OBJECT;
return 0;
return;
}
if (p_inputs[1]->get_type()!=Variant::STRING && p_inputs[1]->get_type()!=Variant::NODE_PATH) {
@ -925,7 +933,7 @@ public:
r_error.argument=1;
r_error.expected=Variant::STRING;
return 0;
return;
}
@ -934,7 +942,7 @@ public:
fr->set_instance(*p_inputs[0]);
fr->set_function(*p_inputs[1]);
*p_outputs[0]=fr;
*r_return=fr;
} break;
case VisualScriptBuiltinFunc::TYPE_CONVERT: {
@ -943,35 +951,35 @@ public:
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_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 0;
return;
} else {
*p_outputs[0]=Variant::construct(Variant::Type(type),p_inputs,1,r_error);
*r_return=Variant::construct(Variant::Type(type),p_inputs,1,r_error);
}
} break;
case VisualScriptBuiltinFunc::TYPE_OF: {
*p_outputs[0] = p_inputs[0]->get_type();
*r_return = p_inputs[0]->get_type();
} break;
case VisualScriptBuiltinFunc::TYPE_EXISTS: {
*p_outputs[0] = ObjectTypeDB::type_exists(*p_inputs[0]);
*r_return = ObjectTypeDB::type_exists(*p_inputs[0]);
} break;
case VisualScriptBuiltinFunc::TEXT_STR: {
String str = *p_inputs[0];
*p_outputs[0]=str;
*r_return=str;
} break;
case VisualScriptBuiltinFunc::TEXT_PRINT: {
@ -1003,7 +1011,7 @@ public:
String vars;
VariantWriter::write_to_string(*p_inputs[0],vars);
*p_outputs[0]=vars;
*r_return=vars;
} break;
case VisualScriptBuiltinFunc::STR_TO_VAR: {
@ -1012,7 +1020,7 @@ public:
r_error.argument=0;
r_error.expected=Variant::STRING;
return 0;
return;
}
VariantParser::StreamString ss;
@ -1020,14 +1028,14 @@ public:
String errs;
int line;
Error err = VariantParser::parse(&ss,*p_outputs[0],errs,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;
*p_outputs[0]="Parse error at line "+itos(line)+": "+errs;
return 0;
*r_return="Parse error at line "+itos(line)+": "+errs;
return;
}
} break;
@ -1041,8 +1049,8 @@ public:
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;
r_error_str="Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).";
return;
}
barr.resize(len);
@ -1051,7 +1059,7 @@ public:
encode_variant(*p_inputs[0],w.ptr(),len);
}
*p_outputs[0]=barr;
*r_return=barr;
} break;
case VisualScriptBuiltinFunc::BYTES_TO_VAR: {
@ -1060,7 +1068,7 @@ public:
r_error.argument=0;
r_error.expected=Variant::RAW_ARRAY;
return 0;
return;
}
ByteArray varr=*p_inputs[0];
@ -1069,20 +1077,40 @@ public:
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_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::RAW_ARRAY;
return 0;
return;
}
}
*p_outputs[0]=ret;
*r_return=ret;
} 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;
}

View file

@ -68,6 +68,11 @@ public:
FUNC_MAX
};
static int get_func_argument_count(BuiltinFunc p_func);
static String get_func_name(BuiltinFunc p_func);
static void exec_func(BuiltinFunc p_func, const Variant** p_inputs, Variant* r_return, Variant::CallError& r_error, String& r_error_str);
static BuiltinFunc find_function(const String& p_string);
private:
static const char* func_name[FUNC_MAX];
BuiltinFunc func;

View file

@ -577,6 +577,13 @@ Error VisualScriptExpression::_get_token(Token& r_token) {
}
}
VisualScriptBuiltinFunc::BuiltinFunc bifunc = VisualScriptBuiltinFunc::find_function(id);
if (bifunc!=VisualScriptBuiltinFunc::FUNC_MAX) {
r_token.type=TK_BUILTIN_FUNC;
r_token.value=bifunc;
return OK;
}
r_token.type=TK_IDENTIFIER;
r_token.value=id;
}
@ -603,6 +610,7 @@ const char* VisualScriptExpression::token_name[TK_MAX]={
"PARENTHESIS OPEN",
"PARENTHESIS CLOSE",
"IDENTIFIER",
"BUILTIN FUNC",
"SELF",
"CONSTANT",
"BASIC TYPE",
@ -813,6 +821,53 @@ VisualScriptExpression::ENode* VisualScriptExpression::_parse_expression() {
expr=constructor;
} break;
case TK_BUILTIN_FUNC: {
//builtin function
Variant::Type bt = Variant::Type(int(tk.value));
_get_token(tk);
if (tk.type!=TK_PARENTHESIS_OPEN) {
_set_error("Expected '('");
return NULL;
}
BuiltinFuncNode *bifunc = alloc_node<BuiltinFuncNode>();
bifunc->func=VisualScriptBuiltinFunc::BuiltinFunc(int(tk.value));
while(true) {
int cofs=str_ofs;
_get_token(tk);
if (tk.type==TK_PARENTHESIS_CLOSE) {
break;
}
str_ofs=cofs; //revert
//parse an expression
ENode* expr=_parse_expression();
if (!expr)
return NULL;
bifunc->arguments.push_back(expr);
cofs=str_ofs;
_get_token(tk);
if (tk.type==TK_COMMA) {
//all good
} else if (tk.type==TK_PARENTHESIS_CLOSE) {
str_ofs=cofs;
} else {
_set_error("Expected ',' or ')'");
}
}
int expected_args = VisualScriptBuiltinFunc::get_func_argument_count(bifunc->func);
if (bifunc->arguments.size() != expected_args) {
_set_error("Builtin func '"+VisualScriptBuiltinFunc::get_func_name(bifunc->func)+"' expects "+itos(expected_args)+" arguments.");
}
expr=bifunc;
} break;
case TK_OP_SUB: {
@ -1337,6 +1392,34 @@ public:
}
} break;
case VisualScriptExpression::ENode::TYPE_BUILTIN_FUNC: {
const VisualScriptExpression::BuiltinFuncNode *bifunc = static_cast<const VisualScriptExpression::BuiltinFuncNode*>(p_node);
Vector<Variant> arr;
Vector<const Variant*> argp;
arr.resize(bifunc->arguments.size());
argp.resize(bifunc->arguments.size());
for (int i=0;i<bifunc->arguments.size();i++) {
Variant value;
bool ret = _execute(p_inputs,bifunc->arguments[i],value,r_error_str,ce);
if (ret)
return true;
arr[i]=value;
argp[i]=&arr[i];
}
VisualScriptBuiltinFunc::exec_func(bifunc->func,argp.ptr(),&r_ret,ce,r_error_str);
if (ce.error!=Variant::CallError::CALL_OK) {
r_error_str="Builtin Call Failed. "+r_error_str;
return true;
}
} break;
case VisualScriptExpression::ENode::TYPE_CALL: {

View file

@ -2,6 +2,7 @@
#define VISUALSCRIPTEXPRESSION_H
#include "visual_script.h"
#include "visual_script_builtin_funcs.h"
class VisualScriptExpression : public VisualScriptNode {
@ -35,6 +36,7 @@ friend class VisualScriptNodeInstanceExpression;
TK_PARENTHESIS_OPEN,
TK_PARENTHESIS_CLOSE,
TK_IDENTIFIER,
TK_BUILTIN_FUNC,
TK_SELF,
TK_CONSTANT,
TK_BASIC_TYPE,
@ -101,6 +103,7 @@ friend class VisualScriptNodeInstanceExpression;
TYPE_ARRAY,
TYPE_DICTIONARY,
TYPE_CONSTRUCTOR,
TYPE_BUILTIN_FUNC,
TYPE_CALL
};
@ -214,6 +217,14 @@ friend class VisualScriptNodeInstanceExpression;
};
struct BuiltinFuncNode : public ENode {
VisualScriptBuiltinFunc::BuiltinFunc func;
Vector<ENode*> arguments;
BuiltinFuncNode() {
type=TYPE_BUILTIN_FUNC;
}
};
template<class T>
T* alloc_node() {
T* node = memnew(T);