/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #include "hsTypes.h" #include "hsConverterUtils.h" #include "hsResMgr.h" #if HS_BUILD_FOR_WIN32 #include #include "hsMaxLayerBase.h" #include "../plInterp/plController.h" #include "../MaxExport/plErrorMsg.h" #include "UserPropMgr.h" #include "hsStringTokenizer.h" //#include "hsDXTDirectXCodec.h" //#include "hsDXTSoftwareCodec.h" #include "../plGImage/hsCodecManager.h" ///#include "SwitchUtil.h" #include "hsExceptionStack.h" #include "hsHashTable.h" #include "../pnKeyedObject/plKey.h" #include "../pnKeyedObject/hsKeyedObject.h" const char hsConverterUtils::fTagSeps[] = " ,\t\n=:;"; extern UserPropMgr gUserPropMgr; namespace { class ObjectInstancedEnumProc : public DependentEnumProc { public: ObjectInstancedEnumProc() : fInstanceCount(0) { } int proc(ReferenceMaker *rmaker) { hsGuardBegin("ObjectInstancedEnumProc::proc"); if (rmaker->SuperClassID()==BASENODE_CLASS_ID) { fInstanceCount++; } return 0; hsGuardEnd; } Int32 GetInstanceCount() { return fInstanceCount; } private: Int32 fInstanceCount; }; } hsConverterUtils& hsConverterUtils::Instance() { static hsConverterUtils the_instance; return the_instance; } hsConverterUtils::hsConverterUtils() : fInterface(GetCOREInterface()), fErrorMsg(nil), fSuppressMangling(false), fWarned(0) { } void hsConverterUtils::Init(hsBool save, plErrorMsg *msg) { hsGuardBegin("hsConverterUtils::Init"); fErrorMsg = msg; fSuppressMangling = false; fWarned = 0; fSave = save; hsGuardEnd; } TimeValue hsConverterUtils::GetTime(Interface *gi) { hsGuardBegin("hsConverterUtils::GetTime"); return ((TimeValue)0); hsGuardEnd; // return gi->GetTime(); // return theSceneEnum->time; } hsBool hsConverterUtils::IsEnvironHolder(INode *node) { hsGuardBegin("hsConverterUtils::IsEnvironHolder"); return (gUserPropMgr.UserPropExists(node, "EnvironMap")); hsGuardEnd; } hsBool hsConverterUtils::AutoStartDynamics(INode *node) { hsGuardBegin("hsConverterUtils::AutoStartDynamics"); return (gUserPropMgr.UserPropExists(node,"AutoStart") || gUserPropMgr.UserPropExists(node,"aud")); hsGuardEnd; } hsBool hsConverterUtils::RandomStartDynamics(INode *node) { hsGuardBegin("hsConverterUtils::RandomStartDynamics"); return (gUserPropMgr.UserPropExists(node,"RandomStart")); hsGuardEnd; } void hsConverterUtils::StripOffTail(char* path) { hsGuardBegin("hsConverterUtils::StripOffTail"); int i = strlen(path)-1; while(path[i] != '\\') i--; path[i+1] = 0; hsGuardEnd; } void hsConverterUtils::StripOffPath(char* fileName) { hsGuardBegin("hsConverterUtils::StripOffPath"); char tmp[256]; // Remove preceding path int i = strlen(fileName)-1; while(fileName[i] != '\\') i--; strcpy(tmp, fileName+i+1); strcpy(fileName, tmp); hsGuardEnd; } // // static // hsBool hsConverterUtils::IsReservedKeyword(const char* nodeName) { hsGuardBegin("hsConverterUtils::IsReservedKeyword"); return (nodeName!=nil && ( !_stricmp(nodeName, "theplayer") || !_stricmp(nodeName, "the_player") || !_stricmp(nodeName, "thecamera") || !_stricmp(nodeName, "the_camera") || !_stricmp(nodeName, "thedetector") || !_stricmp(nodeName, "the_detector") || !_stricmp(nodeName, "themonitor") || !_stricmp(nodeName, "the_monitor") || !_stricmp(nodeName, "thedetectorshape") || !_stricmp(nodeName, "the_detector_shape")) ); hsGuardEnd; } char *hsConverterUtils::MangleReference(char *mangName, const char *nodeName, const char* defRoom) { hsGuardBegin("hsConverterUtils::MangleReference"); //hsAssert(nodeName, "No node name in hsConverterUtils::MangleReference."); if(!nodeName) { fErrorMsg->Set(true, "Mangle Reference Error", "No node name in hsConverterUtils::MangleReference.").Show(); fErrorMsg->Set(); return mangName; } if (!*nodeName) return hsStrcpy(mangName, nodeName); // doesn't want to be mangled if (('.' == nodeName[0])&&('.' == nodeName[1])) return hsStrcpy(mangName, nodeName + 2); // already mangled or reserved if (strstr(nodeName, "..") || IsReservedKeyword(nodeName)) return hsStrcpy(mangName, nodeName); INode *node = GetINodeByName(nodeName); if (!node) { // no room so make global // Default is to make it global, but you can set another default (like same // room as referencer) with defRoom. char tempName[256]; sprintf(tempName, "%s..%s", defRoom, nodeName); return hsStrcpy(mangName, tempName); } return MangleReference(mangName, node); hsGuardEnd; } char *hsConverterUtils::MangleReference(char *mangName, INode *node, const char* defRoom) { hsGuardBegin("hsConverterUtils::MangleReference"); if (!node) return nil; char tempName[256]; char *nodeName = node->GetName(); char *roomName = nil; TSTR sdata; hsStringTokenizer toker; if (gUserPropMgr.GetUserPropString(node, "Rooms", sdata)) { toker.Reset(sdata, fTagSeps); roomName = toker.next(); } if (fSuppressMangling) { return hsStrcpy(mangName, nodeName); } if (('.' == nodeName[0])&&('.' == nodeName[1])) hsStrcpy(tempName, nodeName + 2); else if (!*nodeName || strstr(nodeName, "..") || IsReservedKeyword(nodeName) ) hsStrcpy(tempName, nodeName); else if (roomName && *roomName) sprintf(tempName, "%s..%s", roomName, nodeName); else sprintf(tempName, "%s..%s", defRoom, nodeName); return hsStrcpy(mangName, tempName); hsGuardEnd; } char *hsConverterUtils::MangleRefWithRoom(char *mangName, const char *nodeName, const char* roomName) { hsGuardBegin("hsConverterUtils::MangleRefWithRoom"); //hsAssert(nodeName && roomName, "No node or room name in hsConverterUtils::MangleRefWithRoom."); if(!(nodeName && roomName)) { fErrorMsg->Set(true, "Mangle Room Reference Error", "No node or room name in hsConverterUtils::MangleRefWithRoom.").Show(); fErrorMsg->Set(); return mangName; } if (!*nodeName) return hsStrcpy(mangName,nodeName); // doesn't want to be mangled if (('.' == nodeName[0])&&('.' == nodeName[1])) return hsStrcpy(mangName, nodeName + 2); // already mangled or reserved if (strstr(nodeName, "..") || IsReservedKeyword(nodeName)) return hsStrcpy(mangName, nodeName); sprintf(mangName, "%s..%s", roomName, nodeName); return mangName; hsGuardEnd; } INode* hsConverterUtils::FindINodeFromMangledName(const char* mangName) { hsGuardBegin("hsConverterUtils::FindINodeFromMangledName"); if( !(mangName && *mangName) ) return nil; const char* nodeName = mangName; char* p; while( p = strstr(nodeName, "..") ) { nodeName = p + 2; } if( !(nodeName && *nodeName) ) nodeName = mangName; return GetINodeByName(nodeName); hsGuardEnd; } INode* hsConverterUtils::FindINodeFromKeyedObject(hsKeyedObject* obj) { hsGuardBegin("hsConverterUtils::FindINodeFromKeyedObject"); INode* retVal = FindINodeFromMangledName(obj->GetKey()->GetName()); if( retVal ) return (retVal); /* No more other Keys plasma 2.0 int i; for( i = 0; i < obj->GetNumOtherKeys(); i++ ) { retVal = FindINodeFromMangledName(obj->GetOtherKey(i)->GetName()); if( retVal ) return retVal; } */ return nil; hsGuardEnd; } // Uses MangleRef so all mangling happens in one place. Compares the name with a mangled version of it hsBool hsConverterUtils::IsMangled(const char *name) { hsGuardBegin("hsConverterUtils::IsMangled"); char mang[255]; return !strcmp(name,MangleReference(mang,name)); hsGuardEnd; } // Undoes the process of mangling. This includes taking a "name" back to "..name" char *hsConverterUtils::UnMangleReference(char *dest, const char *name) { hsGuardBegin("hsConverterUtils::IsMangled"); char *u = strstr(name,".."); if (u) { u+=2; strcpy(dest,u); } else if (!IsMangled(name)) { strcpy(dest,".."); strcat(dest,name); } else { strcpy(dest,name); } return dest; hsGuardEnd; } // Similar to UnMangle but doesn't take "name" back to "..name" char* hsConverterUtils::StripMangledReference(char* dest, const char* name) { hsGuardBegin("hsConverterUtils::StripMangledReference"); char *u = strstr(name,".."); if (u) { u+=2; strcpy(dest,u); } else { strcpy(dest,name); } return dest; hsGuardEnd; } Int32 hsConverterUtils::FindNamedSelSetFromName(const char *name) { hsGuardBegin("hsConverterUtils::FindNamedSelSetFromName"); for (Int32 i=0; iGetNumNamedSelSets(); i++) { if (!_stricmp(name, fInterface->GetNamedSelSetName(i))) return (i); } return (-1); hsGuardEnd; } hsBool hsConverterUtils::IsInstanced(Object* maxObject) { hsGuardBegin("hsConverterUtils::IsInstanced"); if (!maxObject) { return false; } ObjectInstancedEnumProc instProc; maxObject->EnumDependents(&instProc); return (instProc.GetInstanceCount() > 1); hsGuardEnd; } INode* hsConverterUtils::IGetINodeByNameRecur(INode* node, const char* wantName) { hsGuardBegin("hsConverterUtils::IGetINodeByNameRecur"); if (!node || !node->GetName()) return nil; char* nodeName=node->GetName(); if (!_stricmp(nodeName, wantName)) return node; // Process children int num = node->NumberOfChildren(); int i; for(i=0; iGetChildNode(i), wantName))) return ret; } return nil; hsGuardEnd; } // // Matches name against node's name, case-insensitive, // INode* hsConverterUtils::GetINodeByName(const char* name, hsBool caseSensitive) { hsGuardBegin("hsConverterUtils::GetINodeByName"); if (!name) { return nil; } if (fNodeSearchCache) { CacheNode cNode(name); cNode.SetCaseSensitive(caseSensitive); hsHashTableIterator it = fNodeSearchCache->find(cNode); return it->GetNode(); } //hsAssert(fInterface, "nil fInterface in hsConverterUtils::GetINodeByName()"); if(!fInterface) { fErrorMsg->Set(true, "Get INode by Name Error", "nil fInterface in hsConverterUtils::GetINodeByName()").Show(); fErrorMsg->Set(); return NULL; } if (caseSensitive) { return fInterface->GetINodeByName(name); } return IGetINodeByNameRecur(fInterface->GetRootNode(), name); hsGuardEnd; } void hsConverterUtils::CreateNodeSearchCache() { if (!fNodeSearchCache) { fNodeSearchCache = TRACKED_NEW hsHashTable(); } fNodeSearchCache->clear(); IBuildNodeSearchCacheRecur(fInterface->GetRootNode()); } void hsConverterUtils::DestroyNodeSearchCache() { delete fNodeSearchCache; fNodeSearchCache = nil; } void hsConverterUtils::IBuildNodeSearchCacheRecur(INode* node) { if (!node || !node->GetName()) return ; CacheNode cNode(node); fNodeSearchCache->insert(cNode); // Process children int num = node->NumberOfChildren(); int i; for(i=0; iGetChildNode(i)); } } UInt32 hsConverterUtils::CacheNode::GetHash() const { const char* k = GetName(); int len = k ? strlen(k) : 0; for (int h=len; len--;) { h = ((h<<5)^(h>>27))^tolower(*k++); } return h; } bool hsConverterUtils::CacheNode::operator==(const CacheNode& other) const { const char* k1 = GetName(); const char* k2 = other.GetName(); if (other.fCaseSensitive || fCaseSensitive) return !strcmp(k1,k2); else return !_stricmp(k1,k2); } #endif // HS_BUILD_FOR_WIN32