|
|
|
/*==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/>.
|
|
|
|
|
|
|
|
Additional permissions under GNU GPL version 3 section 7
|
|
|
|
|
|
|
|
If you modify this Program, or any covered work, by linking or
|
|
|
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
|
|
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
|
|
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
|
|
|
(or a modified version of those libraries),
|
|
|
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
|
|
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
|
|
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
|
|
|
licensors of this Program grant you additional
|
|
|
|
permission to convey the resulting work. Corresponding Source for a
|
|
|
|
non-source form of such a combination shall include the source code for
|
|
|
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
|
|
|
work.
|
|
|
|
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
}
|