1 /*
2 	Copyright (C) 2005-2007 Feeling Software Inc.
3 	Portions of the code are:
4 	Copyright (C) 2005-2007 Sony Computer Entertainment America
5 
6 	MIT License: http://www.opensource.org/licenses/mit-license.php
7 */
8 /*
9 	Based on the FS Import classes:
10 	Copyright (C) 2005-2006 Feeling Software Inc
11 	Copyright (C) 2005-2006 Autodesk Media Entertainment
12 	MIT License: http://www.opensource.org/licenses/mit-license.php
13 */
14 
15 #include "StdAfx.h"
16 #include "FCDocument/FCDocument.h"
17 #include "FCDocument/FCDAnimated.h"
18 #include "FCDocument/FCDAnimation.h"
19 #include "FCDocument/FCDAnimationChannel.h"
20 #include "FCDocument/FCDAnimationClip.h"
21 #include "FCDocument/FCDAnimationCurve.h"
22 #include "FCDocument/FCDAsset.h"
23 #include "FCDocument/FCDCamera.h"
24 #include "FCDocument/FCDController.h"
25 #include "FCDocument/FCDEffect.h"
26 #include "FCDocument/FCDEmitter.h"
27 #include "FCDocument/FCDEntityReference.h"
28 #include "FCDocument/FCDExternalReferenceManager.h"
29 #include "FCDocument/FCDExtra.h"
30 #include "FCDocument/FCDForceField.h"
31 #include "FCDocument/FCDGeometry.h"
32 #include "FCDocument/FCDImage.h"
33 #include "FCDocument/FCDLight.h"
34 #include "FCDocument/FCDLibrary.h"
35 #include "FCDocument/FCDMaterial.h"
36 #include "FCDocument/FCDPlaceHolder.h"
37 #include "FCDocument/FCDPhysicsMaterial.h"
38 #include "FCDocument/FCDPhysicsModel.h"
39 #include "FCDocument/FCDPhysicsScene.h"
40 #include "FCDocument/FCDSceneNode.h"
41 #include "FCDocument/FCDTexture.h"
42 #include "FCDocument/FCDVersion.h"
43 #include "FUtils/FUFileManager.h"
44 #include "FUtils/FUUniqueStringMap.h"
45 #include "FUtils/FUDaeSyntax.h"
46 
47 //
48 // FCDocument
49 //
50 
51 ImplementObjectType(FCDocument);
52 
53 ImplementParameterObject(FCDocument, FCDEntityReference, visualSceneRoot, new FCDEntityReference(parent->GetDocument(), NULL));
54 ImplementParameterObject(FCDocument, FCDEntityReference, physicsSceneRoots, new FCDEntityReference(parent->GetDocument(), NULL));
55 ImplementParameterObject(FCDocument, FCDAsset, asset, new FCDAsset(parent->GetDocument()));
56 ImplementParameterObject(FCDocument, FCDExtra, extra, new FCDExtra(parent->GetDocument(), parent));
57 ImplementParameterObject(FCDocument, FCDAnimationLibrary, animationLibrary, new FCDAnimationLibrary(parent->GetDocument()));
58 ImplementParameterObject(FCDocument, FCDAnimationClipLibrary, animationClipLibrary, new FCDAnimationClipLibrary(parent->GetDocument()));
59 ImplementParameterObject(FCDocument, FCDCameraLibrary, cameraLibrary, new FCDCameraLibrary(parent->GetDocument()));
60 ImplementParameterObject(FCDocument, FCDControllerLibrary, controllerLibrary, new FCDControllerLibrary(parent->GetDocument()));
61 ImplementParameterObject(FCDocument, FCDEffectLibrary, effectLibrary, new FCDEffectLibrary(parent->GetDocument()));
62 ImplementParameterObject(FCDocument, FCDForceFieldLibrary, forceFieldLibrary, new FCDForceFieldLibrary(parent->GetDocument()));
63 ImplementParameterObject(FCDocument, FCDGeometryLibrary, geometryLibrary, new FCDGeometryLibrary(parent->GetDocument()));
64 ImplementParameterObject(FCDocument, FCDImageLibrary, imageLibrary, new FCDImageLibrary(parent->GetDocument()));
65 ImplementParameterObject(FCDocument, FCDLightLibrary, lightLibrary, new FCDLightLibrary(parent->GetDocument()));
66 ImplementParameterObject(FCDocument, FCDMaterialLibrary, materialLibrary, new FCDMaterialLibrary(parent->GetDocument()));
67 ImplementParameterObject(FCDocument, FCDPhysicsModelLibrary, physicsModelLibrary, new FCDPhysicsModelLibrary(parent->GetDocument()));
68 ImplementParameterObject(FCDocument, FCDPhysicsMaterialLibrary, physicsMaterialLibrary, new FCDPhysicsMaterialLibrary(parent->GetDocument()));
69 ImplementParameterObject(FCDocument, FCDPhysicsSceneLibrary, physicsSceneLibrary, new FCDPhysicsSceneLibrary(parent->GetDocument()));
70 ImplementParameterObject(FCDocument, FCDVisualSceneNodeLibrary, visualSceneLibrary, new FCDVisualSceneNodeLibrary(parent->GetDocument()));
71 ImplementParameterObject(FCDocument, FCDEmitterLibrary, emitterLibrary, new FCDEmitterLibrary(parent->GetDocument()));
72 
FCDocument()73 FCDocument::FCDocument()
74 :	FCDObject(this)
75 ,	fileManager(NULL), version(NULL), uniqueNameMap(NULL)
76 ,	InitializeParameterNoArg(visualSceneRoot)
77 ,	InitializeParameterNoArg(physicsSceneRoots)
78 ,	InitializeParameterNoArg(asset)
79 ,	InitializeParameterNoArg(extra)
80 ,	hasStartTime(false), hasEndTime(false)
81 ,	InitializeParameter(startTime, 0.0f)
82 ,	InitializeParameter(endTime, 0.0f)
83 ,	InitializeParameterNoArg(animationLibrary)
84 ,	InitializeParameterNoArg(animationClipLibrary)
85 ,	InitializeParameterNoArg(cameraLibrary)
86 ,	InitializeParameterNoArg(controllerLibrary)
87 ,	InitializeParameterNoArg(effectLibrary)
88 ,	InitializeParameterNoArg(forceFieldLibrary)
89 ,	InitializeParameterNoArg(geometryLibrary)
90 ,	InitializeParameterNoArg(imageLibrary)
91 ,	InitializeParameterNoArg(lightLibrary)
92 ,	InitializeParameterNoArg(materialLibrary)
93 ,	InitializeParameterNoArg(physicsModelLibrary)
94 ,	InitializeParameterNoArg(physicsMaterialLibrary)
95 ,	InitializeParameterNoArg(physicsSceneLibrary)
96 ,	InitializeParameterNoArg(visualSceneLibrary)
97 ,	InitializeParameterNoArg(emitterLibrary)
98 {
99 	fileManager = new FUFileManager();
100 	version = new FCDVersion(DAE_SCHEMA_VERSION);
101 	uniqueNameMap = new FUSUniqueStringMap();
102 
103 	asset = new FCDAsset(this);
104 	externalReferenceManager = new FCDExternalReferenceManager(this);
105 	extra = new FCDExtra(this, this);
106 	visualSceneRoot = new FCDEntityReference(this, NULL);
107 
108 	animationLibrary = new FCDAnimationLibrary(this);
109 	animationClipLibrary = new FCDAnimationClipLibrary(this);
110 	cameraLibrary = new FCDCameraLibrary(this);
111 	controllerLibrary = new FCDControllerLibrary(this);
112 	emitterLibrary = new FCDEmitterLibrary(this);
113 	forceFieldLibrary = new FCDForceFieldLibrary(this);
114 	effectLibrary = new FCDEffectLibrary(this);
115 	geometryLibrary = new FCDGeometryLibrary(this);
116 	imageLibrary = new FCDImageLibrary(this);
117 	lightLibrary = new FCDLightLibrary(this);
118 	materialLibrary = new FCDMaterialLibrary(this);
119 	visualSceneLibrary = new FCDVisualSceneNodeLibrary(this);
120 	physicsMaterialLibrary = new FCDPhysicsMaterialLibrary(this);
121 	physicsModelLibrary = new FCDPhysicsModelLibrary(this);
122 	physicsSceneLibrary = new FCDPhysicsSceneLibrary(this);
123 }
124 
~FCDocument()125 FCDocument::~FCDocument()
126 {
127 	// Release the external references to and from this document
128 	// before all clearing the entities.
129 	FUTrackable::Detach();
130 
131 	externalReferenceManager = NULL;
132 
133 	// Release the libraries and the asset
134 	animationLibrary = NULL;
135 	animationClipLibrary = NULL;
136 	cameraLibrary = NULL;
137 	controllerLibrary = NULL;
138 	effectLibrary = NULL;
139 	emitterLibrary = NULL;
140 	forceFieldLibrary = NULL;
141 	geometryLibrary = NULL;
142 	imageLibrary = NULL;
143 	lightLibrary = NULL;
144 	materialLibrary = NULL;
145 	visualSceneLibrary = NULL;
146 	physicsMaterialLibrary = NULL;
147 	physicsModelLibrary = NULL;
148 	physicsSceneLibrary = NULL;
149 	asset = NULL;
150 
151 	// Must be released last
152 	CLEAR_POINTER_VECTOR(layers);
153 	while (!animatedValues.empty()) { animatedValues.begin()->first->Release(); }
154 //	animatedValueMap.clear();
155 
156 	SAFE_DELETE(fileManager);
157 	SAFE_DELETE(uniqueNameMap);
158 	SAFE_DELETE(version);
159 }
160 
GetVisualSceneInstance() const161 const FCDSceneNode* FCDocument::GetVisualSceneInstance() const
162 {
163 	if (visualSceneRoot == NULL) return NULL;
164 	const FCDEntity* entity = visualSceneRoot->GetEntity();
165 	if (entity != NULL && entity->HasType(FCDSceneNode::GetClassType())) return (const FCDSceneNode*) entity;
166 	else return NULL;
167 }
168 
GetPhysicsSceneInstance(size_t index) const169 const FCDPhysicsScene* FCDocument::GetPhysicsSceneInstance(size_t index) const
170 {
171 	if (index == 0 && physicsSceneRoots.empty()) return NULL;
172 	FUAssert(index < physicsSceneRoots.size(), return NULL);
173 	const FCDEntity* entity = physicsSceneRoots[index]->GetEntity();
174 	if (entity != NULL && entity->HasType(FCDPhysicsScene::GetClassType())) return (const FCDPhysicsScene*) entity;
175 	else return NULL;
176 }
177 
AddPhysicsSceneInstanceReference()178 FCDEntityReference* FCDocument::AddPhysicsSceneInstanceReference()
179 {
180 	physicsSceneRoots.push_back(new FCDEntityReference(this, (FCDObjectWithId*) NULL));
181 	return physicsSceneRoots.back();
182 }
183 
AddPhysicsSceneInstance(FCDPhysicsScene * scene)184 void FCDocument::AddPhysicsSceneInstance(FCDPhysicsScene* scene)
185 {
186 	FCDEntityReference* reference = AddPhysicsSceneInstanceReference();
187 	reference->SetEntity(scene);
188 }
189 
190 // Adds an entity layer to the document.
AddLayer()191 FCDLayer* FCDocument::AddLayer()
192 {
193 	FCDLayer* layer = new FCDLayer();
194 	layers.push_back(layer);
195 	return layer;
196 }
197 
198 // Releases an entity layer from the document.
ReleaseLayer(FCDLayer * layer)199 void FCDocument::ReleaseLayer(FCDLayer* layer)
200 {
201 	layers.release(layer);
202 }
203 
204 // Search for a specific COLLADA library items with a given COLLADA id.
FindAnimation(const fm::string & daeId)205 FCDAnimation* FCDocument::FindAnimation(const fm::string& daeId) { return animationLibrary->FindDaeId(daeId); }
FindAnimationClip(const fm::string & daeId)206 FCDAnimationClip* FCDocument::FindAnimationClip(const fm::string& daeId) { return animationClipLibrary->FindDaeId(daeId); }
FindCamera(const fm::string & daeId)207 FCDCamera* FCDocument::FindCamera(const fm::string& daeId) { return cameraLibrary->FindDaeId(daeId); }
FindController(const fm::string & daeId)208 FCDController* FCDocument::FindController(const fm::string& daeId) { return controllerLibrary->FindDaeId(daeId); }
FindEffect(const fm::string & daeId)209 FCDEffect* FCDocument::FindEffect(const fm::string& daeId) { return effectLibrary->FindDaeId(daeId); }
FindEmitter(const fm::string & daeId)210 FCDEmitter* FCDocument::FindEmitter(const fm::string& daeId) { return emitterLibrary->FindDaeId(daeId); }
FindForceField(const fm::string & daeId)211 FCDForceField* FCDocument::FindForceField(const fm::string& daeId) { return forceFieldLibrary->FindDaeId(daeId); }
FindGeometry(const fm::string & daeId)212 FCDGeometry* FCDocument::FindGeometry(const fm::string& daeId) { return geometryLibrary->FindDaeId(daeId); }
FindImage(const fm::string & daeId)213 FCDImage* FCDocument::FindImage(const fm::string& daeId) { return imageLibrary->FindDaeId(daeId); }
FindLayer(const fm::string & name)214 FCDLayer* FCDocument::FindLayer(const fm::string& name) { for (FCDLayerList::iterator itL = layers.begin(); itL != layers.end(); ++itL) { if ((*itL)->name == name) return *itL; } return NULL; }
FindLight(const fm::string & daeId)215 FCDLight* FCDocument::FindLight(const fm::string& daeId) { return lightLibrary->FindDaeId(daeId); }
FindMaterial(const fm::string & daeId)216 FCDMaterial* FCDocument::FindMaterial(const fm::string& daeId) { return  materialLibrary->FindDaeId(daeId); }
FindVisualScene(const fm::string & daeId)217 FCDSceneNode* FCDocument::FindVisualScene(const fm::string& daeId) { return visualSceneLibrary->FindDaeId(daeId); }
FindPhysicsScene(const fm::string & daeId)218 FCDPhysicsScene* FCDocument::FindPhysicsScene(const fm::string& daeId) { return physicsSceneLibrary->FindDaeId(daeId); }
FindPhysicsMaterial(const fm::string & daeId)219 FCDPhysicsMaterial* FCDocument::FindPhysicsMaterial(const fm::string& daeId) { return physicsMaterialLibrary->FindDaeId(daeId); }
FindPhysicsModel(const fm::string & daeId)220 FCDPhysicsModel* FCDocument::FindPhysicsModel(const fm::string& daeId) { return physicsModelLibrary->FindDaeId(daeId); }
FindSceneNode(const char * daeId) const221 const FCDSceneNode* FCDocument::FindSceneNode(const char* daeId) const { return visualSceneLibrary->FindDaeId(daeId); }
FindEntity(const fm::string & daeId)222 FCDEntity* FCDocument::FindEntity(const fm::string& daeId)
223 {
224 #define CHECK_LIB(libraryName) { \
225 	FCDEntity* e = libraryName->FindDaeId(daeId); \
226 	if (e != NULL) return e; }
227 
228 	CHECK_LIB(animationLibrary);
229 	CHECK_LIB(animationClipLibrary);
230 	CHECK_LIB(cameraLibrary);
231 	CHECK_LIB(controllerLibrary);
232 	CHECK_LIB(effectLibrary);
233 	CHECK_LIB(emitterLibrary);
234 	CHECK_LIB(forceFieldLibrary);
235 	CHECK_LIB(geometryLibrary);
236 	CHECK_LIB(imageLibrary);
237 	CHECK_LIB(lightLibrary);
238 	CHECK_LIB(materialLibrary);
239 	CHECK_LIB(visualSceneLibrary);
240 	CHECK_LIB(physicsSceneLibrary);
241 	CHECK_LIB(physicsMaterialLibrary);
242 	CHECK_LIB(physicsModelLibrary);
243 #undef CHECK_LIB
244 
245 	return NULL;
246 }
247 
248 // Add an animated value to the list
RegisterAnimatedValue(FCDAnimated * animated)249 void FCDocument::RegisterAnimatedValue(FCDAnimated* animated)
250 {
251 	// Look for a duplicate in order to avoid memory loss
252 	//if (animated->GetValueCount() == 0 || FindAnimatedValue(animated->GetValue(0)) != NULL)
253 	if (animated->GetValueCount() == 0)
254 	{
255 		SAFE_RELEASE(animated);
256 		return;
257 	}
258 
259 	// List the new animated value
260 	animatedValues.insert(animated, animated);
261 
262 	//// Also add to the map the individual values for easy retrieval
263 	//size_t count = animated->GetValueCount();
264 	//for (size_t i = 0; i < count; ++i)
265 	//{
266 	//	const float* value = animated->GetValue(i);
267 	//	animatedValueMap.insert(value, animated);
268 	//}
269 }
270 
271 // Unregisters an animated value of the document.
UnregisterAnimatedValue(FCDAnimated * animated)272 void FCDocument::UnregisterAnimatedValue(FCDAnimated* animated)
273 {
274 	if (animated != NULL)
275 	{
276 		// Intentionally search from the end:
277 		// - In the destructor of the document, we delete from the end.
278 		// - In animation exporters, we add to the end and are likely to delete right away.
279 		FCDAnimatedSet::iterator it = animatedValues.find(animated);
280 		if (it != animatedValues.end())
281 		{
282 			animatedValues.erase(it);
283 
284 			//// Also remove to the map the individual values contained
285 			//size_t count = animated->GetValueCount();
286 			//for (size_t i = 0; i < count; ++i)
287 			//{
288 			//	const float* value = animated->GetValue(i);
289 			//	FCDAnimatedValueMap::iterator itV = animatedValueMap.find(value);
290 			//	if (itV != animatedValueMap.end() && (*itV).second == animated)
291 			//	{
292 			//		animatedValueMap.erase(itV);
293 			//	}
294 			//}
295 		}
296 	}
297 }
298 //
299 //// Retrieve an animated value, given a value pointer
300 //const FCDAnimated* FCDocument::FindAnimatedValue(const float* ptr) const
301 //{
302 //	FCDAnimatedValueMap::const_iterator it = animatedValueMap.find(ptr);
303 //	return (it != animatedValueMap.end()) ? (*it).second : NULL;
304 //}
305 //
306 //// Retrieve an animated float value for a given fully qualified target
307 //const float* FCDocument::FindAnimatedTarget(const fm::string& fullyQualifiedTarget)
308 //{
309 //	if (fullyQualifiedTarget.empty()) return NULL;
310 //	fm::string target = (fullyQualifiedTarget[0] == '#') ? fullyQualifiedTarget.substr(1) : fullyQualifiedTarget;
311 //	fm::string pointer, qualifier;
312 //	FUStringConversion::SplitTarget(target, pointer, qualifier);
313 //
314 //	// Find the pointer
315 //	FCDAnimated* animatedValue = NULL;
316 //	for (FCDAnimatedSet::iterator itA = animatedValues.begin(); itA != animatedValues.end(); ++itA)
317 //	{
318 //		FCDAnimated* animated = (*itA).first;
319 //		if (animated->GetTargetPointer() == pointer) { animatedValue = animated; break; }
320 //	}
321 //	if (animatedValue == NULL) return NULL;
322 //
323 //	// Return the qualified value
324 //	size_t index = animatedValue->FindQualifier(qualifier);
325 //	if (index == size_t(-1)) return NULL;
326 //	return animatedValue->GetValue(index);
327 //}
328 //
329 //// Returns whether a given value pointer is animated
330 //bool FCDocument::IsValueAnimated(const float* ptr) const
331 //{
332 //	const FCDAnimated* animated = FindAnimatedValue(ptr);
333 //	return (animated != NULL) ? animated->HasCurve() : false;
334 //}
335 
336 // Insert new library elements
AddVisualScene()337 FCDSceneNode* FCDocument::AddVisualScene()
338 {
339 	FCDSceneNode* visualScene = visualSceneLibrary->AddEntity();
340 	if (visualSceneRoot->GetEntity() == NULL) visualSceneRoot->SetEntity(visualScene);
341 	return visualScene;
342 }
AddPhysicsScene()343 FCDPhysicsScene* FCDocument::AddPhysicsScene()
344 {
345 	FCDPhysicsScene* physicsScene = physicsSceneLibrary->AddEntity();
346 	AddPhysicsSceneInstance(physicsScene);
347 	return physicsScene;
348 }
349 
SetFileUrl(const fstring & filename)350 void FCDocument::SetFileUrl(const fstring& filename)
351 {
352 	fileManager->PopRootFile();
353 	fileUrl = GetFileManager()->GetCurrentUri().MakeAbsolute(filename);
354 	fileManager->PushRootFile(fileUrl);
355 }
356 
SetCurrentTime(float time)357 void FCDocument::SetCurrentTime(float time)
358 {
359 	for (FCDAnimatedSet::iterator itA = animatedValues.begin(); itA != animatedValues.end(); ++itA)
360 	{
361 		FCDAnimated* animated = (*itA).first;
362 		animated->Evaluate(time);
363 	}
364 
365 	// We must evaluate all our child documents as well!
366 	for (size_t i = 0; i < externalReferenceManager->GetPlaceHolderCount(); i++)
367 	{
368 		FCDPlaceHolder* placeHolder = externalReferenceManager->GetPlaceHolder(i);
369 		if (placeHolder->IsTargetLoaded()) placeHolder->GetTarget()->SetCurrentTime(time);
370 	}
371 }
372 
373 // More linker-tricking for DLL support.
CreateLibraryFunctions(FCDocument * doc)374 extern bool CreateLibraryFunctions(FCDocument* doc)
375 {
376 	doc->GetForceFieldLibrary()->GetEntityCount();
377 	doc->GetForceFieldLibrary()->GetEntity(0);
378 	doc->GetImageLibrary()->GetEntityCount();
379 	doc->GetImageLibrary()->GetEntity(0);
380 	doc->GetPhysicsMaterialLibrary()->GetEntityCount();
381 	doc->GetPhysicsMaterialLibrary()->GetEntity(0);
382 	doc->GetPhysicsModelLibrary()->GetEntityCount();
383 	doc->GetPhysicsModelLibrary()->GetEntity(0);
384 	return true;
385 }
386