From: <rly...@us...> - 2011-11-21 13:25:30
|
Revision: 7742 http://planeshift.svn.sourceforge.net/planeshift/?rev=7742&view=rev Author: rlydontknow Date: 2011-11-21 13:25:24 +0000 (Mon, 21 Nov 2011) Log Message: ----------- removed sanity check for triggers while parsing sequences as triggers aren't known at that point added sanity check for trivial loadables that'll prevent them from trying to be loaded if they have no data (which would result in undefined behaviour) Modified Paths: -------------- trunk/src/plugins/common/bgloader/loader.h trunk/src/plugins/common/bgloader/parser.cpp Modified: trunk/src/plugins/common/bgloader/loader.h =================================================================== --- trunk/src/plugins/common/bgloader/loader.h 2011-11-21 13:04:44 UTC (rev 7741) +++ trunk/src/plugins/common/bgloader/loader.h 2011-11-21 13:25:24 UTC (rev 7742) @@ -816,6 +816,11 @@ { if(!status.IsValid()) { + if(!data.IsValid()) + { + LOADER_DEBUG_MESSAGE("%s %s was created, but never parsed!\n", TypeName, GetName()); + return true; + } status = GetParent()->GetLoader()->LoadNode(path, data); } Modified: trunk/src/plugins/common/bgloader/parser.cpp =================================================================== --- trunk/src/plugins/common/bgloader/parser.cpp 2011-11-21 13:04:44 UTC (rev 7741) +++ trunk/src/plugins/common/bgloader/parser.cpp 2011-11-21 13:25:24 UTC (rev 7742) @@ -849,17 +849,19 @@ csString name(node->GetAttributeValue("trigger")); csRef<Trigger> t = parserData.triggers.Get(name); - if(t.IsValid()) + if(!t.IsValid()) { - AddDependency(t); + // not yet loaded, attach a new one + t.AttachNew(new Trigger(GetParent())); + parserData.triggers.Put(t, name); + + //csString msg; + //msg.Format("Invalid trigger reference '%s' in sequence '%s'", name.GetData(), GetName()); + //CS_ASSERT_MSG(msg.GetData(), false); + //failed = true; } - else - { - csString msg; - msg.Format("Invalid trigger reference '%s' in sequence '%s'", name.GetData(), GetName()); - CS_ASSERT_MSG(msg.GetData(), false); - failed = true; - } + + AddDependency(t); } break; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Rly...@us...> - 2012-03-23 14:25:02
|
Revision: 8131 http://planeshift.svn.sourceforge.net/planeshift/?rev=8131&view=rev Author: RlyDontKnow Date: 2012-03-23 14:24:53 +0000 (Fri, 23 Mar 2012) Log Message: ----------- parse and set maximum render distance for portals Modified Paths: -------------- trunk/src/plugins/common/bgloader/loader.h trunk/src/plugins/common/bgloader/loader_objects.cpp trunk/src/plugins/common/bgloader/parser.cpp Modified: trunk/src/plugins/common/bgloader/loader.h =================================================================== --- trunk/src/plugins/common/bgloader/loader.h 2012-03-23 13:57:41 UTC (rev 8130) +++ trunk/src/plugins/common/bgloader/loader.h 2012-03-23 14:24:53 UTC (rev 8131) @@ -1446,8 +1446,8 @@ public: typedef iMeshWrapper ObjectType; - Portal(BgLoader* parent) : Loadable(parent), flags(0), warp(false), ww_given(false), - wv(0.f), ww(0.f), + Portal(BgLoader* parent, float renderDist) : Loadable(parent), flags(0), renderDist(renderDist), + warp(false), ww_given(false), wv(0.f), ww(0.f), autoresolve(0), targetSector(0), sector(0) { } @@ -1466,6 +1466,7 @@ private: // parser results uint32 flags; + float renderDist; // transformation data bool warp; Modified: trunk/src/plugins/common/bgloader/loader_objects.cpp =================================================================== --- trunk/src/plugins/common/bgloader/loader_objects.cpp 2012-03-23 13:57:41 UTC (rev 8130) +++ trunk/src/plugins/common/bgloader/loader_objects.cpp 2012-03-23 14:24:53 UTC (rev 8131) @@ -409,6 +409,11 @@ mObject = GetParent()->GetEngine()->CreatePortal(GetName(), source, csVector3(0), target, poly.GetVertices(), (int)poly.GetVertexCount(), pObject); + if(renderDist > 0.f) + { + mObject->SetMaximumRenderDistance(renderDist); + } + // set name on portal object for debugging purposes pObject->SetName(GetName()); Modified: trunk/src/plugins/common/bgloader/parser.cpp =================================================================== --- trunk/src/plugins/common/bgloader/parser.cpp 2012-03-23 13:57:41 UTC (rev 8130) +++ trunk/src/plugins/common/bgloader/parser.cpp 2012-03-23 14:24:53 UTC (rev 8131) @@ -617,12 +617,19 @@ case PARSERTOKEN_PORTALS: { + csRef<iDocumentNode> renderDistNode = node->GetNode("maxrenderdist"); + float renderDist = 0.f; + if(renderDistNode.IsValid()) + { + renderDist = renderDistNode->GetAttributeValueAsFloat("value"); + } + csRef<iDocumentNodeIterator> it(node->GetNodes("portal")); while(it->HasNext()) { csRef<iDocumentNode> portalNode(it->Next()); csRef<Portal> p; - p.AttachNew(new Portal(GetParent())); + p.AttachNew(new Portal(GetParent(), renderDist)); if(p->Parse(portalNode, parserData)) { AddDependency(p); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lpa...@us...> - 2013-09-26 22:07:52
|
Revision: 8815 http://sourceforge.net/p/planeshift/code/8815 Author: lpancallo Date: 2013-09-26 22:07:50 +0000 (Thu, 26 Sep 2013) Log Message: ----------- patch to fix the loading of sequences and triggers by Ralph Campbell. Modified Paths: -------------- trunk/src/plugins/common/bgloader/loader.cpp trunk/src/plugins/common/bgloader/loader.h trunk/src/plugins/common/bgloader/loader_objects.cpp trunk/src/plugins/common/bgloader/parser.cpp trunk/src/plugins/common/bgloader/parser.tok Modified: trunk/src/plugins/common/bgloader/loader.cpp =================================================================== --- trunk/src/plugins/common/bgloader/loader.cpp 2013-09-25 22:55:00 UTC (rev 8814) +++ trunk/src/plugins/common/bgloader/loader.cpp 2013-09-26 22:07:50 UTC (rev 8815) @@ -44,7 +44,7 @@ SCF_IMPLEMENT_FACTORY(BgLoader) BgLoader::BgLoader(iBase *p) - : scfImplementationType (this, p), loadOffset(0), delayedOffset(0), loadCount(0), + : scfImplementationType (this, p), loadOffset(0), delayedOffset(0), loadRange(500), validPosition(false), loadStep(0), currRot_h(0), currRot_v(0), resetHitbeam(true) { } @@ -63,7 +63,7 @@ engine = csQueryRegistry<iEngine> (object_reg); g2d = csQueryRegistryOrLoad<iGraphics2D> (object_reg, "crystalspace.graphics2d.null"); - tloader = csQueryRegistryOrLoad<iThreadedLoader> (object_reg, "crystalspace.level.loader"); + tloader = csQueryRegistryOrLoad<iThreadedLoader> (object_reg, "crystalspace.level.threadedloader"); tman = csQueryRegistry<iThreadManager> (object_reg); vfs = csQueryRegistry<iVFS> (object_reg); parserData.svstrings = csQueryRegistryTagInterface<iShaderVarStringSet>(object_reg, "crystalspace.shader.variablenameset"); Modified: trunk/src/plugins/common/bgloader/loader.h =================================================================== --- trunk/src/plugins/common/bgloader/loader.h 2013-09-25 22:55:00 UTC (rev 8814) +++ trunk/src/plugins/common/bgloader/loader.h 2013-09-26 22:07:50 UTC (rev 8815) @@ -78,6 +78,15 @@ extern const char sector[7]; } +/** + * The BgLoader is a wrapper around the Crystalspace iThreadedLoader interface. + * The main idea is to read all the files that iThreadedLoader would read + * but instead of creating the iEngine objects, the XML information is saved + * and used later to create the iEngine objects. The iEngine objects are + * created when the player's character is moved across sectors or comes within + * visible range of an object. Thus, the BgLoader can load and unload + * iEngine objects as needed, saving memory and load time. + */ class BgLoader : public ThreadedCallable<BgLoader>, public scfImplementation3<BgLoader, iBgLoader, @@ -170,7 +179,7 @@ /** * Returns the number of objects currently loading. */ - size_t GetLoadingCount() { return loadCount; } + size_t GetLoadingCount() { return loadList.GetSize(); } /** * Returns a pointer to the object registry. @@ -312,7 +321,6 @@ void RegisterPendingObject(Loadable* obj) { CS::Threading::RecursiveMutexScopedLock lock(loadLock); - ++loadCount; loadList.Push(obj); } @@ -328,8 +336,6 @@ --loadOffset; } loadList.DeleteIndex(index); - - --loadCount; } // register delayed loader @@ -374,6 +380,9 @@ class Sector; class Zone; class Texture; + class MeshObj; + class Sequence; + class Light; struct ParserData; struct GlobalParserData; @@ -394,6 +403,9 @@ } }; + /** + * LockedType is used to store BgLoader objects. + */ template<typename T, bool check = true> struct LockedType { public: @@ -402,7 +414,7 @@ csStringSet stringSet; CS::Threading::ReadWriteMutex lock; - csPtr<T> Get(const csString& name) + csPtr<T> Get(const char* name) { csRef<T> object; CS::Threading::ScopedReadLock scopedLock(lock); @@ -444,7 +456,7 @@ } } - void Delete(const csString& name) + void Delete(const char* name) { CS::Threading::ScopedWriteLock scopedLock(lock); if(stringSet.Contains(name)) @@ -479,6 +491,7 @@ } }; + // Loaded unconditionally - not range based. class AlwaysLoaded { public: @@ -493,6 +506,9 @@ } }; + /** + * Base class for BgLoader objects. + */ class Loadable : public csObject { public: @@ -511,6 +527,9 @@ { } + /* + * Return true if underlying CS object was loaded. + */ bool Load(bool wait = false) { CS::Threading::RecursiveMutexScopedLock lock(busy); @@ -857,8 +876,7 @@ csRef<iBase> rawObj = status->GetResultRefPtr(); if(rawObj.IsValid()) { - csRef<T> obj = scfQueryInterface<T>(status->GetResultRefPtr()); - return csPtr<T>(obj); + return scfQueryInterface<T>(rawObj); } } @@ -1027,19 +1045,24 @@ } // workaround for bug in gcc 4.0: fails to parse default function argument in template classes - const csRef<T>& GetDependency(const csString& name) const + const csRef<T>& GetDependency(const char* name) const { return GetDependency(name, csRef<T>()); } - const csRef<T>& GetDependency(const csString& name, const csRef<T>& fallbackobj) const + const csRef<T>& GetDependency(const char* name, const csRef<T>& fallbackobj) const { CS::Threading::RecursiveMutexScopedLock lock(busy); - HashObjectType fallback(fallbackobj); const HashObjectType& ref = objects.Get(name,fallbackobj); return ref.obj; } + bool HasDependency(const char* name) const + { + CS::Threading::RecursiveMutexScopedLock lock(busy); + return objects.Contains(name); + } + HashType& GetDependencies() { return objects; @@ -1147,28 +1170,55 @@ void ParseMaterialReference(GlobalParserData& data, const char* name, const char* parentName, const char* type); }; - class Trigger : public TrivialLoadable<iSequenceTrigger,ObjectNames::trigger>, public AlwaysLoaded + class Trigger : public ObjectLoader<Sequence>, + public ObjectLoader<MeshObj>, + public ObjectLoader<Light>, + public TrivialLoadable<iSequenceTrigger,ObjectNames::trigger>, + public AlwaysLoaded { public: + using ObjectLoader<Sequence>::AddDependency; + using ObjectLoader<MeshObj>::AddDependency; + using ObjectLoader<Light>::AddDependency; + Trigger(BgLoader* parent) : TrivialLoadable<iSequenceTrigger,ObjectNames::trigger>(parent) { } bool LoadObject(bool wait) { - return TrivialLoadable<iSequenceTrigger,ObjectNames::trigger>::LoadObject(true); + bool ready = ObjectLoader<Sequence>::LoadObjects(true); + ready &= ObjectLoader<MeshObj>::LoadObjects(true); + ready &= ObjectLoader<Light>::LoadObjects(true); + ready &= TrivialLoadable<iSequenceTrigger,ObjectNames::trigger>::LoadObject(true); + return ready; + //return TrivialLoadable<iSequenceTrigger,ObjectNames::trigger>::LoadObject(true); } + void UnloadObject() + { + TrivialLoadable<iSequenceTrigger,ObjectNames::trigger>::UnloadObject(); + ObjectLoader<Sequence>::UnloadObjects(); + ObjectLoader<MeshObj>::UnloadObjects(); + ObjectLoader<Light>::UnloadObjects(); + } + bool Parse(iDocumentNode* node, ParserData& data); }; - class Sequence : public ObjectLoader<Sequence>, public ObjectLoader<Trigger>, + class Sequence : public ObjectLoader<Sequence>, + public ObjectLoader<Trigger>, + public ObjectLoader<Light>, + public ObjectLoader<MeshObj>, + public MaterialLoader, public TrivialLoadable<iSequenceWrapper,ObjectNames::sequence>, public AlwaysLoaded { public: using ObjectLoader<Sequence>::AddDependency; using ObjectLoader<Trigger>::AddDependency; + using ObjectLoader<Light>::AddDependency; + using ObjectLoader<MeshObj>::AddDependency; Sequence(BgLoader* parent) : TrivialLoadable<iSequenceWrapper,ObjectNames::sequence>(parent) { @@ -1184,6 +1234,11 @@ bool ready = true; if(ready) { + ready = ObjectLoader<MeshObj>::LoadObjects(wait); + } + + if(ready) + { ready = ObjectLoader<Sequence>::LoadObjects(wait); } @@ -1201,21 +1256,18 @@ void UnloadObject() { + TrivialLoadable<iSequenceWrapper,ObjectNames::sequence>::UnloadObject(); + ObjectLoader<Sequence>::UnloadObjects(); ObjectLoader<Trigger>::UnloadObjects(); - ObjectLoader<Sequence>::UnloadObjects(); - TrivialLoadable<iSequenceWrapper,ObjectNames::sequence>::UnloadObject(); + ObjectLoader<MeshObj>::UnloadObjects(); } }; - class Light : public Loadable, public RangeBased, public ObjectLoader<Sequence>, - public ObjectLoader<Trigger> + class Light : public Loadable, public RangeBased { public: typedef iLight ObjectType; - using ObjectLoader<Sequence>::AddDependency; - using ObjectLoader<Trigger>::AddDependency; - Light(BgLoader* parent) : Loadable(parent) { } @@ -1227,8 +1279,7 @@ csPtr<iLight> GetObject() { - csRef<iLight> obj(light); - return csPtr<iLight>(obj); + return csPtr<iLight>(light); } private: @@ -1371,15 +1422,12 @@ class MeshObj : public TrivialLoadable<iMeshWrapper,ObjectNames::meshobj>, public RangeBased, public ObjectLoader<Texture>, - public MaterialLoader, public ObjectLoader<MeshFact>, - public ObjectLoader<Sequence>, public ObjectLoader<Trigger> + public MaterialLoader, public ObjectLoader<MeshFact> { public: using ObjectLoader<Texture>::AddDependency; using ObjectLoader<Material>::AddDependency; using ObjectLoader<MeshFact>::AddDependency; - using ObjectLoader<Sequence>::AddDependency; - using ObjectLoader<Trigger>::AddDependency; MeshObj(BgLoader* parent) : TrivialLoadable<iMeshWrapper,ObjectNames::meshobj>(parent) { @@ -1729,6 +1777,8 @@ /* Internal unloading methods. */ void CleanDisconnectedSectors(Sector* sector); + bool LoadSequencesAndTriggers (iDocumentNode* snode, iDocumentNode* tnode, ParserData& data); + // Pointers to other needed plugins. iObjectRegistry* object_reg; csRef<iEngine> engine; @@ -1749,9 +1799,6 @@ csArray<csPtrKey<Loadable> > loadList; csArray<csPtrKey<iDelayedLoader> > delayedLoadList; - // number of objects currently loading - size_t loadCount; - // Our load range ^_^ float loadRange; Modified: trunk/src/plugins/common/bgloader/loader_objects.cpp =================================================================== --- trunk/src/plugins/common/bgloader/loader_objects.cpp 2013-09-25 22:55:00 UTC (rev 8814) +++ trunk/src/plugins/common/bgloader/loader_objects.cpp 2013-09-26 22:07:50 UTC (rev 8815) @@ -145,22 +145,11 @@ parent->GetLights()->Add(light); } - // Load all light sequences. - bool ready = ObjectLoader<Sequence>::LoadObjects(wait); - - if(ready) - { - ready &= ObjectLoader<Trigger>::LoadObjects(wait); - } - - return ready; + return true; } void BgLoader::Light::UnloadObject() { - ObjectLoader<Trigger>::UnloadObjects(); - ObjectLoader<Sequence>::UnloadObjects(); - Loadable::CheckRemove<iLight,ObjectNames::light>(light); } @@ -289,16 +278,6 @@ ready = TrivialLoadable<iMeshWrapper,ObjectNames::meshobj>::LoadObject(wait); } - if(ready) - { - ready = ObjectLoader<Sequence>::LoadObjects(wait); - } - - if(ready) - { - ready &= ObjectLoader<Trigger>::LoadObjects(wait); - } - return ready; } @@ -346,9 +325,6 @@ void BgLoader::MeshObj::UnloadObject() { - ObjectLoader<Trigger>::UnloadObjects(); - ObjectLoader<Sequence>::UnloadObjects(); - TrivialLoadable<iMeshWrapper,ObjectNames::meshobj>::UnloadObject(); ObjectLoader<Texture>::UnloadObjects(); Modified: trunk/src/plugins/common/bgloader/parser.cpp =================================================================== --- trunk/src/plugins/common/bgloader/parser.cpp 2013-09-25 22:55:00 UTC (rev 8814) +++ trunk/src/plugins/common/bgloader/parser.cpp 2013-09-26 22:07:50 UTC (rev 8815) @@ -75,18 +75,18 @@ { csRef<iDocumentNode> shaderNode(nodeItr->Next()); - csString typeName(shaderNode->GetNode("type")->GetContentsValue()); - csString shaderName(shaderNode->GetAttributeValue("name")); + const char* typeName = shaderNode->GetNode("type")->GetContentsValue(); + const char* shaderName = shaderNode->GetAttributeValue("name"); csRef<iDocumentNode> file = shaderNode->GetNode("file"); if(file.IsValid()) { - csString fileName(file->GetContentsValue()); + const char* fileName = file->GetContentsValue(); if(parserData.shaders.Contains(fileName) == csArrayItemNotFound) { CS::Threading::ScopedWriteLock lock(parserData.shaderLock); - parserData.shaders.Push(file->GetContentsValue()); - csRef<iThreadReturn> shaderRet = tloader->LoadShader(path, file->GetContentsValue()); + parserData.shaders.Push(fileName); + csRef<iThreadReturn> shaderRet = tloader->LoadShader(path, fileName); if(parserData.config.blockShaderLoad) { shaderRet->Wait(); @@ -107,18 +107,18 @@ while(nodeItr->HasNext()) { csRef<iDocumentNode> aliasNode(nodeItr->Next()); - csString shaderName(aliasNode->GetAttributeValue("name")); + const char* shaderName = aliasNode->GetAttributeValue("name"); csString aliasName(aliasNode->GetAttributeValue("alias")); csRef<iDocumentNode> file = aliasNode->GetNode("file"); if(file.IsValid()) { - csString fileName(file->GetContentsValue()); + const char* fileName = file->GetContentsValue(); if(parserData.shaders.Contains(fileName) == csArrayItemNotFound) { CS::Threading::ScopedWriteLock lock(parserData.shaderLock); - parserData.shaders.Push(file->GetContentsValue()); - csRef<iThreadReturn> shaderRet = tloader->LoadShader(path, file->GetContentsValue()); + parserData.shaders.Push(fileName); + csRef<iThreadReturn> shaderRet = tloader->LoadShader(path, fileName); if(parserData.config.blockShaderLoad) { shaderRet->Wait(); @@ -409,7 +409,7 @@ case PARSERTOKEN_SECTOR: { - csString sectorName = node->GetContentsValue(); + const char* sectorName = node->GetContentsValue(); targetSector = csRef<Sector>(parserData.data.sectors.Get(sectorName)); if(!targetSector) @@ -759,7 +759,7 @@ case PARSERTOKEN_SETFOG: case PARSERTOKEN_FADEFOG: { - csString name(node->GetAttributeValue("sector")); + const char* name = node->GetAttributeValue("sector"); csRef<Sector> s = parserData.data.sectors.Get(name); if(s.IsValid()) @@ -770,7 +770,7 @@ else { csString msg; - msg.Format("Invalid sector reference '%s' in sequence '%s'", name.GetData(), GetName()); + msg.Format("Invalid sector reference '%s' in sequence '%s'", name, GetName()); CS_ASSERT_MSG(msg.GetData(), false); failed = true; } @@ -784,18 +784,17 @@ case PARSERTOKEN_ROTATE: case PARSERTOKEN_MOVE: { - csString name(node->GetAttributeValue("mesh")); + const char* name = node->GetAttributeValue("mesh"); csRef<MeshObj> m = parserData.data.meshes.Get(name); if(m.IsValid()) { - m->AddDependency(self); - parents.Push(m); + AddDependency(m); } else { csString msg; - msg.Format("Invalid mesh reference '%s' in sequence '%s'", name.GetData(), GetName()); + msg.Format("Invalid mesh reference '%s' in sequence '%s'", name, GetName()); CS_ASSERT_MSG(msg.GetData(), false); failed = true; } @@ -808,18 +807,17 @@ case PARSERTOKEN_FADELIGHT: case PARSERTOKEN_SETLIGHT: { - csString name(node->GetAttributeValue("light")); + const char* name = node->GetAttributeValue("light"); csRef<Light> l = parserData.lights.Get(name); if(l.IsValid()) { - l->AddDependency(self); - parents.Push(l); + AddDependency(l); } else { csString msg; - msg.Format("Invalid light reference '%s' in sequence '%s'", name.GetData(), GetName()); + msg.Format("Invalid light reference '%s' in sequence '%s'", name, GetName()); CS_ASSERT_MSG(msg.GetData(), false); failed = true; } @@ -829,7 +827,7 @@ // sequence types operating on a sequence. case PARSERTOKEN_RUN: { - csString name(node->GetAttributeValue("sequence")); + const char* name = node->GetAttributeValue("sequence"); csRef<Sequence> seq = parserData.sequences.Get(name); if(seq.IsValid()) @@ -840,7 +838,7 @@ else { csString msg; - msg.Format("Invalid sequence reference '%s' in sequence '%s'", name.GetData(), GetName()); + msg.Format("Invalid sequence reference '%s' in sequence '%s'", name, GetName()); CS_ASSERT_MSG(msg.GetData(), false); failed = true; } @@ -853,7 +851,7 @@ case PARSERTOKEN_CHECK: case PARSERTOKEN_TEST: { - csString name(node->GetAttributeValue("trigger")); + const char* name = node->GetAttributeValue("trigger"); csRef<Trigger> t = parserData.triggers.Get(name); if(t.IsValid()) @@ -863,14 +861,14 @@ else { csString msg; - msg.Format("Invalid trigger reference '%s' in sequence '%s'", name.GetData(), GetName()); + msg.Format("Invalid trigger reference '%s' in sequence '%s'", name, GetName()); CS_ASSERT_MSG(msg.GetData(), false); failed = true; } } break; - // miscallenous sequence types. + // miscellanous sequence types. case PARSERTOKEN_DELAY: case PARSERTOKEN_SETVAR: default: @@ -923,7 +921,7 @@ // triggers fired by a sector. case PARSERTOKEN_SECTORVIS: { - csString name(node->GetAttributeValue("sector")); + const char* name = node->GetAttributeValue("sector"); csRef<Sector> s = parserData.data.sectors.Get(name); if(s.IsValid()) @@ -934,7 +932,7 @@ else { csString msg; - msg.Format("Invalid sector reference '%s' in trigger '%s'", name.GetData(), GetName()); + msg.Format("Invalid sector reference '%s' in trigger '%s'", name, GetName()); CS_ASSERT_MSG(msg.GetData(), false); failed = true; } @@ -944,18 +942,17 @@ // triggers fired by a mesh. case PARSERTOKEN_ONCLICK: { - csString name(node->GetAttributeValue("mesh")); + const char* name = node->GetAttributeValue("mesh"); csRef<MeshObj> m = parserData.data.meshes.Get(name); if(m.IsValid()) { - m->AddDependency(self); - parents.Push(m); + AddDependency(m); } else { csString msg; - msg.Format("Invalid mesh reference '%s' in trigger '%s'", name.GetData(), GetName()); + msg.Format("Invalid mesh reference '%s' in trigger '%s'", name, GetName()); CS_ASSERT_MSG(msg.GetData(), false); failed = true; } @@ -965,18 +962,17 @@ // triggers fired by a light. case PARSERTOKEN_LIGHTVALUE: { - csString name(node->GetAttributeValue("light")); + const char* name = node->GetAttributeValue("light"); csRef<Light> l = parserData.lights.Get(name); if(l.IsValid()) { - l->AddDependency(self); - parents.Push(l); + AddDependency(l); } else { csString msg; - msg.Format("Invalid light reference '%s' in trigger '%s'", name.GetData(), GetName()); + msg.Format("Invalid light reference '%s' in trigger '%s'", name, GetName()); CS_ASSERT_MSG(msg.GetData(), false); failed = true; } @@ -986,25 +982,30 @@ // triggers fired by a sequence. case PARSERTOKEN_FIRE: { - csString name(node->GetAttributeValue("sequence")); + const char* name = node->GetAttributeValue("sequence"); csRef<Sequence> seq = parserData.sequences.Get(name); if(seq.IsValid()) { - seq->AddDependency(self); - parents.Push(seq); + // Since sequences are parsed first, if it has + // a dependency on this trigger, there is a loop. + if(seq->ObjectLoader<Trigger>::HasDependency(GetName())) + { + seq->ObjectLoader<Trigger>::RemoveDependency(this); + } + AddDependency(seq); } else { csString msg; - msg.Format("Invalid sequence reference '%s' in trigger '%s'", name.GetData(), GetName()); + msg.Format("Invalid sequence reference '%s' in trigger '%s'", name, GetName()); CS_ASSERT_MSG(msg.GetData(), false); failed = true; } } break; - // triggers fired by a miscallenous operation. + // triggers fired by a miscellanous operation. case PARSERTOKEN_MANUAL: default: { @@ -1099,6 +1100,8 @@ bool portalsOnly = parserData.config.portalsOnly; bool meshesOnly = parserData.config.meshesOnly; data.parsedMeshFact = false; + csRef<iDocumentNode> sequences; + csRef<iDocumentNode> triggers; csRef<iDocumentNodeIterator> nodeIt(root->GetNodes()); while(nodeIt->HasNext()) @@ -1230,7 +1233,7 @@ // Parse sector. case PARSERTOKEN_SECTOR: { - csString name(node->GetAttributeValue("name")); + const char* name = node->GetAttributeValue("name"); csRef<Sector> sector = parserData.sectors.Get(name); if(!sector.IsValid()) { @@ -1243,7 +1246,7 @@ parserData.sectors.Delete(name); csString msg; - msg.Format("Sector %s failed to parse!", name.GetData()); + msg.Format("Sector %s failed to parse!", name); CS_ASSERT_MSG(msg.GetData(), false); } } @@ -1269,39 +1272,7 @@ { break; } - - // do a 2 pass parsing of sequences - // first create all sequences. - csRef<iDocumentNodeIterator> sequenceIt(node->GetNodes("sequence")); - while(sequenceIt->HasNext()) - { - csRef<iDocumentNode> sequenceNode(sequenceIt->Next()); - csString sequenceName(sequenceNode->GetAttributeValue("name")); - - csRef<Sequence> seq; - seq.AttachNew(new Sequence(this)); - data.sequences.Put(seq, sequenceName); - } - - // now actually parse them. - sequenceIt = node->GetNodes("sequence"); - while(sequenceIt->HasNext()) - { - csRef<iDocumentNode> sequenceNode(sequenceIt->Next()); - csString sequenceName(sequenceNode->GetAttributeValue("name")); - - csRef<Sequence> seq = data.sequences.Get(sequenceName); - - if(!seq->Parse(sequenceNode, data)) - { - // failed to parse the sequence, remove it from the lookup table - data.sequences.Delete(sequenceName); - - csString msg; - msg.Format("Sequence %s failed to parse!", sequenceName.GetData()); - CS_ASSERT_MSG(msg.GetData(), false); - } - } + sequences = node; } break; @@ -1311,35 +1282,15 @@ { break; } - - csRef<iDocumentNodeIterator> triggerIt(node->GetNodes("trigger")); - while(triggerIt->HasNext()) - { - csRef<iDocumentNode> triggerNode(triggerIt->Next()); - csString triggerName(triggerNode->GetAttributeValue("name")); - - csRef<Trigger> trigger = data.triggers.Get(triggerName); - if(!trigger.IsValid()) - { - // not yet loaded, attach a new one - trigger.AttachNew(new Trigger(this)); - data.triggers.Put(trigger, triggerName); - } - - if(!trigger->Parse(triggerNode, data)) - { - // failed to parse the trigger, remove it from the lookup table - data.triggers.Delete(triggerName); - - csString msg; - msg.Format("Trigger %s failed to parse!", triggerName.GetData()); - CS_ASSERT_MSG(msg.GetData(), false); - } - } + triggers = node; } break; } } + // Sequences and triggers are parsed at the end because + // all sectors and other objects need to be present. + if (!LoadSequencesAndTriggers(sequences, triggers, data)) + return false; } // Wait for plugin and shader loads to finish. @@ -1348,6 +1299,121 @@ return true; } + + bool BgLoader::LoadSequencesAndTriggers (iDocumentNode* snode, + iDocumentNode* tnode, + ParserData& data) + { + // We load sequences and triggers in three passes. + // In the first pass, we will create all triggers. + // In the second pass, we will create and parse sequences. + // In the third pass, we will parse the triggers. + // This will create the data structures and dependencies but + // not the actual Crystalspace engine data structures until + // they are visible or needed. + // It also makes sure that sequences are created before triggers + // regardless of the order they may appear in the XML file. + + if (tnode) + { + csRef<iDocumentNodeIterator> it = tnode->GetNodes (); + while (it->HasNext ()) + { + csRef<iDocumentNode> child = it->Next (); + if (child->GetType () != CS_NODE_ELEMENT) + continue; + const char* value = child->GetValue (); + csStringID id = parserData.xmltokens.Request (value); + switch (id) + { + case PARSERTOKEN_TRIGGER: + { + const char* name = child->GetAttributeValue ("name"); + csRef<Trigger> trig; + trig.AttachNew(new Trigger(this)); + data.triggers.Put(trig, name); + trig->SetName(name); + } + break; + default: + parserData.syntaxService->ReportBadToken (child); + return false; + } + } + } + + if (snode) + { + csRef<iDocumentNodeIterator> it = snode->GetNodes (); + while (it->HasNext ()) + { + csRef<iDocumentNode> child = it->Next (); + if (child->GetType () != CS_NODE_ELEMENT) + continue; + const char* value = child->GetValue (); + csStringID id = parserData.xmltokens.Request (value); + switch (id) + { + case PARSERTOKEN_SEQUENCE: + { + const char* name = child->GetAttributeValue ("name"); + csRef<Sequence> seq; + seq.AttachNew(new Sequence(this)); + data.sequences.Put(seq, name); + if (!seq->Parse (child, data)) + { + data.sequences.Delete(name); + csString msg; + msg.Format("Sequence %s failed to parse!", name); + CS_ASSERT_MSG(msg.GetData(), false); + return false; + } + break; + } + default: + parserData.syntaxService->ReportBadToken (child); + return false; + } + } + } + + if (tnode) + { + csRef<iDocumentNodeIterator> it = tnode->GetNodes (); + while (it->HasNext ()) + { + csRef<iDocumentNode> child = it->Next (); + if (child->GetType () != CS_NODE_ELEMENT) + continue; + const char* value = child->GetValue (); + csStringID id = parserData.xmltokens.Request (value); + switch (id) + { + case PARSERTOKEN_TRIGGER: + { + const char* name = child->GetAttributeValue ("name"); + csRef<Trigger> trig (data.triggers.Get(name)); + if (!trig->Parse (child, data)) + { + // failed to parse the trigger, remove it from the lookup table + data.triggers.Delete(name); + csString msg; + msg.Format("Trigger %s failed to parse!", name); + CS_ASSERT_MSG(msg.GetData(), false); + return false; + } + break; + } + default: + parserData.syntaxService->ReportBadToken (child); + return false; + } + } + } + + return true; + } + } CS_PLUGIN_NAMESPACE_END(bgLoader) Modified: trunk/src/plugins/common/bgloader/parser.tok =================================================================== --- trunk/src/plugins/common/bgloader/parser.tok 2013-09-25 22:55:00 UTC (rev 8814) +++ trunk/src/plugins/common/bgloader/parser.tok 2013-09-26 22:07:50 UTC (rev 8815) @@ -22,7 +22,9 @@ CS_TOKEN_LIST_TOKEN(SECTOR) CS_TOKEN_LIST_TOKEN(START) CS_TOKEN_LIST_TOKEN(SEQUENCES) +CS_TOKEN_LIST_TOKEN(SEQUENCE) CS_TOKEN_LIST_TOKEN(TRIGGERS) +CS_TOKEN_LIST_TOKEN(TRIGGER) CS_TOKEN_LIST_TOKEN(PORTALS) // object types CS_TOKEN_LIST_TOKEN(MESHFACT) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |