summaryrefslogtreecommitdiff
path: root/scene/io
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
committerJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
commit0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch)
tree276c4d099e178eb67fbd14f61d77b05e3808e9e3 /scene/io
parent0e49da1687bc8192ed210947da52c9e5c5f301bb (diff)
GODOT IS OPEN SOURCE
Diffstat (limited to 'scene/io')
-rw-r--r--scene/io/SCsub7
-rw-r--r--scene/io/resource_format_image.cpp199
-rw-r--r--scene/io/resource_format_image.h51
-rw-r--r--scene/io/resource_format_wav.cpp255
-rw-r--r--scene/io/resource_format_wav.h43
-rw-r--r--scene/io/scene_format_object.cpp851
-rw-r--r--scene/io/scene_format_object.h128
-rw-r--r--scene/io/scene_format_script.cpp65
-rw-r--r--scene/io/scene_format_script.h45
-rw-r--r--scene/io/scene_loader.cpp161
-rw-r--r--scene/io/scene_loader.h90
-rw-r--r--scene/io/scene_saver.cpp94
-rw-r--r--scene/io/scene_saver.h80
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