1 /*
2  * Copyright 2006 Sony Computer Entertainment Inc.
3  *
4  * Licensed under the MIT Open Source License, for details please see license.txt or the website
5  * http://www.opensource.org/licenses/mit-license.php
6  *
7  */
8 
9 #ifndef __DAE__
10 #define __DAE__
11 
12 // We use the boost filesystem library for cross-platform file system support. You'll need
13 // to have boost on your machine for this to work. For the Windows build boost is provided
14 // in the external-libs folder, but for Linux it's expected that you'll install a boost
15 // obtained via your distro's package manager. For example on Debian/Ubuntu, you can run
16 //   apt-get install libboost-filesystem-dev
17 // to install the boost filesystem library on your machine.
18 //
19 // Disable the warnings we get from Boost
20 // warning C4180: qualifier applied to function type has no meaning; ignored
21 // warning C4245: 'argument' : conversion from 'int' to 'boost::filesystem::system_error_type',
22 //   signed/unsigned mismatch
23 #ifdef _MSC_VER
24 #pragma warning(push)
25 #pragma warning(disable: 4180 4245)
26 #endif
27 #ifndef NO_BOOST
28 #include <boost/filesystem/convenience.hpp>
29 #endif
30 #ifdef _MSC_VER
31 #pragma warning(pop)
32 #endif
33 
34 #include <dae/daeTypes.h>
35 #include <dae/daeError.h>
36 #include <dae/daeDatabase.h>
37 #include <dae/daeIOPlugin.h>
38 #include <dae/daeAtomicType.h>
39 #include <dae/daeMetaElement.h>
40 #include <dae/daeIDRef.h>
41 #include <dae/daeURI.h>
42 #include <dae/daeUtils.h>
43 #include <dae/daeRawResolver.h>
44 #include <dae/daeSIDResolver.h>
45 
46 // needed for backward compatibility
47 #ifdef COLLADA_DOM_SUPPORT150
48 namespace ColladaDOM150 {
49 class domCOLLADA;
50 typedef daeSmartRef<domCOLLADA> domCOLLADARef;
51 }
52 #endif
53 #ifdef COLLADA_DOM_SUPPORT141
54 namespace ColladaDOM141 {
55 class domCOLLADA;
56 typedef daeSmartRef<domCOLLADA> domCOLLADARef;
57 }
58 #endif
59 
60 typedef daeElement domCOLLADAProxy;
61 typedef daeSmartRef<daeElement> domCOLLADAProxyRef;
62 
63 class daeDatabase;
64 
65 // The DAE class is the core interface via which you interact with the DOM. It
66 // has methods to load/save documents, get the root element of each document,
67 // etc. Although internally the DOM works exclusively with URIs, the methods of
68 // the DAE class that take document paths can take URIs or OS-specific file
69 // paths.
70 class DLLSPEC DAE
71 {
72 public:
73     // Constructor. If no database or IO plugin are provided, a default database and
74     // IO plugin will be used.
75     // \param specversion the collada specification to load into memory. For example: "1.4.1" or "1.5.0". If NULL, then the highest version found will be loaded.
76     DAE(daeDatabase* database = NULL, daeIOPlugin* ioPlugin = NULL, const char* specversion = NULL)
77         : atomicTypes(*this),
78         baseUri(*this, cdom::getCurrentDirAsUri().c_str())
79     {
80         // See the end of the thread linked below for an explanation of why we have the DAE
81         // constructor set up this way. Basically, I'm going to be changing the build output
82         // location, and when this happens people sometimes continue to link against the old
83         // libraries by accident (e.g. if they just do an svn update). By introducing a new
84         // function that gets called from a function in a header file, I'm ensuring that someone
85         // who tries linking against old libraries will get a link error. This may not sound
86         // very nice, but it's certainly better than getting bizarre runtime crashes.
87         // https://collada.org/public_forum/viewtopic.php?t=771&sid=f13c34f2d17ca720c5021bccbe5128b7
88         init(database, ioPlugin,specversion);
89         dummyFunction1();
90     }
91 
92     virtual ~DAE();
93 
94     // Release all memory used by the DOM. You never need to call this explicitly. It's
95     // called automatically when all DAE objects go out of scope.
96     // Deletes directory returned by cdom::getSafeTmpDir().
97     static void cleanup();
98 
99 public:
100     // Database setup
101     virtual daeDatabase* getDatabase();
102     virtual daeInt setDatabase(daeDatabase* database);
103 
104     // IO Plugin setup
105     virtual daeIOPlugin* getIOPlugin();
106     virtual daeInt setIOPlugin(daeIOPlugin* plugin);
107 
108     // Creates a new document, returning null on failure. Cast to ColladaDOMXXX::domCOLLADA
109     virtual domCOLLADAProxy* add(const std::string& path);
110     // Opens an existing document, returning null on failure. Cast to ColladaDOMXXX::domCOLLADA
111     virtual domCOLLADAProxy* open(const std::string& path);
112     // Opens a document from memory, returning null on failure. Cast to ColladaDOMXXX::domCOLLADA
113     virtual domCOLLADAProxy* openFromMemory(const std::string& path, daeString buffer);
114 #ifdef COLLADA_DOM_SUPPORT141
add141(const std::string & path)115     virtual ColladaDOM141::domCOLLADA* add141(const std::string& path) {
116         return (ColladaDOM141::domCOLLADA*)add(path);
117     }
open141(const std::string & path)118     virtual ColladaDOM141::domCOLLADA* open141(const std::string& path) {
119         return (ColladaDOM141::domCOLLADA*)open(path);
120     }
121     // Opens a document from memory, returning null on failure.
openFromMemory141(const std::string & path,daeString buffer)122     virtual ColladaDOM141::domCOLLADA* openFromMemory141(const std::string& path, daeString buffer) {
123         return (ColladaDOM141::domCOLLADA*)openFromMemory(path,buffer);
124     }
125 #endif
126 #ifdef COLLADA_DOM_SUPPORT150
add150(const std::string & path)127     virtual ColladaDOM150::domCOLLADA* add150(const std::string& path) {
128         return (ColladaDOM150::domCOLLADA*)add(path);
129     }
open150(const std::string & path)130     virtual ColladaDOM150::domCOLLADA* open150(const std::string& path) {
131         return (ColladaDOM150::domCOLLADA*)open(path);
132     }
133     // Opens a document from memory, returning null on failure.
openFromMemory150(const std::string & path,daeString buffer)134     virtual ColladaDOM150::domCOLLADA* openFromMemory150(const std::string& path, daeString buffer) {
135         return (ColladaDOM150::domCOLLADA*)openFromMemory(path,buffer);
136     }
137 #endif
138 
139     // Write a document to the path specified by the document's URI, returning false on failure.
140     virtual bool write(const std::string& path);
141     // Write a document to the path specified in the second parameter, returning false on failure.
142     virtual bool writeTo(const std::string& docPath, const std::string& pathToWriteTo);
143     // Write a document to memory, returning false on failure.
144     virtual bool writeToMemory(const std::string& docPath, std::vector<char>& output);
145 
146     // Writes all documents, returning false if any document failed to write.
147     virtual bool writeAll();
148     // Close a specific document, unloading all memory used by the document. Returns false on failure.
149     virtual void close(const std::string& path);
150     // Remove all loaded documents. Always returns DAE_OK.
151     virtual daeInt clear();
152 
153     // Returns the total number of documents.
154     virtual int getDocCount();
155     // Returns the i'th document .
156     virtual daeDocument* getDoc(int i);
157     // Returns a document matching the path.
158     virtual daeDocument* getDoc(const std::string& path);
159 
160     // Get the root daeElement object corresponding to a particular document. Cast to ColladaDOMXXX::domCOLLADA
161     virtual domCOLLADAProxy* getRoot(const std::string& path);
162     // Set the root daeElement object corresponding to a particular document, returning false on failure.
163     virtual bool        setRoot(const std::string& path, domCOLLADAProxy* root);
164 #ifdef COLLADA_DOM_SUPPORT141
getRoot141(const std::string & path)165     virtual ColladaDOM141::domCOLLADA* getRoot141(const std::string& path) {
166         return (ColladaDOM141::domCOLLADA*)getRoot(path);
167     }
setRoot141(const std::string & path,ColladaDOM141::domCOLLADA * root)168     virtual bool        setRoot141(const std::string& path, ColladaDOM141::domCOLLADA* root) {
169         return setRoot(path,(domCOLLADAProxy*)root);
170     }
171 #endif
172 #ifdef COLLADA_DOM_SUPPORT150
getRoot150(const std::string & path)173     virtual ColladaDOM150::domCOLLADA* getRoot150(const std::string& path) {
174         return (ColladaDOM150::domCOLLADA*)getRoot(path);
175     }
setRoot150(const std::string & path,ColladaDOM150::domCOLLADA * root)176     virtual bool        setRoot150(const std::string& path, ColladaDOM150::domCOLLADA* root) {
177         return setRoot(path,(domCOLLADAProxy*)root);
178     }
179 #endif
180 
181     // Returns the Collada version, i.e. 1.4, 1.5, etc. Note that this _isn't_ the
182     // same as the DOM version (1.3, 2.0, ...).
183     virtual daeString getDomVersion();
184 
185     // Returns the (modifiable) list of atomic type objects.
186     daeAtomicTypeList& getAtomicTypes();
187 
188     // Get/set a daeMetaElement object given the meta object's type ID.
189     daeMetaElement* getMeta(daeInt typeID);
190     void setMeta(daeInt typeID, daeMetaElement& meta);
191 
192     // Get all daeMetaElement objects.
193     daeMetaElementRefArray& getAllMetas();
194 
195     // Returns the list of URI resolvers. You can modify the list to add new resolvers.
196     daeURIResolverList& getURIResolvers();
197 
198     // The base URI used for resolving relative URI references.
199     daeURI& getBaseURI();
200     void setBaseURI(const daeURI& uri);
201     void setBaseURI(const std::string& uri);
202 
203     // Returns the list of ID reference resolvers. You can modify the list to add new
204     // resolvers.
205     daeIDRefResolverList& getIDRefResolvers();
206 
207     // Meant for internal DOM use only.
208     daeRawRefCache& getRawRefCache();
209     daeSidRefCache& getSidRefCache();
210 
211     // These functions specify the client's character encoding for the DOM. The
212     // default is Utf8, but if you specify Latin1 then the DOM will use libxml's
213     // character conversion functions to convert to Utf8 when writing data and
214     // convert to Latin1 when reading data. This can help with the handling of
215     // non-ASCII characters on Windows. Only when using libxml for xml I/O does
216     // any character conversion occur.
217     //
218     // Most people can probably just ignore this completely. If you have trouble
219     // with non-ASCII characters on Windows, try setting the char encoding to
220     // Latin1 to see if that helps.
221     //
222     // Frankly this certainly isn't the best way of handling non-ASCII character
223     // support on Windows, so this interface is a likely target for significant
224     // changes in the future.
225     //
226     // See this Sourceforge thread for more info:
227     // http://sourceforge.net/tracker/index.php?func=detail&aid=1818473&group_id=157838&atid=805426
228     //
229     enum charEncoding {
230         Utf8,
231         Latin1
232     };
233 
234     // Global encoding setting. Defaults to Utf8. Set this if you want to make a
235     // char encoding change and apply it to all DAE objects.
236     static charEncoding getGlobalCharEncoding();
237     static void setGlobalCharEncoding(charEncoding encoding);
238 
239     // Local encoding setting. If set, overrides the global setting. Useful for setting
240     // a specific char encoding for a single DAE object but not for all DAE objects.
241     charEncoding getCharEncoding();
242     void setCharEncoding(charEncoding encoding);
243 
244     // Deprecated. Alternative methods are given.
245     virtual daeInt load(daeString uri, daeString docBuffer = NULL); // Use open
246     virtual daeInt save(daeString uri, daeBool replace=true); // Use write
247     virtual daeInt save(daeUInt documentIndex, daeBool replace=true); // Use write
248     virtual daeInt saveAs(daeString uriToSaveTo, daeString docUri, daeBool replace=true); // Use writeTo
249     virtual daeInt saveAs(daeString uriToSaveTo, daeUInt documentIndex=0, daeBool replace=true); // Use writeTo
250     virtual daeInt unload(daeString uri); // Use close
251 
252     virtual domCOLLADAProxy* getDom(daeString uri); // use getRoot, Cast to ColladaDOMXXX::domCOLLADA
253     virtual daeInt      setDom(daeString uri, domCOLLADAProxy* dom); // use setRoot,
254 #ifdef COLLADA_DOM_SUPPORT141
getDom141(daeString uri)255     virtual ColladaDOM141::domCOLLADA* getDom141(daeString uri) {
256         return (ColladaDOM141::domCOLLADA*)getDom(uri);
257     }
setDom141(daeString uri,ColladaDOM141::domCOLLADA * dom)258     virtual daeInt      setDom141(daeString uri, ColladaDOM141::domCOLLADA* dom) {
259         return setDom(uri,(domCOLLADAProxy*)dom);
260     }
261 #endif
262 #ifdef COLLADA_DOM_SUPPORT150
getDom150(daeString uri)263     virtual ColladaDOM150::domCOLLADA* getDom150(daeString uri) {
264         return (ColladaDOM150::domCOLLADA*)getDom(uri);
265     }
setDom150(daeString uri,ColladaDOM150::domCOLLADA * dom)266     virtual daeInt      setDom150(daeString uri, ColladaDOM150::domCOLLADA* dom) {
267         return setDom(uri,(domCOLLADAProxy*)dom);
268     }
269 #endif
270 
271     virtual daeString getColladaNamespace();
272 
273 private:
274     void init(daeDatabase* database, daeIOPlugin* ioPlugin, const char* specversion);
275     void dummyFunction1();
276     std::string makeFullUri(const std::string& path);
277     domCOLLADAProxy* openCommon(const std::string& path, daeString buffer);
278     bool writeCommon(const std::string& docPath, const std::string& pathToWriteTo, bool replace);
279 
280     daeDatabase *database;
281     daeIOPlugin *plugin;
282     bool defaultDatabase;
283     bool defaultPlugin;
284     daeAtomicTypeList atomicTypes;
285     daeMetaElementRefArray metas;
286     daeURI baseUri;
287     daeURIResolverList uriResolvers;
288     daeIDRefResolverList idRefResolvers;
289     daeRawRefCache rawRefCache;
290     daeSidRefCache sidRefCache;
291     daeString COLLADA_VERSION, COLLADA_NAMESPACE; // dynamic
292 
293     std::auto_ptr<charEncoding> localCharEncoding;
294     static charEncoding globalCharEncoding;
295 };
296 
297 
298 template <typename T>
daeSafeCast(daeElement * element)299 inline T *daeSafeCast(daeElement *element)
300 {
301     if (element  &&  element->typeID() == T::ID())
302         return (T*)element;
303     return NULL;
304 }
305 
306 
307 #endif // __DAE_INTERFACE__
308