diff options
author | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
commit | 0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch) | |
tree | 276c4d099e178eb67fbd14f61d77b05e3808e9e3 /scene/io | |
parent | 0e49da1687bc8192ed210947da52c9e5c5f301bb (diff) |
GODOT IS OPEN SOURCE
Diffstat (limited to 'scene/io')
-rw-r--r-- | scene/io/SCsub | 7 | ||||
-rw-r--r-- | scene/io/resource_format_image.cpp | 199 | ||||
-rw-r--r-- | scene/io/resource_format_image.h | 51 | ||||
-rw-r--r-- | scene/io/resource_format_wav.cpp | 255 | ||||
-rw-r--r-- | scene/io/resource_format_wav.h | 43 | ||||
-rw-r--r-- | scene/io/scene_format_object.cpp | 851 | ||||
-rw-r--r-- | scene/io/scene_format_object.h | 128 | ||||
-rw-r--r-- | scene/io/scene_format_script.cpp | 65 | ||||
-rw-r--r-- | scene/io/scene_format_script.h | 45 | ||||
-rw-r--r-- | scene/io/scene_loader.cpp | 161 | ||||
-rw-r--r-- | scene/io/scene_loader.h | 90 | ||||
-rw-r--r-- | scene/io/scene_saver.cpp | 94 | ||||
-rw-r--r-- | scene/io/scene_saver.h | 80 |
13 files changed, 2069 insertions, 0 deletions
diff --git a/scene/io/SCsub b/scene/io/SCsub new file mode 100644 index 0000000000..055d2f2474 --- /dev/null +++ b/scene/io/SCsub @@ -0,0 +1,7 @@ +Import('env') + +env.add_source_files(env.scene_sources,"*.cpp") + +Export('env') + + diff --git a/scene/io/resource_format_image.cpp b/scene/io/resource_format_image.cpp new file mode 100644 index 0000000000..d71f544628 --- /dev/null +++ b/scene/io/resource_format_image.cpp @@ -0,0 +1,199 @@ +/*************************************************************************/ +/* resource_format_image.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "resource_format_image.h" +#include "scene/resources/texture.h" +#include "io/image_loader.h" +#include "globals.h" +#include "os/os.h" +RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_original_path) { + + + if (p_path.extension()=="cube") { + // open as cubemap txture + + CubeMap* ptr = memnew(CubeMap); + Ref<CubeMap> cubemap( ptr ); + + Error err; + FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); + if (err) { + + ERR_FAIL_COND_V( err, RES() ); + } + + String base_path=p_path.substr( 0, p_path.find_last("/")+1 ); + + for(int i=0;i<6;i++) { + + String file = f->get_line().strip_edges(); + Image image; + + Error err = ImageLoader::load_image(base_path+file,&image); + + + if (err) { + + memdelete(f); + ERR_FAIL_COND_V( err, RES() ); + } + + if (i==0) { + + //cubemap->create(image.get_width(),image.get_height(),image.get_format(),Texture::FLAGS_DEFAULT|Texture::FLAG_CUBEMAP); + } + + static const CubeMap::Side cube_side[6]= { + CubeMap::SIDE_LEFT, + CubeMap::SIDE_RIGHT, + CubeMap::SIDE_BOTTOM, + CubeMap::SIDE_TOP, + CubeMap::SIDE_FRONT, + CubeMap::SIDE_BACK + }; + + cubemap->set_side(cube_side[i],image); + } + + memdelete(f); + + cubemap->set_name(p_path.get_file()); + + return cubemap; + + } else { + // simple image + + ImageTexture* ptr = memnew(ImageTexture); + Ref<ImageTexture> texture( ptr ); + + uint64_t begtime; + double total; + + Image image; + + if (debug_load_times) + begtime=OS::get_singleton()->get_ticks_usec(); + + + Error err = ImageLoader::load_image(p_path,&image); + + if (!err && debug_load_times) { + double total=(double)(OS::get_singleton()->get_ticks_usec()-begtime)/1000000.0; + print_line("IMAGE: "+itos(image.get_width())+"x"+itos(image.get_height())); + print_line(" -load: "+rtos(total)); + } + + + ERR_EXPLAIN("Failed loading image: "+p_path); + ERR_FAIL_COND_V(err, RES()); + +#ifdef DEBUG_ENABLED +#ifdef TOOLS_ENABLED + + if (max_texture_size && (image.get_width() > max_texture_size || image.get_height() > max_texture_size)) { + + + if (bool(Globals::get_singleton()->get("debug/max_texture_size_alert"))) { + OS::get_singleton()->alert("Texture is too large: '"+p_path+"', at "+itos(image.get_width())+"x"+itos(image.get_height())+". Max allowed size is: "+itos(max_texture_size)+"x"+itos(max_texture_size)+".","BAD ARTIST, NO COOKIE!"); + } + + ERR_EXPLAIN("Texture is too large: '"+p_path+"', at "+itos(image.get_width())+"x"+itos(image.get_height())+". Max allowed size is: "+itos(max_texture_size)+"x"+itos(max_texture_size)+"."); + ERR_FAIL_V(RES()); + } +#endif +#endif + + + uint32_t flags=0; + if (bool(GLOBAL_DEF("texture_import/filter",true))) + flags|=Texture::FLAG_FILTER; + if (bool(GLOBAL_DEF("texture_import/gen_mipmaps",true))) + flags|=Texture::FLAG_MIPMAPS; + if (bool(GLOBAL_DEF("texture_import/repeat",true))) + flags|=Texture::FLAG_REPEAT; + + + + if (debug_load_times) + begtime=OS::get_singleton()->get_ticks_usec(); + + //print_line("img: "+p_path+" flags: "+itos(flags)); + texture->create_from_image( image,flags ); + texture->set_name(p_path.get_file()); + + + if (debug_load_times) { + total=(double)(OS::get_singleton()->get_ticks_usec()-begtime)/1000000.0; + print_line(" -make texture: "+rtos(total)); + } + + return RES( texture ); + } + + +} + +bool ResourceFormatLoaderImage::handles_type(const String& p_type) const { + + return ObjectTypeDB::is_type(p_type,"Texture") || ObjectTypeDB::is_type(p_type,"CubeMap"); +} + +void ResourceFormatLoaderImage::get_recognized_extensions(List<String> *p_extensions) const { + + ImageLoader::get_recognized_extensions(p_extensions); + p_extensions->push_back("cube"); +} + +String ResourceFormatLoaderImage::get_resource_type(const String &p_path) const { + + String ext=p_path.extension().to_lower(); + if (ext=="cube") + return "CubeMap"; + + List<String> extensions; + ImageLoader::get_recognized_extensions(&extensions); + + for(List<String>::Element *E=extensions.front();E;E=E->next()) { + if (E->get()==ext) + return "ImageTexture"; + } + return ""; +} + + +ResourceFormatLoaderImage::ResourceFormatLoaderImage() { + + max_texture_size = GLOBAL_DEF("debug/max_texture_size",0); + GLOBAL_DEF("debug/max_texture_size_alert",false); + debug_load_times=GLOBAL_DEF("debug/image_load_times",false); + GLOBAL_DEF("texture_import/filter",true); + GLOBAL_DEF("texture_import/gen_mipmaps",true); + GLOBAL_DEF("texture_import/repeat",true); + +} diff --git a/scene/io/resource_format_image.h b/scene/io/resource_format_image.h new file mode 100644 index 0000000000..d9fe45a244 --- /dev/null +++ b/scene/io/resource_format_image.h @@ -0,0 +1,51 @@ +/*************************************************************************/ +/* resource_format_image.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef RESOURCE_FORMAT_IMAGE_H +#define RESOURCE_FORMAT_IMAGE_H + +#include "io/resource_loader.h" +#include "io/resource_saver.h" +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ +class ResourceFormatLoaderImage : public ResourceFormatLoader { + + bool debug_load_times; + int max_texture_size; +public: + + virtual RES load(const String &p_path,const String& p_original_path=""); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String& p_type) const; + virtual String get_resource_type(const String &p_path) const; + + ResourceFormatLoaderImage(); +}; + +#endif diff --git a/scene/io/resource_format_wav.cpp b/scene/io/resource_format_wav.cpp new file mode 100644 index 0000000000..74eeb819b8 --- /dev/null +++ b/scene/io/resource_format_wav.cpp @@ -0,0 +1,255 @@ +/*************************************************************************/ +/* resource_format_wav.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "resource_format_wav.h" +#include "os/file_access.h" +#include "scene/resources/sample.h" + + +RES ResourceFormatLoaderWAV::load(const String &p_path,const String& p_original_path) { + + Error err; + FileAccess *file=FileAccess::open(p_path, FileAccess::READ,&err); + + ERR_FAIL_COND_V( err!=OK, RES() ); + + /* CHECK RIFF */ + char riff[5]; + riff[4]=0; + file->get_buffer((uint8_t*)&riff,4); //RIFF + + if (riff[0]!='R' || riff[1]!='I' || riff[2]!='F' || riff[3]!='F') { + + file->close(); + memdelete(file); + ERR_FAIL_V( RES() ); + } + + + /* GET FILESIZE */ + uint32_t filesize=file->get_32(); + + /* CHECK WAVE */ + + char wave[4]; + + file->get_buffer((uint8_t*)&wave,4); //RIFF + + if (wave[0]!='W' || wave[1]!='A' || wave[2]!='V' || wave[3]!='E') { + + + file->close(); + memdelete(file); + ERR_EXPLAIN("Not a WAV file (no WAVE RIFF Header)") + ERR_FAIL_V( RES() ); + } + + bool format_found=false; + bool data_found=false; + int format_bits=0; + int format_channels=0; + int format_freq=0; + Sample::LoopFormat loop=Sample::LOOP_NONE; + int loop_begin=0; + int loop_end=0; + + + Ref<Sample> sample( memnew( Sample ) ); + + + while (!file->eof_reached()) { + + + /* chunk */ + char chunkID[4]; + file->get_buffer((uint8_t*)&chunkID,4); //RIFF + + /* chunk size */ + uint32_t chunksize=file->get_32(); + uint32_t file_pos=file->get_pos(); //save file pos, so we can skip to next chunk safely + + if (file->eof_reached()) { + + //ERR_PRINT("EOF REACH"); + break; + } + + if (chunkID[0]=='f' && chunkID[1]=='m' && chunkID[2]=='t' && chunkID[3]==' ' && !format_found) { + /* IS FORMAT CHUNK */ + + uint16_t compression_code=file->get_16(); + + + if (compression_code!=1) { + ERR_PRINT("Format not supported for WAVE file (not PCM). Save WAVE files as uncompressed PCM instead."); + break; + } + + format_channels=file->get_16(); + if (format_channels!=1 && format_channels !=2) { + + ERR_PRINT("Format not supported for WAVE file (not stereo or mono)"); + break; + + } + + format_freq=file->get_32(); //sampling rate + + file->get_32(); // average bits/second (unused) + file->get_16(); // block align (unused) + format_bits=file->get_16(); // bits per sample + + if (format_bits%8) { + + ERR_PRINT("Strange number of bits in sample (not 8,16,24,32)"); + break; + } + + /* Dont need anything else, continue */ + format_found=true; + } + + + if (chunkID[0]=='d' && chunkID[1]=='a' && chunkID[2]=='t' && chunkID[3]=='a' && !data_found) { + /* IS FORMAT CHUNK */ + data_found=true; + + if (!format_found) { + ERR_PRINT("'data' chunk before 'format' chunk found."); + break; + + } + + int frames=chunksize; + frames/=format_channels; + frames/=(format_bits>>3); + + + sample->create( + (format_bits==8) ? Sample::FORMAT_PCM8 : Sample::FORMAT_PCM16, + (format_channels==2)?true:false, + frames ); + sample->set_mix_rate( format_freq ); + + DVector<uint8_t> data; + data.resize(chunksize); + DVector<uint8_t>::Write dataw = data.write(); + void * data_ptr = dataw.ptr(); + + for (int i=0;i<frames;i++) { + + + for (int c=0;c<format_channels;c++) { + + + if (format_bits==8) { + // 8 bit samples are UNSIGNED + + uint8_t s = file->get_8(); + s-=128; + int8_t *sp=(int8_t*)&s; + + int8_t *data_ptr8=&((int8_t*)data_ptr)[i*format_channels+c]; + + *data_ptr8=*sp; + + } else { + //16+ bits samples are SIGNED + // if sample is > 16 bits, just read extra bytes + + uint32_t data=0; + for (int b=0;b<(format_bits>>3);b++) { + + data|=((uint32_t)file->get_8())<<(b*8); + } + data<<=(32-format_bits); + + + int32_t s=data; + + int16_t *data_ptr16=&((int16_t*)data_ptr)[i*format_channels+c]; + + *data_ptr16=s>>16; + } + } + + } + + dataw=DVector<uint8_t>::Write(); + + sample->set_data(data); + + + if (file->eof_reached()) { + file->close(); + memdelete(file); + ERR_EXPLAIN("Premature end of file."); + ERR_FAIL_V(RES()); + } + } + + if (chunkID[0]=='s' && chunkID[1]=='m' && chunkID[2]=='p' && chunkID[3]=='l') { + //loop point info! + + for(int i=0;i<10;i++) + file->get_32(); // i wish to know why should i do this... no doc! + + loop=file->get_32()?Sample::LOOP_PING_PONG:Sample::LOOP_FORWARD; + loop_begin=file->get_32(); + loop_end=file->get_32(); + + } + file->seek( file_pos+chunksize ); + } + + sample->set_loop_format(loop); + sample->set_loop_begin(loop_begin); + sample->set_loop_end(loop_end); + + file->close(); + memdelete(file); + + return sample; + +} +void ResourceFormatLoaderWAV::get_recognized_extensions(List<String> *p_extensions) const { + + p_extensions->push_back("wav"); +} +bool ResourceFormatLoaderWAV::handles_type(const String& p_type) const { + + return (p_type=="Sample"); +} + +String ResourceFormatLoaderWAV::get_resource_type(const String &p_path) const { + + if (p_path.extension().to_lower()=="wav") + return "Sample"; + return ""; +} + diff --git a/scene/io/resource_format_wav.h b/scene/io/resource_format_wav.h new file mode 100644 index 0000000000..1011521079 --- /dev/null +++ b/scene/io/resource_format_wav.h @@ -0,0 +1,43 @@ +/*************************************************************************/ +/* resource_format_wav.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef RESOURCE_FORMAT_WAV_H +#define RESOURCE_FORMAT_WAV_H + +#include "io/resource_loader.h" + +class ResourceFormatLoaderWAV : public ResourceFormatLoader { +public: + virtual RES load(const String &p_path,const String& p_original_path=""); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String& p_type) const; + virtual String get_resource_type(const String &p_path) const; + +}; + +#endif // RESOURCE_FORMAT_WAV_H diff --git a/scene/io/scene_format_object.cpp b/scene/io/scene_format_object.cpp new file mode 100644 index 0000000000..6ffae30282 --- /dev/null +++ b/scene/io/scene_format_object.cpp @@ -0,0 +1,851 @@ +/*************************************************************************/ +/* scene_format_object.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "scene_format_object.h" +#include "print_string.h" +#include "globals.h" +#include "scene/resources/packed_scene.h" +#include "io/resource_loader.h" + +#ifdef OLD_SCENE_FORMAT_ENABLED + +void SceneFormatSaverObject::save_node(const Node* p_root,const Node* p_node,const Node* p_owner,ObjectFormatSaver *p_saver,String p_base_path,uint32_t p_flags,Map<const Node*,uint32_t>& owner_id) const { + + if (p_node!=p_root && p_node->get_owner()==NULL) + return; + + + if (p_flags&SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES || p_node->get_owner() == p_owner || p_node == p_owner ) { + + Dictionary d; + if (p_root!=p_node) { + d["path"]=p_root->get_path_to(p_node->get_parent()); + } + + d["name"]=p_node->get_name(); + + /* Connections */ + + List<MethodInfo> signal_list; + + p_node->get_signal_list(&signal_list); + + int conn_count=0; + + Set<Node::Connection> exclude_connections; + + if (!(p_flags&SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES)) { + + Vector<Node::Connection> ex = p_node->get_instance_connections(); + for(int i=0;i<ex.size();i++) { + exclude_connections.insert(ex[i]); + } + } + + for (List<MethodInfo>::Element *S=signal_list.front();S;S=S->next()) { + + List<Node::Connection> connections; + p_node->get_signal_connection_list(S->get().name,&connections); + for(List<Node::Connection>::Element *E=connections.front();E;E=E->next()) { + + Node::Connection &c=E->get(); + if (!(c.flags&Object::CONNECT_PERSIST)) + continue; + if (exclude_connections.has(c)) + continue; + + Node *target = c.target->cast_to<Node>(); + if (!target) + continue; //connected to something not a node, ignoring + + Dictionary cd; + cd["signal"]=c.signal; + cd["target"]=p_node->get_path_to(target); + cd["method"]=c.method; + cd["realtime"]=!(c.flags&Object::CONNECT_DEFERRED); + if (c.binds.size()) + cd["binds"]=c.binds; + d["connection/"+itos(conn_count+1)]=cd; + + conn_count++; + } + } + + d["connection_count"]=conn_count; + if (owner_id.has(p_node->get_owner())) { + + d["owner"]=owner_id[p_node->get_owner()]; + } + + /* Groups */ + + DVector<String> group_array; + List<Node::GroupInfo> groups; + p_node->get_groups(&groups); + Set<StringName> exclude_groups; + + if (!(p_flags&SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES)) { + //generate groups to exclude (came from instance) + Vector<StringName> eg; + eg=p_node->get_instance_groups(); + for(int i=0;i<eg.size();i++) + exclude_groups.insert(eg[i]); + } + + for(List<Node::GroupInfo>::Element*E=groups.front();E;E=E->next()) { + + if (E->get().persistent && !exclude_groups.has(E->get().name)) + group_array.push_back(E->get().name); + } + + if (group_array.size()) + d["groups"]=group_array; + + /* Save */ + + if (p_owner!=p_node && p_node->get_filename()!="") { + + String instance_path; + if (p_flags&SceneSaver::FLAG_RELATIVE_PATHS) + instance_path=p_base_path.path_to_file(Globals::get_singleton()->localize_path(p_node->get_filename())); + else + instance_path=p_node->get_filename(); + d["instance"]=instance_path; + + if (p_flags&SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES) { + + int id = owner_id.size(); + d["owner_id"]=id; + owner_id[p_node]=id; + + p_saver->save(p_node,d); + + //owner change! + for (int i=0;i<p_node->get_child_count();i++) { + + save_node(p_root,p_node->get_child(i),p_node,p_saver,p_base_path,p_flags,owner_id); + } + return; + + } else { + DVector<String> prop_names; + Array prop_values; + + List<PropertyInfo> properties; + p_node->get_property_list(&properties); + + //instance state makes sure that only changes to instance are saved + Dictionary instance_state=p_node->get_instance_state(); + + for(List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) { + + if (!(E->get().usage&PROPERTY_USAGE_STORAGE)) + continue; + + String name=E->get().name; + Variant value=p_node->get(E->get().name); + + if (!instance_state.has(name)) + continue; // did not change since it was loaded, not save + if (value==instance_state[name]) + continue; + prop_names.push_back( name ); + prop_values.push_back( value ); + + } + + d["override_names"]=prop_names; + d["override_values"]=prop_values; + + p_saver->save(NULL,d); + } + } else { + + p_saver->save(p_node,d); + } + } + + for (int i=0;i<p_node->get_child_count();i++) { + + save_node(p_root,p_node->get_child(i),p_owner,p_saver,p_base_path,p_flags,owner_id); + } +} + + +Error SceneFormatSaverObject::save(const String &p_path,const Node* p_scene,uint32_t p_flags,const Ref<OptimizedSaver> &p_optimizer) { + + String extension=p_path.extension(); + if (extension=="scn") + extension="bin"; + if (extension=="xscn") + extension="xml"; + + String local_path=Globals::get_singleton()->localize_path(p_path); + uint32_t saver_flags=0; + if (p_flags&SceneSaver::FLAG_RELATIVE_PATHS) + saver_flags|=ObjectSaver::FLAG_RELATIVE_PATHS; + if (p_flags&SceneSaver::FLAG_BUNDLE_RESOURCES) + saver_flags|=ObjectSaver::FLAG_BUNDLE_RESOURCES; + if (p_flags&SceneSaver::FLAG_OMIT_EDITOR_PROPERTIES) + saver_flags|=ObjectSaver::FLAG_OMIT_EDITOR_PROPERTIES; + if (p_flags&SceneSaver::FLAG_SAVE_BIG_ENDIAN) + saver_flags|=ObjectSaver::FLAG_SAVE_BIG_ENDIAN; + + ObjectFormatSaver *saver = ObjectSaver::instance_format_saver(local_path,"SCENE",extension,saver_flags,p_optimizer); + + ERR_FAIL_COND_V(!saver,ERR_FILE_UNRECOGNIZED); + + /* SAVE SCENE */ + + Map<const Node*,uint32_t> node_id_map; + save_node(p_scene,p_scene,p_scene,saver,local_path,p_flags,node_id_map); + + memdelete(saver); + + return OK; +} + +void SceneFormatSaverObject::get_recognized_extensions(List<String> *p_extensions) const { + + p_extensions->push_back("xml"); + p_extensions->push_back("scn"); + p_extensions->push_back("xscn"); + +// ObjectSaver::get_recognized_extensions(p_extensions); +} + + +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// + +void SceneFormatLoaderObject::_apply_meta(Node *node, const Variant&meta, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,Map<uint32_t,Node*>& owner_map) { + + r_err = OK; + + + Dictionary d=meta; + + if (!d.has("name")) { + + r_err=ERR_WTF; + memdelete(node); + ERR_FAIL_COND(!d.has("name")); + } + + + node->set_name(d["name"]); + int connection_count=d.has("connection_count")?d["connection_count"].operator int():0; + + + for (int i=0;i<connection_count;i++) { + + Dictionary cd=d["connection/"+itos(i+1)]; + + ERR_CONTINUE(!cd.has("target")); + ERR_CONTINUE(!cd.has("method")); + ERR_CONTINUE(!cd.has("realtime")); + ERR_CONTINUE(!cd.has("signal")); + + ConnectionItem ci; + + ci.node=node; + ci.target=cd["target"]; + ci.method=cd["method"]; + ci.signal=cd["signal"]; + ci.realtime=cd["realtime"]; + if (cd.has("binds")) + ci.binds=cd["binds"]; + + connections.push_back(ci); + + } + + DVector<String> groups=d.has("groups")?d["groups"].operator DVector<String>():DVector<String>(); + for (int i=0;i<groups.size();i++) { + + node->add_to_group(groups[i],true); + } + +} + + + +Ref<SceneInteractiveLoader> SceneFormatLoaderObject::load_interactive(const String &p_path,bool p_save_root_state) { + + SceneInteractiveLoaderObject *sil = memnew( SceneInteractiveLoaderObject(p_path,p_save_root_state) ); + + if (sil->error!=OK) { + + memdelete( sil ); + return Ref<SceneInteractiveLoader>(); + } + + return Ref<SceneInteractiveLoader>( sil ); + +} + + +Node* SceneFormatLoaderObject::load_node(Object *obj, const Variant& meta, Node *p_root, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,bool p_save_instance_state,Map<uint32_t,Node*>& owner_map) { + + r_err = OK; + + Node *node=obj->cast_to<Node>(); + + _apply_meta(node,meta,p_loader,connections,r_err,owner_map); + if (r_err!=OK) + return NULL; + + Dictionary d=meta; + + if (p_root) { + NodePath path=d.has("path")?d["path"].operator NodePath():NodePath("."); + + Node *parent=p_root->get_node(path); + if (!parent) { + memdelete(node); + r_err=ERR_FILE_CORRUPT; + ERR_FAIL_COND_V(!parent,NULL); + } + + parent->add_child(node); + + if (d.has("owner_id")) { + //is owner + owner_map[d["owner_id"]]=node; + if (d.has("instance")) + node->set_filename(d["instance"]); + + } + + if (d.has("owner")) { + + uint32_t owner = d["owner"]; + ERR_FAIL_COND_V(!owner_map.has(owner),NULL); + node->set_owner(owner_map[owner]); + } else { + + node->set_owner(p_root); + } + } + + return node; +} + +void SceneFormatLoaderObject::_apply_connections(List<ConnectionItem>& connections) { + + int idx=0; + for (List<ConnectionItem>::Element *E=connections.front();E;E=E->next()) { + + ConnectionItem &ci=E->get(); + Node *target = ci.node->get_node(ci.target); + ERR_CONTINUE(!target); + ci.node->connect(ci.signal,target,ci.method,ci.binds,(ci.realtime?0:Object::CONNECT_DEFERRED)|Object::CONNECT_PERSIST); + idx++; + } + +} + +Node* SceneFormatLoaderObject::load(const String &p_path,bool p_save_instance_state) { + + List<ConnectionItem> connections; + + String extension=p_path.extension(); + if (extension=="scn") + extension="bin"; + if (extension=="xscn") + extension="xml"; + + String local_path = Globals::get_singleton()->localize_path(p_path); + + ObjectFormatLoader *loader = ObjectLoader::instance_format_loader(local_path,"SCENE",extension); + + ERR_EXPLAIN("Couldn't load scene: "+p_path); + ERR_FAIL_COND_V(!loader,NULL); + + Node *root=NULL; + Map<uint32_t,Node*> owner_map; + + while(true) { + + Object *obj=NULL; + Variant metav; + Error r_err=loader->load(&obj,metav); + + if (r_err == ERR_SKIP) { + continue; + }; + + if (r_err==ERR_FILE_EOF) { + memdelete(loader); + ERR_FAIL_COND_V(!root,NULL); + _apply_connections(connections); + return root; + } + + if (r_err || (!obj && metav.get_type()==Variant::NIL)) { + memdelete(loader); + ERR_EXPLAIN("Object Loader Failed for Scene: "+p_path) ; + ERR_FAIL_COND_V( r_err, NULL); + ERR_EXPLAIN("Object Loader Failed for Scene: "+p_path) ; + ERR_FAIL_COND_V( !obj && metav.get_type()==Variant::NIL,NULL); + } + + if (obj) { + if (obj->cast_to<Node>()) { + + Error err; + Node* node = load_node(obj, metav, root, loader,connections,err,p_save_instance_state,owner_map); + if (err) + memdelete(loader); + + ERR_FAIL_COND_V( err, NULL ); + if (!root) + root=node; + } else { + + memdelete(loader); + ERR_FAIL_V( NULL ); + + } + } else { + + // check for instance + Dictionary meta=metav; + if (meta.has("instance")) { + if (!root) { + + memdelete(loader); + ERR_FAIL_COND_V(!root,NULL); + } + + String path = meta["instance"]; + + 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( + local_path.get_base_dir()+"/"+path); + } + + + Node *scene = SceneLoader::load(path); + + if (!scene) { + + Ref<PackedScene> sd = ResourceLoader::load(path); + if (sd.is_valid()) { + + scene=sd->instance(); + } + } + + + if (!scene) { + + memdelete(loader); + ERR_FAIL_COND_V(!scene,NULL); + } + + if (p_save_instance_state) + scene->generate_instance_state(); + + + Error err; + _apply_meta(scene,metav,loader,connections,err,owner_map); + if (err!=OK) { + memdelete(loader); + ERR_FAIL_COND_V(err!=OK,NULL); + } + + Node *parent=root; + + if (meta.has("path")) + parent=root->get_node(meta["path"]); + + + if (!parent) { + + memdelete(loader); + ERR_FAIL_COND_V(!parent,NULL); + } + + + if (meta.has("override_names") && meta.has("override_values")) { + + DVector<String> override_names=meta["override_names"]; + Array override_values=meta["override_values"]; + + int len = override_names.size(); + if ( len > 0 && len == override_values.size() ) { + + DVector<String>::Read names = override_names.read(); + + for(int i=0;i<len;i++) { + + scene->set(names[i],override_values[i]); + } + + } + + } + + scene->set_filename(path); + + parent->add_child(scene); + scene->set_owner(root); + } + } + } + + return NULL; +} + +void SceneFormatLoaderObject::get_recognized_extensions(List<String> *p_extensions) const { + + p_extensions->push_back("xml"); + p_extensions->push_back("scn"); + p_extensions->push_back("xscn"); + +// ObjectLoader::get_recognized_extensions(p_extensions); + +} + + + +/////////////////////////////////////////////////// + + +void SceneInteractiveLoaderObject::_apply_meta(Node *node, const Variant&meta, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,Map<uint32_t,Node*>& owner_map) { + + r_err = OK; + + + Dictionary d=meta; + + if (!d.has("name")) { + + r_err=ERR_WTF; + memdelete(node); + ERR_FAIL_COND(!d.has("name")); + } + + + node->set_name(d["name"]); + int connection_count=d.has("connection_count")?d["connection_count"].operator int():0; + + + for (int i=0;i<connection_count;i++) { + + Dictionary cd=d["connection/"+itos(i+1)]; + + ERR_CONTINUE(!cd.has("target")); + ERR_CONTINUE(!cd.has("method")); + ERR_CONTINUE(!cd.has("realtime")); + ERR_CONTINUE(!cd.has("signal")); + + ConnectionItem ci; + + ci.node=node; + ci.target=cd["target"]; + ci.method=cd["method"]; + ci.signal=cd["signal"]; + ci.realtime=cd["realtime"]; + if (cd.has("binds")) + ci.binds=cd["binds"]; + + connections.push_back(ci); + + } + + DVector<String> groups=d.has("groups")?d["groups"].operator DVector<String>():DVector<String>(); + for (int i=0;i<groups.size();i++) { + + node->add_to_group(groups[i],true); + } + +} + + + +Node* SceneInteractiveLoaderObject::load_node(Object *obj, const Variant& meta, Node *p_root, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,bool p_save_instance_state,Map<uint32_t,Node*>& owner_map) { + + r_err = OK; + + Node *node=obj->cast_to<Node>(); + + _apply_meta(node,meta,p_loader,connections,r_err,owner_map); + if (r_err!=OK) + return NULL; + + Dictionary d=meta; + + if (p_root) { + NodePath path=d.has("path")?d["path"].operator NodePath():NodePath("."); + + Node *parent=p_root->get_node(path); + if (!parent) { + memdelete(node); + r_err=ERR_FILE_CORRUPT; + ERR_FAIL_COND_V(!parent,NULL); + } + + parent->add_child(node); + + if (d.has("owner_id")) { + //is owner + owner_map[d["owner_id"]]=node; + if (d.has("instance")) + node->set_filename(d["instance"]); + + } + + if (d.has("owner")) { + + uint32_t owner = d["owner"]; + ERR_FAIL_COND_V(!owner_map.has(owner),NULL); + node->set_owner(owner_map[owner]); + } else { + + node->set_owner(p_root); + } + } + + return node; +} + +void SceneInteractiveLoaderObject::_apply_connections(List<ConnectionItem>& connections) { + + int idx=0; + for (List<ConnectionItem>::Element *E=connections.front();E;E=E->next()) { + + ConnectionItem &ci=E->get(); + Node *target = ci.node->get_node(ci.target); + ERR_CONTINUE(!target); + ci.node->connect(ci.signal,target,ci.method,ci.binds,(ci.realtime?0:Object::CONNECT_DEFERRED)|Object::CONNECT_PERSIST); + idx++; + } + +} + +SceneInteractiveLoaderObject::SceneInteractiveLoaderObject(const String &p_path,bool p_save_root_state) { + + error=OK; + path=p_path; + save_instance_state=p_save_root_state; + node_path=p_path; + root=NULL; + stage_max=1; + stage=0; + + + String extension=p_path.extension(); + if (extension=="scn") + extension="bin"; + if (extension=="xscn") + extension="xml"; + + local_path = Globals::get_singleton()->localize_path(p_path); + + loader = ObjectLoader::instance_format_loader(local_path,"SCENE",extension); + + if (!loader) { + + error=ERR_CANT_OPEN; + } + ERR_EXPLAIN("Couldn't load scene: "+p_path); + ERR_FAIL_COND(!loader); + +} + + + +void SceneInteractiveLoaderObject::set_local_path(const String& p_local_path) { + + node_path=p_local_path; +} + +Node *SceneInteractiveLoaderObject::get_scene() { + + if (error==ERR_FILE_EOF) + return root; + return NULL; +} +Error SceneInteractiveLoaderObject::poll() { + + if (error!=OK) + return error; + + Object *obj=NULL; + Variant metav; + Error r_err=loader->load(&obj,metav); + + + if (r_err == ERR_SKIP) { + stage++; + return OK; + }; + + if (r_err==ERR_FILE_EOF) { + memdelete(loader); + error=ERR_FILE_CORRUPT; + ERR_FAIL_COND_V(!root,ERR_FILE_CORRUPT); + _apply_connections(connections); + error=ERR_FILE_EOF; + if (root) + root->set_filename(node_path); + return error; + } + + if (r_err || (!obj && metav.get_type()==Variant::NIL)) { + memdelete(loader); + error=ERR_FILE_CORRUPT; + ERR_EXPLAIN("Object Loader Failed for Scene: "+path); + ERR_FAIL_COND_V( r_err, ERR_FILE_CORRUPT); + ERR_EXPLAIN("Object Loader Failed for Scene: "+path); + ERR_FAIL_COND_V( !obj && metav.get_type()==Variant::NIL,ERR_FILE_CORRUPT); + } + + if (obj) { + if (obj->cast_to<Node>()) { + + Error err; + Node* node = load_node(obj, metav, root, loader,connections,err,save_instance_state,owner_map); + if (err) { + error=ERR_FILE_CORRUPT; + memdelete(loader); + } + + ERR_FAIL_COND_V( err, ERR_FILE_CORRUPT ); + if (!root) + root=node; + } else { + + error=ERR_FILE_CORRUPT; + memdelete(loader); + ERR_EXPLAIN("Loaded something not a node.. (?)"); + ERR_FAIL_V( ERR_FILE_CORRUPT ); + + } + } else { + + // check for instance + Dictionary meta=metav; + if (meta.has("instance")) { + + if (!root) { + + error=ERR_FILE_CORRUPT; + memdelete(loader); + ERR_FAIL_COND_V(!root,ERR_FILE_CORRUPT); + } + + String path = meta["instance"]; + + 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( + local_path.get_base_dir()+"/"+path); + } + + Node *scene = SceneLoader::load(path); + + if (!scene) { + + error=ERR_FILE_CORRUPT; + memdelete(loader); + ERR_FAIL_COND_V(!scene,ERR_FILE_CORRUPT); + } + + if (save_instance_state) + scene->generate_instance_state(); + + + Error err; + _apply_meta(scene,metav,loader,connections,err,owner_map); + if (err!=OK) { + error=ERR_FILE_CORRUPT; + memdelete(loader); + ERR_FAIL_COND_V(err!=OK,ERR_FILE_CORRUPT); + } + + Node *parent=root; + + if (meta.has("path")) + parent=root->get_node(meta["path"]); + + + if (!parent) { + + error=ERR_FILE_CORRUPT; + memdelete(loader); + ERR_FAIL_COND_V(!parent,ERR_FILE_CORRUPT); + } + + + if (meta.has("override_names") && meta.has("override_values")) { + + DVector<String> override_names=meta["override_names"]; + Array override_values=meta["override_values"]; + + int len = override_names.size(); + if ( len > 0 && len == override_values.size() ) { + + DVector<String>::Read names = override_names.read(); + + for(int i=0;i<len;i++) { + + scene->set(names[i],override_values[i]); + } + + } + + } + + scene->set_filename(path); + + parent->add_child(scene); + scene->set_owner(root); + } + } + + stage++; + error=OK; + return error; + +} +int SceneInteractiveLoaderObject::get_stage() const { + + return stage; +} +int SceneInteractiveLoaderObject::get_stage_count() const { + + return stage_max; +} + + +#endif diff --git a/scene/io/scene_format_object.h b/scene/io/scene_format_object.h new file mode 100644 index 0000000000..3f0bbd4627 --- /dev/null +++ b/scene/io/scene_format_object.h @@ -0,0 +1,128 @@ +/*************************************************************************/ +/* scene_format_object.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef SCENE_FORMAT_OBJECT_H +#define SCENE_FORMAT_OBJECT_H + + +#include "scene/main/node.h" +#include "scene/io/scene_saver.h" +#include "scene/io/scene_loader.h" +#include "io/object_saver.h" +#include "io/object_loader.h" +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ + + +#ifdef OLD_SCENE_FORMAT_ENABLED + +class SceneFormatSaverObject : public SceneFormatSaver { + + void save_node(const Node* p_root,const Node* p_node,const Node* p_owner,ObjectFormatSaver *p_saver,String p_base_path,uint32_t p_flags,Map<const Node*,uint32_t>& owner_id) const; + +public: + + virtual Error save(const String &p_path,const Node* p_scenezz,uint32_t p_flags=0,const Ref<OptimizedSaver> &p_optimizer=Ref<OptimizedSaver>()); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual ~SceneFormatSaverObject() {} +}; + + + +class SceneFormatLoaderObject : public SceneFormatLoader { + + + struct ConnectionItem { + Node *node; + NodePath target; + StringName method; + StringName signal; + Vector<Variant> binds; + bool realtime; + }; + + Node* load_node(Object *obj, const Variant& meta, Node *p_root, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,bool p_root_scene_hint,Map<uint32_t,Node*>& owner_map); + void _apply_connections(List<ConnectionItem>& connections); + void _apply_meta(Node *node, const Variant& meta, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,Map<uint32_t,Node*>& owner_map); + +public: + + virtual Ref<SceneInteractiveLoader> load_interactive(const String &p_path,bool p_root_scene_hint=false); + virtual Node* load(const String &p_path,bool p_save_root_state=false); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + +}; + + +class SceneInteractiveLoaderObject : public SceneInteractiveLoader { + + OBJ_TYPE(SceneInteractiveLoaderObject,SceneInteractiveLoader); + + struct ConnectionItem { + Node *node; + NodePath target; + StringName method; + StringName signal; + Vector<Variant> binds; + bool realtime; + }; + ObjectFormatLoader *loader; + String path; + String node_path; + String local_path; + Error error; + bool save_instance_state; + List<ConnectionItem> connections; + Map<uint32_t,Node*> owner_map; + Node *root; + int stage_max; + int stage; + + + Node* load_node(Object *obj, const Variant& meta, Node *p_root, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,bool p_root_scene_hint,Map<uint32_t,Node*>& owner_map); + void _apply_connections(List<ConnectionItem>& connections); + void _apply_meta(Node *node, const Variant& meta, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,Map<uint32_t,Node*>& owner_map); + +friend class SceneFormatLoaderObject; +public: + + virtual void set_local_path(const String& p_local_path); + virtual Node *get_scene(); + virtual Error poll(); + virtual int get_stage() const; + virtual int get_stage_count() const; + + + SceneInteractiveLoaderObject(const String &p_path,bool p_save_root_state=false); +}; + + + +#endif +#endif diff --git a/scene/io/scene_format_script.cpp b/scene/io/scene_format_script.cpp new file mode 100644 index 0000000000..a6f1596d2b --- /dev/null +++ b/scene/io/scene_format_script.cpp @@ -0,0 +1,65 @@ +/*************************************************************************/ +/* scene_format_script.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "scene_format_script.h" +#if 0 +Node* SceneFormatLoaderScript::load(const String &p_path,bool p_save_instance_state) { + + Ref<Script> script = ResourceLoader::load(p_path); + ERR_EXPLAIN("Can't load script-based scene: "+p_path); + ERR_FAIL_COND_V(script.is_null(),NULL); + ERR_EXPLAIN("Script does not instance in a node: "+p_path); + ERR_FAIL_COND_V(script->get_node_type()=="",NULL); + String node_type=script->get_node_type(); + Object *obj = ObjectTypeDB::instance(node_type); + ERR_EXPLAIN("Unknown node type for instancing '"+node_type+"' in script: "+p_path); + ERR_FAIL_COND_V(!obj,NULL); + Node *node = obj->cast_to<Node>(); + if (!node) + memdelete(obj); + ERR_EXPLAIN("Node type '"+node_type+"' not of type 'Node'' in script: "+p_path); + ERR_FAIL_COND_V(!node,NULL); + + node->set_script(script.get_ref_ptr()); + + return node; +} + +void SceneFormatLoaderScript::get_recognized_extensions(List<String> *p_extensions) const { + + for (int i=0;i<ScriptServer::get_language_count();i++) { + + ScriptServer::get_language(i)->get_recognized_extensions(p_extensions); + } +} + + +SceneFormatLoaderScript::SceneFormatLoaderScript() +{ +} +#endif diff --git a/scene/io/scene_format_script.h b/scene/io/scene_format_script.h new file mode 100644 index 0000000000..9bfcc0b1e3 --- /dev/null +++ b/scene/io/scene_format_script.h @@ -0,0 +1,45 @@ +/*************************************************************************/ +/* scene_format_script.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef SCENE_FORMAT_SCRIPT_H +#define SCENE_FORMAT_SCRIPT_H + +#include "scene/io/scene_loader.h" +#include "io/resource_loader.h" +#if 0 + +class SceneFormatLoaderScript : public SceneFormatLoader { +public: + + virtual Node* load(const String &p_path,bool p_save_instance_state=false); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + + SceneFormatLoaderScript(); +}; +#endif +#endif // SCENE_FORMAT_SCRIPT_H diff --git a/scene/io/scene_loader.cpp b/scene/io/scene_loader.cpp new file mode 100644 index 0000000000..8615e64ae9 --- /dev/null +++ b/scene/io/scene_loader.cpp @@ -0,0 +1,161 @@ +/*************************************************************************/ +/* scene_loader.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "scene_loader.h" +#include "globals.h" +#include "path_remap.h" + +#ifdef OLD_SCENE_FORMAT_ENABLED + +SceneFormatLoader *SceneLoader::loader[MAX_LOADERS]; + +int SceneLoader::loader_count=0; + + +void SceneInteractiveLoader::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("get_scene"),&SceneInteractiveLoader::get_scene); + ObjectTypeDB::bind_method(_MD("poll"),&SceneInteractiveLoader::poll); + ObjectTypeDB::bind_method(_MD("get_stage"),&SceneInteractiveLoader::get_stage); + ObjectTypeDB::bind_method(_MD("get_stage_count"),&SceneInteractiveLoader::get_stage_count); +} + +class SceneInteractiveLoaderDefault : public SceneInteractiveLoader { + + OBJ_TYPE( SceneInteractiveLoaderDefault, SceneInteractiveLoader ); +public: + Node *scene; + + virtual void set_local_path(const String& p_local_path) { scene->set_filename(p_local_path); } + virtual Node *get_scene() { return scene; } + virtual Error poll() { return ERR_FILE_EOF; } + virtual int get_stage() const { return 1; } + virtual int get_stage_count() const { return 1; } + + SceneInteractiveLoaderDefault() {} +}; + + +Ref<SceneInteractiveLoader> SceneFormatLoader::load_interactive(const String &p_path,bool p_root_scene_hint) { + + Node *scene = load(p_path,p_root_scene_hint); + if (!scene) + return Ref<SceneInteractiveLoader>(); + Ref<SceneInteractiveLoaderDefault> sil = Ref<SceneInteractiveLoaderDefault>( memnew( SceneInteractiveLoaderDefault )); + sil->scene=scene; + return sil; +} + + + +bool SceneFormatLoader::recognize(const String& p_extension) const { + + + List<String> extensions; + get_recognized_extensions(&extensions); + for (List<String>::Element *E=extensions.front();E;E=E->next()) { + + if (E->get().nocasecmp_to(p_extension.extension())==0) + return true; + } + + return false; +} + +Ref<SceneInteractiveLoader> SceneLoader::load_interactive(const String &p_path,bool p_save_root_state) { + + String 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; + Ref<SceneInteractiveLoader> il = loader[i]->load_interactive(remapped_path,p_save_root_state); + + if (il.is_null() && remapped_path!=local_path) + il = loader[i]->load_interactive(local_path,p_save_root_state); + + ERR_EXPLAIN("Error loading scene: "+local_path); + ERR_FAIL_COND_V(il.is_null(),Ref<SceneInteractiveLoader>()); + il->set_local_path(local_path); + + return il; + } + + ERR_EXPLAIN("No loader found for scene: "+p_path); + ERR_FAIL_V(Ref<SceneInteractiveLoader>()); + return Ref<SceneInteractiveLoader>(); +} + +Node* SceneLoader::load(const String &p_path,bool p_root_scene_hint) { + + String 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; + Node*node = loader[i]->load(remapped_path,p_root_scene_hint); + + if (!node && remapped_path!=local_path) + node = loader[i]->load(local_path,p_root_scene_hint); + + ERR_EXPLAIN("Error loading scene: "+local_path); + ERR_FAIL_COND_V(!node,NULL); + node->set_filename(local_path); + + return node; + } + + ERR_EXPLAIN("No loader found for scene: "+p_path); + ERR_FAIL_V(NULL); +} + +void SceneLoader::get_recognized_extensions(List<String> *p_extensions) { + + for (int i=0;i<loader_count;i++) { + + loader[i]->get_recognized_extensions(p_extensions); + } + +} + +void SceneLoader::add_scene_format_loader(SceneFormatLoader *p_format_loader) { + + ERR_FAIL_COND( loader_count >= MAX_LOADERS ); + loader[loader_count++]=p_format_loader; +} + + +#endif diff --git a/scene/io/scene_loader.h b/scene/io/scene_loader.h new file mode 100644 index 0000000000..2562fc0520 --- /dev/null +++ b/scene/io/scene_loader.h @@ -0,0 +1,90 @@ +/*************************************************************************/ +/* scene_loader.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef SCENE_LOADER_H +#define SCENE_LOADER_H + +#include "scene/main/node.h" + +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ + +#ifdef OLD_SCENE_FORMAT_ENABLED + +class SceneInteractiveLoader : public Reference { + + OBJ_TYPE(SceneInteractiveLoader,Reference); +protected: + + static void _bind_methods(); +public: + + virtual void set_local_path(const String& p_local_path)=0; + virtual Node *get_scene()=0; + virtual Error poll()=0; + virtual int get_stage() const=0; + virtual int get_stage_count() const=0; + + + SceneInteractiveLoader() {} +}; + +class SceneFormatLoader { +public: + + virtual Ref<SceneInteractiveLoader> load_interactive(const String &p_path,bool p_root_scene_hint=false); + virtual Node* load(const String &p_path,bool p_root_scene_hint=false)=0; + virtual void get_recognized_extensions(List<String> *p_extensions) const=0; + bool recognize(const String& p_extension) const; + + virtual ~SceneFormatLoader() {} +}; + +class SceneLoader { + + enum { + MAX_LOADERS=64 + }; + + static SceneFormatLoader *loader[MAX_LOADERS]; + static int loader_count; + +public: + + static Ref<SceneInteractiveLoader> load_interactive(const String &p_path,bool p_save_root_state=false); + static Node* load(const String &p_path,bool p_save_root_state=false); + static void add_scene_format_loader(SceneFormatLoader *p_format_loader); + static void get_recognized_extensions(List<String> *p_extensions); + + +}; + +#endif + +#endif diff --git a/scene/io/scene_saver.cpp b/scene/io/scene_saver.cpp new file mode 100644 index 0000000000..f1b503ef27 --- /dev/null +++ b/scene/io/scene_saver.cpp @@ -0,0 +1,94 @@ +/*************************************************************************/ +/* scene_saver.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "scene_saver.h" +#include "print_string.h" + +#ifdef OLD_SCENE_FORMAT_ENABLED +SceneFormatSaver *SceneSaver::saver[MAX_SAVERS]; + +int SceneSaver::saver_count=0; + +bool SceneFormatSaver::recognize(const String& p_extension) const { + + + List<String> extensions; + get_recognized_extensions(&extensions); + for (List<String>::Element *E=extensions.front();E;E=E->next()) { + + + if (E->get().nocasecmp_to(p_extension.extension())==0) + return true; + } + + return false; +} + +Error SceneSaver::save(const String &p_path,const Node* p_scene,uint32_t p_flags,const Ref<OptimizedSaver> &p_optimizer) { + + String extension=p_path.extension(); + Error err=ERR_FILE_UNRECOGNIZED; + bool recognized=false; + + for (int i=0;i<saver_count;i++) { + + if (!saver[i]->recognize(extension)) + continue; + recognized=true; + err = saver[i]->save(p_path,p_scene,p_flags,p_optimizer); + if (err == OK ) + return OK; + } + + if (err) { + if (!recognized) { + ERR_EXPLAIN("No saver format found for scene: "+p_path); + } else { + ERR_EXPLAIN("Couldn't save scene: "+p_path); + } + ERR_FAIL_V(err); + } + + return err; +} + +void SceneSaver::get_recognized_extensions(List<String> *p_extensions) { + + for (int i=0;i<saver_count;i++) { + + saver[i]->get_recognized_extensions(p_extensions); + } +} + +void SceneSaver::add_scene_format_saver(SceneFormatSaver *p_format_saver) { + + ERR_FAIL_COND( saver_count >= MAX_SAVERS ); + saver[saver_count++]=p_format_saver; +} + +#endif diff --git a/scene/io/scene_saver.h b/scene/io/scene_saver.h new file mode 100644 index 0000000000..3028dce133 --- /dev/null +++ b/scene/io/scene_saver.h @@ -0,0 +1,80 @@ +/*************************************************************************/ +/* scene_saver.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef SCENE_SAVER_H +#define SCENE_SAVER_H + +#include "scene/main/node.h" +#include "io/object_saver.h" +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ + + +#ifdef OLD_SCENE_FORMAT_ENABLED + +class SceneFormatSaver { +public: + + virtual Error save(const String &p_path,const Node* p_scen,uint32_t p_flags=0,const Ref<OptimizedSaver> &p_optimizer=Ref<OptimizedSaver>())=0; + virtual void get_recognized_extensions(List<String> *p_extensions) const=0; + bool recognize(const String& p_extension) const; + virtual ~SceneFormatSaver() {} +}; + + + + +class SceneSaver { + + enum { + MAX_SAVERS=64 + }; + + static SceneFormatSaver *saver[MAX_SAVERS]; + static int saver_count; + +public: + enum SaverFlags { + + FLAG_RELATIVE_PATHS=1, + FLAG_BUNDLE_RESOURCES=2, + FLAG_BUNDLE_INSTANCED_SCENES=4, + FLAG_OMIT_EDITOR_PROPERTIES=8, + FLAG_SAVE_BIG_ENDIAN=16 + }; + + static Error save(const String &p_path,const Node* p_scenezz,uint32_t p_flags=0,const Ref<OptimizedSaver> &p_optimizer=Ref<OptimizedSaver>()); + static void add_scene_format_saver(SceneFormatSaver *p_format_saver); + static void get_recognized_extensions(List<String> *p_extensions); +}; + + + +#endif +#endif |