2014-02-10 01:10:30 +00:00
/*************************************************************************/
/* resource_format_binary.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
2017-01-01 21:01:57 +00:00
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
2017-04-07 22:45:00 +00:00
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
2014-02-10 01:10:30 +00:00
/* */
/* 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 "resource_format_binary.h"
# include "globals.h"
# include "io/file_access_compressed.h"
# include "io/marshalls.h"
2015-08-23 23:15:56 +00:00
# include "os/dir_access.h"
2017-03-18 23:36:26 +00:00
# include "version.h"
2014-02-10 01:10:30 +00:00
//#define print_bl(m_what) print_line(m_what)
# define print_bl(m_what)
enum {
//numbering must be different from variant, in case new variant types are added (variant must be always contiguous for jumptable optimization)
2017-03-18 23:36:26 +00:00
VARIANT_NIL = 1 ,
VARIANT_BOOL = 2 ,
VARIANT_INT = 3 ,
VARIANT_REAL = 4 ,
VARIANT_STRING = 5 ,
VARIANT_VECTOR2 = 10 ,
VARIANT_RECT2 = 11 ,
VARIANT_VECTOR3 = 12 ,
VARIANT_PLANE = 13 ,
VARIANT_QUAT = 14 ,
VARIANT_AABB = 15 ,
VARIANT_MATRIX3 = 16 ,
VARIANT_TRANSFORM = 17 ,
VARIANT_MATRIX32 = 18 ,
VARIANT_COLOR = 20 ,
VARIANT_IMAGE = 21 ,
VARIANT_NODE_PATH = 22 ,
VARIANT_RID = 23 ,
VARIANT_OBJECT = 24 ,
VARIANT_INPUT_EVENT = 25 ,
VARIANT_DICTIONARY = 26 ,
VARIANT_ARRAY = 30 ,
VARIANT_RAW_ARRAY = 31 ,
VARIANT_INT_ARRAY = 32 ,
VARIANT_REAL_ARRAY = 33 ,
VARIANT_STRING_ARRAY = 34 ,
VARIANT_VECTOR3_ARRAY = 35 ,
VARIANT_COLOR_ARRAY = 36 ,
VARIANT_VECTOR2_ARRAY = 37 ,
IMAGE_ENCODING_EMPTY = 0 ,
IMAGE_ENCODING_RAW = 1 ,
IMAGE_ENCODING_LOSSLESS = 2 ,
IMAGE_ENCODING_LOSSY = 3 ,
IMAGE_FORMAT_GRAYSCALE = 0 ,
IMAGE_FORMAT_INTENSITY = 1 ,
IMAGE_FORMAT_GRAYSCALE_ALPHA = 2 ,
IMAGE_FORMAT_RGB = 3 ,
IMAGE_FORMAT_RGBA = 4 ,
IMAGE_FORMAT_INDEXED = 5 ,
IMAGE_FORMAT_INDEXED_ALPHA = 6 ,
IMAGE_FORMAT_BC1 = 7 ,
IMAGE_FORMAT_BC2 = 8 ,
IMAGE_FORMAT_BC3 = 9 ,
IMAGE_FORMAT_BC4 = 10 ,
IMAGE_FORMAT_BC5 = 11 ,
IMAGE_FORMAT_PVRTC2 = 12 ,
IMAGE_FORMAT_PVRTC2_ALPHA = 13 ,
IMAGE_FORMAT_PVRTC4 = 14 ,
IMAGE_FORMAT_PVRTC4_ALPHA = 15 ,
IMAGE_FORMAT_ETC = 16 ,
IMAGE_FORMAT_ATC = 17 ,
IMAGE_FORMAT_ATC_ALPHA_EXPLICIT = 18 ,
IMAGE_FORMAT_ATC_ALPHA_INTERPOLATED = 19 ,
IMAGE_FORMAT_CUSTOM = 30 ,
OBJECT_EMPTY = 0 ,
OBJECT_EXTERNAL_RESOURCE = 1 ,
OBJECT_INTERNAL_RESOURCE = 2 ,
OBJECT_EXTERNAL_RESOURCE_INDEX = 3 ,
FORMAT_VERSION = 1 ,
FORMAT_VERSION_CAN_RENAME_DEPS = 1
2014-02-10 01:10:30 +00:00
} ;
void ResourceInteractiveLoaderBinary : : _advance_padding ( uint32_t p_len ) {
2017-03-18 23:36:26 +00:00
uint32_t extra = 4 - ( p_len % 4 ) ;
if ( extra < 4 ) {
for ( uint32_t i = 0 ; i < extra ; i + + )
2014-02-10 01:10:30 +00:00
f - > get_8 ( ) ; //pad to 32
}
}
2017-03-18 23:36:26 +00:00
Error ResourceInteractiveLoaderBinary : : parse_variant ( Variant & r_v , bool p_for_export_data ) {
2014-02-10 01:10:30 +00:00
uint32_t type = f - > get_32 ( ) ;
2017-03-18 23:36:26 +00:00
print_bl ( " find property of type: " + itos ( type ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
switch ( type ) {
2014-02-10 01:10:30 +00:00
case VARIANT_NIL : {
2017-03-18 23:36:26 +00:00
r_v = Variant ( ) ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_BOOL : {
2017-03-18 23:36:26 +00:00
r_v = bool ( f - > get_32 ( ) ) ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_INT : {
2017-03-18 23:36:26 +00:00
r_v = int ( f - > get_32 ( ) ) ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_REAL : {
2017-03-18 23:36:26 +00:00
r_v = f - > get_real ( ) ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_STRING : {
2017-03-18 23:36:26 +00:00
r_v = get_unicode_string ( ) ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_VECTOR2 : {
Vector2 v ;
2017-03-18 23:36:26 +00:00
v . x = f - > get_real ( ) ;
v . y = f - > get_real ( ) ;
r_v = v ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_RECT2 : {
Rect2 v ;
2017-03-18 23:36:26 +00:00
v . pos . x = f - > get_real ( ) ;
v . pos . y = f - > get_real ( ) ;
v . size . x = f - > get_real ( ) ;
v . size . y = f - > get_real ( ) ;
r_v = v ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_VECTOR3 : {
Vector3 v ;
2017-03-18 23:36:26 +00:00
v . x = f - > get_real ( ) ;
v . y = f - > get_real ( ) ;
v . z = f - > get_real ( ) ;
r_v = v ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_PLANE : {
Plane v ;
2017-03-18 23:36:26 +00:00
v . normal . x = f - > get_real ( ) ;
v . normal . y = f - > get_real ( ) ;
v . normal . z = f - > get_real ( ) ;
v . d = f - > get_real ( ) ;
r_v = v ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_QUAT : {
Quat v ;
2017-03-18 23:36:26 +00:00
v . x = f - > get_real ( ) ;
v . y = f - > get_real ( ) ;
v . z = f - > get_real ( ) ;
v . w = f - > get_real ( ) ;
r_v = v ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_AABB : {
AABB v ;
2017-03-18 23:36:26 +00:00
v . pos . x = f - > get_real ( ) ;
v . pos . y = f - > get_real ( ) ;
v . pos . z = f - > get_real ( ) ;
v . size . x = f - > get_real ( ) ;
v . size . y = f - > get_real ( ) ;
v . size . z = f - > get_real ( ) ;
r_v = v ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_MATRIX32 : {
Matrix32 v ;
2017-03-18 23:36:26 +00:00
v . elements [ 0 ] . x = f - > get_real ( ) ;
v . elements [ 0 ] . y = f - > get_real ( ) ;
v . elements [ 1 ] . x = f - > get_real ( ) ;
v . elements [ 1 ] . y = f - > get_real ( ) ;
v . elements [ 2 ] . x = f - > get_real ( ) ;
v . elements [ 2 ] . y = f - > get_real ( ) ;
r_v = v ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_MATRIX3 : {
Matrix3 v ;
2017-03-18 23:36:26 +00:00
v . elements [ 0 ] . x = f - > get_real ( ) ;
v . elements [ 0 ] . y = f - > get_real ( ) ;
v . elements [ 0 ] . z = f - > get_real ( ) ;
v . elements [ 1 ] . x = f - > get_real ( ) ;
v . elements [ 1 ] . y = f - > get_real ( ) ;
v . elements [ 1 ] . z = f - > get_real ( ) ;
v . elements [ 2 ] . x = f - > get_real ( ) ;
v . elements [ 2 ] . y = f - > get_real ( ) ;
v . elements [ 2 ] . z = f - > get_real ( ) ;
r_v = v ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_TRANSFORM : {
Transform v ;
2017-03-18 23:36:26 +00:00
v . basis . elements [ 0 ] . x = f - > get_real ( ) ;
v . basis . elements [ 0 ] . y = f - > get_real ( ) ;
v . basis . elements [ 0 ] . z = f - > get_real ( ) ;
v . basis . elements [ 1 ] . x = f - > get_real ( ) ;
v . basis . elements [ 1 ] . y = f - > get_real ( ) ;
v . basis . elements [ 1 ] . z = f - > get_real ( ) ;
v . basis . elements [ 2 ] . x = f - > get_real ( ) ;
v . basis . elements [ 2 ] . y = f - > get_real ( ) ;
v . basis . elements [ 2 ] . z = f - > get_real ( ) ;
v . origin . x = f - > get_real ( ) ;
v . origin . y = f - > get_real ( ) ;
v . origin . z = f - > get_real ( ) ;
r_v = v ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_COLOR : {
Color v ;
2017-03-18 23:36:26 +00:00
v . r = f - > get_real ( ) ;
v . g = f - > get_real ( ) ;
v . b = f - > get_real ( ) ;
v . a = f - > get_real ( ) ;
r_v = v ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_IMAGE : {
uint32_t encoding = f - > get_32 ( ) ;
2017-03-18 23:36:26 +00:00
if ( encoding = = IMAGE_ENCODING_EMPTY ) {
r_v = Variant ( ) ;
2014-02-10 01:10:30 +00:00
break ;
2017-03-18 23:36:26 +00:00
} else if ( encoding = = IMAGE_ENCODING_RAW ) {
2014-02-10 01:10:30 +00:00
uint32_t width = f - > get_32 ( ) ;
uint32_t height = f - > get_32 ( ) ;
uint32_t mipmaps = f - > get_32 ( ) ;
uint32_t format = f - > get_32 ( ) ;
Image : : Format fmt ;
2017-03-18 23:36:26 +00:00
switch ( format ) {
case IMAGE_FORMAT_GRAYSCALE : {
fmt = Image : : FORMAT_GRAYSCALE ;
} break ;
case IMAGE_FORMAT_INTENSITY : {
fmt = Image : : FORMAT_INTENSITY ;
} break ;
case IMAGE_FORMAT_GRAYSCALE_ALPHA : {
fmt = Image : : FORMAT_GRAYSCALE_ALPHA ;
} break ;
case IMAGE_FORMAT_RGB : {
fmt = Image : : FORMAT_RGB ;
} break ;
case IMAGE_FORMAT_RGBA : {
fmt = Image : : FORMAT_RGBA ;
} break ;
case IMAGE_FORMAT_INDEXED : {
fmt = Image : : FORMAT_INDEXED ;
} break ;
case IMAGE_FORMAT_INDEXED_ALPHA : {
fmt = Image : : FORMAT_INDEXED_ALPHA ;
} break ;
case IMAGE_FORMAT_BC1 : {
fmt = Image : : FORMAT_BC1 ;
} break ;
case IMAGE_FORMAT_BC2 : {
fmt = Image : : FORMAT_BC2 ;
} break ;
case IMAGE_FORMAT_BC3 : {
fmt = Image : : FORMAT_BC3 ;
} break ;
case IMAGE_FORMAT_BC4 : {
fmt = Image : : FORMAT_BC4 ;
} break ;
case IMAGE_FORMAT_BC5 : {
fmt = Image : : FORMAT_BC5 ;
} break ;
case IMAGE_FORMAT_PVRTC2 : {
fmt = Image : : FORMAT_PVRTC2 ;
} break ;
case IMAGE_FORMAT_PVRTC2_ALPHA : {
fmt = Image : : FORMAT_PVRTC2_ALPHA ;
} break ;
case IMAGE_FORMAT_PVRTC4 : {
fmt = Image : : FORMAT_PVRTC4 ;
} break ;
case IMAGE_FORMAT_PVRTC4_ALPHA : {
fmt = Image : : FORMAT_PVRTC4_ALPHA ;
} break ;
case IMAGE_FORMAT_ETC : {
fmt = Image : : FORMAT_ETC ;
} break ;
case IMAGE_FORMAT_ATC : {
fmt = Image : : FORMAT_ATC ;
} break ;
case IMAGE_FORMAT_ATC_ALPHA_EXPLICIT : {
fmt = Image : : FORMAT_ATC_ALPHA_EXPLICIT ;
} break ;
case IMAGE_FORMAT_ATC_ALPHA_INTERPOLATED : {
fmt = Image : : FORMAT_ATC_ALPHA_INTERPOLATED ;
} break ;
case IMAGE_FORMAT_CUSTOM : {
fmt = Image : : FORMAT_CUSTOM ;
} break ;
2014-02-10 01:10:30 +00:00
default : {
ERR_FAIL_V ( ERR_FILE_CORRUPT ) ;
}
}
uint32_t datalen = f - > get_32 ( ) ;
DVector < uint8_t > imgdata ;
imgdata . resize ( datalen ) ;
DVector < uint8_t > : : Write w = imgdata . write ( ) ;
2017-03-18 23:36:26 +00:00
f - > get_buffer ( w . ptr ( ) , datalen ) ;
2014-02-10 01:10:30 +00:00
_advance_padding ( datalen ) ;
2017-03-18 23:36:26 +00:00
w = DVector < uint8_t > : : Write ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
r_v = Image ( width , height , mipmaps , fmt , imgdata ) ;
2014-02-10 01:10:30 +00:00
} else {
//compressed
DVector < uint8_t > data ;
data . resize ( f - > get_32 ( ) ) ;
DVector < uint8_t > : : Write w = data . write ( ) ;
2017-03-18 23:36:26 +00:00
f - > get_buffer ( w . ptr ( ) , data . size ( ) ) ;
2014-02-10 01:10:30 +00:00
w = DVector < uint8_t > : : Write ( ) ;
Image img ;
2017-03-18 23:36:26 +00:00
if ( encoding = = IMAGE_ENCODING_LOSSY & & Image : : lossy_unpacker ) {
2014-02-10 01:10:30 +00:00
img = Image : : lossy_unpacker ( data ) ;
2017-03-18 23:36:26 +00:00
} else if ( encoding = = IMAGE_ENCODING_LOSSLESS & & Image : : lossless_unpacker ) {
2014-02-10 01:10:30 +00:00
img = Image : : lossless_unpacker ( data ) ;
}
_advance_padding ( data . size ( ) ) ;
2017-03-18 23:36:26 +00:00
r_v = img ;
2014-02-10 01:10:30 +00:00
}
} break ;
case VARIANT_NODE_PATH : {
Vector < StringName > names ;
Vector < StringName > subnames ;
StringName property ;
bool absolute ;
int name_count = f - > get_16 ( ) ;
uint32_t subname_count = f - > get_16 ( ) ;
2017-03-18 23:36:26 +00:00
absolute = subname_count & 0x8000 ;
subname_count & = 0x7FFF ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < name_count ; i + + )
2014-02-10 01:10:30 +00:00
names . push_back ( string_map [ f - > get_32 ( ) ] ) ;
2017-03-18 23:36:26 +00:00
for ( uint32_t i = 0 ; i < subname_count ; i + + )
2014-02-10 01:10:30 +00:00
subnames . push_back ( string_map [ f - > get_32 ( ) ] ) ;
2017-03-18 23:36:26 +00:00
property = string_map [ f - > get_32 ( ) ] ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
NodePath np = NodePath ( names , subnames , absolute , property ) ;
2014-02-10 01:10:30 +00:00
//print_line("got path: "+String(np));
2017-03-18 23:36:26 +00:00
r_v = np ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_RID : {
2017-03-18 23:36:26 +00:00
r_v = f - > get_32 ( ) ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_OBJECT : {
2017-03-18 23:36:26 +00:00
uint32_t type = f - > get_32 ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
switch ( type ) {
2014-02-10 01:10:30 +00:00
case OBJECT_EMPTY : {
//do none
} break ;
case OBJECT_INTERNAL_RESOURCE : {
2017-03-18 23:36:26 +00:00
uint32_t index = f - > get_32 ( ) ;
2017-02-13 01:52:02 +00:00
if ( p_for_export_data ) {
2017-03-18 23:36:26 +00:00
r_v = " @RESLOCAL: " + itos ( index ) ;
2017-02-13 01:52:02 +00:00
} else {
2017-03-18 23:36:26 +00:00
String path = res_path + " :: " + itos ( index ) ;
2017-02-13 01:52:02 +00:00
RES res = ResourceLoader : : load ( path ) ;
if ( res . is_null ( ) ) {
2017-03-18 23:36:26 +00:00
WARN_PRINT ( String ( " Couldn't load resource: " + path ) . utf8 ( ) . get_data ( ) ) ;
2017-02-13 01:52:02 +00:00
}
2017-03-18 23:36:26 +00:00
r_v = res ;
2014-02-10 01:10:30 +00:00
}
} break ;
case OBJECT_EXTERNAL_RESOURCE : {
2015-08-23 23:15:56 +00:00
//old file format, still around for compatibility
2014-02-10 01:10:30 +00:00
String type = get_unicode_string ( ) ;
String path = get_unicode_string ( ) ;
2017-02-13 01:52:02 +00:00
if ( p_for_export_data ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
r_v = " @RESPATH: " + type + " : " + path ;
2017-02-13 01:52:02 +00:00
} else {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
if ( path . find ( " :// " ) = = - 1 & & path . is_rel_path ( ) ) {
2017-02-13 01:52:02 +00:00
// path is relative to file being loaded, so convert to a resource path
2017-03-18 23:36:26 +00:00
path = Globals : : get_singleton ( ) - > localize_path ( res_path . get_base_dir ( ) . plus_file ( path ) ) ;
2017-02-13 01:52:02 +00:00
}
if ( remaps . find ( path ) ) {
2017-03-18 23:36:26 +00:00
path = remaps [ path ] ;
2017-02-13 01:52:02 +00:00
}
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
RES res = ResourceLoader : : load ( path , type ) ;
2017-02-13 01:52:02 +00:00
if ( res . is_null ( ) ) {
2017-03-18 23:36:26 +00:00
WARN_PRINT ( String ( " Couldn't load resource: " + path ) . utf8 ( ) . get_data ( ) ) ;
2017-02-13 01:52:02 +00:00
}
2017-03-18 23:36:26 +00:00
r_v = res ;
2014-02-10 01:10:30 +00:00
}
2015-08-23 23:15:56 +00:00
} break ;
case OBJECT_EXTERNAL_RESOURCE_INDEX : {
//new file format, just refers to an index in the external list
uint32_t erindex = f - > get_32 ( ) ;
2017-02-13 01:52:02 +00:00
if ( p_for_export_data ) {
2017-03-18 23:36:26 +00:00
r_v = " @RESEXTERNAL: " + itos ( erindex ) ;
2015-08-23 23:15:56 +00:00
} else {
2017-03-18 23:36:26 +00:00
if ( erindex > = external_resources . size ( ) ) {
2017-02-13 01:52:02 +00:00
WARN_PRINT ( " Broken external resource! (index out of size " ) ;
2017-03-18 23:36:26 +00:00
r_v = Variant ( ) ;
2017-02-13 01:52:02 +00:00
} else {
2015-08-23 23:15:56 +00:00
2017-02-13 01:52:02 +00:00
String type = external_resources [ erindex ] . type ;
String path = external_resources [ erindex ] . path ;
2015-08-23 23:15:56 +00:00
2017-03-18 23:36:26 +00:00
if ( path . find ( " :// " ) = = - 1 & & path . is_rel_path ( ) ) {
2017-02-13 01:52:02 +00:00
// path is relative to file being loaded, so convert to a resource path
2017-03-18 23:36:26 +00:00
path = Globals : : get_singleton ( ) - > localize_path ( res_path . get_base_dir ( ) . plus_file ( path ) ) ;
2017-02-13 01:52:02 +00:00
}
2015-08-23 23:15:56 +00:00
2017-03-18 23:36:26 +00:00
RES res = ResourceLoader : : load ( path , type ) ;
2015-08-23 23:15:56 +00:00
2017-02-13 01:52:02 +00:00
if ( res . is_null ( ) ) {
2017-03-18 23:36:26 +00:00
WARN_PRINT ( String ( " Couldn't load resource: " + path ) . utf8 ( ) . get_data ( ) ) ;
2017-02-13 01:52:02 +00:00
}
2017-03-18 23:36:26 +00:00
r_v = res ;
2015-08-23 23:15:56 +00:00
}
}
2014-02-10 01:10:30 +00:00
} break ;
default : {
ERR_FAIL_V ( ERR_FILE_CORRUPT ) ;
} break ;
}
} break ;
case VARIANT_INPUT_EVENT : {
} break ;
case VARIANT_DICTIONARY : {
2017-03-18 23:36:26 +00:00
uint32_t len = f - > get_32 ( ) ;
Dictionary d ( len & 0x80000000 ) ; //last bit means shared
len & = 0x7FFFFFFF ;
for ( uint32_t i = 0 ; i < len ; i + + ) {
2014-02-10 01:10:30 +00:00
Variant key ;
2017-03-18 23:36:26 +00:00
Error err = parse_variant ( key , p_for_export_data ) ;
ERR_FAIL_COND_V ( err , ERR_FILE_CORRUPT ) ;
2014-02-10 01:10:30 +00:00
Variant value ;
2017-03-18 23:36:26 +00:00
err = parse_variant ( value , p_for_export_data ) ;
ERR_FAIL_COND_V ( err , ERR_FILE_CORRUPT ) ;
d [ key ] = value ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
r_v = d ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_ARRAY : {
2017-03-18 23:36:26 +00:00
uint32_t len = f - > get_32 ( ) ;
Array a ( len & 0x80000000 ) ; //last bit means shared
len & = 0x7FFFFFFF ;
2014-02-10 01:10:30 +00:00
a . resize ( len ) ;
2017-03-18 23:36:26 +00:00
for ( uint32_t i = 0 ; i < len ; i + + ) {
2014-02-10 01:10:30 +00:00
Variant val ;
2017-03-18 23:36:26 +00:00
Error err = parse_variant ( val , p_for_export_data ) ;
ERR_FAIL_COND_V ( err , ERR_FILE_CORRUPT ) ;
a [ i ] = val ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
r_v = a ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_RAW_ARRAY : {
uint32_t len = f - > get_32 ( ) ;
DVector < uint8_t > array ;
array . resize ( len ) ;
DVector < uint8_t > : : Write w = array . write ( ) ;
2017-03-18 23:36:26 +00:00
f - > get_buffer ( w . ptr ( ) , len ) ;
2014-02-10 01:10:30 +00:00
_advance_padding ( len ) ;
2017-03-18 23:36:26 +00:00
w = DVector < uint8_t > : : Write ( ) ;
r_v = array ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_INT_ARRAY : {
uint32_t len = f - > get_32 ( ) ;
DVector < int > array ;
array . resize ( len ) ;
DVector < int > : : Write w = array . write ( ) ;
2017-03-18 23:36:26 +00:00
f - > get_buffer ( ( uint8_t * ) w . ptr ( ) , len * 4 ) ;
2014-02-10 01:10:30 +00:00
# ifdef BIG_ENDIAN_ENABLED
{
2017-03-18 23:36:26 +00:00
uint32_t * ptr = ( uint32_t * ) w . ptr ( ) ;
for ( int i = 0 ; i < len ; i + + ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
ptr [ i ] = BSWAP32 ( ptr [ i ] ) ;
2014-02-10 01:10:30 +00:00
}
}
# endif
2017-03-18 23:36:26 +00:00
w = DVector < int > : : Write ( ) ;
r_v = array ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_REAL_ARRAY : {
uint32_t len = f - > get_32 ( ) ;
DVector < real_t > array ;
array . resize ( len ) ;
DVector < real_t > : : Write w = array . write ( ) ;
2017-03-18 23:36:26 +00:00
f - > get_buffer ( ( uint8_t * ) w . ptr ( ) , len * sizeof ( real_t ) ) ;
2014-02-10 01:10:30 +00:00
# ifdef BIG_ENDIAN_ENABLED
{
2017-03-18 23:36:26 +00:00
uint32_t * ptr = ( uint32_t * ) w . ptr ( ) ;
for ( int i = 0 ; i < len ; i + + ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
ptr [ i ] = BSWAP32 ( ptr [ i ] ) ;
2014-02-10 01:10:30 +00:00
}
}
# endif
2017-03-18 23:36:26 +00:00
w = DVector < real_t > : : Write ( ) ;
r_v = array ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_STRING_ARRAY : {
uint32_t len = f - > get_32 ( ) ;
DVector < String > array ;
array . resize ( len ) ;
DVector < String > : : Write w = array . write ( ) ;
2017-03-18 23:36:26 +00:00
for ( uint32_t i = 0 ; i < len ; i + + )
w [ i ] = get_unicode_string ( ) ;
w = DVector < String > : : Write ( ) ;
r_v = array ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_VECTOR2_ARRAY : {
uint32_t len = f - > get_32 ( ) ;
DVector < Vector2 > array ;
array . resize ( len ) ;
DVector < Vector2 > : : Write w = array . write ( ) ;
2017-03-18 23:36:26 +00:00
if ( sizeof ( Vector2 ) = = 8 ) {
f - > get_buffer ( ( uint8_t * ) w . ptr ( ) , len * sizeof ( real_t ) * 2 ) ;
2014-02-10 01:10:30 +00:00
# ifdef BIG_ENDIAN_ENABLED
2017-03-18 23:36:26 +00:00
{
uint32_t * ptr = ( uint32_t * ) w . ptr ( ) ;
for ( int i = 0 ; i < len * 2 ; i + + ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
ptr [ i ] = BSWAP32 ( ptr [ i ] ) ;
}
2014-02-10 01:10:30 +00:00
}
# endif
} else {
ERR_EXPLAIN ( " Vector2 size is NOT 8! " ) ;
ERR_FAIL_V ( ERR_UNAVAILABLE ) ;
}
2017-03-18 23:36:26 +00:00
w = DVector < Vector2 > : : Write ( ) ;
r_v = array ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_VECTOR3_ARRAY : {
uint32_t len = f - > get_32 ( ) ;
DVector < Vector3 > array ;
array . resize ( len ) ;
DVector < Vector3 > : : Write w = array . write ( ) ;
2017-03-18 23:36:26 +00:00
if ( sizeof ( Vector3 ) = = 12 ) {
f - > get_buffer ( ( uint8_t * ) w . ptr ( ) , len * sizeof ( real_t ) * 3 ) ;
2014-02-10 01:10:30 +00:00
# ifdef BIG_ENDIAN_ENABLED
{
2017-03-18 23:36:26 +00:00
uint32_t * ptr = ( uint32_t * ) w . ptr ( ) ;
for ( int i = 0 ; i < len * 3 ; i + + ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
ptr [ i ] = BSWAP32 ( ptr [ i ] ) ;
2014-02-10 01:10:30 +00:00
}
}
# endif
} else {
ERR_EXPLAIN ( " Vector3 size is NOT 12! " ) ;
ERR_FAIL_V ( ERR_UNAVAILABLE ) ;
}
2017-03-18 23:36:26 +00:00
w = DVector < Vector3 > : : Write ( ) ;
r_v = array ;
2014-02-10 01:10:30 +00:00
} break ;
case VARIANT_COLOR_ARRAY : {
uint32_t len = f - > get_32 ( ) ;
DVector < Color > array ;
array . resize ( len ) ;
DVector < Color > : : Write w = array . write ( ) ;
2017-03-18 23:36:26 +00:00
if ( sizeof ( Color ) = = 16 ) {
f - > get_buffer ( ( uint8_t * ) w . ptr ( ) , len * sizeof ( real_t ) * 4 ) ;
2014-02-10 01:10:30 +00:00
# ifdef BIG_ENDIAN_ENABLED
2017-03-18 23:36:26 +00:00
{
uint32_t * ptr = ( uint32_t * ) w . ptr ( ) ;
for ( int i = 0 ; i < len * 4 ; i + + ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
ptr [ i ] = BSWAP32 ( ptr [ i ] ) ;
}
2014-02-10 01:10:30 +00:00
}
# endif
} else {
ERR_EXPLAIN ( " Color size is NOT 16! " ) ;
ERR_FAIL_V ( ERR_UNAVAILABLE ) ;
}
2017-03-18 23:36:26 +00:00
w = DVector < Color > : : Write ( ) ;
r_v = array ;
2014-02-10 01:10:30 +00:00
} break ;
default : {
ERR_FAIL_V ( ERR_FILE_CORRUPT ) ;
} break ;
}
return OK ; //never reach anyway
}
2017-03-18 23:36:26 +00:00
void ResourceInteractiveLoaderBinary : : set_local_path ( const String & p_local_path ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
res_path = p_local_path ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
Ref < Resource > ResourceInteractiveLoaderBinary : : get_resource ( ) {
2014-02-10 01:10:30 +00:00
return resource ;
}
2017-03-18 23:36:26 +00:00
Error ResourceInteractiveLoaderBinary : : poll ( ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
if ( error ! = OK )
2014-02-10 01:10:30 +00:00
return error ;
int s = stage ;
2017-03-18 23:36:26 +00:00
if ( s < external_resources . size ( ) ) {
2014-02-10 01:10:30 +00:00
2015-08-23 23:15:56 +00:00
String path = external_resources [ s ] . path ;
if ( remaps . has ( path ) ) {
2017-03-18 23:36:26 +00:00
path = remaps [ path ] ;
2015-08-23 23:15:56 +00:00
}
2017-03-18 23:36:26 +00:00
RES res = ResourceLoader : : load ( path , external_resources [ s ] . type ) ;
2014-02-10 01:10:30 +00:00
if ( res . is_null ( ) ) {
if ( ! ResourceLoader : : get_abort_on_missing_resources ( ) ) {
2017-03-18 23:36:26 +00:00
ResourceLoader : : notify_dependency_error ( local_path , path , external_resources [ s ] . type ) ;
2014-02-10 01:10:30 +00:00
} else {
2017-03-18 23:36:26 +00:00
error = ERR_FILE_MISSING_DEPENDENCIES ;
ERR_EXPLAIN ( " Can't load dependency: " + path ) ;
2014-02-10 01:10:30 +00:00
ERR_FAIL_V ( error ) ;
}
} else {
resource_cache . push_back ( res ) ;
}
stage + + ;
2014-03-14 01:57:24 +00:00
return error ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
s - = external_resources . size ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
if ( s > = internal_resources . size ( ) ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
error = ERR_BUG ;
ERR_FAIL_COND_V ( s > = internal_resources . size ( ) , error ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
bool main = s = = ( internal_resources . size ( ) - 1 ) ;
2014-02-10 01:10:30 +00:00
//maybe it is loaded already
String path ;
2017-03-18 23:36:26 +00:00
int subindex = 0 ;
2014-02-10 01:10:30 +00:00
if ( ! main ) {
2017-03-18 23:36:26 +00:00
path = internal_resources [ s ] . path ;
2015-06-22 03:03:19 +00:00
if ( path . begins_with ( " local:// " ) ) {
2017-03-18 23:36:26 +00:00
path = path . replace_first ( " local:// " , " " ) ;
2015-06-22 03:03:19 +00:00
subindex = path . to_int ( ) ;
2017-03-18 23:36:26 +00:00
path = res_path + " :: " + path ;
2015-06-22 03:03:19 +00:00
}
2014-02-10 01:10:30 +00:00
if ( ResourceCache : : has ( path ) ) {
//already loaded, don't do anything
stage + + ;
2017-03-18 23:36:26 +00:00
error = OK ;
2014-02-10 01:10:30 +00:00
return error ;
}
} else {
2016-01-14 14:06:20 +00:00
if ( ! ResourceCache : : has ( res_path ) )
2017-03-18 23:36:26 +00:00
path = res_path ;
2014-02-10 01:10:30 +00:00
}
uint64_t offset = internal_resources [ s ] . offset ;
f - > seek ( offset ) ;
String t = get_unicode_string ( ) ;
Object * obj = ObjectTypeDB : : instance ( t ) ;
if ( ! obj ) {
2017-03-18 23:36:26 +00:00
error = ERR_FILE_CORRUPT ;
ERR_EXPLAIN ( local_path + " :Resource of unrecognized type in file: " + t ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
ERR_FAIL_COND_V ( ! obj , ERR_FILE_CORRUPT ) ;
2014-02-10 01:10:30 +00:00
Resource * r = obj - > cast_to < Resource > ( ) ;
if ( ! r ) {
2017-03-18 23:36:26 +00:00
error = ERR_FILE_CORRUPT ;
2014-02-10 01:10:30 +00:00
memdelete ( obj ) ; //bye
2017-03-18 23:36:26 +00:00
ERR_EXPLAIN ( local_path + " :Resoucre type in resource field not a resource, type is: " + obj - > get_type ( ) ) ;
ERR_FAIL_COND_V ( ! r , ERR_FILE_CORRUPT ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
RES res = RES ( r ) ;
2014-02-10 01:10:30 +00:00
r - > set_path ( path ) ;
2015-06-22 03:03:19 +00:00
r - > set_subindex ( subindex ) ;
2014-02-10 01:10:30 +00:00
int pc = f - > get_32 ( ) ;
//set properties
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < pc ; i + + ) {
2014-02-10 01:10:30 +00:00
uint32_t name_idx = f - > get_32 ( ) ;
2017-03-18 23:36:26 +00:00
if ( name_idx > = ( uint32_t ) string_map . size ( ) ) {
error = ERR_FILE_CORRUPT ;
2014-02-10 01:10:30 +00:00
ERR_FAIL_V ( ERR_FILE_CORRUPT ) ;
}
Variant value ;
error = parse_variant ( value ) ;
if ( error )
return error ;
2017-03-18 23:36:26 +00:00
res - > set ( string_map [ name_idx ] , value ) ;
2014-02-10 01:10:30 +00:00
}
# ifdef TOOLS_ENABLED
res - > set_edited ( false ) ;
# endif
stage + + ;
resource_cache . push_back ( res ) ;
if ( main ) {
if ( importmd_ofs ) {
f - > seek ( importmd_ofs ) ;
2017-03-18 23:36:26 +00:00
Ref < ResourceImportMetadata > imd = memnew ( ResourceImportMetadata ) ;
2014-02-10 01:10:30 +00:00
imd - > set_editor ( get_unicode_string ( ) ) ;
int sc = f - > get_32 ( ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < sc ; i + + ) {
2014-02-10 01:10:30 +00:00
String src = get_unicode_string ( ) ;
String md5 = get_unicode_string ( ) ;
2017-03-18 23:36:26 +00:00
imd - > add_source ( src , md5 ) ;
2014-02-10 01:10:30 +00:00
}
int pc = f - > get_32 ( ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < pc ; i + + ) {
2014-02-10 01:10:30 +00:00
String name = get_unicode_string ( ) ;
Variant val ;
parse_variant ( val ) ;
2017-03-18 23:36:26 +00:00
imd - > set_option ( name , val ) ;
2014-02-10 01:10:30 +00:00
}
res - > set_import_metadata ( imd ) ;
}
f - > close ( ) ;
2017-03-18 23:36:26 +00:00
resource = res ;
error = ERR_FILE_EOF ;
2014-02-10 01:10:30 +00:00
} else {
2017-03-18 23:36:26 +00:00
error = OK ;
2014-02-10 01:10:30 +00:00
}
return OK ;
}
2017-03-18 23:36:26 +00:00
int ResourceInteractiveLoaderBinary : : get_stage ( ) const {
2014-02-10 01:10:30 +00:00
return stage ;
}
int ResourceInteractiveLoaderBinary : : get_stage_count ( ) const {
2017-03-18 23:36:26 +00:00
return external_resources . size ( ) + internal_resources . size ( ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
static void save_ustring ( FileAccess * f , const String & p_string ) {
2015-08-23 23:15:56 +00:00
CharString utf8 = p_string . utf8 ( ) ;
2017-03-18 23:36:26 +00:00
f - > store_32 ( utf8 . length ( ) + 1 ) ;
f - > store_buffer ( ( const uint8_t * ) utf8 . get_data ( ) , utf8 . length ( ) + 1 ) ;
2015-08-23 23:15:56 +00:00
}
static String get_ustring ( FileAccess * f ) {
int len = f - > get_32 ( ) ;
Vector < char > str_buf ;
str_buf . resize ( len ) ;
2017-03-18 23:36:26 +00:00
f - > get_buffer ( ( uint8_t * ) & str_buf [ 0 ] , len ) ;
2015-08-23 23:15:56 +00:00
String s ;
s . parse_utf8 ( & str_buf [ 0 ] ) ;
return s ;
}
2014-02-10 01:10:30 +00:00
String ResourceInteractiveLoaderBinary : : get_unicode_string ( ) {
int len = f - > get_32 ( ) ;
2017-03-18 23:36:26 +00:00
if ( len > str_buf . size ( ) ) {
2014-02-10 01:10:30 +00:00
str_buf . resize ( len ) ;
}
2017-03-18 23:36:26 +00:00
if ( len = = 0 )
2015-12-09 12:08:41 +00:00
return String ( ) ;
2017-03-18 23:36:26 +00:00
f - > get_buffer ( ( uint8_t * ) & str_buf [ 0 ] , len ) ;
2014-02-10 01:10:30 +00:00
String s ;
s . parse_utf8 ( & str_buf [ 0 ] ) ;
return s ;
}
2017-03-18 23:36:26 +00:00
Error ResourceInteractiveLoaderBinary : : get_export_data ( ExportData & r_export_data ) {
2017-02-13 01:52:02 +00:00
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < external_resources . size ( ) ; i + + ) {
2017-02-13 01:52:02 +00:00
ExportData : : Dependency dep ;
2017-03-18 23:36:26 +00:00
dep . path = external_resources [ i ] . path ;
dep . type = external_resources [ i ] . type ;
r_export_data . dependencies [ i ] = dep ;
2017-02-13 01:52:02 +00:00
}
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < internal_resources . size ( ) ; i + + ) {
2017-02-13 01:52:02 +00:00
2017-03-18 23:36:26 +00:00
bool main = i = = ( internal_resources . size ( ) - 1 ) ;
2017-02-13 01:52:02 +00:00
//maybe it is loaded already
2017-03-18 23:36:26 +00:00
r_export_data . resources . resize ( r_export_data . resources . size ( ) + 1 ) ;
ExportData : : ResourceData & res_data = r_export_data . resources [ r_export_data . resources . size ( ) - 1 ] ;
2017-02-13 01:52:02 +00:00
2017-03-18 23:36:26 +00:00
res_data . index = - 1 ;
2017-02-13 01:52:02 +00:00
if ( ! main ) {
2017-03-18 23:36:26 +00:00
String path = internal_resources [ i ] . path ;
2017-02-13 01:52:02 +00:00
if ( path . begins_with ( " local:// " ) ) {
2017-03-18 23:36:26 +00:00
path = path . replace_first ( " local:// " , " " ) ;
2017-02-13 01:52:02 +00:00
res_data . index = path . to_int ( ) ;
}
} else {
}
uint64_t offset = internal_resources [ i ] . offset ;
f - > seek ( offset ) ;
String t = get_unicode_string ( ) ;
2017-03-18 23:36:26 +00:00
res_data . type = t ;
2017-02-13 01:52:02 +00:00
int pc = f - > get_32 ( ) ;
//set properties
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < pc ; i + + ) {
2017-02-13 01:52:02 +00:00
uint32_t name_idx = f - > get_32 ( ) ;
2017-03-18 23:36:26 +00:00
if ( name_idx > = ( uint32_t ) string_map . size ( ) ) {
error = ERR_FILE_CORRUPT ;
2017-02-13 01:52:02 +00:00
ERR_FAIL_V ( ERR_FILE_CORRUPT ) ;
}
Variant value ;
2017-03-18 23:36:26 +00:00
error = parse_variant ( value , true ) ;
2017-02-13 01:52:02 +00:00
if ( error )
return error ;
ExportData : : PropertyData pdata ;
2017-03-18 23:36:26 +00:00
pdata . name = string_map [ name_idx ] ;
pdata . value = value ;
2017-02-13 01:52:02 +00:00
res_data . properties . push_back ( pdata ) ;
}
}
return OK ;
}
2017-03-18 23:36:26 +00:00
void ResourceInteractiveLoaderBinary : : get_dependencies ( FileAccess * p_f , List < String > * p_dependencies , bool p_add_types ) {
2014-02-10 01:10:30 +00:00
open ( p_f ) ;
if ( error )
return ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < external_resources . size ( ) ; i + + ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
String dep = external_resources [ i ] . path ;
2014-03-14 01:57:24 +00:00
if ( dep . ends_with ( " * " ) ) {
2017-03-18 23:36:26 +00:00
dep = ResourceLoader : : guess_full_filename ( dep , external_resources [ i ] . type ) ;
2014-03-14 01:57:24 +00:00
}
2017-03-18 23:36:26 +00:00
if ( p_add_types & & external_resources [ i ] . type ! = String ( ) ) {
dep + = " :: " + external_resources [ i ] . type ;
2015-08-23 23:15:56 +00:00
}
2014-03-14 01:57:24 +00:00
p_dependencies - > push_back ( dep ) ;
2014-02-10 01:10:30 +00:00
}
}
void ResourceInteractiveLoaderBinary : : open ( FileAccess * p_f ) {
2017-03-18 23:36:26 +00:00
error = OK ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
f = p_f ;
2014-02-10 01:10:30 +00:00
uint8_t header [ 4 ] ;
2017-03-18 23:36:26 +00:00
f - > get_buffer ( header , 4 ) ;
if ( header [ 0 ] = = ' R ' & & header [ 1 ] = = ' S ' & & header [ 2 ] = = ' C ' & & header [ 3 ] = = ' C ' ) {
2014-02-10 01:10:30 +00:00
//compressed
2017-03-18 23:36:26 +00:00
FileAccessCompressed * fac = memnew ( FileAccessCompressed ) ;
2014-02-10 01:10:30 +00:00
fac - > open_after_magic ( f ) ;
2017-03-18 23:36:26 +00:00
f = fac ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
} else if ( header [ 0 ] ! = ' R ' | | header [ 1 ] ! = ' S ' | | header [ 2 ] ! = ' R ' | | header [ 3 ] ! = ' C ' ) {
2014-02-10 01:10:30 +00:00
//not normal
2017-03-18 23:36:26 +00:00
error = ERR_FILE_UNRECOGNIZED ;
ERR_EXPLAIN ( " Unrecognized binary resource file: " + local_path ) ;
2015-12-06 23:22:45 +00:00
ERR_FAIL ( ) ;
2014-02-10 01:10:30 +00:00
}
bool big_endian = f - > get_32 ( ) ;
# ifdef BIG_ENDIAN_ENABLED
endian_swap = ! big_endian ;
# else
bool endian_swap = big_endian ;
# endif
bool use_real64 = f - > get_32 ( ) ;
2017-03-18 23:36:26 +00:00
f - > set_endian_swap ( big_endian ! = 0 ) ; //read big endian if saved as big endian
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
uint32_t ver_major = f - > get_32 ( ) ;
uint32_t ver_minor = f - > get_32 ( ) ;
uint32_t ver_format = f - > get_32 ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
print_bl ( " big endian: " + itos ( big_endian ) ) ;
print_bl ( " endian swap: " + itos ( endian_swap ) ) ;
print_bl ( " real64: " + itos ( use_real64 ) ) ;
print_bl ( " major: " + itos ( ver_major ) ) ;
print_bl ( " minor: " + itos ( ver_minor ) ) ;
print_bl ( " format: " + itos ( ver_format ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
if ( ver_format > FORMAT_VERSION | | ver_major > VERSION_MAJOR ) {
2014-02-10 01:10:30 +00:00
f - > close ( ) ;
2017-03-18 23:36:26 +00:00
ERR_EXPLAIN ( " File Format ' " + itos ( FORMAT_VERSION ) + " . " + itos ( ver_major ) + " . " + itos ( ver_minor ) + " ' is too new! Please upgrade to a a new engine version: " + local_path ) ;
2014-02-10 01:10:30 +00:00
ERR_FAIL ( ) ;
}
2017-03-18 23:36:26 +00:00
type = get_unicode_string ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
print_bl ( " type: " + type ) ;
2014-02-10 01:10:30 +00:00
importmd_ofs = f - > get_64 ( ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < 14 ; i + + )
2014-02-10 01:10:30 +00:00
f - > get_32 ( ) ; //skip a few reserved fields
2017-03-18 23:36:26 +00:00
uint32_t string_table_size = f - > get_32 ( ) ;
2014-02-10 01:10:30 +00:00
string_map . resize ( string_table_size ) ;
2017-03-18 23:36:26 +00:00
for ( uint32_t i = 0 ; i < string_table_size ; i + + ) {
2014-02-10 01:10:30 +00:00
StringName s = get_unicode_string ( ) ;
2017-03-18 23:36:26 +00:00
string_map [ i ] = s ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
print_bl ( " strings: " + itos ( string_table_size ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
uint32_t ext_resources_size = f - > get_32 ( ) ;
for ( uint32_t i = 0 ; i < ext_resources_size ; i + + ) {
2014-02-10 01:10:30 +00:00
ExtResoucre er ;
2017-03-18 23:36:26 +00:00
er . type = get_unicode_string ( ) ;
er . path = get_unicode_string ( ) ;
2014-02-10 01:10:30 +00:00
external_resources . push_back ( er ) ;
}
2014-03-14 01:57:24 +00:00
//see if the exporter has different set of external resources for more efficient loading
2015-08-23 23:15:56 +00:00
/*
2014-03-14 01:57:24 +00:00
String preload_depts = " deps/ " + res_path . md5_text ( ) ;
if ( Globals : : get_singleton ( ) - > has ( preload_depts ) ) {
external_resources . clear ( ) ;
//ignore external resources and use these
NodePath depts = Globals : : get_singleton ( ) - > get ( preload_depts ) ;
external_resources . resize ( depts . get_name_count ( ) ) ;
for ( int i = 0 ; i < depts . get_name_count ( ) ; i + + ) {
external_resources [ i ] . path = depts . get_name ( i ) ;
}
print_line ( res_path + " - EXTERNAL RESOURCES: " + itos ( external_resources . size ( ) ) ) ;
2015-08-23 23:15:56 +00:00
} */
2014-03-14 01:57:24 +00:00
2017-03-18 23:36:26 +00:00
print_bl ( " ext resources: " + itos ( ext_resources_size ) ) ;
uint32_t int_resources_size = f - > get_32 ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
for ( uint32_t i = 0 ; i < int_resources_size ; i + + ) {
2014-02-10 01:10:30 +00:00
IntResoucre ir ;
2017-03-18 23:36:26 +00:00
ir . path = get_unicode_string ( ) ;
ir . offset = f - > get_64 ( ) ;
2014-02-10 01:10:30 +00:00
internal_resources . push_back ( ir ) ;
}
2017-03-18 23:36:26 +00:00
print_bl ( " int resources: " + itos ( int_resources_size ) ) ;
2014-02-10 01:10:30 +00:00
if ( f - > eof_reached ( ) ) {
2017-03-18 23:36:26 +00:00
error = ERR_FILE_CORRUPT ;
ERR_EXPLAIN ( " Premature End Of File: " + local_path ) ;
2014-02-10 01:10:30 +00:00
ERR_FAIL ( ) ;
}
}
String ResourceInteractiveLoaderBinary : : recognize ( FileAccess * p_f ) {
2017-03-18 23:36:26 +00:00
error = OK ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
f = p_f ;
2014-02-10 01:10:30 +00:00
uint8_t header [ 4 ] ;
2017-03-18 23:36:26 +00:00
f - > get_buffer ( header , 4 ) ;
if ( header [ 0 ] = = ' R ' & & header [ 1 ] = = ' S ' & & header [ 2 ] = = ' C ' & & header [ 3 ] = = ' C ' ) {
2014-02-10 01:10:30 +00:00
//compressed
2017-03-18 23:36:26 +00:00
FileAccessCompressed * fac = memnew ( FileAccessCompressed ) ;
2014-02-10 01:10:30 +00:00
fac - > open_after_magic ( f ) ;
2017-03-18 23:36:26 +00:00
f = fac ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
} else if ( header [ 0 ] ! = ' R ' | | header [ 1 ] ! = ' S ' | | header [ 2 ] ! = ' R ' | | header [ 3 ] ! = ' C ' ) {
2014-02-10 01:10:30 +00:00
//not normal
2017-03-18 23:36:26 +00:00
error = ERR_FILE_UNRECOGNIZED ;
2014-02-10 01:10:30 +00:00
return " " ;
}
bool big_endian = f - > get_32 ( ) ;
# ifdef BIG_ENDIAN_ENABLED
endian_swap = ! big_endian ;
# else
bool endian_swap = big_endian ;
# endif
bool use_real64 = f - > get_32 ( ) ;
2017-03-18 23:36:26 +00:00
f - > set_endian_swap ( big_endian ! = 0 ) ; //read big endian if saved as big endian
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
uint32_t ver_major = f - > get_32 ( ) ;
uint32_t ver_minor = f - > get_32 ( ) ;
uint32_t ver_format = f - > get_32 ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
if ( ver_format > FORMAT_VERSION | | ver_major > VERSION_MAJOR ) {
2014-02-10 01:10:30 +00:00
f - > close ( ) ;
return " " ;
}
2017-03-18 23:36:26 +00:00
String type = get_unicode_string ( ) ;
2014-02-10 01:10:30 +00:00
return type ;
}
ResourceInteractiveLoaderBinary : : ResourceInteractiveLoaderBinary ( ) {
2017-03-18 23:36:26 +00:00
f = NULL ;
stage = 0 ;
endian_swap = false ;
use_real64 = false ;
error = OK ;
2014-02-10 01:10:30 +00:00
}
ResourceInteractiveLoaderBinary : : ~ ResourceInteractiveLoaderBinary ( ) {
if ( f )
memdelete ( f ) ;
}
2015-08-23 23:15:56 +00:00
Ref < ResourceInteractiveLoader > ResourceFormatLoaderBinary : : load_interactive ( const String & p_path , Error * r_error ) {
2014-02-10 01:10:30 +00:00
2015-08-23 23:15:56 +00:00
if ( r_error )
2017-03-18 23:36:26 +00:00
* r_error = ERR_FILE_CANT_OPEN ;
2014-02-10 01:10:30 +00:00
Error err ;
2017-03-18 23:36:26 +00:00
FileAccess * f = FileAccess : : open ( p_path , FileAccess : : READ , & err ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
if ( err ! = OK ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
ERR_FAIL_COND_V ( err ! = OK , Ref < ResourceInteractiveLoader > ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
Ref < ResourceInteractiveLoaderBinary > ria = memnew ( ResourceInteractiveLoaderBinary ) ;
ria - > local_path = Globals : : get_singleton ( ) - > localize_path ( p_path ) ;
ria - > res_path = ria - > local_path ;
// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
2014-02-10 01:10:30 +00:00
ria - > open ( f ) ;
return ria ;
}
2017-03-18 23:36:26 +00:00
void ResourceFormatLoaderBinary : : get_recognized_extensions_for_type ( const String & p_type , List < String > * p_extensions ) const {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
if ( p_type = = " " ) {
2014-02-10 01:10:30 +00:00
get_recognized_extensions ( p_extensions ) ;
return ;
}
List < String > extensions ;
2017-03-18 23:36:26 +00:00
ObjectTypeDB : : get_extensions_for_type ( p_type , & extensions ) ;
2014-02-10 01:10:30 +00:00
extensions . sort ( ) ;
2017-03-18 23:36:26 +00:00
for ( List < String > : : Element * E = extensions . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 01:10:30 +00:00
String ext = E - > get ( ) . to_lower ( ) ;
p_extensions - > push_back ( ext ) ;
}
}
2017-03-18 23:36:26 +00:00
void ResourceFormatLoaderBinary : : get_recognized_extensions ( List < String > * p_extensions ) const {
2014-02-10 01:10:30 +00:00
List < String > extensions ;
ObjectTypeDB : : get_resource_base_extensions ( & extensions ) ;
extensions . sort ( ) ;
2017-03-18 23:36:26 +00:00
for ( List < String > : : Element * E = extensions . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 01:10:30 +00:00
String ext = E - > get ( ) . to_lower ( ) ;
p_extensions - > push_back ( ext ) ;
}
}
2017-03-18 23:36:26 +00:00
bool ResourceFormatLoaderBinary : : handles_type ( const String & p_type ) const {
2014-02-10 01:10:30 +00:00
return true ; //handles all
}
2017-03-18 23:36:26 +00:00
Error ResourceFormatLoaderBinary : : load_import_metadata ( const String & p_path , Ref < ResourceImportMetadata > & r_var ) const {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
FileAccess * f = FileAccess : : open ( p_path , FileAccess : : READ ) ;
2014-02-10 01:10:30 +00:00
if ( ! f ) {
return ERR_FILE_CANT_OPEN ;
}
2017-03-18 23:36:26 +00:00
Ref < ResourceInteractiveLoaderBinary > ria = memnew ( ResourceInteractiveLoaderBinary ) ;
ria - > local_path = Globals : : get_singleton ( ) - > localize_path ( p_path ) ;
ria - > res_path = ria - > local_path ;
// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
2014-02-10 01:10:30 +00:00
ria - > recognize ( f ) ;
2017-03-18 23:36:26 +00:00
if ( ria - > error ! = OK )
2014-02-10 01:10:30 +00:00
return ERR_FILE_UNRECOGNIZED ;
2017-03-18 23:36:26 +00:00
f = ria - > f ;
2014-02-10 01:10:30 +00:00
uint64_t imp_ofs = f - > get_64 ( ) ;
2017-03-18 23:36:26 +00:00
if ( imp_ofs = = 0 )
2014-02-10 01:10:30 +00:00
return ERR_UNAVAILABLE ;
f - > seek ( imp_ofs ) ;
2017-03-18 23:36:26 +00:00
Ref < ResourceImportMetadata > imd = memnew ( ResourceImportMetadata ) ;
2014-02-10 01:10:30 +00:00
imd - > set_editor ( ria - > get_unicode_string ( ) ) ;
int sc = f - > get_32 ( ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < sc ; i + + ) {
2014-02-10 01:10:30 +00:00
String src = ria - > get_unicode_string ( ) ;
String md5 = ria - > get_unicode_string ( ) ;
2017-03-18 23:36:26 +00:00
imd - > add_source ( src , md5 ) ;
2014-02-10 01:10:30 +00:00
}
int pc = f - > get_32 ( ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < pc ; i + + ) {
2014-02-10 01:10:30 +00:00
String name = ria - > get_unicode_string ( ) ;
Variant val ;
ria - > parse_variant ( val ) ;
2017-03-18 23:36:26 +00:00
imd - > set_option ( name , val ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
r_var = imd ;
2014-02-10 01:10:30 +00:00
return OK ;
}
2017-03-18 23:36:26 +00:00
ResourceFormatLoaderBinary * ResourceFormatLoaderBinary : : singleton = NULL ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
void ResourceFormatLoaderBinary : : get_dependencies ( const String & p_path , List < String > * p_dependencies , bool p_add_types ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
FileAccess * f = FileAccess : : open ( p_path , FileAccess : : READ ) ;
2014-02-10 01:10:30 +00:00
ERR_FAIL_COND ( ! f ) ;
2017-03-18 23:36:26 +00:00
Ref < ResourceInteractiveLoaderBinary > ria = memnew ( ResourceInteractiveLoaderBinary ) ;
ria - > local_path = Globals : : get_singleton ( ) - > localize_path ( p_path ) ;
ria - > res_path = ria - > local_path ;
// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
ria - > get_dependencies ( f , p_dependencies , p_add_types ) ;
2015-08-23 23:15:56 +00:00
}
2017-03-18 23:36:26 +00:00
Error ResourceFormatLoaderBinary : : get_export_data ( const String & p_path , ExportData & r_export_data ) {
2017-02-13 01:52:02 +00:00
Error err ;
2017-03-18 23:36:26 +00:00
FileAccess * f = FileAccess : : open ( p_path , FileAccess : : READ , & err ) ;
2017-02-13 01:52:02 +00:00
2017-03-18 23:36:26 +00:00
if ( err ! = OK ) {
2017-02-13 01:52:02 +00:00
2017-03-18 23:36:26 +00:00
ERR_FAIL_COND_V ( err ! = OK , ERR_CANT_OPEN ) ;
2017-02-13 01:52:02 +00:00
}
2017-03-18 23:36:26 +00:00
Ref < ResourceInteractiveLoaderBinary > ria = memnew ( ResourceInteractiveLoaderBinary ) ;
ria - > local_path = Globals : : get_singleton ( ) - > localize_path ( p_path ) ;
ria - > res_path = ria - > local_path ;
// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
2017-02-13 01:52:02 +00:00
ria - > open ( f ) ;
return ria - > get_export_data ( r_export_data ) ;
}
2017-03-18 23:36:26 +00:00
Error ResourceFormatLoaderBinary : : rename_dependencies ( const String & p_path , const Map < String , String > & p_map ) {
2015-08-23 23:15:56 +00:00
2017-03-18 23:36:26 +00:00
// Error error=OK;
2015-08-23 23:15:56 +00:00
2017-03-18 23:36:26 +00:00
FileAccess * f = FileAccess : : open ( p_path , FileAccess : : READ ) ;
ERR_FAIL_COND_V ( ! f , ERR_CANT_OPEN ) ;
2015-08-23 23:15:56 +00:00
2017-03-18 23:36:26 +00:00
FileAccess * fw = NULL ; //=FileAccess::open(p_path+".depren");
2015-08-23 23:15:56 +00:00
2017-03-18 23:36:26 +00:00
String local_path = p_path . get_base_dir ( ) ;
2015-08-23 23:15:56 +00:00
uint8_t header [ 4 ] ;
2017-03-18 23:36:26 +00:00
f - > get_buffer ( header , 4 ) ;
if ( header [ 0 ] = = ' R ' & & header [ 1 ] = = ' S ' & & header [ 2 ] = = ' C ' & & header [ 3 ] = = ' C ' ) {
2015-08-23 23:15:56 +00:00
//compressed
2017-03-18 23:36:26 +00:00
FileAccessCompressed * fac = memnew ( FileAccessCompressed ) ;
2015-08-23 23:15:56 +00:00
fac - > open_after_magic ( f ) ;
2017-03-18 23:36:26 +00:00
f = fac ;
2015-08-23 23:15:56 +00:00
2017-03-18 23:36:26 +00:00
FileAccessCompressed * facw = memnew ( FileAccessCompressed ) ;
2015-08-23 23:15:56 +00:00
facw - > configure ( " RSCC " ) ;
2017-03-18 23:36:26 +00:00
Error err = facw - > _open ( p_path + " .depren " , FileAccess : : WRITE ) ;
2015-08-23 23:15:56 +00:00
if ( err ) {
memdelete ( fac ) ;
memdelete ( facw ) ;
2017-03-18 23:36:26 +00:00
ERR_FAIL_COND_V ( err , ERR_FILE_CORRUPT ) ;
2015-08-23 23:15:56 +00:00
}
2017-03-18 23:36:26 +00:00
fw = facw ;
2015-08-23 23:15:56 +00:00
2017-03-18 23:36:26 +00:00
} else if ( header [ 0 ] ! = ' R ' | | header [ 1 ] ! = ' S ' | | header [ 2 ] ! = ' R ' | | header [ 3 ] ! = ' C ' ) {
2015-08-23 23:15:56 +00:00
//not normal
//error=ERR_FILE_UNRECOGNIZED;
memdelete ( f ) ;
2017-03-18 23:36:26 +00:00
ERR_EXPLAIN ( " Unrecognized binary resource file: " + local_path ) ;
2015-08-23 23:15:56 +00:00
ERR_FAIL_V ( ERR_FILE_UNRECOGNIZED ) ;
} else {
2017-03-18 23:36:26 +00:00
fw = FileAccess : : open ( p_path + " .depren " , FileAccess : : WRITE ) ;
2015-08-23 23:15:56 +00:00
if ( ! fw ) {
memdelete ( f ) ;
}
2017-03-18 23:36:26 +00:00
ERR_FAIL_COND_V ( ! fw , ERR_CANT_CREATE ) ;
2015-08-23 23:15:56 +00:00
}
bool big_endian = f - > get_32 ( ) ;
# ifdef BIG_ENDIAN_ENABLED
endian_swap = ! big_endian ;
# else
bool endian_swap = big_endian ;
# endif
bool use_real64 = f - > get_32 ( ) ;
2017-03-18 23:36:26 +00:00
f - > set_endian_swap ( big_endian ! = 0 ) ; //read big endian if saved as big endian
2015-08-23 23:15:56 +00:00
fw - > store_32 ( endian_swap ) ;
2017-03-18 23:36:26 +00:00
fw - > set_endian_swap ( big_endian ! = 0 ) ;
2015-08-23 23:15:56 +00:00
fw - > store_32 ( use_real64 ) ; //use real64
2017-03-18 23:36:26 +00:00
uint32_t ver_major = f - > get_32 ( ) ;
uint32_t ver_minor = f - > get_32 ( ) ;
uint32_t ver_format = f - > get_32 ( ) ;
2015-08-23 23:15:56 +00:00
2017-03-18 23:36:26 +00:00
if ( ver_format < FORMAT_VERSION_CAN_RENAME_DEPS ) {
2015-08-23 23:15:56 +00:00
memdelete ( f ) ;
memdelete ( fw ) ;
DirAccess * da = DirAccess : : create ( DirAccess : : ACCESS_FILESYSTEM ) ;
2017-03-18 23:36:26 +00:00
da - > remove ( p_path + " .depren " ) ;
2015-08-23 23:15:56 +00:00
memdelete ( da ) ;
//fuck it, use the old approach;
2017-03-18 23:36:26 +00:00
WARN_PRINT ( ( " This file is old, so it can't refactor dependencies, opening and resaving: " + p_path ) . utf8 ( ) . get_data ( ) ) ;
2015-08-23 23:15:56 +00:00
Error err ;
2017-03-18 23:36:26 +00:00
f = FileAccess : : open ( p_path , FileAccess : : READ , & err ) ;
if ( err ! = OK ) {
ERR_FAIL_COND_V ( err ! = OK , ERR_FILE_CANT_OPEN ) ;
2015-08-23 23:15:56 +00:00
}
2017-03-18 23:36:26 +00:00
Ref < ResourceInteractiveLoaderBinary > ria = memnew ( ResourceInteractiveLoaderBinary ) ;
ria - > local_path = Globals : : get_singleton ( ) - > localize_path ( p_path ) ;
ria - > res_path = ria - > local_path ;
ria - > remaps = p_map ;
// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
2015-08-23 23:15:56 +00:00
ria - > open ( f ) ;
err = ria - > poll ( ) ;
2017-03-18 23:36:26 +00:00
while ( err = = OK ) {
err = ria - > poll ( ) ;
2015-08-23 23:15:56 +00:00
}
2017-03-18 23:36:26 +00:00
ERR_FAIL_COND_V ( err ! = ERR_FILE_EOF , ERR_FILE_CORRUPT ) ;
2015-08-23 23:15:56 +00:00
RES res = ria - > get_resource ( ) ;
2017-03-18 23:36:26 +00:00
ERR_FAIL_COND_V ( ! res . is_valid ( ) , ERR_FILE_CORRUPT ) ;
2015-08-23 23:15:56 +00:00
2017-03-18 23:36:26 +00:00
return ResourceFormatSaverBinary : : singleton - > save ( p_path , res ) ;
2015-08-23 23:15:56 +00:00
}
2017-03-18 23:36:26 +00:00
if ( ver_format > FORMAT_VERSION | | ver_major > VERSION_MAJOR ) {
2015-08-23 23:15:56 +00:00
memdelete ( f ) ;
memdelete ( fw ) ;
2017-03-18 23:36:26 +00:00
ERR_EXPLAIN ( " File Format ' " + itos ( FORMAT_VERSION ) + " . " + itos ( ver_major ) + " . " + itos ( ver_minor ) + " ' is too new! Please upgrade to a a new engine version: " + local_path ) ;
2015-08-23 23:15:56 +00:00
ERR_FAIL_V ( ERR_FILE_UNRECOGNIZED ) ;
}
2017-03-18 23:36:26 +00:00
fw - > store_32 ( VERSION_MAJOR ) ; //current version
fw - > store_32 ( VERSION_MINOR ) ;
fw - > store_32 ( FORMAT_VERSION ) ;
2015-08-23 23:15:56 +00:00
2017-03-18 23:36:26 +00:00
save_ustring ( fw , get_ustring ( f ) ) ; //type
2015-08-23 23:15:56 +00:00
size_t md_ofs = f - > get_pos ( ) ;
size_t importmd_ofs = f - > get_64 ( ) ;
fw - > store_64 ( 0 ) ; //metadata offset
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < 14 ; i + + ) {
2015-08-23 23:15:56 +00:00
fw - > store_32 ( 0 ) ;
f - > get_32 ( ) ;
}
//string table
2017-03-18 23:36:26 +00:00
uint32_t string_table_size = f - > get_32 ( ) ;
2015-08-23 23:15:56 +00:00
fw - > store_32 ( string_table_size ) ;
2017-03-18 23:36:26 +00:00
for ( uint32_t i = 0 ; i < string_table_size ; i + + ) {
2015-08-23 23:15:56 +00:00
String s = get_ustring ( f ) ;
2017-03-18 23:36:26 +00:00
save_ustring ( fw , s ) ;
2015-08-23 23:15:56 +00:00
}
//external resources
2017-03-18 23:36:26 +00:00
uint32_t ext_resources_size = f - > get_32 ( ) ;
2015-08-23 23:15:56 +00:00
fw - > store_32 ( ext_resources_size ) ;
2017-03-18 23:36:26 +00:00
for ( uint32_t i = 0 ; i < ext_resources_size ; i + + ) {
2015-08-23 23:15:56 +00:00
String type = get_ustring ( f ) ;
String path = get_ustring ( f ) ;
2017-03-18 23:36:26 +00:00
bool relative = false ;
2015-08-23 23:15:56 +00:00
if ( ! path . begins_with ( " res:// " ) ) {
2017-03-18 23:36:26 +00:00
path = local_path . plus_file ( path ) . simplify_path ( ) ;
relative = true ;
2015-08-23 23:15:56 +00:00
}
if ( p_map . has ( path ) ) {
2017-03-18 23:36:26 +00:00
String np = p_map [ path ] ;
path = np ;
2015-08-23 23:15:56 +00:00
}
if ( relative ) {
//restore relative
2017-03-18 23:36:26 +00:00
path = local_path . path_to_file ( path ) ;
2015-08-23 23:15:56 +00:00
}
2017-03-18 23:36:26 +00:00
save_ustring ( fw , type ) ;
save_ustring ( fw , path ) ;
2015-08-23 23:15:56 +00:00
}
int64_t size_diff = ( int64_t ) fw - > get_pos ( ) - ( int64_t ) f - > get_pos ( ) ;
//internal resources
2017-03-18 23:36:26 +00:00
uint32_t int_resources_size = f - > get_32 ( ) ;
2015-08-23 23:15:56 +00:00
fw - > store_32 ( int_resources_size ) ;
2017-03-18 23:36:26 +00:00
for ( uint32_t i = 0 ; i < int_resources_size ; i + + ) {
2015-08-23 23:15:56 +00:00
2017-03-18 23:36:26 +00:00
String path = get_ustring ( f ) ;
uint64_t offset = f - > get_64 ( ) ;
save_ustring ( fw , path ) ;
fw - > store_64 ( offset + size_diff ) ;
2015-08-23 23:15:56 +00:00
}
//rest of file
uint8_t b = f - > get_8 ( ) ;
2017-03-18 23:36:26 +00:00
while ( ! f - > eof_reached ( ) ) {
2015-08-23 23:15:56 +00:00
fw - > store_8 ( b ) ;
b = f - > get_8 ( ) ;
}
2017-03-18 23:36:26 +00:00
bool all_ok = fw - > get_error ( ) = = OK ;
2015-08-23 23:15:56 +00:00
fw - > seek ( md_ofs ) ;
2017-03-18 23:36:26 +00:00
fw - > store_64 ( importmd_ofs + size_diff ) ;
2015-08-23 23:15:56 +00:00
memdelete ( f ) ;
memdelete ( fw ) ;
if ( ! all_ok ) {
return ERR_CANT_CREATE ;
}
DirAccess * da = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
da - > remove ( p_path ) ;
2017-03-18 23:36:26 +00:00
da - > rename ( p_path + " .depren " , p_path ) ;
2015-08-23 23:15:56 +00:00
memdelete ( da ) ;
return OK ;
2014-02-10 01:10:30 +00:00
}
String ResourceFormatLoaderBinary : : get_resource_type ( const String & p_path ) const {
2017-03-18 23:36:26 +00:00
FileAccess * f = FileAccess : : open ( p_path , FileAccess : : READ ) ;
2014-02-10 01:10:30 +00:00
if ( ! f ) {
return " " ; //could not rwead
}
2017-03-18 23:36:26 +00:00
Ref < ResourceInteractiveLoaderBinary > ria = memnew ( ResourceInteractiveLoaderBinary ) ;
ria - > local_path = Globals : : get_singleton ( ) - > localize_path ( p_path ) ;
ria - > res_path = ria - > local_path ;
// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
2014-02-10 01:10:30 +00:00
String r = ria - > recognize ( f ) ;
return r ;
}
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
void ResourceFormatSaverBinaryInstance : : _pad_buffer ( int p_bytes ) {
2017-03-18 23:36:26 +00:00
int extra = 4 - ( p_bytes % 4 ) ;
if ( extra < 4 ) {
for ( int i = 0 ; i < extra ; i + + )
2014-02-10 01:10:30 +00:00
f - > store_8 ( 0 ) ; //pad to 32
}
}
2017-03-18 23:36:26 +00:00
void ResourceFormatSaverBinaryInstance : : write_variant ( const Variant & p_property , const PropertyInfo & p_hint ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
switch ( p_property . get_type ( ) ) {
2014-02-10 01:10:30 +00:00
case Variant : : NIL : {
f - > store_32 ( VARIANT_NIL ) ;
// don't store anything
} break ;
case Variant : : BOOL : {
f - > store_32 ( VARIANT_BOOL ) ;
2017-03-18 23:36:26 +00:00
bool val = p_property ;
2014-02-10 01:10:30 +00:00
f - > store_32 ( val ) ;
} break ;
case Variant : : INT : {
f - > store_32 ( VARIANT_INT ) ;
2017-03-18 23:36:26 +00:00
int val = p_property ;
2014-02-10 01:10:30 +00:00
f - > store_32 ( val ) ;
} break ;
case Variant : : REAL : {
f - > store_32 ( VARIANT_REAL ) ;
2017-03-18 23:36:26 +00:00
real_t val = p_property ;
2014-02-10 01:10:30 +00:00
f - > store_real ( val ) ;
} break ;
case Variant : : STRING : {
f - > store_32 ( VARIANT_STRING ) ;
2017-03-18 23:36:26 +00:00
String val = p_property ;
2014-02-10 01:10:30 +00:00
save_unicode_string ( val ) ;
} break ;
case Variant : : VECTOR2 : {
f - > store_32 ( VARIANT_VECTOR2 ) ;
2017-03-18 23:36:26 +00:00
Vector2 val = p_property ;
2014-02-10 01:10:30 +00:00
f - > store_real ( val . x ) ;
f - > store_real ( val . y ) ;
} break ;
case Variant : : RECT2 : {
f - > store_32 ( VARIANT_RECT2 ) ;
2017-03-18 23:36:26 +00:00
Rect2 val = p_property ;
2014-02-10 01:10:30 +00:00
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 ) ;
2017-03-18 23:36:26 +00:00
Vector3 val = p_property ;
2014-02-10 01:10:30 +00:00
f - > store_real ( val . x ) ;
f - > store_real ( val . y ) ;
f - > store_real ( val . z ) ;
} break ;
case Variant : : PLANE : {
f - > store_32 ( VARIANT_PLANE ) ;
2017-03-18 23:36:26 +00:00
Plane val = p_property ;
2014-02-10 01:10:30 +00:00
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 ) ;
2017-03-18 23:36:26 +00:00
Quat val = p_property ;
2014-02-10 01:10:30 +00:00
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 ) ;
2017-03-18 23:36:26 +00:00
AABB val = p_property ;
2014-02-10 01:10:30 +00:00
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 ) ;
2017-03-18 23:36:26 +00:00
Matrix32 val = p_property ;
2014-02-10 01:10:30 +00:00
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 ) ;
2017-03-18 23:36:26 +00:00
Matrix3 val = p_property ;
2014-02-10 01:10:30 +00:00
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 ) ;
2017-03-18 23:36:26 +00:00
Transform val = p_property ;
2014-02-10 01:10:30 +00:00
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 ) ;
2017-03-18 23:36:26 +00:00
Color val = p_property ;
2014-02-10 01:10:30 +00:00
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 ) ;
2017-03-18 23:36:26 +00:00
Image val = p_property ;
2014-02-10 01:10:30 +00:00
if ( val . empty ( ) ) {
f - > store_32 ( IMAGE_ENCODING_EMPTY ) ;
break ;
}
2017-03-18 23:36:26 +00:00
int encoding = IMAGE_ENCODING_RAW ;
float quality = 0.7 ;
2014-02-10 01:10:30 +00:00
if ( val . get_format ( ) < = Image : : FORMAT_INDEXED_ALPHA ) {
//can only compress uncompressed stuff
2017-03-18 23:36:26 +00:00
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 ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
} else if ( p_hint . hint = = PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS & & Image : : lossless_packer ) {
encoding = IMAGE_ENCODING_LOSSLESS ;
2014-02-10 01:10:30 +00:00
}
}
f - > store_32 ( encoding ) ; //raw encoding
2017-03-18 23:36:26 +00:00
if ( encoding = = IMAGE_ENCODING_RAW ) {
2014-02-10 01:10:30 +00:00
f - > store_32 ( val . get_width ( ) ) ;
f - > store_32 ( val . get_height ( ) ) ;
f - > store_32 ( val . get_mipmaps ( ) ) ;
2017-03-18 23:36:26 +00:00
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 ;
2014-02-10 01:10:30 +00:00
case Image : : FORMAT_ETC : f - > store_32 ( IMAGE_FORMAT_ETC ) ; break ;
2014-02-26 13:08:17 +00:00
case Image : : FORMAT_ATC : f - > store_32 ( IMAGE_FORMAT_ATC ) ; break ;
case Image : : FORMAT_ATC_ALPHA_EXPLICIT : f - > store_32 ( IMAGE_FORMAT_ATC_ALPHA_EXPLICIT ) ; break ;
case Image : : FORMAT_ATC_ALPHA_INTERPOLATED : f - > store_32 ( IMAGE_FORMAT_ATC_ALPHA_INTERPOLATED ) ; break ;
2017-03-18 23:36:26 +00:00
case Image : : FORMAT_CUSTOM : f - > store_32 ( IMAGE_FORMAT_CUSTOM ) ; break ;
2014-02-10 01:10:30 +00:00
default : { }
}
int dlen = val . get_data ( ) . size ( ) ;
f - > store_32 ( dlen ) ;
DVector < uint8_t > : : Read r = val . get_data ( ) . read ( ) ;
2017-03-18 23:36:26 +00:00
f - > store_buffer ( r . ptr ( ) , dlen ) ;
2014-02-10 01:10:30 +00:00
_pad_buffer ( dlen ) ;
} else {
DVector < uint8_t > data ;
2017-03-18 23:36:26 +00:00
if ( encoding = = IMAGE_ENCODING_LOSSY ) {
data = Image : : lossy_packer ( val , quality ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
} else if ( encoding = = IMAGE_ENCODING_LOSSLESS ) {
data = Image : : lossless_packer ( val ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
int ds = data . size ( ) ;
2014-02-10 01:10:30 +00:00
f - > store_32 ( ds ) ;
2017-03-18 23:36:26 +00:00
if ( ds > 0 ) {
2014-02-10 01:10:30 +00:00
DVector < uint8_t > : : Read r = data . read ( ) ;
2017-03-18 23:36:26 +00:00
f - > store_buffer ( r . ptr ( ) , ds ) ;
2014-02-10 01:10:30 +00:00
_pad_buffer ( ds ) ;
}
}
} break ;
case Variant : : NODE_PATH : {
f - > store_32 ( VARIANT_NODE_PATH ) ;
2017-03-18 23:36:26 +00:00
NodePath np = p_property ;
2014-02-10 01:10:30 +00:00
f - > store_16 ( np . get_name_count ( ) ) ;
uint16_t snc = np . get_subname_count ( ) ;
if ( np . is_absolute ( ) )
2017-03-18 23:36:26 +00:00
snc | = 0x8000 ;
2014-02-10 01:10:30 +00:00
f - > store_16 ( snc ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < np . get_name_count ( ) ; i + + )
2014-02-10 01:10:30 +00:00
f - > store_32 ( get_string_index ( np . get_name ( i ) ) ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < np . get_subname_count ( ) ; i + + )
2014-02-10 01:10:30 +00:00
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
}
2017-03-18 23:36:26 +00:00
if ( res - > get_path ( ) . length ( ) & & res - > get_path ( ) . find ( " :: " ) = = - 1 ) {
2015-08-23 23:15:56 +00:00
f - > store_32 ( OBJECT_EXTERNAL_RESOURCE_INDEX ) ;
f - > store_32 ( external_resources [ res ] ) ;
2014-02-10 01:10:30 +00:00
} else {
2015-06-22 03:03:19 +00:00
if ( ! resource_set . has ( res ) ) {
2014-02-10 01:10:30 +00:00
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 ) ;
2015-06-22 03:03:19 +00:00
f - > store_32 ( res - > get_subindex ( ) ) ;
2014-02-10 01:10:30 +00:00
//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 ;
2017-03-18 23:36:26 +00:00
f - > store_32 ( uint32_t ( d . size ( ) ) | ( d . is_shared ( ) ? 0x80000000 : 0 ) ) ;
2014-02-10 01:10:30 +00:00
List < Variant > keys ;
d . get_key_list ( & keys ) ;
2017-03-18 23:36:26 +00:00
for ( List < Variant > : : Element * E = keys . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 01:10:30 +00:00
//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 ) ;
2017-03-18 23:36:26 +00:00
Array a = p_property ;
f - > store_32 ( uint32_t ( a . size ( ) ) | ( a . is_shared ( ) ? 0x80000000 : 0 ) ) ;
for ( int i = 0 ; i < a . size ( ) ; i + + ) {
2014-02-10 01:10:30 +00:00
write_variant ( a [ i ] ) ;
}
} break ;
case Variant : : RAW_ARRAY : {
f - > store_32 ( VARIANT_RAW_ARRAY ) ;
DVector < uint8_t > arr = p_property ;
2017-03-18 23:36:26 +00:00
int len = arr . size ( ) ;
2014-02-10 01:10:30 +00:00
f - > store_32 ( len ) ;
DVector < uint8_t > : : Read r = arr . read ( ) ;
2017-03-18 23:36:26 +00:00
f - > store_buffer ( r . ptr ( ) , len ) ;
2014-02-10 01:10:30 +00:00
_pad_buffer ( len ) ;
} break ;
case Variant : : INT_ARRAY : {
f - > store_32 ( VARIANT_INT_ARRAY ) ;
DVector < int > arr = p_property ;
2017-03-18 23:36:26 +00:00
int len = arr . size ( ) ;
2014-02-10 01:10:30 +00:00
f - > store_32 ( len ) ;
DVector < int > : : Read r = arr . read ( ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < len ; i + + )
2014-02-10 01:10:30 +00:00
f - > store_32 ( r [ i ] ) ;
} break ;
case Variant : : REAL_ARRAY : {
f - > store_32 ( VARIANT_REAL_ARRAY ) ;
DVector < real_t > arr = p_property ;
2017-03-18 23:36:26 +00:00
int len = arr . size ( ) ;
2014-02-10 01:10:30 +00:00
f - > store_32 ( len ) ;
DVector < real_t > : : Read r = arr . read ( ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < len ; i + + ) {
2014-02-10 01:10:30 +00:00
f - > store_real ( r [ i ] ) ;
}
} break ;
case Variant : : STRING_ARRAY : {
f - > store_32 ( VARIANT_STRING_ARRAY ) ;
DVector < String > arr = p_property ;
2017-03-18 23:36:26 +00:00
int len = arr . size ( ) ;
2014-02-10 01:10:30 +00:00
f - > store_32 ( len ) ;
DVector < String > : : Read r = arr . read ( ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < len ; i + + ) {
2014-02-10 01:10:30 +00:00
save_unicode_string ( r [ i ] ) ;
}
} break ;
case Variant : : VECTOR3_ARRAY : {
f - > store_32 ( VARIANT_VECTOR3_ARRAY ) ;
DVector < Vector3 > arr = p_property ;
2017-03-18 23:36:26 +00:00
int len = arr . size ( ) ;
2014-02-10 01:10:30 +00:00
f - > store_32 ( len ) ;
DVector < Vector3 > : : Read r = arr . read ( ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < len ; i + + ) {
2014-02-10 01:10:30 +00:00
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 ;
2017-03-18 23:36:26 +00:00
int len = arr . size ( ) ;
2014-02-10 01:10:30 +00:00
f - > store_32 ( len ) ;
DVector < Vector2 > : : Read r = arr . read ( ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < len ; i + + ) {
2014-02-10 01:10:30 +00:00
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 ;
2017-03-18 23:36:26 +00:00
int len = arr . size ( ) ;
2014-02-10 01:10:30 +00:00
f - > store_32 ( len ) ;
DVector < Color > : : Read r = arr . read ( ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < len ; i + + ) {
2014-02-10 01:10:30 +00:00
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 ( ) ;
}
}
}
2017-03-18 23:36:26 +00:00
void ResourceFormatSaverBinaryInstance : : _find_resources ( const Variant & p_variant , bool p_main ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
switch ( p_variant . get_type ( ) ) {
2014-02-10 01:10:30 +00:00
case Variant : : OBJECT : {
RES res = p_variant . operator RefPtr ( ) ;
2015-08-23 23:15:56 +00:00
if ( res . is_null ( ) | | external_resources . has ( res ) )
2014-02-10 01:10:30 +00:00
return ;
2017-03-18 23:36:26 +00:00
if ( ! p_main & & ( ! bundle_resources ) & & res - > get_path ( ) . length ( ) & & res - > get_path ( ) . find ( " :: " ) = = - 1 ) {
2015-08-23 23:15:56 +00:00
int idx = external_resources . size ( ) ;
2017-03-18 23:36:26 +00:00
external_resources [ res ] = idx ;
2014-02-10 01:10:30 +00:00
return ;
}
2015-06-22 03:03:19 +00:00
if ( resource_set . has ( res ) )
2014-02-10 01:10:30 +00:00
return ;
List < PropertyInfo > property_list ;
res - > get_property_list ( & property_list ) ;
2017-03-18 23:36:26 +00:00
for ( List < PropertyInfo > : : Element * E = property_list . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
if ( E - > get ( ) . usage & PROPERTY_USAGE_STORAGE | | ( bundle_resources & & E - > get ( ) . usage & PROPERTY_USAGE_BUNDLE ) ) {
2014-02-10 01:10:30 +00:00
_find_resources ( res - > get ( E - > get ( ) . name ) ) ;
}
}
2015-06-22 03:03:19 +00:00
resource_set . insert ( res ) ;
2014-02-10 01:10:30 +00:00
saved_resources . push_back ( res ) ;
} break ;
case Variant : : ARRAY : {
2017-03-18 23:36:26 +00:00
Array varray = p_variant ;
int len = varray . size ( ) ;
for ( int i = 0 ; i < len ; i + + ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
Variant v = varray . get ( i ) ;
2014-02-10 01:10:30 +00:00
_find_resources ( v ) ;
}
} break ;
case Variant : : DICTIONARY : {
2017-03-18 23:36:26 +00:00
Dictionary d = p_variant ;
2014-02-10 01:10:30 +00:00
List < Variant > keys ;
d . get_key_list ( & keys ) ;
2017-03-18 23:36:26 +00:00
for ( List < Variant > : : Element * E = keys . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 01:10:30 +00:00
_find_resources ( E - > get ( ) ) ;
Variant v = d [ E - > get ( ) ] ;
_find_resources ( v ) ;
}
} break ;
case Variant : : NODE_PATH : {
//take the chance and save node path strings
NodePath np = p_variant ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < np . get_name_count ( ) ; i + + )
2014-02-10 01:10:30 +00:00
get_string_index ( np . get_name ( i ) ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < np . get_subname_count ( ) ; i + + )
2014-02-10 01:10:30 +00:00
get_string_index ( np . get_subname ( i ) ) ;
get_string_index ( np . get_property ( ) ) ;
} break ;
default : { }
}
}
#if 0
Error ResourceFormatSaverBinary : : _save_obj ( const Object * p_object , SavedObject * so ) {
//use classic way
List < PropertyInfo > property_list ;
p_object - > get_property_list ( & property_list ) ;
for ( List < PropertyInfo > : : Element * E = property_list . front ( ) ; E ; E = E - > next ( ) ) {
if ( skip_editor & & E - > get ( ) . name . begins_with ( " __editor " ) )
continue ;
if ( E - > get ( ) . usage & PROPERTY_USAGE_STORAGE | | ( bundle_resources & & E - > get ( ) . usage & PROPERTY_USAGE_BUNDLE ) ) {
SavedObject : : SavedProperty sp ;
sp . name_idx = get_string_index ( E - > get ( ) . name ) ;
sp . value = p_object - > get ( E - > get ( ) . name ) ;
_find_resources ( sp . value ) ;
so - > properties . push_back ( sp ) ;
}
}
return OK ;
}
Error ResourceFormatSaverBinary : : save ( const Object * p_object , const Variant & p_meta ) {
ERR_FAIL_COND_V ( ! f , ERR_UNCONFIGURED ) ;
ERR_EXPLAIN ( " write_object should supply either an object, a meta, or both " ) ;
ERR_FAIL_COND_V ( ! p_object & & p_meta . get_type ( ) = = Variant : : NIL , ERR_INVALID_PARAMETER ) ;
SavedObject * so = memnew ( SavedObject ) ;
if ( p_object )
so - > type = p_object - > get_type ( ) ;
_find_resources ( p_meta ) ;
so - > meta = p_meta ;
Error err = _save_obj ( p_object , so ) ;
ERR_FAIL_COND_V ( err , ERR_INVALID_DATA ) ;
saved_objects . push_back ( so ) ;
return OK ;
}
# endif
2017-03-18 23:36:26 +00:00
void ResourceFormatSaverBinaryInstance : : save_unicode_string ( const String & p_string ) {
2014-02-10 01:10:30 +00:00
CharString utf8 = p_string . utf8 ( ) ;
2017-03-18 23:36:26 +00:00
f - > store_32 ( utf8 . length ( ) + 1 ) ;
f - > store_buffer ( ( const uint8_t * ) utf8 . get_data ( ) , utf8 . length ( ) + 1 ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
int ResourceFormatSaverBinaryInstance : : get_string_index ( const String & p_string ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
StringName s = p_string ;
2014-02-10 01:10:30 +00:00
if ( string_map . has ( s ) )
return string_map [ s ] ;
2017-03-18 23:36:26 +00:00
string_map [ s ] = strings . size ( ) ;
2014-02-10 01:10:30 +00:00
strings . push_back ( s ) ;
2017-03-18 23:36:26 +00:00
return strings . size ( ) - 1 ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
Error ResourceFormatSaverBinaryInstance : : save ( const String & p_path , const RES & p_resource , uint32_t p_flags ) {
2014-02-10 01:10:30 +00:00
Error err ;
2017-03-18 23:36:26 +00:00
if ( p_flags & ResourceSaver : : FLAG_COMPRESS ) {
FileAccessCompressed * fac = memnew ( FileAccessCompressed ) ;
2014-02-10 01:10:30 +00:00
fac - > configure ( " RSCC " ) ;
2017-03-18 23:36:26 +00:00
f = fac ;
err = fac - > _open ( p_path , FileAccess : : WRITE ) ;
2014-02-10 01:10:30 +00:00
if ( err )
memdelete ( f ) ;
} else {
2017-03-18 23:36:26 +00:00
f = FileAccess : : open ( p_path , FileAccess : : WRITE , & err ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
ERR_FAIL_COND_V ( err , err ) ;
2014-02-10 01:10:30 +00:00
FileAccessRef _fref ( f ) ;
2017-03-18 23:36:26 +00:00
relative_paths = p_flags & ResourceSaver : : FLAG_RELATIVE_PATHS ;
skip_editor = p_flags & ResourceSaver : : FLAG_OMIT_EDITOR_PROPERTIES ;
bundle_resources = p_flags & ResourceSaver : : FLAG_BUNDLE_RESOURCES ;
big_endian = p_flags & ResourceSaver : : FLAG_SAVE_BIG_ENDIAN ;
takeover_paths = p_flags & ResourceSaver : : FLAG_REPLACE_SUBRESOURCE_PATHS ;
2014-03-14 01:57:24 +00:00
2014-06-28 02:21:45 +00:00
if ( ! p_path . begins_with ( " res:// " ) )
2017-03-18 23:36:26 +00:00
takeover_paths = false ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
local_path = p_path . get_base_dir ( ) ;
2014-02-10 01:10:30 +00:00
//bin_meta_idx = get_string_index("__bin_meta__"); //is often used, so create
2017-03-18 23:36:26 +00:00
_find_resources ( p_resource , true ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
if ( ! ( p_flags & ResourceSaver : : FLAG_COMPRESS ) ) {
2014-02-10 01:10:30 +00:00
//save header compressed
2017-03-18 23:36:26 +00:00
static const uint8_t header [ 4 ] = { ' R ' , ' S ' , ' R ' , ' C ' } ;
f - > store_buffer ( header , 4 ) ;
2014-02-10 01:10:30 +00:00
}
if ( big_endian ) {
f - > store_32 ( 1 ) ;
f - > set_endian_swap ( true ) ;
} else
f - > store_32 ( 0 ) ;
f - > store_32 ( 0 ) ; //64 bits file, false for now
f - > store_32 ( VERSION_MAJOR ) ;
f - > store_32 ( VERSION_MINOR ) ;
f - > store_32 ( FORMAT_VERSION ) ;
2017-03-18 23:36:26 +00:00
if ( f - > get_error ( ) ! = OK & & f - > get_error ( ) ! = ERR_FILE_EOF ) {
2015-03-02 03:54:10 +00:00
f - > close ( ) ;
return ERR_CANT_CREATE ;
}
2014-02-10 01:10:30 +00:00
//f->store_32(saved_resources.size()+external_resources.size()); // load steps -not needed
save_unicode_string ( p_resource - > get_type ( ) ) ;
uint64_t md_at = f - > get_pos ( ) ;
f - > store_64 ( 0 ) ; //offset to impoty metadata
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < 14 ; i + + )
2014-02-10 01:10:30 +00:00
f - > store_32 ( 0 ) ; // reserved
List < ResourceData > resources ;
{
2017-03-18 23:36:26 +00:00
for ( List < RES > : : Element * E = saved_resources . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 01:10:30 +00:00
ResourceData & rd = resources . push_back ( ResourceData ( ) ) - > get ( ) ;
2017-03-18 23:36:26 +00:00
rd . type = E - > get ( ) - > get_type ( ) ;
2014-02-10 01:10:30 +00:00
List < PropertyInfo > property_list ;
2017-03-18 23:36:26 +00:00
E - > get ( ) - > get_property_list ( & property_list ) ;
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
for ( List < PropertyInfo > : : Element * F = property_list . front ( ) ; F ; F = F - > next ( ) ) {
2014-02-10 01:10:30 +00:00
if ( skip_editor & & F - > get ( ) . name . begins_with ( " __editor " ) )
continue ;
2017-03-18 23:36:26 +00:00
if ( F - > get ( ) . usage & PROPERTY_USAGE_STORAGE | | ( bundle_resources & & F - > get ( ) . usage & PROPERTY_USAGE_BUNDLE ) ) {
2014-02-10 01:10:30 +00:00
Property p ;
2017-03-18 23:36:26 +00:00
p . name_idx = get_string_index ( F - > get ( ) . name ) ;
p . value = E - > get ( ) - > get ( F - > get ( ) . name ) ;
if ( ( F - > get ( ) . usage & PROPERTY_USAGE_STORE_IF_NONZERO & & p . value . is_zero ( ) ) | | ( F - > get ( ) . usage & PROPERTY_USAGE_STORE_IF_NONONE & & p . value . is_one ( ) ) )
2014-02-10 01:10:30 +00:00
continue ;
2017-03-18 23:36:26 +00:00
p . pi = F - > get ( ) ;
2014-02-10 01:10:30 +00:00
rd . properties . push_back ( p ) ;
}
}
}
}
f - > store_32 ( strings . size ( ) ) ; //string table size
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < strings . size ( ) ; i + + ) {
2014-02-10 01:10:30 +00:00
//print_bl("saving string: "+strings[i]);
save_unicode_string ( strings [ i ] ) ;
}
// save external resource table
f - > store_32 ( external_resources . size ( ) ) ; //amount of external resources
2015-08-23 23:15:56 +00:00
Vector < RES > save_order ;
save_order . resize ( external_resources . size ( ) ) ;
2017-03-18 23:36:26 +00:00
for ( Map < RES , int > : : Element * E = external_resources . front ( ) ; E ; E = E - > next ( ) ) {
save_order [ E - > get ( ) ] = E - > key ( ) ;
2015-08-23 23:15:56 +00:00
}
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < save_order . size ( ) ; i + + ) {
2015-08-23 23:15:56 +00:00
save_unicode_string ( save_order [ i ] - > get_save_type ( ) ) ;
String path = save_order [ i ] - > get_path ( ) ;
2017-03-18 23:36:26 +00:00
path = relative_paths ? local_path . path_to_file ( path ) : path ;
2014-02-10 01:10:30 +00:00
save_unicode_string ( path ) ;
}
// save internal resource table
f - > store_32 ( saved_resources . size ( ) ) ; //amount of internal resources
Vector < uint64_t > ofs_pos ;
2015-06-22 03:03:19 +00:00
Set < int > used_indices ;
2017-03-18 23:36:26 +00:00
for ( List < RES > : : Element * E = saved_resources . front ( ) ; E ; E = E - > next ( ) ) {
2015-06-22 03:03:19 +00:00
RES r = E - > get ( ) ;
2017-03-18 23:36:26 +00:00
if ( r - > get_path ( ) = = " " | | r - > get_path ( ) . find ( " :: " ) ! = - 1 ) {
2015-06-22 03:03:19 +00:00
2017-03-18 23:36:26 +00:00
if ( r - > get_subindex ( ) ! = 0 ) {
2015-06-22 03:03:19 +00:00
if ( used_indices . has ( r - > get_subindex ( ) ) ) {
r - > set_subindex ( 0 ) ; //repeated
} else {
used_indices . insert ( r - > get_subindex ( ) ) ;
}
}
}
}
2017-03-18 23:36:26 +00:00
for ( List < RES > : : Element * E = saved_resources . front ( ) ; E ; E = E - > next ( ) ) {
2015-06-22 03:03:19 +00:00
2014-02-10 01:10:30 +00:00
RES r = E - > get ( ) ;
2017-03-18 23:36:26 +00:00
if ( r - > get_path ( ) = = " " | | r - > get_path ( ) . find ( " :: " ) ! = - 1 ) {
if ( r - > get_subindex ( ) = = 0 ) {
int new_subindex = 1 ;
2015-06-22 03:03:19 +00:00
if ( used_indices . size ( ) ) {
2017-03-18 23:36:26 +00:00
new_subindex = used_indices . back ( ) - > get ( ) + 1 ;
2015-06-22 03:03:19 +00:00
}
r - > set_subindex ( new_subindex ) ;
used_indices . insert ( new_subindex ) ;
}
2017-03-18 23:36:26 +00:00
save_unicode_string ( " local:// " + itos ( r - > get_subindex ( ) ) ) ;
2014-06-28 02:21:45 +00:00
if ( takeover_paths ) {
2017-03-18 23:36:26 +00:00
r - > set_path ( p_path + " :: " + itos ( r - > get_subindex ( ) ) , true ) ;
2014-06-28 02:21:45 +00:00
}
2015-10-22 02:57:43 +00:00
} else {
2014-02-10 01:10:30 +00:00
save_unicode_string ( r - > get_path ( ) ) ; //actual external
2015-10-22 02:57:43 +00:00
}
2014-02-10 01:10:30 +00:00
ofs_pos . push_back ( f - > get_pos ( ) ) ;
f - > store_64 ( 0 ) ; //offset in 64 bits
}
Vector < uint64_t > ofs_table ;
2017-03-18 23:36:26 +00:00
// int saved_idx=0;
2014-02-10 01:10:30 +00:00
//now actually save the resources
2017-03-18 23:36:26 +00:00
for ( List < ResourceData > : : Element * E = resources . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
ResourceData & rd = E - > get ( ) ;
2014-02-10 01:10:30 +00:00
ofs_table . push_back ( f - > get_pos ( ) ) ;
save_unicode_string ( rd . type ) ;
f - > store_32 ( rd . properties . size ( ) ) ;
2017-03-18 23:36:26 +00:00
for ( List < Property > : : Element * F = rd . properties . front ( ) ; F ; F = F - > next ( ) ) {
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
Property & p = F - > get ( ) ;
2014-02-10 01:10:30 +00:00
f - > store_32 ( p . name_idx ) ;
2017-03-18 23:36:26 +00:00
write_variant ( p . value , F - > get ( ) . pi ) ;
2014-02-10 01:10:30 +00:00
}
}
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < ofs_table . size ( ) ; i + + ) {
2014-02-10 01:10:30 +00:00
f - > seek ( ofs_pos [ i ] ) ;
f - > store_64 ( ofs_table [ i ] ) ;
}
f - > seek_end ( ) ;
2017-03-18 23:36:26 +00:00
print_line ( " SAVING: " + p_path ) ;
2014-02-10 01:10:30 +00:00
if ( p_resource - > get_import_metadata ( ) . is_valid ( ) ) {
uint64_t md_pos = f - > get_pos ( ) ;
2017-03-18 23:36:26 +00:00
Ref < ResourceImportMetadata > imd = p_resource - > get_import_metadata ( ) ;
2014-02-10 01:10:30 +00:00
save_unicode_string ( imd - > get_editor ( ) ) ;
f - > store_32 ( imd - > get_source_count ( ) ) ;
2017-03-18 23:36:26 +00:00
for ( int i = 0 ; i < imd - > get_source_count ( ) ; i + + ) {
2014-02-10 01:10:30 +00:00
save_unicode_string ( imd - > get_source_path ( i ) ) ;
save_unicode_string ( imd - > get_source_md5 ( i ) ) ;
2017-03-18 23:36:26 +00:00
print_line ( " SAVE PATH: " + imd - > get_source_path ( i ) ) ;
print_line ( " SAVE MD5: " + imd - > get_source_md5 ( i ) ) ;
2014-02-10 01:10:30 +00:00
}
List < String > options ;
imd - > get_options ( & options ) ;
f - > store_32 ( options . size ( ) ) ;
2017-03-18 23:36:26 +00:00
for ( List < String > : : Element * E = options . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 01:10:30 +00:00
save_unicode_string ( E - > get ( ) ) ;
write_variant ( imd - > get_option ( E - > get ( ) ) ) ;
}
f - > seek ( md_at ) ;
f - > store_64 ( md_pos ) ;
f - > seek_end ( ) ;
}
2017-03-18 23:36:26 +00:00
f - > store_buffer ( ( const uint8_t * ) " RSRC " , 4 ) ; //magic at end
2014-02-10 01:10:30 +00:00
2017-03-18 23:36:26 +00:00
if ( f - > get_error ( ) ! = OK & & f - > get_error ( ) ! = ERR_FILE_EOF ) {
2015-03-02 03:54:10 +00:00
f - > close ( ) ;
return ERR_CANT_CREATE ;
}
2014-02-10 01:10:30 +00:00
f - > close ( ) ;
return OK ;
}
2017-03-18 23:36:26 +00:00
Error ResourceFormatSaverBinary : : save ( const String & p_path , const RES & p_resource , uint32_t p_flags ) {
2014-02-10 01:10:30 +00:00
String local_path = Globals : : get_singleton ( ) - > localize_path ( p_path ) ;
ResourceFormatSaverBinaryInstance saver ;
2017-03-18 23:36:26 +00:00
return saver . save ( local_path , p_resource , p_flags ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
bool ResourceFormatSaverBinary : : recognize ( const RES & p_resource ) const {
2014-02-10 01:10:30 +00:00
return true ; //all recognized
}
2017-03-18 23:36:26 +00:00
void ResourceFormatSaverBinary : : get_recognized_extensions ( const RES & p_resource , List < String > * p_extensions ) const {
2014-02-10 01:10:30 +00:00
String base = p_resource - > get_base_extension ( ) . to_lower ( ) ;
2016-06-28 16:58:40 +00:00
p_extensions - > push_back ( base ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-18 23:36:26 +00:00
ResourceFormatSaverBinary * ResourceFormatSaverBinary : : singleton = NULL ;
2015-08-23 23:15:56 +00:00
ResourceFormatSaverBinary : : ResourceFormatSaverBinary ( ) {
2017-03-18 23:36:26 +00:00
singleton = this ;
2015-08-23 23:15:56 +00:00
}