void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { ERR_EXPLAIN("Invalid packet received. Size too small."); ERR_FAIL_COND(p_offset >= p_packet_len); // Check that remote can call the RSET on this node. RPCMode rset_mode = RPC_MODE_DISABLED; const Map<StringName, RPCMode>::Element *E = p_node->get_node_rset_mode(p_name); if (E) { rset_mode = E->get(); } else if (p_node->get_script_instance()) { rset_mode = p_node->get_script_instance()->get_rset_mode(p_name); } bool can_call = _can_call_mode(p_node, rset_mode, p_from); ERR_EXPLAIN("RSET '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rset_mode) + ", master is " + itos(p_node->get_network_master()) + "."); ERR_FAIL_COND(!can_call); Variant value; Error err = decode_variant(value, &p_packet[p_offset], p_packet_len - p_offset, NULL, allow_object_decoding || network_peer->is_object_decoding_allowed()); ERR_EXPLAIN("Invalid packet received. Unable to decode RSET value."); ERR_FAIL_COND(err != OK); bool valid; p_node->set(p_name, value, &valid); if (!valid) { String error = "Error setting remote property '" + String(p_name) + "', not found in object of type " + p_node->get_class(); ERR_PRINTS(error); } }
Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, bool &err) const { uint32_t type = decode_uint32(p_buf + p_ofs); if (type == TYPE_ARRAY || type == TYPE_DICT) { Ref<PackedDataContainerRef> pdcr = memnew(PackedDataContainerRef); Ref<PackedDataContainer> pdc = Ref<PackedDataContainer>((PackedDataContainer *)this); pdcr->from = pdc; pdcr->offset = p_ofs; return pdcr; } else { Variant v; Error rerr = decode_variant(v, p_buf + p_ofs, datalen - p_ofs, NULL); if (rerr != OK) { err = true; ERR_FAIL_COND_V(err != OK, Variant()); } return v; } }
void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { if (!p_node->can_call_rpc(p_name, p_from)) return; ERR_FAIL_COND(p_offset >= p_packet_len); int argc = p_packet[p_offset]; Vector<Variant> args; Vector<const Variant *> argp; args.resize(argc); argp.resize(argc); p_offset++; for (int i = 0; i < argc; i++) { ERR_FAIL_COND(p_offset >= p_packet_len); int vlen; Error err = decode_variant(args[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen); ERR_FAIL_COND(err != OK); //args[i]=p_packet[3+i]; argp[i] = &args[i]; p_offset += vlen; } Variant::CallError ce; p_node->call(p_name, (const Variant **)argp.ptr(), argc, ce); if (ce.error != Variant::CallError::CALL_OK) { String error = Variant::get_call_error_text(p_node, p_name, (const Variant **)argp.ptr(), argc, ce); error = "RPC - " + error; ERR_PRINTS(error); } }
void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { ERR_FAIL_COND(p_offset >= p_packet_len); // Check that remote can call the RSET on this node RPCMode rset_mode = RPC_MODE_DISABLED; const Map<StringName, RPCMode>::Element *E = p_node->get_node_rset_mode(p_name); if (E) { rset_mode = E->get(); } else if (p_node->get_script_instance()) { rset_mode = p_node->get_script_instance()->get_rset_mode(p_name); } ERR_FAIL_COND(!_can_call_mode(p_node, rset_mode, p_from)); Variant value; decode_variant(value, &p_packet[p_offset], p_packet_len - p_offset); bool valid; p_node->set(p_name, value, &valid); if (!valid) { String error = "Error setting remote property '" + String(p_name) + "', not found in object of type " + p_node->get_class(); ERR_PRINTS(error); } }
Error PacketPeer::get_var(Variant &r_variant) { const uint8_t *buffer; int buffer_size; Error err = get_packet(&buffer, buffer_size); if (err) return err; return decode_variant(r_variant, buffer, buffer_size, NULL, allow_object_decoding); }
Error PacketPeer::get_var(Variant &r_variant) const { const uint8_t *buffer; int buffer_size; Error err = get_packet(&buffer, buffer_size); if (err) return err; return decode_variant(r_variant, buffer, buffer_size); }
Variant StreamPeer::get_var() { int len = get_32(); Vector<uint8_t> var; var.resize(len); get_data(var.ptr(), len); Variant ret; decode_variant(ret, var.ptr(), len); return ret; }
Variant StreamPeer::get_var() { int len = get_32(); Vector<uint8_t> var; Error err = var.resize(len); ERR_FAIL_COND_V(err != OK, Variant()); err = get_data(var.ptr(), len); ERR_FAIL_COND_V(err != OK, Variant()); Variant ret; decode_variant(ret, var.ptr(), len); return ret; }
void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { ERR_EXPLAIN("Invalid packet received. Size too small."); ERR_FAIL_COND(p_offset >= p_packet_len); // Check that remote can call the RPC on this node. RPCMode rpc_mode = RPC_MODE_DISABLED; const Map<StringName, RPCMode>::Element *E = p_node->get_node_rpc_mode(p_name); if (E) { rpc_mode = E->get(); } else if (p_node->get_script_instance()) { rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_name); } bool can_call = _can_call_mode(p_node, rpc_mode, p_from); ERR_EXPLAIN("RPC '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + "."); ERR_FAIL_COND(!can_call); int argc = p_packet[p_offset]; Vector<Variant> args; Vector<const Variant *> argp; args.resize(argc); argp.resize(argc); p_offset++; for (int i = 0; i < argc; i++) { ERR_EXPLAIN("Invalid packet received. Size too small."); ERR_FAIL_COND(p_offset >= p_packet_len); int vlen; Error err = decode_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen, allow_object_decoding || network_peer->is_object_decoding_allowed()); ERR_EXPLAIN("Invalid packet received. Unable to decode RPC argument."); ERR_FAIL_COND(err != OK); argp.write[i] = &args[i]; p_offset += vlen; } Variant::CallError ce; p_node->call(p_name, (const Variant **)argp.ptr(), argc, ce); if (ce.error != Variant::CallError::CALL_OK) { String error = Variant::get_call_error_text(p_node, p_name, (const Variant **)argp.ptr(), argc, ce); error = "RPC - " + error; ERR_PRINTS(error); } }
Variant _File::get_var() const { ERR_FAIL_COND_V(!f,Variant()); uint32_t len = get_32(); DVector<uint8_t> buff = get_buffer(len); ERR_FAIL_COND_V(buff.size() != len, Variant()); DVector<uint8_t>::Read r = buff.read(); Variant v; Error err = decode_variant(v,&r[0],len); ERR_FAIL_COND_V( err!=OK, Variant() ); return v; }
Variant _Marshalls::base64_to_variant(const String& p_str) { int strlen = p_str.length(); CharString cstr = p_str.ascii(); DVector<uint8_t> buf; buf.resize(strlen / 4 * 3 + 1); DVector<uint8_t>::Write w = buf.write(); int len = base64_decode((char*)(&w[0]), (char*)cstr.get_data(), strlen); Variant v; Error err = decode_variant(v, &w[0], len); ERR_FAIL_COND_V( err!=OK, Variant() ); return v; };
void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { if (!p_node->can_call_rset(p_name, p_from)) return; ERR_FAIL_COND(p_offset >= p_packet_len); Variant value; decode_variant(value, &p_packet[p_offset], p_packet_len - p_offset); bool valid; p_node->set(p_name, value, &valid); if (!valid) { String error = "Error setting remote property '" + String(p_name) + "', not found in object of type " + p_node->get_class(); ERR_PRINTS(error); } }
void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { ERR_FAIL_COND(p_offset >= p_packet_len); // Check that remote can call the RPC on this node RPCMode rpc_mode = RPC_MODE_DISABLED; const Map<StringName, RPCMode>::Element *E = p_node->get_node_rpc_mode(p_name); if (E) { rpc_mode = E->get(); } else if (p_node->get_script_instance()) { rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_name); } ERR_FAIL_COND(!_can_call_mode(p_node, rpc_mode, p_from)); int argc = p_packet[p_offset]; Vector<Variant> args; Vector<const Variant *> argp; args.resize(argc); argp.resize(argc); p_offset++; for (int i = 0; i < argc; i++) { ERR_FAIL_COND(p_offset >= p_packet_len); int vlen; Error err = decode_variant(args[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen); ERR_FAIL_COND(err != OK); //args[i]=p_packet[3+i]; argp[i] = &args[i]; p_offset += vlen; } Variant::CallError ce; p_node->call(p_name, (const Variant **)argp.ptr(), argc, ce); if (ce.error != Variant::CallError::CALL_OK) { String error = Variant::get_call_error_text(p_node, p_name, (const Variant **)argp.ptr(), argc, ce); error = "RPC - " + error; ERR_PRINTS(error); } }
void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Variant &r_ret,Variant::CallError &r_error) { r_error.error=Variant::CallError::CALL_OK; #ifdef DEBUG_ENABLED #define VALIDATE_ARG_COUNT(m_count) \ if (p_arg_count<m_count) {\ r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;\ r_error.argument=m_count;\ r_ret=Variant();\ return;\ }\ if (p_arg_count>m_count) {\ r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;\ r_error.argument=m_count;\ r_ret=Variant();\ return;\ } #define VALIDATE_ARG_NUM(m_arg) \ if (!p_args[m_arg]->is_num()) {\ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;\ r_error.argument=m_arg;\ r_error.expected=Variant::REAL;\ r_ret=Variant();\ return;\ } #else #define VALIDATE_ARG_COUNT(m_count) #define VALIDATE_ARG_NUM(m_arg) #endif //using a switch, so the compiler generates a jumptable switch(p_func) { case MATH_SIN: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::sin((double)*p_args[0]); } break; case MATH_COS: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::cos((double)*p_args[0]); } break; case MATH_TAN: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::tan((double)*p_args[0]); } break; case MATH_SINH: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::sinh((double)*p_args[0]); } break; case MATH_COSH: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::cosh((double)*p_args[0]); } break; case MATH_TANH: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::tanh((double)*p_args[0]); } break; case MATH_ASIN: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::asin((double)*p_args[0]); } break; case MATH_ACOS: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::acos((double)*p_args[0]); } break; case MATH_ATAN: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::atan((double)*p_args[0]); } break; case MATH_ATAN2: { VALIDATE_ARG_COUNT(2); VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); r_ret=Math::atan2((double)*p_args[0],(double)*p_args[1]); } break; case MATH_SQRT: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::sqrt((double)*p_args[0]); } break; case MATH_FMOD: { VALIDATE_ARG_COUNT(2); VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); r_ret=Math::fmod((double)*p_args[0],(double)*p_args[1]); } break; case MATH_FPOSMOD: { VALIDATE_ARG_COUNT(2); VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); r_ret=Math::fposmod((double)*p_args[0],(double)*p_args[1]); } break; case MATH_FLOOR: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::floor((double)*p_args[0]); } break; case MATH_CEIL: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::ceil((double)*p_args[0]); } break; case MATH_ROUND: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::round((double)*p_args[0]); } break; case MATH_ABS: { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type()==Variant::INT) { int64_t i = *p_args[0]; r_ret=ABS(i); } else if (p_args[0]->get_type()==Variant::REAL) { double r = *p_args[0]; r_ret=Math::abs(r); } else { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::REAL; r_ret=Variant(); } } break; case MATH_SIGN: { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type()==Variant::INT) { int64_t i = *p_args[0]; r_ret= i < 0 ? -1 : ( i > 0 ? +1 : 0); } else if (p_args[0]->get_type()==Variant::REAL) { real_t r = *p_args[0]; r_ret= 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; r_ret=Variant(); } } break; case MATH_POW: { VALIDATE_ARG_COUNT(2); VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); r_ret=Math::pow((double)*p_args[0],(double)*p_args[1]); } break; case MATH_LOG: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::log((double)*p_args[0]); } break; case MATH_EXP: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::exp((double)*p_args[0]); } break; case MATH_ISNAN: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::is_nan((double)*p_args[0]); } break; case MATH_ISINF: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::is_inf((double)*p_args[0]); } break; case MATH_EASE: { VALIDATE_ARG_COUNT(2); VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); r_ret=Math::ease((double)*p_args[0],(double)*p_args[1]); } break; case MATH_DECIMALS: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::step_decimals((double)*p_args[0]); } break; case MATH_STEPIFY: { VALIDATE_ARG_COUNT(2); VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); r_ret=Math::stepify((double)*p_args[0],(double)*p_args[1]); } break; case MATH_LERP: { VALIDATE_ARG_COUNT(3); VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); r_ret=Math::lerp((double)*p_args[0],(double)*p_args[1],(double)*p_args[2]); } break; case MATH_DECTIME: { VALIDATE_ARG_COUNT(3); VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); r_ret=Math::dectime((double)*p_args[0],(double)*p_args[1],(double)*p_args[2]); } break; case MATH_RANDOMIZE: { Math::randomize(); r_ret=Variant(); } break; case MATH_RAND: { r_ret=Math::rand(); } break; case MATH_RANDF: { r_ret=Math::randf(); } break; case MATH_RANDOM: { VALIDATE_ARG_COUNT(2); VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); r_ret=Math::random((double)*p_args[0],(double)*p_args[1]); } break; case MATH_SEED: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); uint64_t seed=*p_args[0]; Math::seed(seed); r_ret=Variant(); } break; case MATH_RANDSEED: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); uint64_t seed=*p_args[0]; int ret = Math::rand_from_seed(&seed); Array reta; reta.push_back(ret); reta.push_back(seed); r_ret=reta; } break; case MATH_DEG2RAD: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::deg2rad((double)*p_args[0]); } break; case MATH_RAD2DEG: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::rad2deg((double)*p_args[0]); } break; case MATH_LINEAR2DB: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::linear2db((double)*p_args[0]); } break; case MATH_DB2LINEAR: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret=Math::db2linear((double)*p_args[0]); } break; case LOGIC_MAX: { VALIDATE_ARG_COUNT(2); if (p_args[0]->get_type()==Variant::INT && p_args[1]->get_type()==Variant::INT) { int64_t a = *p_args[0]; int64_t b = *p_args[1]; r_ret=MAX(a,b); } else { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); real_t a = *p_args[0]; real_t b = *p_args[1]; r_ret=MAX(a,b); } } break; case LOGIC_MIN: { VALIDATE_ARG_COUNT(2); if (p_args[0]->get_type()==Variant::INT && p_args[1]->get_type()==Variant::INT) { int64_t a = *p_args[0]; int64_t b = *p_args[1]; r_ret=MIN(a,b); } else { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); real_t a = *p_args[0]; real_t b = *p_args[1]; r_ret=MIN(a,b); } } break; case LOGIC_CLAMP: { VALIDATE_ARG_COUNT(3); if (p_args[0]->get_type()==Variant::INT && p_args[1]->get_type()==Variant::INT && p_args[2]->get_type()==Variant::INT) { int64_t a = *p_args[0]; int64_t b = *p_args[1]; int64_t c = *p_args[2]; r_ret=CLAMP(a,b,c); } else { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); real_t a = *p_args[0]; real_t b = *p_args[1]; real_t c = *p_args[2]; r_ret=CLAMP(a,b,c); } } break; case LOGIC_NEAREST_PO2: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); int64_t num = *p_args[0]; r_ret = nearest_power_of_2(num); } break; case OBJ_WEAKREF: { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type()!=Variant::OBJECT) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::OBJECT; r_ret=Variant(); return; } if (p_args[0]->is_ref()) { REF r = *p_args[0]; if (!r.is_valid()) { r_ret=Variant(); return; } Ref<WeakRef> wref = memnew( WeakRef ); wref->set_ref(r); r_ret=wref; } else { Object *obj = *p_args[0]; if (!obj) { r_ret=Variant(); return; } Ref<WeakRef> wref = memnew( WeakRef ); wref->set_obj(obj); r_ret=wref; } } break; case FUNC_FUNCREF: { VALIDATE_ARG_COUNT(2); if (p_args[0]->get_type()!=Variant::OBJECT) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::OBJECT; r_ret=Variant(); return; } if (p_args[1]->get_type()!=Variant::STRING && p_args[1]->get_type()!=Variant::NODE_PATH) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=1; r_error.expected=Variant::STRING; r_ret=Variant(); return; } Ref<FuncRef> fr = memnew( FuncRef); fr->set_instance(*p_args[0]); fr->set_function(*p_args[1]); r_ret=fr; } break; case TYPE_CONVERT: { VALIDATE_ARG_COUNT(2); VALIDATE_ARG_NUM(1); int type=*p_args[1]; if (type<0 || type>=Variant::VARIANT_MAX) { r_ret=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_ret=Variant::construct(Variant::Type(type),p_args,1,r_error); } } break; case TYPE_OF: { VALIDATE_ARG_COUNT(1); r_ret = p_args[0]->get_type(); } break; case TYPE_EXISTS: { VALIDATE_ARG_COUNT(1); r_ret = ClassDB::class_exists(*p_args[0]); } break; case TEXT_CHAR: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); CharType result[2] = {*p_args[0], 0}; r_ret=String(result); } break; case TEXT_STR: { String str; for(int i=0;i<p_arg_count;i++) { String os = p_args[i]->operator String(); if (i==0) str=os; else str+=os; } r_ret=str; } break; case TEXT_PRINT: { String str; for(int i=0;i<p_arg_count;i++) { str+=p_args[i]->operator String(); } //str+="\n"; print_line(str); r_ret=Variant(); } break; case TEXT_PRINT_TABBED: { String str; for(int i=0;i<p_arg_count;i++) { if (i) str+="\t"; str+=p_args[i]->operator String(); } //str+="\n"; print_line(str); r_ret=Variant(); } break; case TEXT_PRINT_SPACED: { String str; for(int i=0;i<p_arg_count;i++) { if (i) str+=" "; str+=p_args[i]->operator String(); } //str+="\n"; print_line(str); r_ret=Variant(); } break; case TEXT_PRINTERR: { String str; for(int i=0;i<p_arg_count;i++) { str+=p_args[i]->operator String(); } //str+="\n"; OS::get_singleton()->printerr("%s\n",str.utf8().get_data()); r_ret=Variant(); } break; case TEXT_PRINTRAW: { String str; for(int i=0;i<p_arg_count;i++) { str+=p_args[i]->operator String(); } //str+="\n"; OS::get_singleton()->print("%s",str.utf8().get_data()); r_ret=Variant(); } break; case VAR_TO_STR: { VALIDATE_ARG_COUNT(1); String vars; VariantWriter::write_to_string(*p_args[0],vars); r_ret=vars; } break; case STR_TO_VAR: { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type()!=Variant::STRING) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::STRING; r_ret=Variant(); return; } VariantParser::StreamString ss; ss.s=*p_args[0]; String errs; int line; Error err = VariantParser::parse(&ss,r_ret,errs,line); if (err!=OK) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::STRING; r_ret="Parse error at line "+itos(line)+": "+errs; return; } } break; case VAR_TO_BYTES: { VALIDATE_ARG_COUNT(1); PoolByteArray barr; int len; Error err = encode_variant(*p_args[0],NULL,len); if (err) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::NIL; r_ret="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_args[0],w.ptr(),len); } r_ret=barr; } break; case BYTES_TO_VAR: { VALIDATE_ARG_COUNT(1); if (p_args[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; r_ret=Variant(); return; } PoolByteArray varr=*p_args[0]; Variant ret; { PoolByteArray::Read r=varr.read(); Error err = decode_variant(ret,r.ptr(),varr.size(),NULL); if (err!=OK) { r_ret=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_ret=ret; } break; case GEN_RANGE: { switch(p_arg_count) { case 0: { r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument=1; r_ret=Variant(); } break; case 1: { VALIDATE_ARG_NUM(0); int count=*p_args[0]; Array arr; if (count<=0) { r_ret=arr; return; } Error err = arr.resize(count); if (err!=OK) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; r_ret=Variant(); return; } for(int i=0;i<count;i++) { arr[i]=i; } r_ret=arr; } break; case 2: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); int from=*p_args[0]; int to=*p_args[1]; Array arr; if (from>=to) { r_ret=arr; return; } Error err = arr.resize(to-from); if (err!=OK) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; r_ret=Variant(); return; } for(int i=from;i<to;i++) arr[i-from]=i; r_ret=arr; } break; case 3: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); int from=*p_args[0]; int to=*p_args[1]; int incr=*p_args[2]; if (incr==0) { r_ret=RTR("step argument is zero!"); r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; return; } Array arr; if (from>=to && incr>0) { r_ret=arr; return; } if (from<=to && incr<0) { r_ret=arr; return; } //calculate how many int count=0; if (incr>0) { count=((to-from-1)/incr)+1; } else { count=((from-to-1)/-incr)+1; } Error err = arr.resize(count); if (err!=OK) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; r_ret=Variant(); return; } if (incr>0) { int idx=0; for(int i=from;i<to;i+=incr) { arr[idx++]=i; } } else { int idx=0; for(int i=from;i>to;i+=incr) { arr[idx++]=i; } } r_ret=arr; } break; default: { r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.argument=3; r_ret=Variant(); } break; } } break; case RESOURCE_LOAD: { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type()!=Variant::STRING) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::STRING; r_ret=Variant(); } else { r_ret=ResourceLoader::load(*p_args[0]); } } break; case INST2DICT: { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type()==Variant::NIL) { r_ret=Variant(); } else if (p_args[0]->get_type()!=Variant::OBJECT) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_ret=Variant(); } else { Object *obj = *p_args[0]; if (!obj) { r_ret=Variant(); } else if (!obj->get_script_instance() || obj->get_script_instance()->get_language()!=GDScriptLanguage::get_singleton()) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::DICTIONARY; r_ret=RTR("Not a script with an instance"); return; } else { GDInstance *ins = static_cast<GDInstance*>(obj->get_script_instance()); Ref<GDScript> base = ins->get_script(); if (base.is_null()) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::DICTIONARY; r_ret=RTR("Not based on a script"); return; } GDScript *p = base.ptr(); Vector<StringName> sname; while(p->_owner) { sname.push_back(p->name); p=p->_owner; } sname.invert(); if (!p->path.is_resource_file()) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::DICTIONARY; r_ret=Variant(); r_ret=RTR("Not based on a resource file"); return; } NodePath cp(sname,Vector<StringName>(),false); Dictionary d; d["@subpath"]=cp; d["@path"]=p->path; p = base.ptr(); while(p) { for(Set<StringName>::Element *E=p->members.front();E;E=E->next()) { Variant value; if (ins->get(E->get(),value)) { String k = E->get(); if (!d.has(k)) { d[k]=value; } } } p=p->_base; } r_ret=d; } } } break; case DICT2INST: { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type()!=Variant::DICTIONARY) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::DICTIONARY; r_ret=Variant(); return; } Dictionary d = *p_args[0]; if (!d.has("@path")) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::OBJECT; r_ret=RTR("Invalid instance dictionary format (missing @path)"); return; } Ref<Script> scr = ResourceLoader::load(d["@path"]); if (!scr.is_valid()) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::OBJECT; r_ret=RTR("Invalid instance dictionary format (can't load script at @path)"); return; } Ref<GDScript> gdscr = scr; if (!gdscr.is_valid()) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::OBJECT; r_ret=Variant(); r_ret=RTR("Invalid instance dictionary format (invalid script at @path)"); return; } NodePath sub; if (d.has("@subpath")) { sub=d["@subpath"]; } for(int i=0;i<sub.get_name_count();i++) { gdscr = gdscr->subclasses[ sub.get_name(i)]; if (!gdscr.is_valid()) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::OBJECT; r_ret=Variant(); r_ret=RTR("Invalid instance dictionary (invalid subclasses)"); return; } } r_ret = gdscr->_new(NULL,0,r_error); GDInstance *ins = static_cast<GDInstance*>(static_cast<Object*>(r_ret)->get_script_instance()); Ref<GDScript> gd_ref = ins->get_script(); for(Map<StringName,GDScript::MemberInfo>::Element *E = gd_ref->member_indices.front(); E; E = E->next()) { if(d.has(E->key())) { ins->members[E->get().index] = d[E->key()]; } } } break; case VALIDATE_JSON: { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type()!=Variant::STRING) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::STRING; r_ret=Variant(); return; } String errs; int errl; Error err = JSON::parse(*p_args[0],r_ret,errs,errl); if (err!=OK) { r_ret=itos(errl)+":"+errs; } else { r_ret=""; } } break; case PARSE_JSON: { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type()!=Variant::STRING) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::STRING; r_ret=Variant(); return; } String errs; int errl; Error err = JSON::parse(*p_args[0],r_ret,errs,errl); if (err!=OK) { r_ret=Variant(); } } break; case TO_JSON: { VALIDATE_ARG_COUNT(1); r_ret = JSON::print(*p_args[0]); } break; case HASH: { VALIDATE_ARG_COUNT(1); r_ret=p_args[0]->hash(); } break; case COLOR8: { if (p_arg_count<3) { r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument=3; r_ret=Variant(); return; } if (p_arg_count>4) { r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.argument=4; r_ret=Variant(); return; } VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); Color color((float)*p_args[0]/255.0f,(float)*p_args[1]/255.0f,(float)*p_args[2]/255.0f); if (p_arg_count==4) { VALIDATE_ARG_NUM(3); color.a=(float)*p_args[3]/255.0f; } r_ret=color; } break; case COLORN: { if (p_arg_count<1) { r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument=1; r_ret=Variant(); return; } if (p_arg_count>2) { r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.argument=2; r_ret=Variant(); return; } if (p_args[0]->get_type()!=Variant::STRING) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_ret=Variant(); } else { Color color = Color::named(*p_args[0]); if (p_arg_count==2) { VALIDATE_ARG_NUM(1); color.a=*p_args[1]; } r_ret=color; } } break; case PRINT_STACK: { ScriptLanguage* script = GDScriptLanguage::get_singleton(); for (int i=0; i < script->debug_get_stack_level_count(); i++) { print_line("Frame "+itos(i)+" - "+script->debug_get_stack_level_source(i)+":"+itos(script->debug_get_stack_level_line(i))+" in function '"+script->debug_get_stack_level_function(i)+"'"); }; } break; case INSTANCE_FROM_ID: { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type()!=Variant::INT && p_args[0]->get_type()!=Variant::REAL) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::INT; r_ret=Variant(); break; } uint32_t id=*p_args[0]; r_ret=ObjectDB::get_instance(id); } break; case FUNC_MAX: { ERR_FAIL(); } break; } }
Error GDTokenizerBuffer::set_code_buffer(const Vector<uint8_t> & p_buffer) { const uint8_t *buf=p_buffer.ptr(); int total_len=p_buffer.size(); ERR_FAIL_COND_V( p_buffer.size()<24 || p_buffer[0]!='G' || p_buffer[1]!='D' || p_buffer[2]!='S' || p_buffer[3]!='C',ERR_INVALID_DATA); int version = decode_uint32(&buf[4]); if (version>BYTECODE_VERSION) { ERR_EXPLAIN("Bytecode is too New! Please use a newer engine version."); ERR_FAIL_COND_V(version>BYTECODE_VERSION,ERR_INVALID_DATA); } int identifier_count = decode_uint32(&buf[8]); int constant_count = decode_uint32(&buf[12]); int line_count = decode_uint32(&buf[16]); int token_count = decode_uint32(&buf[20]); const uint8_t *b=buf; b=&buf[24]; total_len-=24; identifiers.resize(identifier_count); for(int i=0;i<identifier_count;i++) { int len = decode_uint32(b); ERR_FAIL_COND_V(len>total_len,ERR_INVALID_DATA); b+=4; Vector<uint8_t> cs; cs.resize(len); for(int j=0;j<len;j++) { cs[j]=b[j]^0xb6; } cs[cs.size()-1]=0; String s; s.parse_utf8((const char*)cs.ptr()); b+=len; total_len-=len+4; identifiers[i]=s; } constants.resize(constant_count); for(int i=0;i<constant_count;i++) { Variant v; int len; Error err = decode_variant(v,b,total_len,&len); if (err) return err; b+=len; total_len-=len; constants[i]=v; } ERR_FAIL_COND_V(line_count*8>total_len,ERR_INVALID_DATA); for(int i=0;i<line_count;i++) { uint32_t token=decode_uint32(b); b+=4; uint32_t linecol=decode_uint32(b); b+=4; lines.insert(token,linecol); total_len-=8; } tokens.resize(token_count); for(int i=0;i<token_count;i++) { ERR_FAIL_COND_V( total_len < 1, ERR_INVALID_DATA); if ((*b)&TOKEN_BYTE_MASK) { //little endian always ERR_FAIL_COND_V( total_len < 4, ERR_INVALID_DATA); tokens[i]=decode_uint32(b)&~TOKEN_BYTE_MASK; b+=4; } else { tokens[i]=*b; b+=1; total_len--; } } token=0; return OK; }
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_INVERSE_LERP: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return = Math::inverse_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; case VisualScriptBuiltinFunc::MATH_RANGE_LERP: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); VALIDATE_ARG_NUM(3); VALIDATE_ARG_NUM(4); *r_return = Math::range_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2], (double)*p_inputs[3], (double)*p_inputs[4]); } break; case VisualScriptBuiltinFunc::MATH_SMOOTHSTEP: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return = Math::smoothstep((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::MATH_POLAR2CARTESIAN: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); double r = *p_inputs[0]; double th = *p_inputs[1]; *r_return = Vector2(r * Math::cos(th), r * Math::sin(th)); } break; case VisualScriptBuiltinFunc::MATH_CARTESIAN2POLAR: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); double x = *p_inputs[0]; double y = *p_inputs[1]; *r_return = Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x)); } break; case VisualScriptBuiltinFunc::MATH_WRAP: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return = Math::wrapi((int64_t)*p_inputs[0], (int64_t)*p_inputs[1], (int64_t)*p_inputs[2]); } break; case VisualScriptBuiltinFunc::MATH_WRAPF: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return = Math::wrapf((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } 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 = next_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<WeakRef> wref = memnew(WeakRef); wref->set_ref(r); *r_return = wref; } else { Object *obj = *p_inputs[0]; if (!obj) { return; } Ref<WeakRef> 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<FuncRef> 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]; print_error(str); } break; case VisualScriptBuiltinFunc::TEXT_PRINTRAW: { String str = *p_inputs[0]; 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: { if (p_inputs[1]->get_type() != Variant::BOOL) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 1; r_error.expected = Variant::BOOL; return; } PoolByteArray barr; int len; bool full_objects = *p_inputs[1]; Error err = encode_variant(*p_inputs[0], NULL, len, full_objects); 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, full_objects); } *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; } if (p_inputs[1]->get_type() != Variant::BOOL) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 1; r_error.expected = Variant::BOOL; return; } PoolByteArray varr = *p_inputs[0]; bool allow_objects = *p_inputs[1]; Variant ret; { PoolByteArray::Read r = varr.read(); Error err = decode_variant(ret, r.ptr(), varr.size(), NULL, allow_objects); 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: { } } }
virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) { switch(func) { case VisualScriptBuiltinFunc::MATH_SIN: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::sin(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_COS: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::cos(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_TAN: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::tan(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_SINH: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::sinh(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_COSH: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::cosh(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_TANH: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::tanh(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ASIN: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::asin(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ACOS: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::acos(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ATAN: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::atan(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ATAN2: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *p_outputs[0]=Math::atan2(*p_inputs[0],*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_SQRT: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::sqrt(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_FMOD: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *p_outputs[0]=Math::fmod(*p_inputs[0],*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_FPOSMOD: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *p_outputs[0]=Math::fposmod(*p_inputs[0],*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_FLOOR: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::floor(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_CEIL: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::ceil(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ROUND: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::round(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ABS: { if (p_inputs[0]->get_type()==Variant::INT) { int64_t i = *p_inputs[0]; *p_outputs[0]=ABS(i); } else if (p_inputs[0]->get_type()==Variant::REAL) { real_t r = *p_inputs[0]; *p_outputs[0]=Math::abs(r); } else { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::REAL; } } break; case VisualScriptBuiltinFunc::MATH_SIGN: { if (p_inputs[0]->get_type()==Variant::INT) { int64_t i = *p_inputs[0]; *p_outputs[0]= i < 0 ? -1 : ( i > 0 ? +1 : 0); } else if (p_inputs[0]->get_type()==Variant::REAL) { real_t r = *p_inputs[0]; *p_outputs[0]= r < 0.0 ? -1.0 : ( r > 0.0 ? +1.0 : 0.0); } else { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::REAL; } } break; case VisualScriptBuiltinFunc::MATH_POW: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *p_outputs[0]=Math::pow(*p_inputs[0],*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_LOG: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::log(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_EXP: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::exp(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ISNAN: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::is_nan(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ISINF: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::is_inf(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_EASE: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *p_outputs[0]=Math::ease(*p_inputs[0],*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_DECIMALS: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::step_decimals(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_STEPIFY: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *p_outputs[0]=Math::stepify(*p_inputs[0],*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_LERP: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *p_outputs[0]=Math::lerp(*p_inputs[0],*p_inputs[1],*p_inputs[2]); } break; case VisualScriptBuiltinFunc::MATH_DECTIME: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *p_outputs[0]=Math::dectime(*p_inputs[0],*p_inputs[1],*p_inputs[2]); } break; case VisualScriptBuiltinFunc::MATH_RANDOMIZE: { Math::randomize(); } break; case VisualScriptBuiltinFunc::MATH_RAND: { *p_outputs[0]=Math::rand(); } break; case VisualScriptBuiltinFunc::MATH_RANDF: { *p_outputs[0]=Math::randf(); } break; case VisualScriptBuiltinFunc::MATH_RANDOM: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *p_outputs[0]=Math::random(*p_inputs[0],*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_SEED: { VALIDATE_ARG_NUM(0); uint32_t seed=*p_inputs[0]; Math::seed(seed); } break; case VisualScriptBuiltinFunc::MATH_RANDSEED: { VALIDATE_ARG_NUM(0); uint32_t seed=*p_inputs[0]; int ret = Math::rand_from_seed(&seed); Array reta; reta.push_back(ret); reta.push_back(seed); *p_outputs[0]=reta; } break; case VisualScriptBuiltinFunc::MATH_DEG2RAD: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::deg2rad(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_RAD2DEG: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::rad2deg(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_LINEAR2DB: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::linear2db(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_DB2LINEAR: { VALIDATE_ARG_NUM(0); *p_outputs[0]=Math::db2linear(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::LOGIC_MAX: { if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT) { int64_t a = *p_inputs[0]; int64_t b = *p_inputs[1]; *p_outputs[0]=MAX(a,b); } else { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); real_t a = *p_inputs[0]; real_t b = *p_inputs[1]; *p_outputs[0]=MAX(a,b); } } break; case VisualScriptBuiltinFunc::LOGIC_MIN: { if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT) { int64_t a = *p_inputs[0]; int64_t b = *p_inputs[1]; *p_outputs[0]=MIN(a,b); } else { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); real_t a = *p_inputs[0]; real_t b = *p_inputs[1]; *p_outputs[0]=MIN(a,b); } } break; case VisualScriptBuiltinFunc::LOGIC_CLAMP: { if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT && p_inputs[2]->get_type()==Variant::INT) { int64_t a = *p_inputs[0]; int64_t b = *p_inputs[1]; int64_t c = *p_inputs[2]; *p_outputs[0]=CLAMP(a,b,c); } else { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); real_t a = *p_inputs[0]; real_t b = *p_inputs[1]; real_t c = *p_inputs[2]; *p_outputs[0]=CLAMP(a,b,c); } } break; case VisualScriptBuiltinFunc::LOGIC_NEAREST_PO2: { VALIDATE_ARG_NUM(0); int64_t num = *p_inputs[0]; *p_outputs[0] = nearest_power_of_2(num); } break; case VisualScriptBuiltinFunc::OBJ_WEAKREF: { if (p_inputs[0]->get_type()!=Variant::OBJECT) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::OBJECT; return 0; } if (p_inputs[0]->is_ref()) { REF r = *p_inputs[0]; if (!r.is_valid()) { return 0; } Ref<WeakRef> wref = memnew( WeakRef ); wref->set_ref(r); *p_outputs[0]=wref; } else { Object *obj = *p_inputs[0]; if (!obj) { return 0; } Ref<WeakRef> wref = memnew( WeakRef ); wref->set_obj(obj); *p_outputs[0]=wref; } } break; case VisualScriptBuiltinFunc::FUNC_FUNCREF: { if (p_inputs[0]->get_type()!=Variant::OBJECT) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::OBJECT; return 0; } if (p_inputs[1]->get_type()!=Variant::STRING && p_inputs[1]->get_type()!=Variant::NODE_PATH) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=1; r_error.expected=Variant::STRING; return 0; } Ref<FuncRef> fr = memnew( FuncRef); fr->set_instance(*p_inputs[0]); fr->set_function(*p_inputs[1]); *p_outputs[0]=fr; } break; case VisualScriptBuiltinFunc::TYPE_CONVERT: { VALIDATE_ARG_NUM(1); int type=*p_inputs[1]; if (type<0 || type>=Variant::VARIANT_MAX) { *p_outputs[0]=RTR("Invalid type argument to convert(), use TYPE_* constants."); r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::INT; return 0; } else { *p_outputs[0]=Variant::construct(Variant::Type(type),p_inputs,1,r_error); } } break; case VisualScriptBuiltinFunc::TYPE_OF: { *p_outputs[0] = p_inputs[0]->get_type(); } break; case VisualScriptBuiltinFunc::TYPE_EXISTS: { *p_outputs[0] = ObjectTypeDB::type_exists(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::TEXT_STR: { String str = *p_inputs[0]; *p_outputs[0]=str; } break; case VisualScriptBuiltinFunc::TEXT_PRINT: { String str = *p_inputs[0]; print_line(str); } break; case VisualScriptBuiltinFunc::TEXT_PRINTERR: { String str = *p_inputs[0]; //str+="\n"; OS::get_singleton()->printerr("%s\n",str.utf8().get_data()); } break; case VisualScriptBuiltinFunc::TEXT_PRINTRAW: { String str = *p_inputs[0]; //str+="\n"; OS::get_singleton()->print("%s",str.utf8().get_data()); } break; case VisualScriptBuiltinFunc::VAR_TO_STR: { String vars; VariantWriter::write_to_string(*p_inputs[0],vars); *p_outputs[0]=vars; } break; case VisualScriptBuiltinFunc::STR_TO_VAR: { if (p_inputs[0]->get_type()!=Variant::STRING) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::STRING; return 0; } VariantParser::StreamString ss; ss.s=*p_inputs[0]; String errs; int line; Error err = VariantParser::parse(&ss,*p_outputs[0],errs,line); if (err!=OK) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::STRING; *p_outputs[0]="Parse error at line "+itos(line)+": "+errs; return 0; } } break; case VisualScriptBuiltinFunc::VAR_TO_BYTES: { ByteArray barr; int len; Error err = encode_variant(*p_inputs[0],NULL,len); if (err) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::NIL; *p_outputs[0]="Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID)."; return 0; } barr.resize(len); { ByteArray::Write w = barr.write(); encode_variant(*p_inputs[0],w.ptr(),len); } *p_outputs[0]=barr; } break; case VisualScriptBuiltinFunc::BYTES_TO_VAR: { if (p_inputs[0]->get_type()!=Variant::RAW_ARRAY) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::RAW_ARRAY; return 0; } ByteArray varr=*p_inputs[0]; Variant ret; { ByteArray::Read r=varr.read(); Error err = decode_variant(ret,r.ptr(),varr.size(),NULL); if (err!=OK) { *p_outputs[0]=RTR("Not enough bytes for decoding bytes, or invalid format."); r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_error.expected=Variant::RAW_ARRAY; return 0; } } *p_outputs[0]=ret; } break; default: {} } return 0; }
Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len) { const uint8_t *buf = p_buffer; int len = p_len; if (len < 4) { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); } uint32_t type = decode_uint32(buf); ERR_FAIL_COND_V((type & ENCODE_MASK) >= Variant::VARIANT_MAX, ERR_INVALID_DATA); buf += 4; len -= 4; if (r_len) *r_len = 4; switch (type & ENCODE_MASK) { case Variant::NIL: { r_variant = Variant(); } break; case Variant::BOOL: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); bool val = decode_uint32(buf); r_variant = val; if (r_len) (*r_len) += 4; } break; case Variant::INT: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); if (type & ENCODE_FLAG_64) { int64_t val = decode_uint64(buf); r_variant = val; if (r_len) (*r_len) += 8; } else { int32_t val = decode_uint32(buf); r_variant = val; if (r_len) (*r_len) += 4; } } break; case Variant::REAL: { ERR_FAIL_COND_V(len < (int)4, ERR_INVALID_DATA); if (type & ENCODE_FLAG_64) { double val = decode_double(buf); r_variant = val; if (r_len) (*r_len) += 8; } else { float val = decode_float(buf); r_variant = val; if (r_len) (*r_len) += 4; } } break; case Variant::STRING: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); uint32_t strlen = decode_uint32(buf); buf += 4; len -= 4; ERR_FAIL_COND_V((int)strlen > len, ERR_INVALID_DATA); String str; str.parse_utf8((const char *)buf, strlen); r_variant = str; if (r_len) { if (strlen % 4) (*r_len) += 4 - strlen % 4; (*r_len) += 4 + strlen; } } break; // math types case Variant::VECTOR2: { ERR_FAIL_COND_V(len < (int)4 * 2, ERR_INVALID_DATA); Vector2 val; val.x = decode_float(&buf[0]); val.y = decode_float(&buf[4]); r_variant = val; if (r_len) (*r_len) += 4 * 2; } break; // 5 case Variant::RECT2: { ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA); Rect2 val; val.position.x = decode_float(&buf[0]); val.position.y = decode_float(&buf[4]); val.size.x = decode_float(&buf[8]); val.size.y = decode_float(&buf[12]); r_variant = val; if (r_len) (*r_len) += 4 * 4; } break; case Variant::VECTOR3: { ERR_FAIL_COND_V(len < (int)4 * 3, ERR_INVALID_DATA); Vector3 val; val.x = decode_float(&buf[0]); val.y = decode_float(&buf[4]); val.z = decode_float(&buf[8]); r_variant = val; if (r_len) (*r_len) += 4 * 3; } break; case Variant::TRANSFORM2D: { ERR_FAIL_COND_V(len < (int)4 * 6, ERR_INVALID_DATA); Transform2D val; for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { val.elements[i][j] = decode_float(&buf[(i * 2 + j) * 4]); } } r_variant = val; if (r_len) (*r_len) += 4 * 6; } break; case Variant::PLANE: { ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA); Plane val; val.normal.x = decode_float(&buf[0]); val.normal.y = decode_float(&buf[4]); val.normal.z = decode_float(&buf[8]); val.d = decode_float(&buf[12]); r_variant = val; if (r_len) (*r_len) += 4 * 4; } break; case Variant::QUAT: { ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA); Quat val; val.x = decode_float(&buf[0]); val.y = decode_float(&buf[4]); val.z = decode_float(&buf[8]); val.w = decode_float(&buf[12]); r_variant = val; if (r_len) (*r_len) += 4 * 4; } break; case Variant::RECT3: { ERR_FAIL_COND_V(len < (int)4 * 6, ERR_INVALID_DATA); Rect3 val; val.position.x = decode_float(&buf[0]); val.position.y = decode_float(&buf[4]); val.position.z = decode_float(&buf[8]); val.size.x = decode_float(&buf[12]); val.size.y = decode_float(&buf[16]); val.size.z = decode_float(&buf[20]); r_variant = val; if (r_len) (*r_len) += 4 * 6; } break; case Variant::BASIS: { ERR_FAIL_COND_V(len < (int)4 * 9, ERR_INVALID_DATA); Basis val; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { val.elements[i][j] = decode_float(&buf[(i * 3 + j) * 4]); } } r_variant = val; if (r_len) (*r_len) += 4 * 9; } break; case Variant::TRANSFORM: { ERR_FAIL_COND_V(len < (int)4 * 12, ERR_INVALID_DATA); Transform val; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { val.basis.elements[i][j] = decode_float(&buf[(i * 3 + j) * 4]); } } val.origin[0] = decode_float(&buf[36]); val.origin[1] = decode_float(&buf[40]); val.origin[2] = decode_float(&buf[44]); r_variant = val; if (r_len) (*r_len) += 4 * 12; } break; // misc types case Variant::COLOR: { ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA); Color val; val.r = decode_float(&buf[0]); val.g = decode_float(&buf[4]); val.b = decode_float(&buf[8]); val.a = decode_float(&buf[12]); r_variant = val; if (r_len) (*r_len) += 4 * 4; } break; case Variant::NODE_PATH: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); uint32_t strlen = decode_uint32(buf); if (strlen & 0x80000000) { //new format ERR_FAIL_COND_V(len < 12, ERR_INVALID_DATA); Vector<StringName> names; Vector<StringName> subnames; StringName prop; uint32_t namecount = strlen &= 0x7FFFFFFF; uint32_t subnamecount = decode_uint32(buf + 4); uint32_t flags = decode_uint32(buf + 8); len -= 12; buf += 12; int total = namecount + subnamecount; if (flags & 2) total++; if (r_len) (*r_len) += 12; for (int i = 0; i < total; i++) { ERR_FAIL_COND_V((int)len < 4, ERR_INVALID_DATA); strlen = decode_uint32(buf); int pad = 0; if (strlen % 4) pad += 4 - strlen % 4; buf += 4; len -= 4; ERR_FAIL_COND_V((int)strlen + pad > len, ERR_INVALID_DATA); String str; str.parse_utf8((const char *)buf, strlen); if (i < namecount) names.push_back(str); else if (i < namecount + subnamecount) subnames.push_back(str); else prop = str; buf += strlen + pad; len -= strlen + pad; if (r_len) (*r_len) += 4 + strlen + pad; } r_variant = NodePath(names, subnames, flags & 1, prop); } else { //old format, just a string buf += 4; len -= 4; ERR_FAIL_COND_V((int)strlen > len, ERR_INVALID_DATA); String str; str.parse_utf8((const char *)buf, strlen); r_variant = NodePath(str); if (r_len) (*r_len) += 4 + strlen; } } break; /*case Variant::RESOURCE: { ERR_EXPLAIN("Can't marshallize resources"); ERR_FAIL_V(ERR_INVALID_DATA); //no, i'm sorry, no go } break;*/ case Variant::_RID: { r_variant = RID(); } break; case Variant::OBJECT: { r_variant = (Object *)NULL; } break; case Variant::DICTIONARY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); uint32_t count = decode_uint32(buf); // bool shared = count&0x80000000; count &= 0x7FFFFFFF; buf += 4; len -= 4; if (r_len) { (*r_len) += 4; } Dictionary d; for (uint32_t i = 0; i < count; i++) { Variant key, value; int used; Error err = decode_variant(key, buf, len, &used); ERR_FAIL_COND_V(err, err); buf += used; len -= used; if (r_len) { (*r_len) += used; } err = decode_variant(value, buf, len, &used); ERR_FAIL_COND_V(err, err); buf += used; len -= used; if (r_len) { (*r_len) += used; } d[key] = value; } r_variant = d; } break; case Variant::ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); uint32_t count = decode_uint32(buf); // bool shared = count&0x80000000; count &= 0x7FFFFFFF; buf += 4; len -= 4; if (r_len) { (*r_len) += 4; } Array varr; for (uint32_t i = 0; i < count; i++) { int used = 0; Variant v; Error err = decode_variant(v, buf, len, &used); ERR_FAIL_COND_V(err, err); buf += used; len -= used; varr.push_back(v); if (r_len) { (*r_len) += used; } } r_variant = varr; } break; // arrays case Variant::POOL_BYTE_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); uint32_t count = decode_uint32(buf); buf += 4; len -= 4; ERR_FAIL_COND_V((int)count > len, ERR_INVALID_DATA); PoolVector<uint8_t> data; if (count) { data.resize(count); PoolVector<uint8_t>::Write w = data.write(); for (int i = 0; i < count; i++) { w[i] = buf[i]; } w = PoolVector<uint8_t>::Write(); } r_variant = data; if (r_len) { if (count % 4) (*r_len) += 4 - count % 4; (*r_len) += 4 + count; } } break; case Variant::POOL_INT_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); uint32_t count = decode_uint32(buf); buf += 4; len -= 4; ERR_FAIL_COND_V((int)count * 4 > len, ERR_INVALID_DATA); PoolVector<int> data; if (count) { //const int*rbuf=(const int*)buf; data.resize(count); PoolVector<int>::Write w = data.write(); for (int i = 0; i < count; i++) { w[i] = decode_uint32(&buf[i * 4]); } w = PoolVector<int>::Write(); } r_variant = Variant(data); if (r_len) { (*r_len) += 4 + count * sizeof(int); } } break; case Variant::POOL_REAL_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); uint32_t count = decode_uint32(buf); buf += 4; len -= 4; ERR_FAIL_COND_V((int)count * 4 > len, ERR_INVALID_DATA); PoolVector<float> data; if (count) { //const float*rbuf=(const float*)buf; data.resize(count); PoolVector<float>::Write w = data.write(); for (int i = 0; i < count; i++) { w[i] = decode_float(&buf[i * 4]); } w = PoolVector<float>::Write(); } r_variant = data; if (r_len) { (*r_len) += 4 + count * sizeof(float); } } break; case Variant::POOL_STRING_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); uint32_t count = decode_uint32(buf); PoolVector<String> strings; buf += 4; len -= 4; if (r_len) (*r_len) += 4; //printf("string count: %i\n",count); for (int i = 0; i < (int)count; i++) { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); uint32_t strlen = decode_uint32(buf); buf += 4; len -= 4; ERR_FAIL_COND_V((int)strlen > len, ERR_INVALID_DATA); //printf("loaded string: %s\n",(const char*)buf); String str; str.parse_utf8((const char *)buf, strlen); strings.push_back(str); buf += strlen; len -= strlen; if (r_len) (*r_len) += 4 + strlen; if (strlen % 4) { int pad = 4 - (strlen % 4); buf += pad; len -= pad; if (r_len) { (*r_len) += pad; } } } r_variant = strings; } break; case Variant::POOL_VECTOR2_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); uint32_t count = decode_uint32(buf); buf += 4; len -= 4; ERR_FAIL_COND_V((int)count * 4 * 2 > len, ERR_INVALID_DATA); PoolVector<Vector2> varray; if (r_len) { (*r_len) += 4; } if (count) { varray.resize(count); PoolVector<Vector2>::Write w = varray.write(); for (int i = 0; i < (int)count; i++) { w[i].x = decode_float(buf + i * 4 * 2 + 4 * 0); w[i].y = decode_float(buf + i * 4 * 2 + 4 * 1); } int adv = 4 * 2 * count; if (r_len) (*r_len) += adv; len -= adv; buf += adv; } r_variant = varray; } break; case Variant::POOL_VECTOR3_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); uint32_t count = decode_uint32(buf); buf += 4; len -= 4; ERR_FAIL_COND_V((int)count * 4 * 3 > len, ERR_INVALID_DATA); PoolVector<Vector3> varray; if (r_len) { (*r_len) += 4; } if (count) { varray.resize(count); PoolVector<Vector3>::Write w = varray.write(); for (int i = 0; i < (int)count; i++) { w[i].x = decode_float(buf + i * 4 * 3 + 4 * 0); w[i].y = decode_float(buf + i * 4 * 3 + 4 * 1); w[i].z = decode_float(buf + i * 4 * 3 + 4 * 2); } int adv = 4 * 3 * count; if (r_len) (*r_len) += adv; len -= adv; buf += adv; } r_variant = varray; } break; case Variant::POOL_COLOR_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); uint32_t count = decode_uint32(buf); buf += 4; len -= 4; ERR_FAIL_COND_V((int)count * 4 * 4 > len, ERR_INVALID_DATA); PoolVector<Color> carray; if (r_len) { (*r_len) += 4; } if (count) { carray.resize(count); PoolVector<Color>::Write w = carray.write(); for (int i = 0; i < (int)count; i++) { w[i].r = decode_float(buf + i * 4 * 4 + 4 * 0); w[i].g = decode_float(buf + i * 4 * 4 + 4 * 1); w[i].b = decode_float(buf + i * 4 * 4 + 4 * 2); w[i].a = decode_float(buf + i * 4 * 4 + 4 * 3); } int adv = 4 * 4 * count; if (r_len) (*r_len) += adv; len -= adv; buf += adv; } r_variant = carray; } break; default: { ERR_FAIL_V(ERR_BUG); } } return OK; }