void ResourceFormatSaverBinaryInstance::write_variant(const Variant& p_property,const PropertyInfo& p_hint) { switch(p_property.get_type()) { case Variant::NIL: { f->store_32(VARIANT_NIL); // don't store anything } break; case Variant::BOOL: { f->store_32(VARIANT_BOOL); bool val=p_property; f->store_32(val); } break; case Variant::INT: { f->store_32(VARIANT_INT); int val=p_property; f->store_32(val); } break; case Variant::REAL: { f->store_32(VARIANT_REAL); real_t val=p_property; f->store_real(val); } break; case Variant::STRING: { f->store_32(VARIANT_STRING); String val=p_property; save_unicode_string(val); } break; case Variant::VECTOR2: { f->store_32(VARIANT_VECTOR2); Vector2 val=p_property; f->store_real(val.x); f->store_real(val.y); } break; case Variant::RECT2: { f->store_32(VARIANT_RECT2); Rect2 val=p_property; f->store_real(val.pos.x); f->store_real(val.pos.y); f->store_real(val.size.x); f->store_real(val.size.y); } break; case Variant::VECTOR3: { f->store_32(VARIANT_VECTOR3); Vector3 val=p_property; f->store_real(val.x); f->store_real(val.y); f->store_real(val.z); } break; case Variant::PLANE: { f->store_32(VARIANT_PLANE); Plane val=p_property; f->store_real(val.normal.x); f->store_real(val.normal.y); f->store_real(val.normal.z); f->store_real(val.d); } break; case Variant::QUAT: { f->store_32(VARIANT_QUAT); Quat val=p_property; f->store_real(val.x); f->store_real(val.y); f->store_real(val.z); f->store_real(val.w); } break; case Variant::_AABB: { f->store_32(VARIANT_AABB); AABB val=p_property; f->store_real(val.pos.x); f->store_real(val.pos.y); f->store_real(val.pos.z); f->store_real(val.size.x); f->store_real(val.size.y); f->store_real(val.size.z); } break; case Variant::MATRIX32: { f->store_32(VARIANT_MATRIX32); Matrix32 val=p_property; f->store_real(val.elements[0].x); f->store_real(val.elements[0].y); f->store_real(val.elements[1].x); f->store_real(val.elements[1].y); f->store_real(val.elements[2].x); f->store_real(val.elements[2].y); } break; case Variant::MATRIX3: { f->store_32(VARIANT_MATRIX3); Matrix3 val=p_property; f->store_real(val.elements[0].x); f->store_real(val.elements[0].y); f->store_real(val.elements[0].z); f->store_real(val.elements[1].x); f->store_real(val.elements[1].y); f->store_real(val.elements[1].z); f->store_real(val.elements[2].x); f->store_real(val.elements[2].y); f->store_real(val.elements[2].z); } break; case Variant::TRANSFORM: { f->store_32(VARIANT_TRANSFORM); Transform val=p_property; f->store_real(val.basis.elements[0].x); f->store_real(val.basis.elements[0].y); f->store_real(val.basis.elements[0].z); f->store_real(val.basis.elements[1].x); f->store_real(val.basis.elements[1].y); f->store_real(val.basis.elements[1].z); f->store_real(val.basis.elements[2].x); f->store_real(val.basis.elements[2].y); f->store_real(val.basis.elements[2].z); f->store_real(val.origin.x); f->store_real(val.origin.y); f->store_real(val.origin.z); } break; case Variant::COLOR: { f->store_32(VARIANT_COLOR); Color val=p_property; f->store_real(val.r); f->store_real(val.g); f->store_real(val.b); f->store_real(val.a); } break; case Variant::IMAGE: { f->store_32(VARIANT_IMAGE); Image val =p_property; if (val.empty()) { f->store_32(IMAGE_ENCODING_EMPTY); break; } int encoding=IMAGE_ENCODING_RAW; float quality=0.7; if (val.get_format() <= Image::FORMAT_INDEXED_ALPHA) { //can only compress uncompressed stuff if (p_hint.hint==PROPERTY_HINT_IMAGE_COMPRESS_LOSSY && Image::lossy_packer) { encoding=IMAGE_ENCODING_LOSSY; float qs=p_hint.hint_string.to_double(); if (qs!=0.0) quality=qs; } else if (p_hint.hint==PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS && Image::lossless_packer) { encoding=IMAGE_ENCODING_LOSSLESS; } } f->store_32(encoding); //raw encoding if (encoding==IMAGE_ENCODING_RAW) { f->store_32(val.get_width()); f->store_32(val.get_height()); f->store_32(val.get_mipmaps()); switch(val.get_format()) { case Image::FORMAT_GRAYSCALE: f->store_32(IMAGE_FORMAT_GRAYSCALE ); break; ///< one byte per pixel: f->store_32(IMAGE_FORMAT_ ); break; 0-255 case Image::FORMAT_INTENSITY: f->store_32(IMAGE_FORMAT_INTENSITY ); break; ///< one byte per pixel: f->store_32(IMAGE_FORMAT_ ); break; 0-255 case Image::FORMAT_GRAYSCALE_ALPHA: f->store_32(IMAGE_FORMAT_GRAYSCALE_ALPHA ); break; ///< two bytes per pixel: f->store_32(IMAGE_FORMAT_ ); break; 0-255. alpha 0-255 case Image::FORMAT_RGB: f->store_32(IMAGE_FORMAT_RGB ); break; ///< one byte R: f->store_32(IMAGE_FORMAT_ ); break; one byte G: f->store_32(IMAGE_FORMAT_ ); break; one byte B case Image::FORMAT_RGBA: f->store_32(IMAGE_FORMAT_RGBA ); break; ///< one byte R: f->store_32(IMAGE_FORMAT_ ); break; one byte G: f->store_32(IMAGE_FORMAT_ ); break; one byte B: f->store_32(IMAGE_FORMAT_ ); break; one byte A case Image::FORMAT_INDEXED: f->store_32(IMAGE_FORMAT_INDEXED ); break; ///< index byte 0-256: f->store_32(IMAGE_FORMAT_ ); break; and after image end: f->store_32(IMAGE_FORMAT_ ); break; 256*3 bytes of palette case Image::FORMAT_INDEXED_ALPHA: f->store_32(IMAGE_FORMAT_INDEXED_ALPHA ); break; ///< index byte 0-256: f->store_32(IMAGE_FORMAT_ ); break; and after image end: f->store_32(IMAGE_FORMAT_ ); break; 256*4 bytes of palette (alpha) case Image::FORMAT_BC1: f->store_32(IMAGE_FORMAT_BC1 ); break; // DXT1 case Image::FORMAT_BC2: f->store_32(IMAGE_FORMAT_BC2 ); break; // DXT3 case Image::FORMAT_BC3: f->store_32(IMAGE_FORMAT_BC3 ); break; // DXT5 case Image::FORMAT_BC4: f->store_32(IMAGE_FORMAT_BC4 ); break; // ATI1 case Image::FORMAT_BC5: f->store_32(IMAGE_FORMAT_BC5 ); break; // ATI2 case Image::FORMAT_PVRTC2: f->store_32(IMAGE_FORMAT_PVRTC2 ); break; case Image::FORMAT_PVRTC2_ALPHA: f->store_32(IMAGE_FORMAT_PVRTC2_ALPHA ); break; case Image::FORMAT_PVRTC4: f->store_32(IMAGE_FORMAT_PVRTC4 ); break; case Image::FORMAT_PVRTC4_ALPHA: f->store_32(IMAGE_FORMAT_PVRTC4_ALPHA ); break; case Image::FORMAT_ETC: f->store_32(IMAGE_FORMAT_ETC); break; case Image::FORMAT_CUSTOM: f->store_32(IMAGE_FORMAT_CUSTOM ); break; default: {} } int dlen = val.get_data().size(); f->store_32(dlen); DVector<uint8_t>::Read r = val.get_data().read(); f->store_buffer(r.ptr(),dlen); _pad_buffer(dlen); } else { DVector<uint8_t> data; if (encoding==IMAGE_ENCODING_LOSSY) { data=Image::lossy_packer(val,quality); } else if (encoding==IMAGE_ENCODING_LOSSLESS) { data=Image::lossless_packer(val); } int ds=data.size(); f->store_32(ds); if (ds>0) { DVector<uint8_t>::Read r = data.read(); f->store_buffer(r.ptr(),ds); _pad_buffer(ds); } } } break; case Variant::NODE_PATH: { f->store_32(VARIANT_NODE_PATH); NodePath np=p_property; f->store_16(np.get_name_count()); uint16_t snc = np.get_subname_count(); if (np.is_absolute()) snc|=0x8000; f->store_16(snc); for(int i=0;i<np.get_name_count();i++) f->store_32(get_string_index(np.get_name(i))); for(int i=0;i<np.get_subname_count();i++) f->store_32(get_string_index(np.get_subname(i))); f->store_32(get_string_index(np.get_property())); } break; case Variant::_RID: { f->store_32(VARIANT_RID); WARN_PRINT("Can't save RIDs"); RID val = p_property; f->store_32(val.get_id()); } break; case Variant::OBJECT: { f->store_32(VARIANT_OBJECT); RES res = p_property; if (res.is_null()) { f->store_32(OBJECT_EMPTY); return; // don't save it } if (res->get_path().length() && res->get_path().find("::")==-1) { f->store_32(OBJECT_EXTERNAL_RESOURCE); save_unicode_string(res->get_save_type()); String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path(); if (no_extensions) path=path.basename()+".*"; save_unicode_string(path); } else { if (!resource_map.has(res)) { f->store_32(OBJECT_EMPTY); ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?"); ERR_FAIL(); } f->store_32(OBJECT_INTERNAL_RESOURCE); f->store_32(resource_map[res]); //internal resource } } break; case Variant::INPUT_EVENT: { f->store_32(VARIANT_INPUT_EVENT); WARN_PRINT("Can't save InputEvent (maybe it could..)"); } break; case Variant::DICTIONARY: { f->store_32(VARIANT_DICTIONARY); Dictionary d = p_property; f->store_32(uint32_t(d.size())|(d.is_shared()?0x80000000:0)); List<Variant> keys; d.get_key_list(&keys); for(List<Variant>::Element *E=keys.front();E;E=E->next()) { //if (!_check_type(dict[E->get()])) // continue; write_variant(E->get()); write_variant(d[E->get()]); } } break; case Variant::ARRAY: { f->store_32(VARIANT_ARRAY); Array a=p_property; f->store_32(uint32_t(a.size())|(a.is_shared()?0x80000000:0)); for(int i=0;i<a.size();i++) { write_variant(a[i]); } } break; case Variant::RAW_ARRAY: { f->store_32(VARIANT_RAW_ARRAY); DVector<uint8_t> arr = p_property; int len=arr.size(); f->store_32(len); DVector<uint8_t>::Read r = arr.read(); f->store_buffer(r.ptr(),len); _pad_buffer(len); } break; case Variant::INT_ARRAY: { f->store_32(VARIANT_INT_ARRAY); DVector<int> arr = p_property; int len=arr.size(); f->store_32(len); DVector<int>::Read r = arr.read(); for(int i=0;i<len;i++) f->store_32(r[i]); } break; case Variant::REAL_ARRAY: { f->store_32(VARIANT_REAL_ARRAY); DVector<real_t> arr = p_property; int len=arr.size(); f->store_32(len); DVector<real_t>::Read r = arr.read(); for(int i=0;i<len;i++) { f->store_real(r[i]); } } break; case Variant::STRING_ARRAY: { f->store_32(VARIANT_STRING_ARRAY); DVector<String> arr = p_property; int len=arr.size(); f->store_32(len); DVector<String>::Read r = arr.read(); for(int i=0;i<len;i++) { save_unicode_string(r[i]); } } break; case Variant::VECTOR3_ARRAY: { f->store_32(VARIANT_VECTOR3_ARRAY); DVector<Vector3> arr = p_property; int len=arr.size(); f->store_32(len); DVector<Vector3>::Read r = arr.read(); for(int i=0;i<len;i++) { f->store_real(r[i].x); f->store_real(r[i].y); f->store_real(r[i].z); } } break; case Variant::VECTOR2_ARRAY: { f->store_32(VARIANT_VECTOR2_ARRAY); DVector<Vector2> arr = p_property; int len=arr.size(); f->store_32(len); DVector<Vector2>::Read r = arr.read(); for(int i=0;i<len;i++) { f->store_real(r[i].x); f->store_real(r[i].y); } } break; case Variant::COLOR_ARRAY: { f->store_32(VARIANT_COLOR_ARRAY); DVector<Color> arr = p_property; int len=arr.size(); f->store_32(len); DVector<Color>::Read r = arr.read(); for(int i=0;i<len;i++) { f->store_real(r[i].r); f->store_real(r[i].g); f->store_real(r[i].b); f->store_real(r[i].a); } } break; default: { ERR_EXPLAIN("Invalid variant"); ERR_FAIL(); } } }