Error DirAccessWindows::make_dir(String p_dir) { GLOBAL_LOCK_FUNCTION p_dir = fix_path(p_dir); if (p_dir.is_rel_path()) p_dir = current_dir.plus_file(p_dir); p_dir = p_dir.replace("/", "\\"); bool success; int err; p_dir = "\\\\?\\" + p_dir; //done according to // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363855(v=vs.85).aspx success = CreateDirectoryW(p_dir.c_str(), NULL); err = GetLastError(); if (success) { return OK; }; if (err == ERROR_ALREADY_EXISTS || err == ERROR_ACCESS_DENIED) { return ERR_ALREADY_EXISTS; }; return ERR_CANT_CREATE; }
Error ResourceLoader::rename_dependencies(const String &p_path,const Map<String,String>& p_map) { String local_path; if (p_path.is_rel_path()) local_path="res://"+p_path; else local_path = Globals::get_singleton()->localize_path(p_path); String remapped_path = PathRemap::get_singleton()->get_remap(local_path); String extension=remapped_path.extension(); for (int i=0;i<loader_count;i++) { if (!loader[i]->recognize(extension)) continue; //if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) // continue; return loader[i]->rename_dependencies(p_path,p_map); } return OK; // ?? }
Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { String path = p_path; if (FileAccess::exists(path) && path.is_rel_path()) { // dlopen expects a slash, in this case a leading ./ for it to be interpreted as a relative path, // otherwise it will end up searching various system directories for the lib instead and finally failing. path = "./" + path; } if (!FileAccess::exists(path)) { //this code exists so gdnative can load .so files from within the executable path path = get_executable_path().get_base_dir().plus_file(p_path.get_file()); } if (!FileAccess::exists(path)) { //this code exists so gdnative can load .so files from a standard unix location path = get_executable_path().get_base_dir().plus_file("../lib").plus_file(p_path.get_file()); } p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW); if (!p_library_handle) { ERR_EXPLAIN("Can't open dynamic library: " + p_path + ". Error: " + dlerror()); ERR_FAIL_V(ERR_CANT_OPEN); } return OK; }
bool ResourceLoader::exists(const String &p_path, const String &p_type_hint) { String local_path; if (p_path.is_rel_path()) local_path = "res://" + p_path; else local_path = ProjectSettings::get_singleton()->localize_path(p_path); if (ResourceCache::has(local_path)) { return true; // If cached, it probably exists } bool xl_remapped = false; String path = _path_remap(local_path, &xl_remapped); // Try all loaders and pick the first match for the type hint for (int i = 0; i < loader_count; i++) { if (!loader[i]->recognize_path(path, p_type_hint)) { continue; } if (loader[i]->exists(path)) return true; } return false; }
bool DirAccessJAndroid::dir_exists(String p_dir) { JNIEnv *env = ThreadAndroid::get_env(); String sd; if (current_dir == "") sd = p_dir; else { if (p_dir.is_rel_path()) sd = current_dir.plus_file(p_dir); else sd = fix_path(p_dir); } String path = sd.simplify_path(); if (path.begins_with("/")) path = path.substr(1, path.length()); else if (path.begins_with("res://")) path = path.substr(6, path.length()); jstring js = env->NewStringUTF(path.utf8().get_data()); int res = env->CallIntMethod(io, _dir_open, js); env->DeleteLocalRef(js); if (res <= 0) return false; env->CallVoidMethod(io, _dir_close, res); return true; }
Ref<ResourceImportMetadata> ResourceLoader::load_import_metadata(const String &p_path) { String local_path; if (p_path.is_rel_path()) local_path="res://"+p_path; else local_path = Globals::get_singleton()->localize_path(p_path); String extension=p_path.extension(); Ref<ResourceImportMetadata> ret; for (int i=0;i<loader_count;i++) { if (!loader[i]->recognize(extension)) continue; Error err = loader[i]->load_import_metadata(local_path,ret); if (err==OK) break; } return ret; }
RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) { if (r_error) *r_error = ERR_CANT_OPEN; String local_path; if (p_path.is_rel_path()) local_path = "res://" + p_path; else local_path = GlobalConfig::get_singleton()->localize_path(p_path); ERR_FAIL_COND_V(local_path == "", RES()); if (!p_no_cache && ResourceCache::has(local_path)) { if (OS::get_singleton()->is_stdout_verbose()) print_line("load resource: " + local_path + " (cached)"); return RES(ResourceCache::get(local_path)); } if (OS::get_singleton()->is_stdout_verbose()) print_line("load resource: " + local_path); bool found = false; for (int i = 0; i < loader_count; i++) { if (!loader[i]->recognize_path(local_path, p_type_hint)) { print_line("path not recognized"); continue; } found = true; RES res = loader[i]->load(local_path, local_path, r_error); if (res.is_null()) { continue; } if (!p_no_cache) res->set_path(local_path); #ifdef TOOLS_ENABLED res->set_edited(false); if (timestamp_on_load) { uint64_t mt = FileAccess::get_modified_time(local_path); //printf("mt %s: %lli\n",remapped_path.utf8().get_data(),mt); res->set_last_modified_time(mt); } #endif return res; } if (found) { ERR_EXPLAIN("Failed loading resource: " + p_path); } else { ERR_EXPLAIN("No loader found for resource: " + p_path); } ERR_FAIL_V(RES()); return RES(); }
String EditorImportPlugin::expand_source_path(const String& p_path) { if (p_path.is_rel_path()) { return Globals::get_singleton()->get_resource_path().plus_file(p_path).simplify_path(); } else { return p_path; } }
Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_path,const String& p_type_hint,bool p_no_cache,Error *r_error) { if (r_error) *r_error=ERR_CANT_OPEN; String local_path; if (p_path.is_rel_path()) local_path="res://"+p_path; else local_path = Globals::get_singleton()->localize_path(p_path); local_path=find_complete_path(local_path,p_type_hint); ERR_FAIL_COND_V(local_path=="",Ref<ResourceInteractiveLoader>()); if (!p_no_cache && ResourceCache::has(local_path)) { if (OS::get_singleton()->is_stdout_verbose()) print_line("load resource: "+local_path+" (cached)"); return RES( ResourceCache::get(local_path ) ); } if (OS::get_singleton()->is_stdout_verbose()) print_line("load resource: "); String remapped_path = PathRemap::get_singleton()->get_remap(local_path); String extension=remapped_path.extension(); bool found=false; for (int i=0;i<loader_count;i++) { if (!loader[i]->recognize(extension)) continue; if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) continue; found=true; Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(remapped_path,r_error); if (ril.is_null()) continue; if (!p_no_cache) ril->set_local_path(local_path); return ril; } if (found) { ERR_EXPLAIN("Failed loading resource: "+p_path); } else { ERR_EXPLAIN("No loader found for resource: "+p_path); } ERR_FAIL_V(Ref<ResourceInteractiveLoader>()); return Ref<ResourceInteractiveLoader>(); }
Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) { if (r_error) *r_error = ERR_CANT_OPEN; String local_path; if (p_path.is_rel_path()) local_path = "res://" + p_path; else local_path = ProjectSettings::get_singleton()->localize_path(p_path); bool xl_remapped = false; String path = _path_remap(local_path, &xl_remapped); ERR_FAIL_COND_V(path == "", Ref<ResourceInteractiveLoader>()); if (!p_no_cache && ResourceCache::has(path)) { if (OS::get_singleton()->is_stdout_verbose()) print_line("load resource: " + path + " (cached)"); Ref<Resource> res_cached = ResourceCache::get(path); Ref<ResourceInteractiveLoaderDefault> ril = Ref<ResourceInteractiveLoaderDefault>(memnew(ResourceInteractiveLoaderDefault)); ril->resource = res_cached; return ril; } if (OS::get_singleton()->is_stdout_verbose()) print_line("load resource: "); bool found = false; for (int i = 0; i < loader_count; i++) { if (!loader[i]->recognize_path(path, p_type_hint)) continue; found = true; Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(path, r_error); if (ril.is_null()) continue; if (!p_no_cache) ril->set_local_path(local_path); if (xl_remapped) ril->set_translation_remapped(true); return ril; } if (found) { ERR_EXPLAIN("Failed loading resource: " + path); } else { ERR_EXPLAIN("No loader found for resource: " + path); } ERR_FAIL_V(Ref<ResourceInteractiveLoader>()); return Ref<ResourceInteractiveLoader>(); }
Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags) { List<String> dirs; String curdir = get_current_dir(); list_dir_begin(); String n = get_next(); while (n != String()) { if (n != "." && n != "..") { if (current_is_dir()) dirs.push_back(n); else { String rel_path = n; if (!n.is_rel_path()) { list_dir_end(); return ERR_BUG; } Error err = copy(get_current_dir() + "/" + n, p_to + rel_path, p_chmod_flags); if (err) { list_dir_end(); return err; } } } n = get_next(); } list_dir_end(); for (List<String>::Element *E = dirs.front(); E; E = E->next()) { String rel_path = E->get(); String target_dir = p_to + rel_path; if (!p_target_da->dir_exists(target_dir)) { Error err = p_target_da->make_dir(target_dir); ERR_FAIL_COND_V(err, err); } Error err = change_dir(E->get()); ERR_FAIL_COND_V(err, err); err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags); if (err) { change_dir(".."); ERR_PRINT("Failed to copy recursively"); return err; } err = change_dir(".."); if (err) { ERR_PRINT("Failed to go back"); return err; } } return OK; }
String ResourceLoader::guess_full_filename(const String &p_path,const String& p_type) { String local_path; if (p_path.is_rel_path()) local_path="res://"+p_path; else local_path = Globals::get_singleton()->localize_path(p_path); return find_complete_path(local_path,p_type); }
Error DirAccess::make_dir_recursive(String p_dir) { if (p_dir.length() < 1) { return OK; }; String full_dir; if (p_dir.is_rel_path()) { //append current full_dir=get_current_dir().plus_file(p_dir); } else { full_dir=p_dir; } full_dir=full_dir.replace("\\","/"); //int slices = full_dir.get_slice_count("/"); String base; if (full_dir.begins_with("res://")) base="res://"; else if (full_dir.begins_with("user://")) base="user://"; else if (full_dir.begins_with("/")) base="/"; else if (full_dir.find(":/")!=-1) { base=full_dir.substr(0,full_dir.find(":/")+2); } else { ERR_FAIL_V(ERR_INVALID_PARAMETER); } full_dir=full_dir.replace_first(base,"").simplify_path(); Vector<String> subdirs=full_dir.split("/"); String curpath=base; for(int i=0;i<subdirs.size();i++) { curpath=curpath.plus_file(subdirs[i]); Error err = make_dir(curpath); if (err != OK && err != ERR_ALREADY_EXISTS) { ERR_FAIL_V(err); } } return OK; }
String ResourceLoader::get_resource_type(const String &p_path) { String local_path; if (p_path.is_rel_path()) local_path = "res://" + p_path; else local_path = ProjectSettings::get_singleton()->localize_path(p_path); for (int i = 0; i < loader_count; i++) { String result = loader[i]->get_resource_type(local_path); if (result != "") return result; } return ""; }
Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream* p_stream,Ref<Resource>& r_res,int &line,String &r_err_str){ VariantParser::Token token; VariantParser::get_token(p_stream,token,line,r_err_str); if (token.type!=VariantParser::TK_NUMBER) { r_err_str="Expected number (sub-resource index)"; return ERR_PARSE_ERROR; } int id = token.value; if (!ignore_resource_parsing) { if (!ext_resources.has(id)) { r_err_str="Can't load cached ext-resource #"+itos(id); return ERR_PARSE_ERROR; } String path = ext_resources[id].path; String type = ext_resources[id].type; if (path.find("://")==-1 && path.is_rel_path()) { // path is relative to file being loaded, so convert to a resource path path=Globals::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path)); } r_res=ResourceLoader::load(path,type); if (r_res.is_null()) { WARN_PRINT(String("Couldn't load external resource: "+path).utf8().get_data()); } } else { r_res=RES(); } VariantParser::get_token(p_stream,token,line,r_err_str); if (token.type!=VariantParser::TK_PARENTHESIS_CLOSE) { r_err_str="Expected ')'"; return ERR_PARSE_ERROR; } return OK; }
Error DirAccessFlash::change_dir(String p_dir) { if (p_dir==".") return OK; if (p_dir.is_rel_path()) current_dir+="/"+p_dir; else current_dir=fix_path(p_dir); current_dir=current_dir.simplify_path(); if (current_dir.length()>1 && current_dir.ends_with("/") && !current_dir.ends_with("//")) current_dir=current_dir.substr(0,current_dir.length()-1); return OK; };
void ResourceLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { String local_path; if (p_path.is_rel_path()) local_path = "res://" + p_path; else local_path = GlobalConfig::get_singleton()->localize_path(p_path); for (int i = 0; i < loader_count; i++) { if (!loader[i]->recognize_path(local_path)) continue; /* if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) continue; */ loader[i]->get_dependencies(local_path, p_dependencies, p_add_types); } }
String ResourceLoader::get_resource_type(const String &p_path) { String local_path; if (p_path.is_rel_path()) local_path="res://"+p_path; else local_path = Globals::get_singleton()->localize_path(p_path); String remapped_path = PathRemap::get_singleton()->get_remap(local_path); String extension=remapped_path.extension(); for (int i=0;i<loader_count;i++) { String result = loader[i]->get_resource_type(local_path); if (result!="") return result; } return ""; }
Error ResourceLoader::rename_dependencies(const String &p_path, const Map<String, String> &p_map) { String local_path; if (p_path.is_rel_path()) local_path = "res://" + p_path; else local_path = GlobalConfig::get_singleton()->localize_path(p_path); for (int i = 0; i < loader_count; i++) { if (!loader[i]->recognize_path(local_path)) continue; /* if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) continue; */ return loader[i]->rename_dependencies(local_path, p_map); } return OK; // ?? }
String ResourceLoader::get_import_group_file(const String &p_path) { String path = _path_remap(p_path); String local_path; if (path.is_rel_path()) local_path = "res://" + path; else local_path = ProjectSettings::get_singleton()->localize_path(path); for (int i = 0; i < loader_count; i++) { if (!loader[i]->recognize_path(local_path)) continue; /* if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) continue; */ return loader[i]->get_import_group_file(p_path); } return String(); //not found }
void ResourceLoader::get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types) { String local_path; if (p_path.is_rel_path()) local_path="res://"+p_path; else local_path = Globals::get_singleton()->localize_path(p_path); String remapped_path = PathRemap::get_singleton()->get_remap(local_path); String extension=remapped_path.extension(); for (int i=0;i<loader_count;i++) { if (!loader[i]->recognize(extension)) continue; //if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) // continue; loader[i]->get_dependencies(remapped_path,p_dependencies,p_add_types); } }
static Ref<Reference> _get_parent_class(GDCompletionContext& context) { if (context._class->extends_used) { //do inheritance String path = context._class->extends_file; Ref<GDScript> script; Ref<GDNativeClass> native; if (path!="") { //path (and optionally subclasses) if (path.is_rel_path()) { path=context.base_path.plus_file(path); } script = ResourceLoader::load(path); if (script.is_null()) { return REF(); } if (script->is_valid()) { return REF(); } //print_line("EXTENDS PATH: "+path+" script is "+itos(script.is_valid())+" indices is "+itos(script->member_indices.size())+" valid? "+itos(script->valid)); if (context._class->extends_class.size()) { for(int i=0;i<context._class->extends_class.size();i++) { String sub = context._class->extends_class[i]; if (script->get_subclasses().has(sub)) { script=script->get_subclasses()[sub]; } else { return REF(); } } } if (script.is_valid()) return script; } else { if (context._class->extends_class.size()==0) { ERR_PRINT("BUG"); return REF(); } String base=context._class->extends_class[0]; const GDParser::ClassNode *p = context._class->owner; Ref<GDScript> base_class; #if 0 while(p) { if (p->subclasses.has(base)) { base_class=p->subclasses[base]; break; } p=p->_owner; } #endif if (base_class.is_valid()) { #if 0 for(int i=1;i<context._class->extends_class.size();i++) { String subclass=context._class->extends_class[i]; if (base_class->subclasses.has(subclass)) { base_class=base_class->subclasses[subclass]; } else { print_line("Could not find subclass: "+subclass); return _get_type_from_class(context); //fail please } } script=base_class; #endif } else { if (context._class->extends_class.size()>1) { return REF(); } //if not found, try engine classes if (!GDScriptLanguage::get_singleton()->get_global_map().has(base)) { return REF(); } int base_idx = GDScriptLanguage::get_singleton()->get_global_map()[base]; native = GDScriptLanguage::get_singleton()->get_global_array()[base_idx]; if (!native.is_valid()) { print_line("Global not a class: '"+base+"'"); } return native; } } } return Ref<Reference>(); }
Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) { if (r_error) *r_error = ERR_CANT_OPEN; String local_path; if (p_path.is_rel_path()) local_path = "res://" + p_path; else local_path = ProjectSettings::get_singleton()->localize_path(p_path); if (!p_no_cache) { bool success = _add_to_loading_map(local_path); if (!success) { ERR_EXPLAIN("Resource: '" + local_path + "' is already being loaded. Cyclic reference?"); ERR_FAIL_V(RES()); } if (ResourceCache::has(local_path)) { print_verbose("Loading resource: " + local_path + " (cached)"); Ref<Resource> res_cached = ResourceCache::get(local_path); Ref<ResourceInteractiveLoaderDefault> ril = Ref<ResourceInteractiveLoaderDefault>(memnew(ResourceInteractiveLoaderDefault)); ril->resource = res_cached; ril->path_loading = local_path; ril->path_loading_thread = Thread::get_caller_id(); return ril; } } bool xl_remapped = false; String path = _path_remap(local_path, &xl_remapped); if (path == "") { if (!p_no_cache) { _remove_from_loading_map(local_path); } ERR_EXPLAIN("Remapping '" + local_path + "'failed."); ERR_FAIL_V(RES()); } print_verbose("Loading resource: " + path); bool found = false; for (int i = 0; i < loader_count; i++) { if (!loader[i]->recognize_path(path, p_type_hint)) continue; found = true; Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(path, local_path, r_error); if (ril.is_null()) continue; if (!p_no_cache) { ril->set_local_path(local_path); ril->path_loading = local_path; ril->path_loading_thread = Thread::get_caller_id(); } if (xl_remapped) ril->set_translation_remapped(true); return ril; } if (!p_no_cache) { _remove_from_loading_map(local_path); } if (found) { ERR_EXPLAIN("Failed loading resource: " + path); } else { ERR_EXPLAIN("No loader found for resource: " + path); } ERR_FAIL_V(Ref<ResourceInteractiveLoader>()); return Ref<ResourceInteractiveLoader>(); }
Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) { uint32_t type = f->get_32(); print_bl("find property of type: "+itos(type)); switch(type) { case VARIANT_NIL: { r_v=Variant(); } break; case VARIANT_BOOL: { r_v=bool(f->get_32()); } break; case VARIANT_INT: { r_v=int(f->get_32()); } break; case VARIANT_REAL: { r_v=f->get_real(); } break; case VARIANT_STRING: { r_v=get_unicode_string(); } break; case VARIANT_VECTOR2: { Vector2 v; v.x=f->get_real(); v.y=f->get_real(); r_v=v; } break; case VARIANT_RECT2: { Rect2 v; 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; } break; case VARIANT_VECTOR3: { Vector3 v; v.x=f->get_real(); v.y=f->get_real(); v.z=f->get_real(); r_v=v; } break; case VARIANT_PLANE: { Plane v; 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; } break; case VARIANT_QUAT: { Quat v; v.x=f->get_real(); v.y=f->get_real(); v.z=f->get_real(); v.w=f->get_real(); r_v=v; } break; case VARIANT_AABB: { AABB v; 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; } break; case VARIANT_MATRIX32: { Matrix32 v; 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; } break; case VARIANT_MATRIX3: { Matrix3 v; 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; } break; case VARIANT_TRANSFORM: { Transform v; 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; } break; case VARIANT_COLOR: { Color v; v.r=f->get_real(); v.g=f->get_real(); v.b=f->get_real(); v.a=f->get_real(); r_v=v; } break; case VARIANT_IMAGE: { uint32_t encoding = f->get_32(); if (encoding==IMAGE_ENCODING_EMPTY) { r_v=Variant(); break; } else if (encoding==IMAGE_ENCODING_RAW) { 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; 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_CUSTOM: { fmt=Image::FORMAT_CUSTOM; } break; 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(); f->get_buffer(w.ptr(),datalen); _advance_padding(datalen); w=DVector<uint8_t>::Write(); r_v=Image(width,height,mipmaps,fmt,imgdata); } else { //compressed DVector<uint8_t> data; data.resize(f->get_32()); DVector<uint8_t>::Write w = data.write(); f->get_buffer(w.ptr(),data.size()); w = DVector<uint8_t>::Write(); Image img; if (encoding==IMAGE_ENCODING_LOSSY && Image::lossy_unpacker) { img = Image::lossy_unpacker(data); } else if (encoding==IMAGE_ENCODING_LOSSLESS && Image::lossless_unpacker) { img = Image::lossless_unpacker(data); } _advance_padding(data.size()); r_v=img; } } 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(); absolute=subname_count&0x8000; subname_count&=0x7FFF; for(int i=0;i<name_count;i++) names.push_back(string_map[f->get_32()]); for(uint32_t i=0;i<subname_count;i++) subnames.push_back(string_map[f->get_32()]); property=string_map[f->get_32()]; NodePath np = NodePath(names,subnames,absolute,property); //print_line("got path: "+String(np)); r_v=np; } break; case VARIANT_RID: { r_v=f->get_32(); } break; case VARIANT_OBJECT: { uint32_t type=f->get_32(); switch(type) { case OBJECT_EMPTY: { //do none } break; case OBJECT_INTERNAL_RESOURCE: { uint32_t index=f->get_32(); String path = res_path+"::"+itos(index); RES res = ResourceLoader::load(path); if (res.is_null()) { WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data()); } r_v=res; } break; case OBJECT_EXTERNAL_RESOURCE: { String type = get_unicode_string(); String path = get_unicode_string(); if (path.find("://")==-1 && path.is_rel_path()) { // path is relative to file being loaded, so convert to a resource path path=Globals::get_singleton()->localize_path(res_path.get_base_dir()+"/"+path); } RES res=ResourceLoader::load(path,type); if (res.is_null()) { WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data()); } r_v=res; } break; default: { ERR_FAIL_V(ERR_FILE_CORRUPT); } break; } } break; case VARIANT_INPUT_EVENT: { } break; case VARIANT_DICTIONARY: { uint32_t len=f->get_32(); Dictionary d(len&0x80000000); //last bit means shared len&=0x7FFFFFFF; for(uint32_t i=0;i<len;i++) { Variant key; Error err = parse_variant(key); ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT); Variant value; err = parse_variant(value); ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT); d[key]=value; } r_v=d; } break; case VARIANT_ARRAY: { uint32_t len=f->get_32(); Array a(len&0x80000000); //last bit means shared len&=0x7FFFFFFF; a.resize(len); for(uint32_t i=0;i<len;i++) { Variant val; Error err = parse_variant(val); ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT); a[i]=val; } r_v=a; } 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(); f->get_buffer(w.ptr(),len); _advance_padding(len); w=DVector<uint8_t>::Write(); r_v=array; } break; case VARIANT_INT_ARRAY: { uint32_t len = f->get_32(); DVector<int> array; array.resize(len); DVector<int>::Write w = array.write(); f->get_buffer((uint8_t*)w.ptr(),len*4); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr=(uint32_t*)w.ptr(); for(int i=0;i<len;i++) { ptr[i]=BSWAP32(ptr[i]); } } #endif w=DVector<int>::Write(); r_v=array; } 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(); f->get_buffer((uint8_t*)w.ptr(),len*sizeof(real_t)); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr=(uint32_t*)w.ptr(); for(int i=0;i<len;i++) { ptr[i]=BSWAP32(ptr[i]); } } #endif w=DVector<real_t>::Write(); r_v=array; } break; case VARIANT_STRING_ARRAY: { uint32_t len = f->get_32(); DVector<String> array; array.resize(len); DVector<String>::Write w = array.write(); for(uint32_t i=0;i<len;i++) w[i]=get_unicode_string(); w=DVector<String>::Write(); r_v=array; } break; case VARIANT_VECTOR2_ARRAY: { uint32_t len = f->get_32(); DVector<Vector2> array; array.resize(len); DVector<Vector2>::Write w = array.write(); if (sizeof(Vector2)==8) { f->get_buffer((uint8_t*)w.ptr(),len*sizeof(real_t)*2); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr=(uint32_t*)w.ptr(); for(int i=0;i<len*2;i++) { ptr[i]=BSWAP32(ptr[i]); } } #endif } else { ERR_EXPLAIN("Vector2 size is NOT 8!"); ERR_FAIL_V(ERR_UNAVAILABLE); } w=DVector<Vector2>::Write(); r_v=array; } break; case VARIANT_VECTOR3_ARRAY: { uint32_t len = f->get_32(); DVector<Vector3> array; array.resize(len); DVector<Vector3>::Write w = array.write(); if (sizeof(Vector3)==12) { f->get_buffer((uint8_t*)w.ptr(),len*sizeof(real_t)*3); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr=(uint32_t*)w.ptr(); for(int i=0;i<len*3;i++) { ptr[i]=BSWAP32(ptr[i]); } } #endif } else { ERR_EXPLAIN("Vector3 size is NOT 12!"); ERR_FAIL_V(ERR_UNAVAILABLE); } w=DVector<Vector3>::Write(); r_v=array; } break; case VARIANT_COLOR_ARRAY: { uint32_t len = f->get_32(); DVector<Color> array; array.resize(len); DVector<Color>::Write w = array.write(); if (sizeof(Color)==16) { f->get_buffer((uint8_t*)w.ptr(),len*sizeof(real_t)*4); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr=(uint32_t*)w.ptr(); for(int i=0;i<len*4;i++) { ptr[i]=BSWAP32(ptr[i]); } } #endif } else { ERR_EXPLAIN("Color size is NOT 16!"); ERR_FAIL_V(ERR_UNAVAILABLE); } w=DVector<Color>::Write(); r_v=array; } break; default: { ERR_FAIL_V(ERR_FILE_CORRUPT); } break; } return OK; //never reach anyway }
RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) { if (r_error) *r_error = ERR_CANT_OPEN; String local_path; if (p_path.is_rel_path()) local_path = "res://" + p_path; else local_path = ProjectSettings::get_singleton()->localize_path(p_path); if (!p_no_cache) { { bool success = _add_to_loading_map(local_path); if (!success) { ERR_EXPLAIN("Resource: '" + local_path + "' is already being loaded. Cyclic reference?"); ERR_FAIL_V(RES()); } } //lock first if possible if (ResourceCache::lock) { ResourceCache::lock->read_lock(); } //get ptr Resource **rptr = ResourceCache::resources.getptr(local_path); if (rptr) { RES res(*rptr); //it is possible this resource was just freed in a thread. If so, this referencing will not work and resource is considered not cached if (res.is_valid()) { //referencing is fine if (r_error) *r_error = OK; if (ResourceCache::lock) { ResourceCache::lock->read_unlock(); } _remove_from_loading_map(local_path); return res; } } if (ResourceCache::lock) { ResourceCache::lock->read_unlock(); } } bool xl_remapped = false; String path = _path_remap(local_path, &xl_remapped); if (path == "") { if (!p_no_cache) { _remove_from_loading_map(local_path); } ERR_EXPLAIN("Remapping '" + local_path + "'failed."); ERR_FAIL_V(RES()); } print_verbose("Loading resource: " + path); RES res = _load(path, local_path, p_type_hint, p_no_cache, r_error); if (res.is_null()) { if (!p_no_cache) { _remove_from_loading_map(local_path); } return RES(); } if (!p_no_cache) res->set_path(local_path); if (xl_remapped) res->set_as_translation_remapped(true); #ifdef TOOLS_ENABLED res->set_edited(false); if (timestamp_on_load) { uint64_t mt = FileAccess::get_modified_time(path); //printf("mt %s: %lli\n",remapped_path.utf8().get_data(),mt); res->set_last_modified_time(mt); } #endif if (!p_no_cache) { _remove_from_loading_map(local_path); } if (_loaded_callback) { _loaded_callback(res, p_path); } return res; }
Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDParser::ClassNode *p_class) { p_script->native=Ref<GDNativeClass>(); p_script->base=Ref<GDScript>(); p_script->_base=NULL; p_script->members.clear(); p_script->constants.clear(); p_script->member_functions.clear(); p_script->member_indices.clear(); p_script->member_info.clear(); p_script->initializer=NULL; p_script->subclasses.clear(); p_script->_owner=p_owner; p_script->tool=p_class->tool; p_script->name=p_class->name; int index_from=0; if (p_class->extends_used) { //do inheritance String path = p_class->extends_file; Ref<GDScript> script; Ref<GDNativeClass> native; if (path!="") { //path (and optionally subclasses) if (path.is_rel_path()) { String base = p_script->get_path(); if (base=="" || base.is_rel_path()) { _set_error("Could not resolve relative path for parent class: "+path,p_class); return ERR_FILE_NOT_FOUND; } path=base.get_base_dir().plus_file(path); } script = ResourceLoader::load(path); if (script.is_null()) { _set_error("Could not load base class: "+path,p_class); return ERR_FILE_NOT_FOUND; } if (!script->valid) { _set_error("Script not fully loaded (cyclic preload?): "+path,p_class); return ERR_BUSY; } //print_line("EXTENDS PATH: "+path+" script is "+itos(script.is_valid())+" indices is "+itos(script->member_indices.size())+" valid? "+itos(script->valid)); if (p_class->extends_class.size()) { for(int i=0;i<p_class->extends_class.size();i++) { String sub = p_class->extends_class[i]; if (script->subclasses.has(sub)) { script=script->subclasses[sub]; } else { _set_error("Could not find subclass: "+sub,p_class); return ERR_FILE_NOT_FOUND; } } } } else { ERR_FAIL_COND_V(p_class->extends_class.size()==0,ERR_BUG); //look around for the subclasses String base=p_class->extends_class[0]; GDScript *p = p_owner; Ref<GDScript> base_class; while(p) { if (p->subclasses.has(base)) { base_class=p->subclasses[base]; break; } p=p->_owner; } if (base_class.is_valid()) { for(int i=1;i<p_class->extends_class.size();i++) { String subclass=p_class->extends_class[i]; if (base_class->subclasses.has(subclass)) { base_class=base_class->subclasses[subclass]; } else { _set_error("Could not find subclass: "+subclass,p_class); return ERR_FILE_NOT_FOUND; } } script=base_class; } else { if (p_class->extends_class.size()>1) { _set_error("Invalid inheritance (unknown class+subclasses)",p_class); return ERR_FILE_NOT_FOUND; } //if not found, try engine classes if (!GDScriptLanguage::get_singleton()->get_global_map().has(base)) { _set_error("Unknown class: '"+base+"'",p_class); return ERR_FILE_NOT_FOUND; } int base_idx = GDScriptLanguage::get_singleton()->get_global_map()[base]; native = GDScriptLanguage::get_singleton()->get_global_array()[base_idx]; if (!native.is_valid()) { _set_error("Global not a class: '"+base+"'",p_class); return ERR_FILE_NOT_FOUND; } } } if (script.is_valid()) { p_script->base=script; p_script->_base=p_script->base.ptr(); p_script->member_indices=script->member_indices; } else if (native.is_valid()) { p_script->native=native; } else { _set_error("Could not determine inheritance",p_class); return ERR_FILE_NOT_FOUND; } } //print_line("Script: "+p_script->get_path()+" indices: "+itos(p_script->member_indices.size())); for(int i=0;i<p_class->variables.size();i++) { StringName name = p_class->variables[i].identifier; if (p_script->member_indices.has(name)) { _set_error("Member '"+name+"' already exists (in current or parent class)",p_class); return ERR_ALREADY_EXISTS; } if (p_class->variables[i]._export.type!=Variant::NIL) { p_script->member_info[name]=p_class->variables[i]._export; #ifdef TOOLS_ENABLED if (p_class->variables[i].default_value.get_type()!=Variant::NIL) { p_script->member_default_values[name]=p_class->variables[i].default_value; } #endif } int new_idx = p_script->member_indices.size(); p_script->member_indices[name]=new_idx; p_script->members.insert(name); } for(int i=0;i<p_class->constant_expressions.size();i++) { StringName name = p_class->constant_expressions[i].identifier; ERR_CONTINUE( p_class->constant_expressions[i].expression->type!=GDParser::Node::TYPE_CONSTANT ); GDParser::ConstantNode *constant = static_cast<GDParser::ConstantNode*>(p_class->constant_expressions[i].expression); p_script->constants.insert(name,constant->value); //p_script->constants[constant->value].make_const(); } //parse sub-classes for(int i=0;i<p_class->subclasses.size();i++) { StringName name = p_class->subclasses[i]->name; Ref<GDScript> subclass = memnew( GDScript ); Error err = _parse_class(subclass.ptr(),p_script,p_class->subclasses[i]); if (err) return err; p_script->constants.insert(name,subclass); //once parsed, goes to the list of constants p_script->subclasses.insert(name,subclass); } //parse methods bool has_initializer=false; for(int i=0;i<p_class->functions.size();i++) { if (!has_initializer && p_class->functions[i]->name=="_init") has_initializer=true; Error err = _parse_function(p_script,p_class,p_class->functions[i]); if (err) return err; } //parse static methods for(int i=0;i<p_class->static_functions.size();i++) { Error err = _parse_function(p_script,p_class,p_class->static_functions[i]); if (err) return err; } if (!has_initializer) { //create a constructor Error err = _parse_function(p_script,p_class,NULL); if (err) return err; } return OK; }
Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { uint32_t type = f->get_32(); print_bl("find property of type: " + itos(type)); switch (type) { case VARIANT_NIL: { r_v = Variant(); } break; case VARIANT_BOOL: { r_v = bool(f->get_32()); } break; case VARIANT_INT: { r_v = int(f->get_32()); } break; case VARIANT_INT64: { r_v = int64_t(f->get_64()); } break; case VARIANT_REAL: { r_v = f->get_real(); } break; case VARIANT_DOUBLE: { r_v = f->get_double(); } break; case VARIANT_STRING: { r_v = get_unicode_string(); } break; case VARIANT_VECTOR2: { Vector2 v; v.x = f->get_real(); v.y = f->get_real(); r_v = v; } break; case VARIANT_RECT2: { Rect2 v; v.position.x = f->get_real(); v.position.y = f->get_real(); v.size.x = f->get_real(); v.size.y = f->get_real(); r_v = v; } break; case VARIANT_VECTOR3: { Vector3 v; v.x = f->get_real(); v.y = f->get_real(); v.z = f->get_real(); r_v = v; } break; case VARIANT_PLANE: { Plane v; 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; } break; case VARIANT_QUAT: { Quat v; v.x = f->get_real(); v.y = f->get_real(); v.z = f->get_real(); v.w = f->get_real(); r_v = v; } break; case VARIANT_AABB: { AABB v; v.position.x = f->get_real(); v.position.y = f->get_real(); v.position.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; } break; case VARIANT_MATRIX32: { Transform2D v; 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; } break; case VARIANT_MATRIX3: { Basis v; 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; } break; case VARIANT_TRANSFORM: { Transform v; 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; } break; case VARIANT_COLOR: { Color v; v.r = f->get_real(); v.g = f->get_real(); v.b = f->get_real(); v.a = f->get_real(); r_v = v; } break; case VARIANT_NODE_PATH: { Vector<StringName> names; Vector<StringName> subnames; bool absolute; int name_count = f->get_16(); uint32_t subname_count = f->get_16(); absolute = subname_count & 0x8000; subname_count &= 0x7FFF; if (ver_format < FORMAT_VERSION_NO_NODEPATH_PROPERTY) { subname_count += 1; // has a property field, so we should count it as well } for (int i = 0; i < name_count; i++) names.push_back(_get_string()); for (uint32_t i = 0; i < subname_count; i++) subnames.push_back(_get_string()); NodePath np = NodePath(names, subnames, absolute); r_v = np; } break; case VARIANT_RID: { r_v = f->get_32(); } break; case VARIANT_OBJECT: { uint32_t objtype = f->get_32(); switch (objtype) { case OBJECT_EMPTY: { //do none } break; case OBJECT_INTERNAL_RESOURCE: { uint32_t index = f->get_32(); String path = res_path + "::" + itos(index); RES res = ResourceLoader::load(path); if (res.is_null()) { WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data()); } r_v = res; } break; case OBJECT_EXTERNAL_RESOURCE: { //old file format, still around for compatibility String exttype = get_unicode_string(); String path = get_unicode_string(); if (path.find("://") == -1 && path.is_rel_path()) { // path is relative to file being loaded, so convert to a resource path path = ProjectSettings::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path)); } if (remaps.find(path)) { path = remaps[path]; } RES res = ResourceLoader::load(path, exttype); if (res.is_null()) { WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data()); } r_v = res; } break; case OBJECT_EXTERNAL_RESOURCE_INDEX: { //new file format, just refers to an index in the external list int erindex = f->get_32(); if (erindex < 0 || erindex >= external_resources.size()) { WARN_PRINT("Broken external resource! (index out of size)"); r_v = Variant(); } else { String exttype = external_resources[erindex].type; String path = external_resources[erindex].path; if (path.find("://") == -1 && path.is_rel_path()) { // path is relative to file being loaded, so convert to a resource path path = ProjectSettings::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path)); } RES res = ResourceLoader::load(path, exttype); if (res.is_null()) { WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data()); } r_v = res; } } break; default: { ERR_FAIL_V(ERR_FILE_CORRUPT); } break; } } break; case VARIANT_DICTIONARY: { uint32_t len = f->get_32(); Dictionary d; //last bit means shared len &= 0x7FFFFFFF; for (uint32_t i = 0; i < len; i++) { Variant key; Error err = parse_variant(key); ERR_FAIL_COND_V(err, ERR_FILE_CORRUPT); Variant value; err = parse_variant(value); ERR_FAIL_COND_V(err, ERR_FILE_CORRUPT); d[key] = value; } r_v = d; } break; case VARIANT_ARRAY: { uint32_t len = f->get_32(); Array a; //last bit means shared len &= 0x7FFFFFFF; a.resize(len); for (uint32_t i = 0; i < len; i++) { Variant val; Error err = parse_variant(val); ERR_FAIL_COND_V(err, ERR_FILE_CORRUPT); a[i] = val; } r_v = a; } break; case VARIANT_RAW_ARRAY: { uint32_t len = f->get_32(); PoolVector<uint8_t> array; array.resize(len); PoolVector<uint8_t>::Write w = array.write(); f->get_buffer(w.ptr(), len); _advance_padding(len); w = PoolVector<uint8_t>::Write(); r_v = array; } break; case VARIANT_INT_ARRAY: { uint32_t len = f->get_32(); PoolVector<int> array; array.resize(len); PoolVector<int>::Write w = array.write(); f->get_buffer((uint8_t *)w.ptr(), len * 4); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); for (int i = 0; i < len; i++) { ptr[i] = BSWAP32(ptr[i]); } } #endif w = PoolVector<int>::Write(); r_v = array; } break; case VARIANT_REAL_ARRAY: { uint32_t len = f->get_32(); PoolVector<real_t> array; array.resize(len); PoolVector<real_t>::Write w = array.write(); f->get_buffer((uint8_t *)w.ptr(), len * sizeof(real_t)); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); for (int i = 0; i < len; i++) { ptr[i] = BSWAP32(ptr[i]); } } #endif w = PoolVector<real_t>::Write(); r_v = array; } break; case VARIANT_STRING_ARRAY: { uint32_t len = f->get_32(); PoolVector<String> array; array.resize(len); PoolVector<String>::Write w = array.write(); for (uint32_t i = 0; i < len; i++) w[i] = get_unicode_string(); w = PoolVector<String>::Write(); r_v = array; } break; case VARIANT_VECTOR2_ARRAY: { uint32_t len = f->get_32(); PoolVector<Vector2> array; array.resize(len); PoolVector<Vector2>::Write w = array.write(); if (sizeof(Vector2) == 8) { f->get_buffer((uint8_t *)w.ptr(), len * sizeof(real_t) * 2); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); for (int i = 0; i < len * 2; i++) { ptr[i] = BSWAP32(ptr[i]); } } #endif } else { ERR_EXPLAIN("Vector2 size is NOT 8!"); ERR_FAIL_V(ERR_UNAVAILABLE); } w = PoolVector<Vector2>::Write(); r_v = array; } break; case VARIANT_VECTOR3_ARRAY: { uint32_t len = f->get_32(); PoolVector<Vector3> array; array.resize(len); PoolVector<Vector3>::Write w = array.write(); if (sizeof(Vector3) == 12) { f->get_buffer((uint8_t *)w.ptr(), len * sizeof(real_t) * 3); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); for (int i = 0; i < len * 3; i++) { ptr[i] = BSWAP32(ptr[i]); } } #endif } else { ERR_EXPLAIN("Vector3 size is NOT 12!"); ERR_FAIL_V(ERR_UNAVAILABLE); } w = PoolVector<Vector3>::Write(); r_v = array; } break; case VARIANT_COLOR_ARRAY: { uint32_t len = f->get_32(); PoolVector<Color> array; array.resize(len); PoolVector<Color>::Write w = array.write(); if (sizeof(Color) == 16) { f->get_buffer((uint8_t *)w.ptr(), len * sizeof(real_t) * 4); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); for (int i = 0; i < len * 4; i++) { ptr[i] = BSWAP32(ptr[i]); } } #endif } else { ERR_EXPLAIN("Color size is NOT 16!"); ERR_FAIL_V(ERR_UNAVAILABLE); } w = PoolVector<Color>::Write(); r_v = array; } break; #ifndef DISABLE_DEPRECATED case VARIANT_IMAGE: { uint32_t encoding = f->get_32(); if (encoding == IMAGE_ENCODING_EMPTY) { r_v = Ref<Image>(); break; } else if (encoding == IMAGE_ENCODING_RAW) { uint32_t width = f->get_32(); uint32_t height = f->get_32(); uint32_t mipmaps = f->get_32(); uint32_t format = f->get_32(); const uint32_t format_version_shift = 24; const uint32_t format_version_mask = format_version_shift - 1; uint32_t format_version = format >> format_version_shift; const uint32_t current_version = 0; if (format_version > current_version) { ERR_PRINT("Format version for encoded binary image is too new"); return ERR_PARSE_ERROR; } Image::Format fmt = Image::Format(format & format_version_mask); //if format changes, we can add a compatibility bit on top uint32_t datalen = f->get_32(); PoolVector<uint8_t> imgdata; imgdata.resize(datalen); PoolVector<uint8_t>::Write w = imgdata.write(); f->get_buffer(w.ptr(), datalen); _advance_padding(datalen); w = PoolVector<uint8_t>::Write(); Ref<Image> image; image.instance(); image->create(width, height, mipmaps, fmt, imgdata); r_v = image; } else { //compressed PoolVector<uint8_t> data; data.resize(f->get_32()); PoolVector<uint8_t>::Write w = data.write(); f->get_buffer(w.ptr(), data.size()); w = PoolVector<uint8_t>::Write(); Ref<Image> image; if (encoding == IMAGE_ENCODING_LOSSY && Image::lossy_unpacker) { image = Image::lossy_unpacker(data); } else if (encoding == IMAGE_ENCODING_LOSSLESS && Image::lossless_unpacker) { image = Image::lossless_unpacker(data); } _advance_padding(data.size()); r_v = image; } } break;