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.
411 lines
12 KiB
411 lines
12 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/>. |
|
|
|
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 "plMaterialUpdate.h" |
|
|
|
#define MAXR3 |
|
#define MAXR4 |
|
|
|
//#include "OldMat/hsMaxMtl.h" |
|
#include "OldMat/hsMaxLayer.h" |
|
|
|
#include "../MaxPlasmaMtls/Layers/plLayerTex.h" |
|
#include "../MaxPlasmaMtls/Layers/plLayerTexBitmapPB.h" |
|
|
|
#include "../MaxPlasmaMtls/Materials/plPassMtl.h" |
|
#include "../MaxPlasmaMtls/Materials/plPassMtlBase.h" |
|
#include "../MaxPlasmaMtls/Materials/plPassMtlBasicPB.h" |
|
#include "../MaxPlasmaMtls/Materials/plPassMtlAdvPB.h" |
|
#include "../MaxPlasmaMtls/Materials/plPassMtlLayersPB.h" |
|
|
|
#include "../MaxExport/plExportProgressBar.h" |
|
|
|
#define PLMATERIALUPDATE_CLASS_ID Class_ID(0x70acddfe, 0x68f42f3f) |
|
|
|
#include <map> |
|
|
|
class plMaterialUpdate : public UtilityObj |
|
{ |
|
protected: |
|
HWND fhPanel; |
|
Interface *fInterface; |
|
std::map<MtlBase*, MtlBase*> fDoneMaterials; |
|
bool fConvertSecondLayer; |
|
|
|
plMaterialUpdate(); |
|
|
|
public: |
|
static plMaterialUpdate &Instance(); |
|
|
|
~plMaterialUpdate(); |
|
void DeleteThis() {} |
|
|
|
void BeginEditParams(Interface *ip,IUtil *iu); |
|
void EndEditParams(Interface *ip,IUtil *iu); |
|
|
|
bool ConvertAllMtls(INode *node, plExportProgressBar *bar); |
|
|
|
protected: |
|
static BOOL CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); |
|
|
|
void IRenameMtls(MtlBase *oldMtl, MtlBase *newMtl); |
|
|
|
void IConvert(INode *node); |
|
plPassMtl *IConvertMtl(Mtl *mtl, Mtl *multi=NULL, int subNum=-1); |
|
plLayerTex *IConvertLayer(hsMaxLayer *layer); |
|
|
|
void ICopyMtlParams(plPassMtl *mtl, hsMaxLayer *layer); |
|
}; |
|
|
|
class plMaterialUpdateClassDesc:public ClassDesc2 { |
|
public: |
|
int IsPublic() { return TRUE; } |
|
void * Create(BOOL loading = FALSE) { return &plMaterialUpdate::Instance(); } |
|
const TCHAR * ClassName() { return "Plasma Material Converter"; } |
|
SClass_ID SuperClassID() { return UTILITY_CLASS_ID; } |
|
Class_ID ClassID() { return PLMATERIALUPDATE_CLASS_ID; } |
|
const TCHAR* Category() { return GetString(IDS_CATEGORY); } |
|
|
|
const TCHAR* InternalName() { return _T("plMaterialConverter"); } // returns fixed parsable name (scripter-visible name) |
|
HINSTANCE HInstance() { return hInstance; } // returns owning module handle |
|
}; |
|
|
|
static plMaterialUpdateClassDesc plMaterialUpdateDesc; |
|
ClassDesc2* GetMaterialUpdateDesc() { return &plMaterialUpdateDesc; } |
|
|
|
plMaterialUpdate &plMaterialUpdate::Instance() |
|
{ |
|
static plMaterialUpdate theInstance; |
|
return theInstance; |
|
} |
|
|
|
plMaterialUpdate::plMaterialUpdate() : fInterface(NULL), fhPanel(NULL), fConvertSecondLayer(false) |
|
{ |
|
} |
|
|
|
plMaterialUpdate::~plMaterialUpdate() |
|
{ |
|
} |
|
|
|
BOOL plMaterialUpdate::DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
switch (msg) |
|
{ |
|
case WM_COMMAND: |
|
if (LOWORD(wParam) == IDC_BUTTON1 && HIWORD(wParam) == BN_CLICKED) |
|
{ |
|
plMaterialUpdate &p = Instance(); |
|
|
|
plExportProgressBar bar; |
|
bar.Start("Convert Materials"); |
|
|
|
if (IsDlgButtonChecked(hWnd, IDC_CHECK1) == BST_CHECKED) |
|
p.fConvertSecondLayer = true; |
|
|
|
p.ConvertAllMtls(p.fInterface->GetRootNode(), &bar); |
|
|
|
p.fInterface->RedrawViews(p.fInterface->GetTime()); |
|
p.fDoneMaterials.clear(); |
|
return TRUE; |
|
} |
|
break; |
|
} |
|
|
|
return FALSE; |
|
} |
|
|
|
void plMaterialUpdate::BeginEditParams(Interface *ip, IUtil *iu) |
|
{ |
|
fInterface = ip; |
|
fhPanel = fInterface->AddRollupPage( |
|
hInstance, |
|
MAKEINTRESOURCE(IDD_PANEL), |
|
DlgProc, |
|
GetString(IDS_PARAMS), |
|
0); |
|
} |
|
|
|
void plMaterialUpdate::EndEditParams(Interface *ip, IUtil *iu) |
|
{ |
|
fInterface->DeleteRollupPage(fhPanel); |
|
fInterface = NULL; |
|
fhPanel = NULL; |
|
} |
|
|
|
bool plMaterialUpdate::ConvertAllMtls(INode *node, plExportProgressBar *bar) |
|
{ |
|
IConvert(node); |
|
|
|
bool cancel = bar->Update(); |
|
if (cancel) |
|
return false; |
|
|
|
for (int i = 0; i < node->NumChildren(); i++) |
|
{ |
|
if (!ConvertAllMtls(node->GetChildNode(i), bar)) |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
void plMaterialUpdate::IConvert(INode *node) |
|
{ |
|
Mtl *mtl = node->GetMtl(); |
|
if (!mtl) |
|
return; |
|
|
|
if (mtl->ClassID() == hsMaxMtlClassID) |
|
{ |
|
plPassMtl *pass = IConvertMtl(mtl); |
|
node->SetMtl(pass); |
|
} |
|
else if (mtl->ClassID() == Class_ID(MULTI_CLASS_ID,0)) |
|
{ |
|
for (int i = 0; i < mtl->NumSubMtls(); i++) |
|
{ |
|
Mtl *subMtl = mtl->GetSubMtl(i); |
|
if (subMtl->ClassID() == hsMaxMtlClassID) |
|
{ |
|
plPassMtl *pass = IConvertMtl(subMtl, mtl, i); |
|
mtl->SetSubMtl(i, pass); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void plMaterialUpdate::IRenameMtls(MtlBase *oldMtl, MtlBase *newMtl) |
|
{ |
|
char buf[256]; |
|
const char *name = oldMtl->GetName(); |
|
newMtl->SetName(name); |
|
strcpy(buf, name); |
|
strcat(buf, " old"); |
|
oldMtl->SetName(buf); |
|
} |
|
|
|
plPassMtl *plMaterialUpdate::IConvertMtl(Mtl *mtl, Mtl *multi, int subNum) |
|
{ |
|
// We've already converted this material, use the new one we already made |
|
if (fDoneMaterials.find(mtl) != fDoneMaterials.end()) |
|
return (plPassMtl*)fDoneMaterials[mtl]; |
|
|
|
plPassMtl *newMtl = (plPassMtl*)CreateInstance(MATERIAL_CLASS_ID, PASS_MTL_CLASS_ID); |
|
IParamBlock2 *layersPB = newMtl->GetParamBlockByID(plPassMtl::kBlkLayers); |
|
|
|
IRenameMtls(mtl, newMtl); |
|
|
|
if (mtl->NumSubTexmaps() > 0) |
|
{ |
|
Texmap *map = mtl->GetSubTexmap(0); |
|
if (map->ClassID() == hsMaxLayerClassID) |
|
{ |
|
plLayerTex *layer = IConvertLayer((hsMaxLayer*)map); |
|
|
|
// layer->SetMtlFlag(MTL_TEX_DISPLAY_ENABLED, TRUE); |
|
// layer->ActivateTexDisplay(TRUE); |
|
|
|
newMtl->SetSubTexmap(0, layer); |
|
/* newMtl->SetActiveTexmap(layer); |
|
newMtl->SetMtlFlag(MTL_TEX_DISPLAY_ENABLED, TRUE); |
|
|
|
if (multi) |
|
GetCOREInterface()->ActivateTexture(layer, multi, subNum); |
|
else |
|
GetCOREInterface()->ActivateTexture(layer, newMtl); |
|
*/ |
|
ICopyMtlParams(newMtl, (hsMaxLayer*)map); |
|
} |
|
} |
|
|
|
if (mtl->NumSubTexmaps() > 1 && fConvertSecondLayer && mtl->SubTexmapOn(1)) |
|
{ |
|
Texmap *map = mtl->GetSubTexmap(1); |
|
if (map->ClassID() == hsMaxLayerClassID) |
|
{ |
|
hsMaxLayer *oldLayer = (hsMaxLayer*)map; |
|
plLayerTex *layer = IConvertLayer(oldLayer); |
|
newMtl->SetSubTexmap(1, layer); |
|
|
|
IParamBlock2 *layersPB = newMtl->GetParamBlockByID(plPassMtl::kBlkLayers); |
|
layersPB->SetValue(kPassLayTopOn, 0, TRUE); |
|
|
|
if (oldLayer->GetBlendFlags() & hsMaxLayerBase::kBlendAlpha) |
|
layersPB->SetValue(kPassLayBlend, 0, plPassMtlBase::kBlendAlpha); |
|
else if (oldLayer->GetBlendFlags() & hsMaxLayerBase::kBlendAdd) |
|
layersPB->SetValue(kPassLayBlend, 0, plPassMtlBase::kBlendAdd); |
|
} |
|
} |
|
|
|
//MtlBaseLib& Interface::GetMaterialLibrary() |
|
|
|
// Add this to our converted materials |
|
fDoneMaterials[mtl] = newMtl; |
|
|
|
return newMtl; |
|
} |
|
|
|
plLayerTex *plMaterialUpdate::IConvertLayer(hsMaxLayer *layer) |
|
{ |
|
plLayerTex *newLayer = (plLayerTex*)CreateInstance(TEXMAP_CLASS_ID, LAYER_TEX_CLASS_ID); |
|
IParamBlock2 *bitmapPB = newLayer->GetParamBlockByID(plLayerTex::kBlkBitmap); |
|
|
|
IRenameMtls(layer, newLayer); |
|
|
|
// Copy the bitmap |
|
if (layer->GetMiscFlags() & hsMaxLayerBase::kMiscUseBitmap) |
|
{ |
|
bitmapPB->SetValue(kBmpUseBitmap, 0, 1); |
|
|
|
const char *name = layer->GetMapName(); |
|
PBBitmap pbb; |
|
pbb.bi.SetName(name); |
|
|
|
// Disable annoying missing texture warning |
|
BOOL bmmSilentMode = TheManager->SilentMode(); |
|
TheManager->SetSilentMode(TRUE); |
|
|
|
bitmapPB->SetValue(kBmpBitmap, 0, &pbb); |
|
|
|
TheManager->SetSilentMode(bmmSilentMode); |
|
} |
|
|
|
// Copy the UVGen |
|
newLayer->ReplaceReference(plLayerTex::kRefUVGen, layer->GetUVGen()); |
|
|
|
// Copy the cropping |
|
if (layer->GetApplyCrop()) |
|
{ |
|
bitmapPB->SetValue(kBmpApply, 0, TRUE); |
|
bitmapPB->SetValue(kBmpCropPlace, 0, layer->GetPlaceImage()); |
|
|
|
bitmapPB->SetValue(kBmpClipU, 0, layer->GetClipU(0)); |
|
bitmapPB->SetValue(kBmpClipV, 0, layer->GetClipV(0)); |
|
bitmapPB->SetValue(kBmpClipW, 0, layer->GetClipW(0)); |
|
bitmapPB->SetValue(kBmpClipH, 0, layer->GetClipH(0)); |
|
} |
|
|
|
// Misc |
|
if (layer->GetBlendFlags() & hsMaxLayerBase::kBlendNoColor) |
|
bitmapPB->SetValue(kBmpDiscardColor, 0, TRUE); |
|
if (layer->GetBlendFlags() & hsMaxLayerBase::kBlendInvertColor) |
|
bitmapPB->SetValue(kBmpInvertColor, 0, TRUE); |
|
if (layer->GetAlphaSource() == 2) |
|
bitmapPB->SetValue(kBmpDiscardAlpha, 0, TRUE); |
|
if (layer->GetBlendFlags() & hsMaxLayerBase::kBlendInvertAlpha) |
|
bitmapPB->SetValue(kBmpInvertAlpha, 0, TRUE); |
|
|
|
/* |
|
// Texture quality |
|
kBmpNonCompressed, |
|
kBmpScaling, |
|
*/ |
|
|
|
// Mipmap |
|
if (layer->GetFilterType() == 2) |
|
bitmapPB->SetValue(kBmpNoFilter, 0, TRUE); |
|
|
|
float blur = layer->GetMipMapBlur(TimeValue(0)); |
|
bitmapPB->SetValue(kBmpMipBlur, 0, blur); |
|
|
|
if (layer->GetZFlags() & hsMaxLayerBase::kZLODBias) |
|
{ |
|
bitmapPB->SetValue(kBmpMipBias, 0, TRUE); |
|
bitmapPB->SetValue(kBmpMipBiasAmt, 0, layer->GetLODBias(TimeValue(0))); |
|
} |
|
|
|
// Detail |
|
if (layer->GetBlendFlags() & hsMaxLayerBase::kBlendDetail || |
|
layer->GetBlendFlags() & hsMaxLayerBase::kBlendDetailAdd) |
|
{ |
|
bitmapPB->SetValue(kBmpUseDetail, 0, TRUE); |
|
|
|
bitmapPB->SetValue(kBmpDetailStartSize, 0, layer->GetDetailDropoffStart(0)); |
|
bitmapPB->SetValue(kBmpDetailStopSize, 0, layer->GetDetailDropoffStop(0)); |
|
bitmapPB->SetValue(kBmpDetailStartOpac, 0, layer->GetDetailMax(0)); |
|
bitmapPB->SetValue(kBmpDetailStopOpac, 0, layer->GetDetailMin(0)); |
|
} |
|
|
|
return newLayer; |
|
} |
|
|
|
void plMaterialUpdate::ICopyMtlParams(plPassMtl *mtl, hsMaxLayer *layer) |
|
{ |
|
IParamBlock2 *basicPB = mtl->GetParamBlockByID(plPassMtl::kBlkBasic); |
|
IParamBlock2 *layersPB = mtl->GetParamBlockByID(plPassMtl::kBlkLayers); |
|
|
|
basicPB->SetValue(kPassBasColorAmb, 0, layer->GetAmbient()); |
|
basicPB->SetValue(kPassBasColor, 0, layer->GetColor()); |
|
|
|
basicPB->SetValue(kPassBasOpacity, 0, int(layer->GetOpacity(0)*100.f)); |
|
|
|
if (layer->GetBlendFlags() & hsMaxLayerBase::kBlendAlpha) |
|
layersPB->SetValue(kPassLayOutputBlend, 0, plPassMtlBase::kBlendAlpha); |
|
else if (layer->GetBlendFlags() & hsMaxLayerBase::kBlendAdd) |
|
layersPB->SetValue(kPassLayOutputBlend, 0, plPassMtlBase::kBlendAdd); |
|
|
|
/* |
|
kPassAdvUseSpec, |
|
kPassAdvSpecType, |
|
kPassAdvShine, |
|
kPassAdvShineStr, |
|
|
|
// Misc |
|
kPassAdvWire, |
|
kPassAdvMeshOutlines, |
|
kPassAdvTwoSided, |
|
|
|
// Shading |
|
kPassAdvSoftShadow, |
|
kPassAdvNoProj, |
|
kPassAdvVertexShade, |
|
kPassAdvNoShade, |
|
kPassAdvNoFog, |
|
kPassAdvWhite, |
|
|
|
// Z |
|
kPassAdvZOnly, |
|
kPassAdvZClear, |
|
kPassAdvZNoRead, |
|
kPassAdvZNoWrite, |
|
kPassAdvZInc, |
|
*/ |
|
}
|
|
|