You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

274 lines
7.0 KiB

/*==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 <http://www.gnu.org/licenses/>.
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());
}
}