/*************************************************************************/ /* 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 "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 MATRIX32: { return "Matrix32"; } break; case VECTOR3: { return "Vector3"; } break; case PLANE: { return "Plane"; } break; /* case QUAT: { } break;*/ case _AABB: { return "AABB"; } break; case QUAT: { return "Quat"; } break; case MATRIX3: { return "Matrix3"; } 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 RAW_ARRAY: { return "RawArray"; } break; case INT_ARRAY: { return "IntArray"; } break; case REAL_ARRAY: { return "RealArray"; } break; case STRING_ARRAY: { return "StringArray"; } break; case VECTOR2_ARRAY: { return "Vector2Array"; } break; case VECTOR3_ARRAY: { return "Vector3Array"; } break; case COLOR_ARRAY: { return "ColorArray"; } 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 MATRIX32: { static const Type valid[]={ TRANSFORM, NIL }; valid_types=valid; } break; case QUAT: { static const Type valid[]={ MATRIX3, NIL }; valid_types=valid; } break; case MATRIX3: { static const Type valid[]={ QUAT, NIL }; valid_types=valid; } break; case TRANSFORM: { static const Type valid[]={ MATRIX32, QUAT, MATRIX3, 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[]={ RAW_ARRAY, INT_ARRAY, STRING_ARRAY, REAL_ARRAY, COLOR_ARRAY, VECTOR2_ARRAY, VECTOR3_ARRAY, NIL }; valid_types=valid; } break; // arrays case RAW_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case INT_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case REAL_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case STRING_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case VECTOR2_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case VECTOR3_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case 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 MATRIX32: { static const Type valid[]={ TRANSFORM, NIL }; valid_types=valid; } break; case QUAT: { static const Type valid[]={ MATRIX3, NIL }; valid_types=valid; } break; case MATRIX3: { static const Type valid[]={ QUAT, NIL }; valid_types=valid; } break; case TRANSFORM: { static const Type valid[]={ MATRIX32, QUAT, MATRIX3, 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[]={ RAW_ARRAY, INT_ARRAY, STRING_ARRAY, REAL_ARRAY, COLOR_ARRAY, VECTOR2_ARRAY, VECTOR3_ARRAY, NIL }; valid_types=valid; } break; // arrays case RAW_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case INT_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case REAL_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case STRING_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case VECTOR2_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case VECTOR3_ARRAY: { static const Type valid[]={ ARRAY, NIL }; valid_types=valid; } break; case 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 MATRIX32: { return *_data._matrix32==Matrix32(); } break; case VECTOR3: { return *reinterpret_cast(_data._mem)==Vector3(); } break; case PLANE: { return *reinterpret_cast(_data._mem)==Plane(); } break; /* case QUAT: { } break;*/ case _AABB: { return *_data._aabb==AABB(); } break; case QUAT: { return *reinterpret_cast(_data._mem)==Quat(); } break; case MATRIX3: { return *_data._matrix3==Matrix3(); } 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 RAW_ARRAY: { return reinterpret_cast*>(_data._mem)->size()==0; } break; case INT_ARRAY: { return reinterpret_cast*>(_data._mem)->size()==0; } break; case REAL_ARRAY: { return reinterpret_cast*>(_data._mem)->size()==0; } break; case STRING_ARRAY: { return reinterpret_cast*>(_data._mem)->size()==0; } break; case VECTOR2_ARRAY: { return reinterpret_cast*>(_data._mem)->size()==0; } break; case VECTOR3_ARRAY: { return reinterpret_cast*>(_data._mem)->size()==0; } break; case 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 MATRIX32: { _data._matrix32 = memnew( Matrix32( *p_variant._data._matrix32 ) ); } 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 _AABB: { _data._aabb = memnew( AABB( *p_variant._data._aabb ) ); } break; case QUAT: { memnew_placement( _data._mem, Quat( *reinterpret_cast(p_variant._data._mem) ) ); } break; case MATRIX3: { _data._matrix3 = memnew( Matrix3( *p_variant._data._matrix3 ) ); } 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 RAW_ARRAY: { memnew_placement( _data._mem, PoolVector ( *reinterpret_cast*>(p_variant._data._mem) ) ); } break; case INT_ARRAY: { memnew_placement( _data._mem, PoolVector ( *reinterpret_cast*>(p_variant._data._mem) ) ); } break; case REAL_ARRAY: { memnew_placement( _data._mem, PoolVector ( *reinterpret_cast*>(p_variant._data._mem) ) ); } break; case STRING_ARRAY: { memnew_placement( _data._mem, PoolVector ( *reinterpret_cast*>(p_variant._data._mem) ) ); } break; case VECTOR2_ARRAY: { memnew_placement( _data._mem, PoolVector ( *reinterpret_cast*>(p_variant._data._mem) ) ); } break; case VECTOR3_ARRAY: { memnew_placement( _data._mem, PoolVector ( *reinterpret_cast*>(p_variant._data._mem) ) ); } break; case 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 MATRIX32: { memdelete( _data._matrix32 ); } break; case _AABB: { memdelete( _data._aabb ); } break; case MATRIX3: { memdelete( _data._matrix3 ); } 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 RAW_ARRAY: { reinterpret_cast< PoolVector* >(_data._mem)->~PoolVector(); } break; case INT_ARRAY: { reinterpret_cast< PoolVector* >(_data._mem)->~PoolVector(); } break; case REAL_ARRAY: { reinterpret_cast< PoolVector* >(_data._mem)->~PoolVector(); } break; case STRING_ARRAY: { reinterpret_cast< PoolVector* >(_data._mem)->~PoolVector(); } break; case VECTOR2_ARRAY: { reinterpret_cast< PoolVector* >(_data._mem)->~PoolVector(); } break; case VECTOR3_ARRAY: { reinterpret_cast< PoolVector* >(_data._mem)->~PoolVector(); } break; case 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 MATRIX32: { Matrix32 mat32 = operator Matrix32(); 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 _AABB: return operator AABB(); case QUAT: return "("+operator Quat()+")"; case MATRIX3: { Matrix3 mat3 = operator Matrix3(); 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 VECTOR2_ARRAY: { PoolVector vec = operator PoolVector(); String str("["); for(int i=0;i0) str+=", "; str=str+Variant( vec[i] ); } str += "]"; return str; } break; case VECTOR3_ARRAY: { PoolVector vec = operator PoolVector(); String str("["); for(int i=0;i0) str+=", "; str=str+Variant( vec[i] ); } str += "]"; return str; } break; case STRING_ARRAY: { PoolVector vec = operator PoolVector(); String str("["); for(int i=0;i0) str+=", "; str=str+vec[i]; } str += "]"; return str; } break; case INT_ARRAY: { PoolVector vec = operator PoolVector(); String str("["); for(int i=0;i0) str+=", "; str=str+itos(vec[i]); } str += "]"; return str; } break; case 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 AABB() const { if (type==_AABB) return *_data._aabb; else return AABB(); } Variant::operator Matrix3() const { if (type==MATRIX3) return *_data._matrix3; else if (type==QUAT) return *reinterpret_cast(_data._mem); else if (type==TRANSFORM) return _data._transform->basis; else return Matrix3(); } Variant::operator Quat() const { if (type==QUAT) return *reinterpret_cast(_data._mem); else if (type==MATRIX3) return *_data._matrix3; else if (type==TRANSFORM) return _data._transform->basis; else return Quat(); } Variant::operator Transform() const { if (type==TRANSFORM) return *_data._transform; else if (type==MATRIX3) return Transform(*_data._matrix3,Vector3()); else if (type==QUAT) return Transform(Matrix3(*reinterpret_cast(_data._mem)),Vector3()); else return Transform(); } Variant::operator Matrix32() const { if (type==MATRIX32) { return *_data._matrix32; } else if (type==TRANSFORM) { const Transform& t = *_data._transform;; Matrix32 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 Matrix32(); } 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::RAW_ARRAY: { return _convert_array >( p_variant.operator PoolVector () ); } case Variant::INT_ARRAY: { return _convert_array >( p_variant.operator PoolVector () ); } case Variant::REAL_ARRAY: { return _convert_array >( p_variant.operator PoolVector () ); } case Variant::STRING_ARRAY: { return _convert_array >( p_variant.operator PoolVector () ); } case Variant::VECTOR2_ARRAY: { return _convert_array >( p_variant.operator PoolVector () ); } case Variant::VECTOR3_ARRAY: { return _convert_array >( p_variant.operator PoolVector () ); } case Variant::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==RAW_ARRAY) return *reinterpret_cast* >(_data._mem); else return _convert_array_from_variant >(*this); } Variant::operator PoolVector() const { if (type==INT_ARRAY) return *reinterpret_cast* >(_data._mem); else return _convert_array_from_variant >(*this); } Variant::operator PoolVector() const { if (type==REAL_ARRAY) return *reinterpret_cast* >(_data._mem); else return _convert_array_from_variant >(*this); } Variant::operator PoolVector() const { if (type==STRING_ARRAY) return *reinterpret_cast* >(_data._mem); else return _convert_array_from_variant >(*this); } Variant::operator PoolVector() const { if (type==VECTOR3_ARRAY) return *reinterpret_cast* >(_data._mem); else return _convert_array_from_variant >(*this); } Variant::operator PoolVector() const { if (type==VECTOR2_ARRAY) return *reinterpret_cast* >(_data._mem); else return _convert_array_from_variant >(*this); } Variant::operator PoolVector() const { if (type==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 AABB& p_aabb) { type=_AABB; _data._aabb = memnew( AABB( p_aabb ) ); } Variant::Variant(const Matrix3& p_matrix) { type=MATRIX3; _data._matrix3= memnew( Matrix3( 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 Matrix32& p_transform) { type=MATRIX32; _data._matrix32 = memnew( Matrix32( 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=RAW_ARRAY; memnew_placement( _data._mem, PoolVector(p_raw_array) ); } Variant::Variant(const PoolVector& p_int_array) { type=INT_ARRAY; memnew_placement( _data._mem, PoolVector(p_int_array) ); } Variant::Variant(const PoolVector& p_real_array) { type=REAL_ARRAY; memnew_placement( _data._mem, PoolVector(p_real_array) ); } Variant::Variant(const PoolVector& p_string_array) { type=STRING_ARRAY; memnew_placement( _data._mem, PoolVector(p_string_array) ); } Variant::Variant(const PoolVector& p_vector3_array) { type=VECTOR3_ARRAY; memnew_placement( _data._mem, PoolVector(p_vector3_array) ); } Variant::Variant(const PoolVector& p_vector2_array) { type=VECTOR2_ARRAY; memnew_placement( _data._mem, PoolVector(p_vector2_array) ); } Variant::Variant(const PoolVector& p_color_array) { type=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 MATRIX32: { uint32_t hash = 5831; for(int i=0;i<3;i++) { for(int j=0;j<2;j++) { hash = hash_djb2_one_float(_data._matrix32->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 _AABB: { uint32_t hash = 5831; for(int i=0;i<3;i++) { hash = hash_djb2_one_float(_data._aabb->pos[i],hash); hash = hash_djb2_one_float(_data._aabb->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 MATRIX3: { uint32_t hash = 5831; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { hash = hash_djb2_one_float(_data._matrix3->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 RAW_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 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 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 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 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 reinterpret_cast(_data._mem)->is_shared(); case DICTIONARY: return reinterpret_cast(_data._mem)->is_shared(); 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