/*==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 "HeadSpin.h" #include "plMtlCollector.h" #include "../MaxPlasmaMtls/Layers/plPlasmaMAXLayer.h" #include "../MaxPlasmaMtls/Materials/plCompositeMtl.h" #include "../MaxPlasmaMtls/Materials/plDecalMtl.h" #include "../MaxPlasmaMtls/Materials/plMultipassMtl.h" #include "../MaxPlasmaMtls/Materials/plParticleMtl.h" #include "../MaxPlasmaMtls/Materials/plPassMtl.h" #include "../MaxPlasmaMtls/Materials/plClothingMtl.h" #include "../MaxComponent/plGUIComponents.h" #include "../MaxComponent/pfGUISkinComp.h" #include "../MaxComponent/plMiscComponents.h" #include "../MaxMain/plMaxNodeBase.h" static bool IsPlasmaMtl(Mtl *mtl) { if (mtl->ClassID() == COMP_MTL_CLASS_ID || mtl->ClassID() == DECAL_MTL_CLASS_ID || mtl->ClassID() == MULTIMTL_CLASS_ID || mtl->ClassID() == PARTICLE_MTL_CLASS_ID || mtl->ClassID() == PASS_MTL_CLASS_ID || mtl->ClassID() == CLOTHING_MTL_CLASS_ID) return true; return false; } static bool IsTexmapOK(Texmap *tex, UInt8 flags) { if (flags & plMtlCollector::kPlasmaOnly && !plPlasmaMAXLayer::GetPlasmaMAXLayer(tex)) return false; return true; } static bool IsMtlOK(Mtl *mtl, UInt8 flags) { if (flags & plMtlCollector::kPlasmaOnly && !IsPlasmaMtl(mtl)) return false; if (flags & plMtlCollector::kNoMultiMtl && mtl->ClassID() == MULTIMTL_CLASS_ID) return false; if (flags & plMtlCollector::kClothingMtlOnly && mtl->ClassID() != CLOTHING_MTL_CLASS_ID) return false; return true; } void GetMtlsRecur(MtlBase *mtlBase, MtlSet* mtls, TexSet* texmaps, UInt32 flags) { if (!mtlBase) return; if (mtlBase->SuperClassID() == TEXMAP_CLASS_ID) { Texmap* tex = (Texmap*)mtlBase; if (texmaps && IsTexmapOK(tex, flags)) texmaps->insert(tex); } else if(mtlBase->SuperClassID() == MATERIAL_CLASS_ID) { Mtl* mtl = (Mtl*)mtlBase; if (mtls && IsMtlOK(mtl, flags)) mtls->insert(mtl); // Get the bitmaps from all the textures this material contains int i; int numTex = mtl->NumSubTexmaps(); for (i = 0; i < numTex; i++) { Texmap *tex = mtl->GetSubTexmap(i); if (tex) { if (texmaps && IsTexmapOK(tex, flags)) texmaps->insert(tex); } } // Do the same for any submtls if (!(flags & plMtlCollector::kNoSubMtls)) { int numMtl = mtl->NumSubMtls(); for (i = 0; i < numMtl; i++) GetMtlsRecur(mtl->GetSubMtl(i), mtls, texmaps, flags); } } else { hsAssert(0, "What kind of material is this?"); } } static void GetTexmapPBs(Texmap* tex, PBSet& pbs) { if (!tex) return; plPlasmaMAXLayer *plasma = plPlasmaMAXLayer::GetPlasmaMAXLayer( tex ); if( plasma != nil ) { int i; for( i = 0; i < plasma->GetNumBitmaps(); i++ ) { PBBitmap *pbbm = plasma->GetPBBitmap( i ); if( pbbm != nil ) pbs.insert( pbbm ); } } else { for (int i = 0; i < tex->NumRefs(); i++) { ReferenceTarget* r = tex->GetReference(i); if (r && r->SuperClassID() == PARAMETER_BLOCK2_CLASS_ID) { IParamBlock2* pb = (IParamBlock2*)r; for (int j = 0; j < pb->NumParams(); j++) { if (pb->GetParameterType(pb->IndextoID(j)) == TYPE_BITMAP) { PBBitmap *pbbm = pb->GetBitmap(j); if (pbbm) pbs.insert(pbbm); } } } } } } #include "../MaxPlasmaLights/plRealTimeLightBase.h" static void GetNodeMtlsRecur(INode *node, MtlSet* mtls, TexSet* texmaps, UInt32 flags) { Mtl *mtl = node->GetMtl(); GetMtlsRecur(mtl, mtls, texmaps, flags); Object* obj = node->GetObjectRef(); if (obj && (obj->ClassID() == RTSPOT_LIGHT_CLASSID || obj->ClassID() == RTPDIR_LIGHT_CLASSID)) { Texmap* texmap = ((plRTLightBase*)obj)->GetProjMap(); GetMtlsRecur(texmap, mtls, texmaps, flags); } plGUIControlBase *gui = plGUIControlBase::GetGUIComp( node ); if( gui != nil ) { UInt32 i; for( i = 0; i < gui->GetNumMtls(); i++ ) GetMtlsRecur( gui->GetMtl( i ), mtls, texmaps, flags ); } else { // Skins aren't controls plGUISkinComp *guiSkin = plGUISkinComp::GetGUIComp( node ); if( guiSkin != nil ) { UInt32 i; for( i = 0; i < guiSkin->GetNumMtls(); i++ ) GetMtlsRecur( guiSkin->GetMtl( i ), mtls, texmaps, flags ); } else { // Um, other components plComponentBase *base = ( ( plMaxNodeBase *)node )->ConvertToComponent(); if( base != nil ) { if( base->ClassID() == IMAGE_LIB_CID ) { pfImageLibComponent *iLib = (pfImageLibComponent *)base; UInt32 i; for( i = 0; i < iLib->GetNumBitmaps(); i++ ) GetMtlsRecur( iLib->GetBitmap( i ), mtls, texmaps, flags ); } } } } for (int i = 0; i < node->NumberOfChildren(); i++) GetNodeMtlsRecur(node->GetChildNode(i), mtls, texmaps, flags); } static void GetEditorMtls(MtlSet* mtls, TexSet* texmaps, UInt32 flags) { static const int kNumEditorSlots = 24; Interface *ip = GetCOREInterface(); for (int i = 0; i < kNumEditorSlots; i++) { MtlBase *mtlBase = ip->GetMtlSlot(i); GetMtlsRecur(mtlBase, mtls, texmaps, flags); } } void plMtlCollector::GetMtls(MtlSet* mtls, TexSet* texmaps, UInt32 flags) { Interface *ip = GetCOREInterface(); // Make a list of all the textures from the GetSceneMtls() func MtlBaseLib* sceneMtls = ip->GetSceneMtls(); for(int i = 0; i < sceneMtls->Count(); i++) { GetMtlsRecur((*sceneMtls)[i], mtls, texmaps, flags); } // Add any more we find traversing the node hierarchy INode *root = ip->GetRootNode(); GetNodeMtlsRecur(root, mtls, texmaps, flags); if (!(flags & kUsedOnly)) GetEditorMtls(mtls, texmaps, flags); } void plMtlCollector::GetMtlLayers(Mtl *mtl, LayerSet& layers) { TexSet tex; GetMtlsRecur(mtl, nil, &tex, kPlasmaOnly); TexSet::iterator it = tex.begin(); for (; it != tex.end(); it++) { layers.insert((plPlasmaMAXLayer*)*it); } } void plMtlCollector::GetAllTextures(TexNameSet& texNames) { TexSet tex; GetMtls(nil, &tex); PBSet pbs; TexSet::iterator it = tex.begin(); for (; it != tex.end(); it++) GetTexmapPBs(*it, pbs); PBSet::iterator pbIt = pbs.begin(); for (; pbIt != pbs.end(); pbIt++) { PBBitmap* pbbm = *pbIt; texNames.insert(pbbm->bi.Name()); } }