/*************************************************************************/ /* variant.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "variant.h" #include "math_funcs.h" #include "resource.h" #include "print_string.h" #include "scene/main/node.h" #include "scene/gui/control.h" #include "io/marshalls.h" #include "core_string_names.h" #include "variant_parser.h" String Variant::get_type_name(Variant::Type p_type) { switch( p_type ) { case NIL: { return "Nil"; } break; // atomic types case BOOL: { return "bool"; } break; case INT: { return "int"; } break; case REAL: { return "float"; } break; case STRING: { return "String"; } break; // math types case VECTOR2: { return "Vector2"; } break; case RECT2: { return "Rect2"; } break; case TRANSFORM2D: { return "Transform2D"; } break; case VECTOR3: { return "Vector3"; } break; case PLANE: { return "Plane"; } break; /* case QUAT: { } break;*/ case RECT3: { return "Rect3"; } break; case QUAT: { return "Quat"; } break; case BASIS: { return "Basis"; } break; case TRANSFORM: { return "Transform"; } break; // misc types case COLOR: { return "Color"; } break; case IMAGE: { return "Image"; } break; case _RID: { return "RID"; } break; case OBJECT: { return "Object"; } break; case NODE_PATH: { return "NodePath"; } break; case INPUT_EVENT: { return "InputEvent"; } break; case DICTIONARY: { return "Dictionary"; } break; case ARRAY: { return "Array"; } break; // arrays case POOL_BYTE_ARRAY: { return "PoolByteArray"; } break; case POOL_INT_ARRAY: { return "PoolIntArray"; } break; case POOL_REAL_ARRAY: { return "PoolFloatArray"; } break; case POOL_STRING_ARRAY: { return "PoolStringArray"; } break; case POOL_VECTOR2_ARRAY: { return "PoolVector2Array"; } break; case POOL_VECTOR3_ARRAY: { return "PoolVector3Array"; } break; case POOL_COLOR_ARRAY: { return "PoolColorArray"; } break; default: {} } return ""; } bool Variant::can_convert(Variant::Type p_type_from,Variant::Type p_type_to) { if (p_type_from==p_type_to) return true; if (p_type_to==NIL && p_type_from!=NIL) //nil can convert to anything return true; if (p_type_from == NIL) { return (p_type_to == OBJECT); }; const Type *valid_types=NULL; const Type *invalid_types=NULL; switch(p_type_to) { case BOOL: { static const Type valid[]={ INT, REAL, STRING, NIL, }; valid_types=valid; } break; case INT: { static const Type valid[]={ BOOL, REAL, STRING, NIL, }; valid_types=valid; } break; case REAL: { static const Type valid[]={ BOOL, INT, STRING, NIL, }; valid_types=valid; } break; case STRING: { static const Type invalid[]={ OBJECT, IMAGE, NIL }; invalid_types=invalid; } break; case TRANSFORM2D: { static const Type valid[]={ TRANSFORM, NIL }; valid_types=valid; } break; case QUAT: { static const Type valid[]={ BASIS, NIL }; valid_types=valid; } break; case BASIS: { static const Type valid[]={ QUAT, NIL }; valid_types=valid; } break; case TRANSFORM: { static const Type valid[]={ TRANSFORM2D, QUAT, BASIS, NIL }; valid_types=valid; } break; case COLOR: { static const Type valid[] = { STRING, INT, NIL, }; valid_types = valid; } break; case _RID: { static const Type valid[]={ OBJECT, NIL }; valid_types=valid; } break; case OBJECT: { static const Type valid[]={ NIL }; valid_types=valid; } break; case NODE_PATH: { static const Type valid[]={ STRING, NIL }; valid_types=valid; } break; case ARRAY: { static const Type valid[]={ POOL_BYTE_ARRAY, POOL_INT_ARRAY, POOL_STRING_ARRAY, POOL_REAL_ARRAY, POOL_COLOR_ARRAY, POOL_VECTOR2_ARRAY, POOL_VECTOR3_ARRAY, NIL }; valid_types=valid; } break; // arrays case POOL_BYTE_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case POOL_INT_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case POOL_REAL_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case POOL_STRING_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case POOL_VECTOR2_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case POOL_VECTOR3_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case POOL_COLOR_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; default: {} } if (valid_types) { int i=0; while(valid_types[i]!=NIL) { if (p_type_from==valid_types[i]) return true; i++; } } else if (invalid_types) { int i=0; while(invalid_types[i]!=NIL) { if (p_type_from==invalid_types[i]) return false; i++; } return true; } return false; } bool Variant::can_convert_strict(Variant::Type p_type_from,Variant::Type p_type_to) { if (p_type_from==p_type_to) return true; if (p_type_to==NIL && p_type_from!=NIL) //nil can convert to anything return true; if (p_type_from == NIL) { return (p_type_to == OBJECT); }; const Type *valid_types=NULL; switch(p_type_to) { case BOOL: { static const Type valid[]={ INT, REAL, //STRING, NIL, }; valid_types=valid; } break; case INT: { static const Type valid[]={ BOOL, REAL, //STRING, NIL, }; valid_types=valid; } break; case REAL: { static const Type valid[]={ BOOL, INT, //STRING, NIL, }; valid_types=valid; } break; case STRING: { static const Type valid[]={ NODE_PATH, NIL }; valid_types=valid; } break; case TRANSFORM2D: { static const Type valid[]={ TRANSFORM, NIL }; valid_types=valid; } break; case QUAT: { static const Type valid[]={ BASIS, NIL }; valid_types=valid; } break; case BASIS: { static const Type valid[]={ QUAT, NIL }; valid_types=valid; } break; case TRANSFORM: { static const Type valid[]={ TRANSFORM2D, QUAT, BASIS, NIL }; valid_types=valid; } break; case COLOR: { static const Type valid[] = { STRING, INT, NIL, }; valid_types = valid; } break; case _RID: { static const Type valid[]={ OBJECT, NIL }; valid_types=valid; } break; case OBJECT: { static const Type valid[]={ NIL }; valid_types=valid; } break; case NODE_PATH: { static const Type valid[]={ STRING, NIL }; valid_types=valid; } break; case ARRAY: { static const Type valid[]={ POOL_BYTE_ARRAY, POOL_INT_ARRAY, POOL_STRING_ARRAY, POOL_REAL_ARRAY, POOL_COLOR_ARRAY, POOL_VECTOR2_ARRAY, POOL_VECTOR3_ARRAY, NIL }; valid_types=valid; } break; // arrays case POOL_BYTE_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case POOL_INT_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case POOL_REAL_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case POOL_STRING_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case POOL_VECTOR2_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case POOL_VECTOR3_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case POOL_COLOR_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; default: {} } if (valid_types) { int i=0; while(valid_types[i]!=NIL) { if (p_type_from==valid_types[i]) return true; i++; } } return false; } bool Variant::operator==(const Variant& p_variant) const { if (type!=p_variant.type) //evaluation of operator== needs to be more strict return false; bool v; Variant r; evaluate(OP_EQUAL,*this,p_variant,r,v); return r; } bool Variant::operator!=(const Variant& p_variant) const { if (type!=p_variant.type) //evaluation of operator== needs to be more strict return true; bool v; Variant r; evaluate(OP_NOT_EQUAL,*this,p_variant,r,v); return r; } bool Variant::operator<(const Variant& p_variant) const { if (type!=p_variant.type) //if types differ, then order by type first return type(_data._mem)==String(); } break; // math types case VECTOR2: { return *reinterpret_cast(_data._mem)==Vector2(); } break; case RECT2: { return *reinterpret_cast(_data._mem)==Rect2(); } break; case TRANSFORM2D: { return *_data._transform2d==Transform2D(); } break; case VECTOR3: { return *reinterpret_cast(_data._mem)==Vector3(); } break; case PLANE: { return *reinterpret_cast(_data._mem)==Plane(); } break; /* case QUAT: { } break;*/ case RECT3: { return *_data._rect3==Rect3(); } break; case QUAT: { return *reinterpret_cast(_data._mem)==Quat(); } break; case BASIS: { return *_data._basis==Basis(); } break; case TRANSFORM: { return *_data._transform == Transform(); } break; // misc types case COLOR: { return *reinterpret_cast(_data._mem)==Color(); } break; case IMAGE: { return _data._image->empty(); } break; case _RID: { return *reinterpret_cast(_data._mem)==RID(); } break; case OBJECT: { return _get_obj().obj==NULL; } break; case NODE_PATH: { return reinterpret_cast(_data._mem)->is_empty(); } break; case INPUT_EVENT: { return _data._input_event->type==InputEvent::NONE; } break; case DICTIONARY: { return reinterpret_cast(_data._mem)->empty(); } break; case ARRAY: { return reinterpret_cast(_data._mem)->empty(); } break; // arrays case POOL_BYTE_ARRAY: { return reinterpret_cast*>(_data._mem)->size()==0; } break; case POOL_INT_ARRAY: { return reinterpret_cast*>(_data._mem)->size()==0; } break; case POOL_REAL_ARRAY: { return reinterpret_cast*>(_data._mem)->size()==0; } break; case POOL_STRING_ARRAY: { return reinterpret_cast*>(_data._mem)->size()==0; } break; case POOL_VECTOR2_ARRAY: { return reinterpret_cast*>(_data._mem)->size()==0; } break; case POOL_VECTOR3_ARRAY: { return reinterpret_cast*>(_data._mem)->size()==0; } break; case POOL_COLOR_ARRAY: { return reinterpret_cast*>(_data._mem)->size()==0; } break; default: {} } return false; } bool Variant::is_one() const { switch( type ) { case NIL: { return true; } break; // atomic types case BOOL: { return _data._bool==true; } break; case INT: { return _data._int==1; } break; case REAL: { return _data._real==1; } break; case VECTOR2: { return *reinterpret_cast(_data._mem)==Vector2(1,1); } break; case RECT2: { return *reinterpret_cast(_data._mem)==Rect2(1,1,1,1); } break; case VECTOR3: { return *reinterpret_cast(_data._mem)==Vector3(1,1,1); } break; case PLANE: { return *reinterpret_cast(_data._mem)==Plane(1,1,1,1); } break; case COLOR: { return *reinterpret_cast(_data._mem)==Color(1,1,1,1); } break; default: { return !is_zero(); } } return false; } void Variant::reference(const Variant& p_variant) { if (this == &p_variant) return; clear(); type=p_variant.type; switch( p_variant.type ) { case NIL: { // none } break; // atomic types case BOOL: { _data._bool=p_variant._data._bool; } break; case INT: { _data._int=p_variant._data._int; } break; case REAL: { _data._real=p_variant._data._real; } break; case STRING: { memnew_placement( _data._mem, String( *reinterpret_cast(p_variant._data._mem) ) ); } break; // math types case VECTOR2: { memnew_placement( _data._mem, Vector2( *reinterpret_cast(p_variant._data._mem) ) ); } break; case RECT2: { memnew_placement( _data._mem, Rect2( *reinterpret_cast(p_variant._data._mem) ) ); } break; case TRANSFORM2D: { _data._transform2d = memnew( Transform2D( *p_variant._data._transform2d ) ); } break; case VECTOR3: { memnew_placement( _data._mem, Vector3( *reinterpret_cast(p_variant._data._mem) ) ); } break; case PLANE: { memnew_placement( _data._mem, Plane( *reinterpret_cast(p_variant._data._mem) ) ); } break; /* case QUAT: { } break;*/ case RECT3: { _data._rect3 = memnew( Rect3( *p_variant._data._rect3 ) ); } break; case QUAT: { memnew_placement( _data._mem, Quat( *reinterpret_cast(p_variant._data._mem) ) ); } break; case BASIS: { _data._basis = memnew( Basis( *p_variant._data._basis ) ); } break; case TRANSFORM: { _data._transform = memnew( Transform( *p_variant._data._transform ) ); } break; // misc types case COLOR: { memnew_placement( _data._mem, Color( *reinterpret_cast(p_variant._data._mem) ) ); } break; case IMAGE: { _data._image = memnew( Image( *p_variant._data._image ) ); } break; case _RID: { memnew_placement( _data._mem, RID( *reinterpret_cast(p_variant._data._mem) ) ); } break; case OBJECT: { memnew_placement( _data._mem, ObjData( p_variant._get_obj() ) ); } break; case NODE_PATH: { memnew_placement( _data._mem, NodePath( *reinterpret_cast(p_variant._data._mem) ) ); } break; case INPUT_EVENT: { _data._input_event= memnew( InputEvent( *p_variant._data._input_event ) ); } break; case DICTIONARY: { memnew_placement( _data._mem, Dictionary( *reinterpret_cast(p_variant._data._mem) ) ); } break; case ARRAY: { memnew_placement( _data._mem, Array ( *reinterpret_cast(p_variant._data._mem) ) ); } break; // arrays case POOL_BYTE_ARRAY: { memnew_placement( _data._mem, PoolVector ( *reinterpret_cast*>(p_variant._data._mem) ) ); } break; case POOL_INT_ARRAY: { memnew_placement( _data._mem, PoolVector ( *reinterpret_cast*>(p_variant._data._mem) ) ); } break; case POOL_REAL_ARRAY: { memnew_placement( _data._mem, PoolVector ( *reinterpret_cast*>(p_variant._data._mem) ) ); } break; case POOL_STRING_ARRAY: { memnew_placement( _data._mem, PoolVector ( *reinterpret_cast*>(p_variant._data._mem) ) ); } break; case POOL_VECTOR2_ARRAY: { memnew_placement( _data._mem, PoolVector ( *reinterpret_cast*>(p_variant._data._mem) ) ); } break; case POOL_VECTOR3_ARRAY: { memnew_placement( _data._mem, PoolVector ( *reinterpret_cast*>(p_variant._data._mem) ) ); } break; case POOL_COLOR_ARRAY: { memnew_placement( _data._mem, PoolVector ( *reinterpret_cast*>(p_variant._data._mem) ) ); } break; default: {} } } void Variant::zero() { switch(type) { case NIL: break; case BOOL: this->_data._bool = false; break; case INT: this->_data._int = 0; break; case REAL: this->_data._real = 0; break; case VECTOR2: *reinterpret_cast(this->_data._mem) = Vector2(); break; case RECT2: *reinterpret_cast(this->_data._mem) = Rect2(); break; case VECTOR3: *reinterpret_cast(this->_data._mem) = Vector3(); break; case PLANE: *reinterpret_cast(this->_data._mem) = Plane(); break; case QUAT: *reinterpret_cast(this->_data._mem) = Quat(); break; case COLOR: *reinterpret_cast(this->_data._mem) = Color(); break; default: this->clear(); break; } } void Variant::clear() { switch(type) { case STRING: { reinterpret_cast(_data._mem)->~String(); } break; /* // no point, they don't allocate memory VECTOR3, PLANE, QUAT, COLOR, VECTOR2, RECT2 */ case TRANSFORM2D: { memdelete( _data._transform2d ); } break; case RECT3: { memdelete( _data._rect3 ); } break; case BASIS: { memdelete( _data._basis ); } break; case TRANSFORM: { memdelete( _data._transform ); } break; // misc types case IMAGE: { memdelete( _data._image ); } break; case NODE_PATH: { reinterpret_cast(_data._mem)->~NodePath(); } break; case OBJECT: { _get_obj().obj=NULL; _get_obj().ref.unref(); } break; case _RID: { // not much need probably reinterpret_cast(_data._mem)->~RID(); } break; case DICTIONARY: { reinterpret_cast(_data._mem)->~Dictionary(); } break; case ARRAY: { reinterpret_cast(_data._mem)->~Array(); } break; case INPUT_EVENT: { memdelete( _data._input_event ); } break; // arrays case POOL_BYTE_ARRAY: { reinterpret_cast< PoolVector* >(_data._mem)->~PoolVector(); } break; case POOL_INT_ARRAY: { reinterpret_cast< PoolVector* >(_data._mem)->~PoolVector(); } break; case POOL_REAL_ARRAY: { reinterpret_cast< PoolVector* >(_data._mem)->~PoolVector(); } break; case POOL_STRING_ARRAY: { reinterpret_cast< PoolVector* >(_data._mem)->~PoolVector(); } break; case POOL_VECTOR2_ARRAY: { reinterpret_cast< PoolVector* >(_data._mem)->~PoolVector(); } break; case POOL_VECTOR3_ARRAY: { reinterpret_cast< PoolVector* >(_data._mem)->~PoolVector(); } break; case POOL_COLOR_ARRAY: { reinterpret_cast< PoolVector* >(_data._mem)->~PoolVector(); } break; default: {} /* not needed */ } type=NIL; } Variant::operator signed int() const { switch( type ) { case NIL: return 0; case BOOL: return _data._bool ? 1 : 0; case INT: return _data._int; case REAL: return _data._real; case STRING: return operator String().to_int(); default: { return 0; } } return 0; } Variant::operator unsigned int() const { switch( type ) { case NIL: return 0; case BOOL: return _data._bool ? 1 : 0; case INT: return _data._int; case REAL: return _data._real; case STRING: return operator String().to_int(); default: { return 0; } } return 0; } Variant::operator int64_t() const { switch( type ) { case NIL: return 0; case BOOL: return _data._bool ? 1 : 0; case INT: return _data._int; case REAL: return _data._real; case STRING: return operator String().to_int(); default: { return 0; } } return 0; } /* Variant::operator long unsigned int() const { switch( type ) { case NIL: return 0; case BOOL: return _data._bool ? 1 : 0; case INT: return _data._int; case REAL: return _data._real; case STRING: return operator String().to_int(); default: { return 0; } } return 0; }; */ Variant::operator uint64_t() const { switch( type ) { case NIL: return 0; case BOOL: return _data._bool ? 1 : 0; case INT: return _data._int; case REAL: return _data._real; case STRING: return operator String().to_int(); default: { return 0; } } return 0; } #ifdef NEED_LONG_INT Variant::operator signed long() const { switch( type ) { case NIL: return 0; case BOOL: return _data._bool ? 1 : 0; case INT: return _data._int; case REAL: return _data._real; case STRING: return operator String().to_int(); default: { return 0; } } return 0; }; Variant::operator unsigned long() const { switch( type ) { case NIL: return 0; case BOOL: return _data._bool ? 1 : 0; case INT: return _data._int; case REAL: return _data._real; case STRING: return operator String().to_int(); default: { return 0; } } return 0; }; #endif Variant::operator signed short() const { switch( type ) { case NIL: return 0; case BOOL: return _data._bool ? 1 : 0; case INT: return _data._int; case REAL: return _data._real; case STRING: return operator String().to_int(); default: { return 0; } } return 0; } Variant::operator unsigned short() const { switch( type ) { case NIL: return 0; case BOOL: return _data._bool ? 1 : 0; case INT: return _data._int; case REAL: return _data._real; case STRING: return operator String().to_int(); default: { return 0; } } return 0; } Variant::operator signed char() const { switch( type ) { case NIL: return 0; case BOOL: return _data._bool ? 1 : 0; case INT: return _data._int; case REAL: return _data._real; case STRING: return operator String().to_int(); default: { return 0; } } return 0; } Variant::operator unsigned char() const { switch( type ) { case NIL: return 0; case BOOL: return _data._bool ? 1 : 0; case INT: return _data._int; case REAL: return _data._real; case STRING: return operator String().to_int(); default: { return 0; } } return 0; } Variant::operator CharType() const { return operator unsigned int(); } Variant::operator float() const { switch( type ) { case NIL: return 0; case BOOL: return _data._bool ? 1.0 : 0.0; case INT: return (float)_data._int; case REAL: return _data._real; case STRING: return operator String().to_double(); default: { return 0; } } return 0; } Variant::operator double() const { switch( type ) { case NIL: return 0; case BOOL: return _data._bool ? 1.0 : 0.0; case INT: return (double)_data._int; case REAL: return _data._real; case STRING: return operator String().to_double(); default: { return 0; } } return true; } Variant::operator StringName() const { if (type==NODE_PATH) { return reinterpret_cast(_data._mem)->get_sname(); } return StringName(operator String()); } struct _VariantStrPair { String key; String value; bool operator<(const _VariantStrPair& p) const { return key < p.key; } }; Variant::operator String() const { switch( type ) { case NIL: return "Null"; case BOOL: return _data._bool ? "True" : "False"; case INT: return itos(_data._int); case REAL: return rtos(_data._real); case STRING: return *reinterpret_cast(_data._mem); case VECTOR2: return "("+operator Vector2()+")"; case RECT2: return "("+operator Rect2()+")"; case TRANSFORM2D: { Transform2D mat32 = operator Transform2D(); return "("+Variant(mat32.elements[0]).operator String()+", "+Variant(mat32.elements[1]).operator String()+", "+Variant(mat32.elements[2]).operator String()+")"; } break; case VECTOR3: return "("+operator Vector3()+")"; case PLANE: return operator Plane(); //case QUAT: case RECT3: return operator Rect3(); case QUAT: return "("+operator Quat()+")"; case BASIS: { Basis mat3 = operator Basis(); String mtx("("); for (int i=0;i<3;i++) { if (i!=0) mtx+=", "; mtx+="("; for (int j=0;j<3;j++) { if (j!=0) mtx+=", "; mtx+=Variant( mat3.elements[i][j] ).operator String(); } mtx+=")"; } return mtx+")"; } break; case TRANSFORM: return operator Transform(); case NODE_PATH: return operator NodePath(); case INPUT_EVENT: return operator InputEvent(); case COLOR: return String::num( operator Color().r)+","+String::num( operator Color().g)+","+String::num( operator Color().b)+","+String::num( operator Color().a) ; case DICTIONARY: { const Dictionary &d =*reinterpret_cast(_data._mem); //const String *K=NULL; String str; List keys; d.get_key_list(&keys); Vector<_VariantStrPair> pairs; for(List::Element *E=keys.front();E;E=E->next()) { _VariantStrPair sp; sp.key=String(E->get()); sp.value=d[E->get()]; pairs.push_back(sp); } pairs.sort(); for(int i=0;i0) str+=", "; str+="("+pairs[i].key+":"+pairs[i].value+")"; } return str; } break; case POOL_VECTOR2_ARRAY: { PoolVector vec = operator PoolVector(); String str("["); for(int i=0;i0) str+=", "; str=str+Variant( vec[i] ); } str += "]"; return str; } break; case POOL_VECTOR3_ARRAY: { PoolVector vec = operator PoolVector(); String str("["); for(int i=0;i0) str+=", "; str=str+Variant( vec[i] ); } str += "]"; return str; } break; case POOL_STRING_ARRAY: { PoolVector vec = operator PoolVector(); String str("["); for(int i=0;i0) str+=", "; str=str+vec[i]; } str += "]"; return str; } break; case POOL_INT_ARRAY: { PoolVector vec = operator PoolVector(); String str("["); for(int i=0;i0) str+=", "; str=str+itos(vec[i]); } str += "]"; return str; } break; case POOL_REAL_ARRAY: { PoolVector vec = operator PoolVector(); String str("["); for(int i=0;i0) str+=", "; str=str+rtos(vec[i]); } str += "]"; return str; } break; case ARRAY: { Array arr = operator Array(); String str("["); for (int i=0; iget_class()+":"+itos(_get_obj().obj->get_instance_ID())+"]"; } else return "[Object:null]"; } break; default: { return "["+get_type_name(type)+"]"; } } return ""; } Variant::operator Vector2() const { if (type==VECTOR2) return *reinterpret_cast(_data._mem); else if (type==VECTOR3) return Vector2(reinterpret_cast(_data._mem)->x,reinterpret_cast(_data._mem)->y); else return Vector2(); } Variant::operator Rect2() const { if (type==RECT2) return *reinterpret_cast(_data._mem); else return Rect2(); } Variant::operator Vector3() const { if (type==VECTOR3) return *reinterpret_cast(_data._mem); else return Vector3(); } Variant::operator Plane() const { if (type==PLANE) return *reinterpret_cast(_data._mem); else return Plane(); } Variant::operator Rect3() const { if (type==RECT3) return *_data._rect3; else return Rect3(); } Variant::operator Basis() const { if (type==BASIS) return *_data._basis; else if (type==QUAT) return *reinterpret_cast(_data._mem); else if (type==TRANSFORM) return _data._transform->basis; else return Basis(); } Variant::operator Quat() const { if (type==QUAT) return *reinterpret_cast(_data._mem); else if (type==BASIS) return *_data._basis; else if (type==TRANSFORM) return _data._transform->basis; else return Quat(); } Variant::operator Transform() const { if (type==TRANSFORM) return *_data._transform; else if (type==BASIS) return Transform(*_data._basis,Vector3()); else if (type==QUAT) return Transform(Basis(*reinterpret_cast(_data._mem)),Vector3()); else return Transform(); } Variant::operator Transform2D() const { if (type==TRANSFORM2D) { return *_data._transform2d; } else if (type==TRANSFORM) { const Transform& t = *_data._transform; Transform2D m; m.elements[0][0]=t.basis.elements[0][0]; m.elements[0][1]=t.basis.elements[1][0]; m.elements[1][0]=t.basis.elements[0][1]; m.elements[1][1]=t.basis.elements[1][1]; m.elements[2][0]=t.origin[0]; m.elements[2][1]=t.origin[1]; return m; } else return Transform2D(); } Variant::operator Color() const { if (type==COLOR) return *reinterpret_cast(_data._mem); else if (type==STRING) return Color::html( operator String() ); else if (type==INT) return Color::hex( operator int() ); else return Color(); } Variant::operator Image() const { if (type==IMAGE) return *_data._image; else return Image(); } Variant::operator NodePath() const { if (type==NODE_PATH) return *reinterpret_cast(_data._mem); else if (type==STRING) return NodePath(operator String()); else return NodePath(); } Variant::operator RefPtr() const { if (type==OBJECT) return _get_obj().ref; else return RefPtr(); } Variant::operator RID() const { if (type==_RID) return *reinterpret_cast(_data._mem); else if (type==OBJECT && !_get_obj().ref.is_null()) { return _get_obj().ref.get_rid(); } else if (type==OBJECT && _get_obj().obj) { Variant::CallError ce; Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->get_rid,NULL,0,ce); if (ce.error==Variant::CallError::CALL_OK && ret.get_type()==Variant::_RID) { return ret; } return RID(); } else { return RID(); } } Variant::operator Object*() const { if (type==OBJECT) return _get_obj().obj; else return NULL; } Variant::operator Node*() const { if (type==OBJECT) return _get_obj().obj?_get_obj().obj->cast_to():NULL; else return NULL; } Variant::operator Control*() const { if (type==OBJECT) return _get_obj().obj?_get_obj().obj->cast_to():NULL; else return NULL; } Variant::operator InputEvent() const { if (type==INPUT_EVENT) return *reinterpret_cast(_data._input_event); else return InputEvent(); } Variant::operator Dictionary() const { if (type==DICTIONARY) return *reinterpret_cast(_data._mem); else return Dictionary(); } template inline DA _convert_array(const SA& p_array) { DA da; da.resize(p_array.size()); for(int i=0;i inline DA _convert_array_from_variant(const Variant& p_variant) { switch(p_variant.get_type()) { case Variant::ARRAY: { return _convert_array( p_variant.operator Array () ); } case Variant::POOL_BYTE_ARRAY: { return _convert_array >( p_variant.operator PoolVector () ); } case Variant::POOL_INT_ARRAY: { return _convert_array >( p_variant.operator PoolVector () ); } case Variant::POOL_REAL_ARRAY: { return _convert_array >( p_variant.operator PoolVector () ); } case Variant::POOL_STRING_ARRAY: { return _convert_array >( p_variant.operator PoolVector () ); } case Variant::POOL_VECTOR2_ARRAY: { return _convert_array >( p_variant.operator PoolVector () ); } case Variant::POOL_VECTOR3_ARRAY: { return _convert_array >( p_variant.operator PoolVector () ); } case Variant::POOL_COLOR_ARRAY: { return _convert_array >( p_variant.operator PoolVector() ); } default: { return DA(); } } return DA(); } Variant::operator Array() const { if (type==ARRAY) return *reinterpret_cast(_data._mem); else return _convert_array_from_variant(*this); } Variant::operator PoolVector() const { if (type==POOL_BYTE_ARRAY) return *reinterpret_cast* >(_data._mem); else return _convert_array_from_variant >(*this); } Variant::operator PoolVector() const { if (type==POOL_INT_ARRAY) return *reinterpret_cast* >(_data._mem); else return _convert_array_from_variant >(*this); } Variant::operator PoolVector() const { if (type==POOL_REAL_ARRAY) return *reinterpret_cast* >(_data._mem); else return _convert_array_from_variant >(*this); } Variant::operator PoolVector() const { if (type==POOL_STRING_ARRAY) return *reinterpret_cast* >(_data._mem); else return _convert_array_from_variant >(*this); } Variant::operator PoolVector() const { if (type==POOL_VECTOR3_ARRAY) return *reinterpret_cast* >(_data._mem); else return _convert_array_from_variant >(*this); } Variant::operator PoolVector() const { if (type==POOL_VECTOR2_ARRAY) return *reinterpret_cast* >(_data._mem); else return _convert_array_from_variant >(*this); } Variant::operator PoolVector() const { if (type==POOL_COLOR_ARRAY) return *reinterpret_cast* >(_data._mem); else return _convert_array_from_variant >(*this); } /* helpers */ Variant::operator Vector() const { Array va= operator Array(); Vector rids; rids.resize(va.size()); for(int i=0;i() const { PoolVector from=operator PoolVector(); Vector to; int len=from.size(); if (len==0) return Vector(); to.resize(len); PoolVector::Read r = from.read(); Vector2 *w = &to[0]; for (int i=0;i() const { Array va= operator Array(); PoolVector planes; int va_size=va.size(); if (va_size==0) return planes; planes.resize(va_size); PoolVector::Write w = planes.write(); for(int i=0;i() const { PoolVector va= operator PoolVector(); PoolVector faces; int va_size=va.size(); if (va_size==0) return faces; faces.resize(va_size/3); PoolVector::Write w = faces.write(); PoolVector::Read r = va.read(); for(int i=0;i() const { Array va= operator Array(); Vector planes; int va_size=va.size(); if (va_size==0) return planes; planes.resize(va_size); for(int i=0;i() const { Array from=operator Array(); Vector to; int len=from.size(); to.resize(len); for (int i=0;i() const { PoolVector from=operator PoolVector(); Vector to; int len=from.size(); to.resize(len); for (int i=0;i() const { PoolVector from=operator PoolVector(); Vector to; int len=from.size(); to.resize(len); for (int i=0;i() const { PoolVector from=operator PoolVector(); Vector to; int len=from.size(); to.resize(len); for (int i=0;i() const { PoolVector from=operator PoolVector(); Vector to; int len=from.size(); to.resize(len); for (int i=0;i() const { PoolVector from=operator PoolVector(); Vector to; int len=from.size(); if (len==0) return Vector(); to.resize(len); PoolVector::Read r = from.read(); Vector3 *w = &to[0]; for (int i=0;i() const { PoolVector from=operator PoolVector(); Vector to; int len=from.size(); if (len==0) return Vector(); to.resize(len); PoolVector::Read r = from.read(); Color *w = &to[0]; for (int i=0;i addr=operator PoolVector(); if (addr.size()==4) { return IP_Address(addr.get(0),addr.get(1),addr.get(2),addr.get(3)); } } return IP_Address( operator String() ); } Variant::Variant(bool p_bool) { type=BOOL; _data._bool=p_bool; } /* Variant::Variant(long unsigned int p_long) { type=INT; _data._int=p_long; }; */ Variant::Variant(signed int p_int) { type=INT; _data._int=p_int; } Variant::Variant(unsigned int p_int) { type=INT; _data._int=p_int; } #ifdef NEED_LONG_INT Variant::Variant(signed long p_int) { type=INT; _data._int=p_int; } Variant::Variant(unsigned long p_int) { type=INT; _data._int=p_int; } #endif Variant::Variant(int64_t p_int) { type=INT; _data._int=p_int; } Variant::Variant(uint64_t p_int) { type=INT; _data._int=p_int; } Variant::Variant(signed short p_short) { type=INT; _data._int=p_short; } Variant::Variant(unsigned short p_short) { type=INT; _data._int=p_short; } Variant::Variant(signed char p_char) { type=INT; _data._int=p_char; } Variant::Variant(unsigned char p_char) { type=INT; _data._int=p_char; } Variant::Variant(float p_float) { type=REAL; _data._real=p_float; } Variant::Variant(double p_double) { type=REAL; _data._real=p_double; } Variant::Variant(const StringName& p_string) { type=STRING; memnew_placement( _data._mem, String( p_string.operator String() ) ); } Variant::Variant(const String& p_string) { type=STRING; memnew_placement( _data._mem, String( p_string ) ); } Variant::Variant(const char * const p_cstring) { type=STRING; memnew_placement( _data._mem, String( (const char*)p_cstring ) ); } Variant::Variant(const CharType * p_wstring) { type=STRING; memnew_placement( _data._mem, String( p_wstring ) ); } Variant::Variant(const Vector3& p_vector3) { type=VECTOR3; memnew_placement( _data._mem, Vector3( p_vector3 ) ); } Variant::Variant(const Vector2& p_vector2) { type=VECTOR2; memnew_placement( _data._mem, Vector2( p_vector2 ) ); } Variant::Variant(const Rect2& p_rect2) { type=RECT2; memnew_placement( _data._mem, Rect2( p_rect2 ) ); } Variant::Variant(const Plane& p_plane) { type=PLANE; memnew_placement( _data._mem, Plane( p_plane ) ); } Variant::Variant(const Rect3& p_aabb) { type=RECT3; _data._rect3 = memnew( Rect3( p_aabb ) ); } Variant::Variant(const Basis& p_matrix) { type=BASIS; _data._basis= memnew( Basis( p_matrix ) ); } Variant::Variant(const Quat& p_quat) { type=QUAT; memnew_placement( _data._mem, Quat( p_quat ) ); } Variant::Variant(const Transform& p_transform) { type=TRANSFORM; _data._transform = memnew( Transform( p_transform ) ); } Variant::Variant(const Transform2D& p_transform) { type=TRANSFORM2D; _data._transform2d = memnew( Transform2D( p_transform ) ); } Variant::Variant(const Color& p_color) { type=COLOR; memnew_placement( _data._mem, Color(p_color) ); } Variant::Variant(const Image& p_image) { type=IMAGE; _data._image=memnew( Image(p_image) ); } Variant::Variant(const NodePath& p_node_path) { type=NODE_PATH; memnew_placement( _data._mem, NodePath(p_node_path) ); } Variant::Variant(const InputEvent& p_input_event) { type=INPUT_EVENT; _data._input_event = memnew( InputEvent(p_input_event) ); } Variant::Variant(const RefPtr& p_resource) { type=OBJECT; memnew_placement( _data._mem, ObjData ); REF ref = p_resource; _get_obj().obj=ref.ptr(); _get_obj().ref=p_resource; } Variant::Variant(const RID& p_rid) { type=_RID; memnew_placement( _data._mem, RID(p_rid) ); } Variant::Variant(const Object* p_object) { type=OBJECT; memnew_placement( _data._mem, ObjData ); _get_obj().obj=const_cast(p_object); } Variant::Variant(const Dictionary& p_dictionary) { type=DICTIONARY; memnew_placement( _data._mem, (Dictionary)( p_dictionary) ); } Variant::Variant(const Array& p_array) { type=ARRAY; memnew_placement( _data._mem, Array(p_array) ); } Variant::Variant(const PoolVector& p_array) { type=ARRAY; Array *plane_array=memnew_placement( _data._mem, Array ); plane_array->resize( p_array.size() ); for (int i=0;ioperator [](i)=Variant(p_array[i]); } } Variant::Variant(const Vector& p_array) { type=ARRAY; Array *plane_array=memnew_placement( _data._mem, Array ); plane_array->resize( p_array.size() ); for (int i=0;ioperator [](i)=Variant(p_array[i]); } } Variant::Variant(const Vector& p_array) { type=ARRAY; Array *rid_array=memnew_placement( _data._mem, Array ); rid_array->resize( p_array.size() ); for (int i=0;iset(i,Variant(p_array[i])); } } Variant::Variant(const Vector& p_array) { type=NIL; PoolVector v; int len=p_array.size(); if (len>0) { v.resize(len); PoolVector::Write w = v.write(); const Vector2 *r = p_array.ptr(); for (int i=0;i& p_raw_array) { type=POOL_BYTE_ARRAY; memnew_placement( _data._mem, PoolVector(p_raw_array) ); } Variant::Variant(const PoolVector& p_int_array) { type=POOL_INT_ARRAY; memnew_placement( _data._mem, PoolVector(p_int_array) ); } Variant::Variant(const PoolVector& p_real_array) { type=POOL_REAL_ARRAY; memnew_placement( _data._mem, PoolVector(p_real_array) ); } Variant::Variant(const PoolVector& p_string_array) { type=POOL_STRING_ARRAY; memnew_placement( _data._mem, PoolVector(p_string_array) ); } Variant::Variant(const PoolVector& p_vector3_array) { type=POOL_VECTOR3_ARRAY; memnew_placement( _data._mem, PoolVector(p_vector3_array) ); } Variant::Variant(const PoolVector& p_vector2_array) { type=POOL_VECTOR2_ARRAY; memnew_placement( _data._mem, PoolVector(p_vector2_array) ); } Variant::Variant(const PoolVector& p_color_array) { type=POOL_COLOR_ARRAY; memnew_placement( _data._mem, PoolVector(p_color_array) ); } Variant::Variant(const PoolVector& p_face_array) { PoolVector vertices; int face_count=p_face_array.size(); vertices.resize(face_count*3); if (face_count) { PoolVector::Read r = p_face_array.read(); PoolVector::Write w = vertices.write(); for(int i=0;i::Read(); w=PoolVector::Write(); } type = NIL; *this = vertices; } /* helpers */ Variant::Variant(const Vector& p_array) { type=NIL; Array v; int len=p_array.size(); v.resize(len); for (int i=0;i& p_array) { type=NIL; PoolVector v; int len=p_array.size(); v.resize(len); for (int i=0;i& p_array) { type=NIL; PoolVector v; int len=p_array.size(); v.resize(len); for (int i=0;i& p_array) { type=NIL; PoolVector v; int len=p_array.size(); v.resize(len); for (int i=0;i& p_array) { type=NIL; PoolVector v; int len=p_array.size(); v.resize(len); for (int i=0;i& p_array) { type=NIL; PoolVector v; int len=p_array.size(); if (len>0) { v.resize(len); PoolVector::Write w = v.write(); const Vector3 *r = p_array.ptr(); for (int i=0;i& p_array) { type=NIL; PoolVector v; int len=p_array.size(); v.resize(len); for (int i=0;i(_data._mem)->hash(); } break; // math types case VECTOR2: { uint32_t hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->x); return hash_djb2_one_float(reinterpret_cast(_data._mem)->y,hash); } break; case RECT2: { uint32_t hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->pos.x); hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->pos.y,hash); hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->size.x,hash); return hash_djb2_one_float(reinterpret_cast(_data._mem)->size.y,hash); } break; case TRANSFORM2D: { uint32_t hash = 5831; for(int i=0;i<3;i++) { for(int j=0;j<2;j++) { hash = hash_djb2_one_float(_data._transform2d->elements[i][j],hash); } } return hash; } break; case VECTOR3: { uint32_t hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->x); hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->y,hash); return hash_djb2_one_float(reinterpret_cast(_data._mem)->z,hash); } break; case PLANE: { uint32_t hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->normal.x); hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->normal.y,hash); hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->normal.z,hash); return hash_djb2_one_float(reinterpret_cast(_data._mem)->d,hash); } break; /* case QUAT: { } break;*/ case RECT3: { uint32_t hash = 5831; for(int i=0;i<3;i++) { hash = hash_djb2_one_float(_data._rect3->pos[i],hash); hash = hash_djb2_one_float(_data._rect3->size[i],hash); } return hash; } break; case QUAT: { uint32_t hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->x); hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->y,hash); hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->z,hash); return hash_djb2_one_float(reinterpret_cast(_data._mem)->w,hash); } break; case BASIS: { uint32_t hash = 5831; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { hash = hash_djb2_one_float(_data._basis->elements[i][j],hash); } } return hash; } break; case TRANSFORM: { uint32_t hash = 5831; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { hash = hash_djb2_one_float(_data._transform->basis.elements[i][j],hash); } hash = hash_djb2_one_float(_data._transform->origin[i],hash); } return hash; } break; // misc types case COLOR: { uint32_t hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->r); hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->g,hash); hash = hash_djb2_one_float(reinterpret_cast(_data._mem)->b,hash); return hash_djb2_one_float(reinterpret_cast(_data._mem)->a,hash); } break; case IMAGE: { return 0; } break; case _RID: { return hash_djb2_one_64(reinterpret_cast(_data._mem)->get_id()); } break; case OBJECT: { return hash_djb2_one_64(make_uint64_t(_get_obj().obj)); } break; case NODE_PATH: { return reinterpret_cast(_data._mem)->hash(); } break; case INPUT_EVENT: { return hash_djb2_buffer((uint8_t*)_data._input_event,sizeof(InputEvent)); } break; case DICTIONARY: { return reinterpret_cast(_data._mem)->hash(); } break; case ARRAY: { const Array& arr = *reinterpret_cast(_data._mem); return arr.hash(); } break; case POOL_BYTE_ARRAY: { const PoolVector& arr = *reinterpret_cast* >(_data._mem); int len = arr.size(); PoolVector::Read r = arr.read(); return hash_djb2_buffer((uint8_t*)&r[0],len); } break; case POOL_INT_ARRAY: { const PoolVector& arr = *reinterpret_cast* >(_data._mem); int len = arr.size(); PoolVector::Read r = arr.read(); return hash_djb2_buffer((uint8_t*)&r[0],len*sizeof(int)); } break; case POOL_REAL_ARRAY: { const PoolVector& arr = *reinterpret_cast* >(_data._mem); int len = arr.size(); PoolVector::Read r = arr.read(); return hash_djb2_buffer((uint8_t*)&r[0],len*sizeof(real_t)); } break; case POOL_STRING_ARRAY: { uint32_t hash=5831; const PoolVector& arr = *reinterpret_cast* >(_data._mem); int len = arr.size(); PoolVector::Read r = arr.read(); for(int i=0;i& arr = *reinterpret_cast* >(_data._mem); int len = arr.size(); PoolVector::Read r = arr.read(); for(int i=0;i& arr = *reinterpret_cast* >(_data._mem); int len = arr.size(); PoolVector::Read r = arr.read(); for(int i=0;i& arr = *reinterpret_cast* >(_data._mem); int len = arr.size(); PoolVector::Read r = arr.read(); for(int i=0;i& l = *reinterpret_cast*>(p_lhs);\ const PoolVector& r = *reinterpret_cast*>(p_rhs);\ \ if(l.size() != r.size()) \ return false; \ \ PoolVector::Read lr = l.read(); \ PoolVector::Read rr = r.read(); \ \ for(int i = 0; i < l.size(); ++i) { \ if(! p_compare_func((lr[0]), (rr[0]))) \ return false; \ }\ \ return true bool Variant::hash_compare(const Variant& p_variant) const { if (type != p_variant.type) return false; switch( type ) { case REAL: { return hash_compare_scalar(_data._real, p_variant._data._real); } break; case VECTOR2: { const Vector2* l = reinterpret_cast(_data._mem); const Vector2* r = reinterpret_cast(p_variant._data._mem); return hash_compare_vector2(*l, *r); } break; case RECT2: { const Rect2* l = reinterpret_cast(_data._mem); const Rect2* r = reinterpret_cast(p_variant._data._mem); return (hash_compare_vector2(l->pos, r->pos)) && (hash_compare_vector2(l->size, r->size)); } break; case TRANSFORM2D: { Transform2D* l = _data._transform2d; Transform2D* r = p_variant._data._transform2d; for(int i=0;i<3;i++) { if (! (hash_compare_vector2(l->elements[i], r->elements[i]))) return false; } return true; } break; case VECTOR3: { const Vector3* l = reinterpret_cast(_data._mem); const Vector3* r = reinterpret_cast(p_variant._data._mem); return hash_compare_vector3(*l, *r); } break; case PLANE: { const Plane* l = reinterpret_cast(_data._mem); const Plane* r = reinterpret_cast(p_variant._data._mem); return (hash_compare_vector3(l->normal, r->normal)) && (hash_compare_scalar(l->d, r->d)); } break; case RECT3: { const Rect3* l = _data._rect3; const Rect3* r = p_variant._data._rect3; return (hash_compare_vector3(l->pos, r->pos) && (hash_compare_vector3(l->size, r->size))); } break; case QUAT: { const Quat* l = reinterpret_cast(_data._mem); const Quat* r = reinterpret_cast(p_variant._data._mem); return hash_compare_quat(*l, *r); } break; case BASIS: { const Basis* l = _data._basis; const Basis* r = p_variant._data._basis; for(int i=0;i<3;i++) { if (! (hash_compare_vector3(l->elements[i], r->elements[i]))) return false; } return true; } break; case TRANSFORM: { const Transform* l = _data._transform; const Transform* r = p_variant._data._transform; for(int i=0;i<3;i++) { if (! (hash_compare_vector3(l->basis.elements[i], r->basis.elements[i]))) return false; } return hash_compare_vector3(l->origin, r->origin); } break; case COLOR: { const Color* l = reinterpret_cast(_data._mem); const Color* r = reinterpret_cast(p_variant._data._mem); return hash_compare_color(*l, *r); } break; case ARRAY: { const Array& l = *(reinterpret_cast(_data._mem)); const Array& r = *(reinterpret_cast(p_variant._data._mem)); if(l.size() != r.size()) return false; for(int i = 0; i < l.size(); ++i) { if(! l[0].hash_compare(r[0])) return false; } return true; } break; case POOL_REAL_ARRAY: { hash_compare_pool_array(_data._mem, p_variant._data._mem, real_t, hash_compare_scalar); } break; case POOL_VECTOR2_ARRAY: { hash_compare_pool_array(_data._mem, p_variant._data._mem, Vector2, hash_compare_vector2); } break; case POOL_VECTOR3_ARRAY: { hash_compare_pool_array(_data._mem, p_variant._data._mem, Vector3, hash_compare_vector3); } break; case POOL_COLOR_ARRAY: { hash_compare_pool_array(_data._mem, p_variant._data._mem, Color, hash_compare_color); } break; default: bool v; Variant r; evaluate(OP_EQUAL,*this,p_variant,r,v); return r; } return false; } bool Variant::is_ref() const { return type==OBJECT && !_get_obj().ref.is_null(); } Vector varray() { return Vector(); } Vector varray(const Variant& p_arg1) { Vector v; v.push_back(p_arg1); return v; } Vector varray(const Variant& p_arg1,const Variant& p_arg2) { Vector v; v.push_back(p_arg1); v.push_back(p_arg2); return v; } Vector varray(const Variant& p_arg1,const Variant& p_arg2,const Variant& p_arg3) { Vector v; v.push_back(p_arg1); v.push_back(p_arg2); v.push_back(p_arg3); return v; } Vector varray(const Variant& p_arg1,const Variant& p_arg2,const Variant& p_arg3,const Variant& p_arg4) { Vector v; v.push_back(p_arg1); v.push_back(p_arg2); v.push_back(p_arg3); v.push_back(p_arg4); return v; } Vector varray(const Variant& p_arg1,const Variant& p_arg2,const Variant& p_arg3,const Variant& p_arg4,const Variant& p_arg5) { Vector v; v.push_back(p_arg1); v.push_back(p_arg2); v.push_back(p_arg3); v.push_back(p_arg4); v.push_back(p_arg5); return v; } void Variant::static_assign(const Variant& p_variant) { } bool Variant::is_shared() const { switch(type) { case OBJECT: return true; case ARRAY: return true; case DICTIONARY: return true; default: {} } return false; } Variant Variant::call(const StringName& p_method,VARIANT_ARG_DECLARE) { VARIANT_ARGPTRS; int argc=0; for(int i=0;iget_type()==Variant::NIL) break; argc++; } CallError error; Variant ret = call(p_method,argptr,argc,error); switch(error.error) { case CallError::CALL_ERROR_INVALID_ARGUMENT: { String err = "Invalid type for argument #"+itos(error.argument)+", expected '"+Variant::get_type_name(error.expected)+"'."; ERR_PRINT(err.utf8().get_data()); } break; case CallError::CALL_ERROR_INVALID_METHOD: { String err = "Invalid method '"+p_method+"' for type '"+Variant::get_type_name(type)+"'."; ERR_PRINT(err.utf8().get_data()); } break; case CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: { String err = "Too many arguments for method '"+p_method+"'"; ERR_PRINT(err.utf8().get_data()); } break; default: {} } return ret; } void Variant::construct_from_string(const String& p_string,Variant& r_value,ObjectConstruct p_obj_construct,void *p_construct_ud) { r_value=Variant(); } String Variant::get_construct_string() const { String vars; VariantWriter::write_to_string(*this,vars); return vars; } String Variant::get_call_error_text(Object* p_base, const StringName& p_method,const Variant** p_argptrs,int p_argcount,const Variant::CallError &ce) { String err_text; if (ce.error==Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) { int errorarg=ce.argument; err_text="Cannot convert argument "+itos(errorarg+1)+" from "+Variant::get_type_name(p_argptrs[errorarg]->get_type())+" to "+Variant::get_type_name(ce.expected)+"."; } else if (ce.error==Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) { err_text="Method expected "+itos(ce.argument)+" arguments, but called with "+itos(p_argcount)+"."; } else if (ce.error==Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) { err_text="Method expected "+itos(ce.argument)+" arguments, but called with "+itos(p_argcount)+"."; } else if (ce.error==Variant::CallError::CALL_ERROR_INVALID_METHOD) { err_text="Method not found."; } else if (ce.error==Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL) { err_text="Instance is null"; } else if (ce.error==Variant::CallError::CALL_OK){ return "Call OK"; } String class_name = p_base->get_class(); Ref