2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 02:27:40 -04:00

CWE Directory Reorganization

Rearrange directory structure of CWE to be loosely equivalent to
the H'uru Plasma repository.

Part 1: Movement of directories and files.
This commit is contained in:
rarified
2021-05-15 12:49:46 -06:00
parent c3f4a640a3
commit 96903e8dca
4002 changed files with 159 additions and 644 deletions

View File

@ -0,0 +1,508 @@
/*==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 "hsTypes.h"
#include "plAngleAttenLayer.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "stdmat.h"
#include "plBMSampler.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
class plAngleAttenLayerClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading = FALSE) { return TRACKED_NEW plAngleAttenLayer(); }
const TCHAR* ClassName() { return GetString(IDS_ANGLE_ATTEN_LAYER); }
SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
Class_ID ClassID() { return ANGLE_ATTEN_LAYER_CLASS_ID; }
const TCHAR* Category() { return TEXMAP_CAT_COLMOD; }
const TCHAR* InternalName() { return _T("PlasmaAngleAttenLayer"); }
HINSTANCE HInstance() { return hInstance; }
};
static plAngleAttenLayerClassDesc plAngleAttenLayerDesc;
ClassDesc2* GetAngleAttenLayerDesc() { return &plAngleAttenLayerDesc; }
///////////////////////////////////////////////////////////////////////////////
//// ParamBlock Definition ////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static const float kDefTransp0 = 60.f;
static const float kDefOpaque0 = 90.f;
static const float kDefTransp1 = 30.f;
static const float kDefOpaque1 = 0.f;
static ParamBlockDesc2 gAngleAttenParamBlk
(
plAngleAttenLayer::kBlkAngles, _T("angles"), 0, GetAngleAttenLayerDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI, plAngleAttenLayer::kRefAngles,
IDD_ANGLE_ATTEN_LAYER, IDS_ANGLE_ATTEN_LAYER_PROPS, 0, 0, nil,
// Texture size
plAngleAttenLayer::kTranspAngle0, _T("transp0"), TYPE_FLOAT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_TRANSP_ANGLE_0, IDC_TRANSP_ANGLE_0_SPIN, SPIN_AUTOSCALE,
p_range, 0.0, 180.0,
p_default, kDefTransp0,
end,
plAngleAttenLayer::kOpaqueAngle0, _T("opaque0"), TYPE_FLOAT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_OPAQUE_ANGLE_0, IDC_OPAQUE_ANGLE_0_SPIN, SPIN_AUTOSCALE,
p_range, 0.0, 180.0,
p_default, kDefOpaque0,
end,
plAngleAttenLayer::kDoubleFade, _T("doubleFade"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_DOUBLE_FADE,
p_enable_ctrls, 2, plAngleAttenLayer::kOpaqueAngle1, plAngleAttenLayer::kTranspAngle1,
p_default, false,
end,
plAngleAttenLayer::kOpaqueAngle1, _T("opaque1"), TYPE_FLOAT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_OPAQUE_ANGLE_1, IDC_OPAQUE_ANGLE_1_SPIN, SPIN_AUTOSCALE,
p_range, 0.0, 180.0,
p_default, kDefTransp1,
end,
plAngleAttenLayer::kTranspAngle1, _T("transp1"), TYPE_FLOAT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_TRANSP_ANGLE_1, IDC_TRANSP_ANGLE_1_SPIN, SPIN_AUTOSCALE,
p_range, 0.0, 180.0,
p_default, kDefOpaque1,
end,
plAngleAttenLayer::kReflect, _T("reflect"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_REFLECT,
p_default, false,
end,
plAngleAttenLayer::kLoClamp, _T("loClamp"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_LO_CLAMP, IDC_LO_CLAMP_SPIN, SPIN_AUTOSCALE,
p_range, 0, 100,
p_default, 0,
end,
plAngleAttenLayer::kHiClamp, _T("hiClamp"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_HI_CLAMP, IDC_HI_CLAMP_SPIN, SPIN_AUTOSCALE,
p_range, 0, 100,
p_default, 100,
end,
end
);
plAngleAttenLayer::plAngleAttenLayer() :
fParmsPB(NULL),
fIValid(NEVER),
fCosTransp0(0),
fCosOpaque0(0),
fCosTransp1(0),
fCosOpaque1(0),
fCosinesCached(false)
{
plAngleAttenLayerDesc.MakeAutoParamBlocks(this);
}
plAngleAttenLayer::~plAngleAttenLayer()
{
}
//From MtlBase
void plAngleAttenLayer::Reset()
{
GetAngleAttenLayerDesc()->Reset(this, TRUE); // reset all pb2's
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
fIValid.SetEmpty();
}
void plAngleAttenLayer::Update(TimeValue t, Interval& valid)
{
if (!fIValid.InInterval(t))
{
fIValid.SetInfinite();
}
valid &= fIValid;
}
Interval plAngleAttenLayer::Validity(TimeValue t)
{
//TODO: Update fIValid here
Interval v = FOREVER;
return v;
}
ParamDlg* plAngleAttenLayer::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
IAutoMParamDlg* masterDlg = plAngleAttenLayerDesc.CreateParamDlgs(hwMtlEdit, imp, this);
return masterDlg;
}
BOOL plAngleAttenLayer::SetDlgThing(ParamDlg* dlg)
{
return FALSE;
}
int plAngleAttenLayer::NumRefs()
{
return 1;
}
//From ReferenceMaker
RefTargetHandle plAngleAttenLayer::GetReference(int i)
{
switch (i)
{
case kRefAngles: return fParmsPB;
default: return NULL;
}
}
void plAngleAttenLayer::SetReference(int i, RefTargetHandle rtarg)
{
Interval garbage;
switch (i)
{
case kRefAngles:
fParmsPB = (IParamBlock2 *)rtarg;
break;
}
}
int plAngleAttenLayer::NumParamBlocks()
{
return 1;
}
IParamBlock2* plAngleAttenLayer::GetParamBlock(int i)
{
switch (i)
{
case 0: return fParmsPB;
default: return NULL;
}
}
IParamBlock2* plAngleAttenLayer::GetParamBlockByID(BlockID id)
{
if (fParmsPB->ID() == id)
return fParmsPB;
else
return NULL;
}
//From ReferenceTarget
RefTargetHandle plAngleAttenLayer::Clone(RemapDir &remap)
{
plAngleAttenLayer *mnew = TRACKED_NEW plAngleAttenLayer();
*((MtlBase*)mnew) = *((MtlBase*)this); // copy superclass stuff
mnew->ReplaceReference(kRefAngles, remap.CloneRef(fParmsPB));
BaseClone(this, mnew, remap);
return (RefTargetHandle)mnew;
}
int plAngleAttenLayer::NumSubs()
{
return 1;
}
Animatable* plAngleAttenLayer::SubAnim(int i)
{
//TODO: Return 'i-th' sub-anim
switch (i)
{
case kRefAngles: return fParmsPB;
default: return NULL;
}
}
TSTR plAngleAttenLayer::SubAnimName(int i)
{
switch (i)
{
case kRefAngles: return "Angles";
default: return "";
}
}
RefResult plAngleAttenLayer::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message)
{
switch (message)
{
case REFMSG_CHANGE:
{
fIValid.SetEmpty();
if (hTarget == fParmsPB)
{
// see if this message came from a changing parameter in the pblock,
// if so, limit rollout update to the changing item
ParamID changingParam = fParmsPB->LastNotifyParamID();
fParmsPB->GetDesc()->InvalidateUI(changingParam);
if (changingParam != -1)
IChanged();
}
}
break;
}
return REF_SUCCEED;
}
void plAngleAttenLayer::IChanged()
{
// Cut and paste insanity from DynamicTextLayer.
// Texture wasn't getting updated in the viewports, and this fixes it.
// Don't know if it's the right way though.
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
// And this is so the SceneWatcher gets notified that the material on some of it's
// referenced objects changed.
NotifyDependents(FOREVER, PART_ALL, REFMSG_USER_MAT);
ICacheCosines();
}
void plAngleAttenLayer::ICacheCosines()
{
fCosTransp0 = cosf(DegToRad(fParmsPB->GetFloat(kTranspAngle0)));
fCosOpaque0 = cosf(DegToRad(fParmsPB->GetFloat(kOpaqueAngle0)));
if( fParmsPB->GetInt(kDoubleFade) )
{
fCosTransp1 = cosf(DegToRad(fParmsPB->GetFloat(kTranspAngle1)));
fCosOpaque1 = cosf(DegToRad(fParmsPB->GetFloat(kOpaqueAngle1)));
}
else
{
fCosTransp1 = fCosOpaque1 = 0;
}
fCosinesCached = true;
}
#define TEX_HDR_CHUNK 0x5000
IOResult plAngleAttenLayer::Save(ISave *isave)
{
IOResult res;
isave->BeginChunk(TEX_HDR_CHUNK);
res = MtlBase::Save(isave);
if (res != IO_OK)
return res;
isave->EndChunk();
return IO_OK;
}
IOResult plAngleAttenLayer::Load(ILoad *iload)
{
IOResult res;
while (IO_OK == (res = iload->OpenChunk()))
{
if (iload->CurChunkID() == TEX_HDR_CHUNK)
{
res = MtlBase::Load(iload);
}
iload->CloseChunk();
if (res != IO_OK)
return res;
}
return IO_OK;
}
AColor plAngleAttenLayer::EvalColor(ShadeContext& sc)
{
if( !sc.doMaps )
return AColor(0.0f, 0.0f, 0.0f, 1.0f);
AColor color;
if (sc.GetCache(this, color))
return color;
if( !fCosinesCached )
ICacheCosines();
if (gbufID)
sc.SetGBufferID(gbufID);
// Evaluate the Bitmap
Point3 normal = sc.Normal();
if( fParmsPB->GetInt(kReflect) )
{
normal = sc.ReflectVector();
}
float dotZ = normal.z;
float alpha = 1.f;
if( fCosTransp0 != fCosOpaque0 )
{
float a = (dotZ - fCosTransp0) / (fCosOpaque0 - fCosTransp0);
if( a < 0 )
a = 0;
else if( a > 1.f )
a = 1.f;
alpha *= a;
}
if( fParmsPB->GetInt(kDoubleFade) && (fCosTransp1 != fCosOpaque1) )
{
float a = (dotZ - fCosTransp1) / (fCosOpaque1 - fCosTransp1);
if( a < 0 )
a = 0;
else if( a > 1.f )
a = 1.f;
if( fCosTransp0 < fCosTransp1 )
{
if( fCosTransp0 > fCosOpaque0 )
alpha += a;
else
alpha *= a;
}
else
{
if( fCosTransp0 < fCosOpaque0 )
alpha += a;
else
alpha *= a;
}
}
color = AColor(1.f, 1.f, 1.f, alpha);
sc.PutCache(this, color);
return color;
}
float plAngleAttenLayer::EvalMono(ShadeContext& sc)
{
return Intens(EvalColor(sc));
}
Point3 plAngleAttenLayer::EvalNormalPerturb(ShadeContext& sc)
{
// Return the perturbation to apply to a normal for bump mapping
return Point3(0, 0, 0);
}
ULONG plAngleAttenLayer::LocalRequirements(int subMtlNum)
{
return MTLREQ_VIEW_DEP | MTLREQ_TRANSP;
}
void plAngleAttenLayer::ActivateTexDisplay(BOOL onoff)
{
}
BITMAPINFO *plAngleAttenLayer::GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono, BOOL forceW, BOOL forceH)
{
return nil;
// FIXME
}
DWORD plAngleAttenLayer::GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker)
{
return 0;
}
const char *plAngleAttenLayer::GetTextureName( int which )
{
return NULL;
}
int plAngleAttenLayer::GetLoClamp()
{
return fParmsPB->GetInt(kLoClamp);
}
int plAngleAttenLayer::GetHiClamp()
{
return fParmsPB->GetInt(kHiClamp);
}
Box3 plAngleAttenLayer::GetFade()
{
Point3 pmin, pmax;
pmin.x = fParmsPB->GetFloat(kTranspAngle0);
pmin.y = fParmsPB->GetFloat(kOpaqueAngle0);
if( pmin.x < pmin.y )
pmin.z = -1.f;
else if( pmin.x > pmin.y )
pmin.z = 1.f;
else
pmin.z = 0;
if( fParmsPB->GetInt(kDoubleFade) )
{
pmax.x = fParmsPB->GetFloat(kTranspAngle1);
pmax.y = fParmsPB->GetFloat(kOpaqueAngle1);
if( pmax.x < pmax.y )
pmax.z = -1.f;
else if( pmax.x > pmax.y )
pmax.z = 1.f;
else
pmax.z = 0;
}
else
{
pmax.x = pmax.y = pmax.z = 0;
}
return Box3(pmin, pmax);
}
BOOL plAngleAttenLayer::Reflect()
{
return fParmsPB->GetInt(kReflect);
}

View File

@ -0,0 +1,181 @@
/*==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==*/
#ifndef plAngleAttenLayer_inc
#define plAngleAttenLayer_inc
#include "Max.h"
#include "../resource.h"
#include "plPlasmaMAXLayer.h"
class ClassDesc2;
class IParamBlock2;
ClassDesc2* GetAngleAttenLayerDesc();
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
//// Class Definition /////////////////////////////////////////////////////////
class plAngleAttenLayer : public plPlasmaMAXLayer
{
protected:
// Parameter block
IParamBlock2* fParmsPB;
Interval fIValid;
BOOL fCosinesCached;
float fCosTransp0;
float fCosOpaque0;
float fCosTransp1;
float fCosOpaque1;
public:
// Ref nums
enum
{
kRefAngles
};
// Block ID's
enum
{
kBlkAngles
};
plAngleAttenLayer();
~plAngleAttenLayer();
void DeleteThis() { delete this; }
//From MtlBase
ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
BOOL SetDlgThing(ParamDlg* dlg);
void Update(TimeValue t, Interval& valid);
void Reset();
Interval Validity(TimeValue t);
ULONG LocalRequirements(int subMtlNum);
//From Texmap
RGBA EvalColor(ShadeContext& sc);
float EvalMono(ShadeContext& sc);
Point3 EvalNormalPerturb(ShadeContext& sc);
// For displaying textures in the viewport
BOOL SupportTexDisplay() { return FALSE; }
void ActivateTexDisplay(BOOL onoff);
BITMAPINFO *GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono=FALSE, int forceW=0, int forceH=0);
DWORD GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker);
protected:
void ICacheCosines();
void IChanged();
void IDiscardTexHandle();
public:
//TODO: Return anim index to reference index
int SubNumToRefNum(int subNum) { return subNum; }
virtual BOOL DiscardColor() { return true; }
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
//From Animatable
Class_ID ClassID() { return ANGLE_ATTEN_LAYER_CLASS_ID; }
SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_ANGLE_ATTEN_LAYER); }
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
// TODO: Maintain the number or references here
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
int NumParamBlocks(); // return number of ParamBlocks in this instance
IParamBlock2* GetParamBlock(int i); // return i'th ParamBlock
IParamBlock2* GetParamBlockByID(BlockID id); // return id'd ParamBlock
const char *GetTextureName( int which );
/// ParamBlock accessors
enum
{
kTranspAngle0,
kOpaqueAngle0,
kOpaqueAngle1,
kTranspAngle1,
kDoubleFade,
kReflect,
kLoClamp,
kHiClamp
};
// Pure virtual accessors for the various bitmap related elements
virtual Bitmap *GetMaxBitmap(int index = 0) { hsAssert( false, "Function call not valid on this type of layer." ); return nil; }
virtual PBBitmap *GetPBBitmap( int index = 0 ) { hsAssert( false, "Function call not valid on this type of layer." ); return nil; }
virtual int GetNumBitmaps( void ) { return 0; }
// Some specific to processing this layer type into runtime materials.
virtual Box3 GetFade();
virtual BOOL Reflect();
virtual int GetLoClamp();
virtual int GetHiClamp();
protected:
virtual void ISetMaxBitmap(Bitmap *bitmap, int index = 0) { hsAssert( false, "Function call not valid on this type of layer." ); }
virtual void ISetPBBitmap( PBBitmap *pbbm, int index = 0 ){ hsAssert( false, "Function call not valid on this type of layer." ); }
};
#endif // plAngleAttenLayer_inc

View File

@ -0,0 +1,418 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDynamicEnvLayer - Dynamic EnvironmentMap MAX Layer //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 8.22.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plDynamicEnvLayer.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "stdmat.h"
#include "resource.h"
#include "plBMSampler.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
//// Externs //////////////////////////////////////////////////////////////////
extern TCHAR *GetString( int id );
extern HINSTANCE hInstance;
//// ClassDesc Definition /////////////////////////////////////////////////////
class plDynamicEnvLayerClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading = FALSE) { return TRACKED_NEW plDynamicEnvLayer(); }
const TCHAR* ClassName() { return GetString(IDS_DYNAMIC_ENVMAP_LAYER); }
SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
Class_ID ClassID() { return DYNAMIC_ENV_LAYER_CLASS_ID; }
const TCHAR* Category() { return TEXMAP_CAT_ENV; }
const TCHAR* InternalName() { return _T("PlasmaDynamicEnvMapLayer"); }
HINSTANCE HInstance() { return hInstance; }
};
static plDynamicEnvLayerClassDesc plDynamicEnvLayerDesc;
ClassDesc2* GetDynamicEnvLayerDesc() { return &plDynamicEnvLayerDesc; }
#include "plDynamicEnvLayerBitmapPB.cpp"
//// Constructor/Destructor ///////////////////////////////////////////////////
plDynamicEnvLayer::plDynamicEnvLayer() :
fBitmapPB(NULL),
fUVGen(NULL),
fTexHandle(NULL),
fTexTime(0),
fIValid(NEVER)
{
plDynamicEnvLayerDesc.MakeAutoParamBlocks(this);
ReplaceReference(kRefUVGen, GetNewDefaultUVGen());
}
plDynamicEnvLayer::~plDynamicEnvLayer()
{
IDiscardTexHandle();
}
void plDynamicEnvLayer::GetClassName( TSTR& s )
{
s = GetString( IDS_DYNAMIC_ENVMAP_LAYER );
}
//// Reset ////////////////////////////////////////////////////////////////////
void plDynamicEnvLayer::Reset()
{
GetDynamicEnvLayerDesc()->Reset(this, TRUE); // reset all pb2's
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
fIValid.SetEmpty();
}
//// Update ///////////////////////////////////////////////////////////////////
void plDynamicEnvLayer::Update(TimeValue t, Interval& valid)
{
if (!fIValid.InInterval(t))
{
fIValid.SetInfinite();
fUVGen->Update(t,fIValid);
fBitmapPB->GetValidity(t, fIValid);
}
valid &= fIValid;
}
//// Validity /////////////////////////////////////////////////////////////////
Interval plDynamicEnvLayer::Validity(TimeValue t)
{
//TODO: Update fIValid here
// mf horse - Hacking this in just to get animations working.
// No warranty on this not being stupid.
Interval v = FOREVER;
fBitmapPB->GetValidity(t, v);
v &= fUVGen->Validity(t);
return v;
}
//// CreateParamDlg ///////////////////////////////////////////////////////////
ParamDlg* plDynamicEnvLayer::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
fIMtlParams = imp;
IAutoMParamDlg* masterDlg = plDynamicEnvLayerDesc.CreateParamDlgs(hwMtlEdit, imp, this);
return masterDlg;
}
//// SetDlgThing //////////////////////////////////////////////////////////////
BOOL plDynamicEnvLayer::SetDlgThing(ParamDlg* dlg)
{
return FALSE;
}
//// Reference Functions //////////////////////////////////////////////////////
int plDynamicEnvLayer::NumRefs()
{
return 2;
}
RefTargetHandle plDynamicEnvLayer::GetReference( int i )
{
switch( i )
{
case kRefUVGen: return fUVGen;
case kRefBitmap: return fBitmapPB;
default: return NULL;
}
}
void plDynamicEnvLayer::SetReference( int i, RefTargetHandle rtarg )
{
Interval garbage;
switch( i )
{
case kRefUVGen:
fUVGen = (UVGen *)rtarg;
if( fUVGen )
fUVGen->Update( TimeValue( 0 ), garbage );
break;
case kRefBitmap:
fBitmapPB = (IParamBlock2 *)rtarg;
break;
}
}
//// ParamBlock Functions /////////////////////////////////////////////////////
int plDynamicEnvLayer::NumParamBlocks()
{
return 1;
}
IParamBlock2 *plDynamicEnvLayer::GetParamBlock( int i )
{
switch( i )
{
case 0: return fBitmapPB;
default: return NULL;
}
}
IParamBlock2 *plDynamicEnvLayer::GetParamBlockByID( BlockID id )
{
if( fBitmapPB->ID() == id )
return fBitmapPB;
else
return NULL;
}
//// Clone ////////////////////////////////////////////////////////////////////
RefTargetHandle plDynamicEnvLayer::Clone( RemapDir &remap )
{
plDynamicEnvLayer *mnew = TRACKED_NEW plDynamicEnvLayer();
*((MtlBase*)mnew) = *((MtlBase*)this); // copy superclass stuff
mnew->ReplaceReference(kRefBitmap, remap.CloneRef(fBitmapPB));
mnew->ReplaceReference(kRefUVGen, remap.CloneRef(fUVGen));
BaseClone(this, mnew, remap);
return (RefTargetHandle)mnew;
}
//// SubAnim Functions ////////////////////////////////////////////////////////
int plDynamicEnvLayer::NumSubs()
{
return 1;
}
Animatable *plDynamicEnvLayer::SubAnim( int i )
{
switch( i )
{
case kRefBitmap: return fBitmapPB;
default: return NULL;
}
}
TSTR plDynamicEnvLayer::SubAnimName( int i )
{
switch( i )
{
case kRefBitmap: return fBitmapPB->GetLocalName();
default: return "";
}
}
//// NotifyRefChanged /////////////////////////////////////////////////////////
RefResult plDynamicEnvLayer::NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message )
{
switch (message)
{
case REFMSG_CHANGE:
{
fIValid.SetEmpty();
if (hTarget == fBitmapPB)
{
// see if this message came from a changing parameter in the pblock,
// if so, limit rollout update to the changing item and update any active viewport texture
ParamID changingParam = fBitmapPB->LastNotifyParamID();
fBitmapPB->GetDesc()->InvalidateUI(changingParam);
}
}
break;
case REFMSG_UV_SYM_CHANGE:
IDiscardTexHandle();
break;
}
return REF_SUCCEED;
}
//// Save/Load ////////////////////////////////////////////////////////////////
#define TEX_HDR_CHUNK 0x5000
IOResult plDynamicEnvLayer::Save(ISave *isave)
{
IOResult res;
isave->BeginChunk(TEX_HDR_CHUNK);
res = MtlBase::Save(isave);
if (res != IO_OK)
return res;
isave->EndChunk();
return IO_OK;
}
IOResult plDynamicEnvLayer::Load(ILoad *iload)
{
IOResult res;
while (IO_OK == (res = iload->OpenChunk()))
{
if (iload->CurChunkID() == TEX_HDR_CHUNK)
{
res = MtlBase::Load(iload);
}
iload->CloseChunk();
if (res != IO_OK)
return res;
}
return IO_OK;
}
//// EvalColor ////////////////////////////////////////////////////////////////
inline Point2 CompUV(float x, float y, float z)
{
return Point2( 0.5f * ( x / z + 1.0f ), 0.5f * ( y / z + 1.0f ) );
}
AColor plDynamicEnvLayer::EvalColor(ShadeContext& sc)
{
if (!sc.doMaps)
return AColor(0.0f, 0.0f, 0.0f, 1.0f);
AColor color;
if (sc.GetCache(this, color))
return color;
if (gbufID)
sc.SetGBufferID(gbufID);
color.White();
sc.PutCache(this, color);
return color;
}
float plDynamicEnvLayer::EvalMono(ShadeContext& sc)
{
return Intens(EvalColor(sc));
}
Point3 plDynamicEnvLayer::EvalNormalPerturb(ShadeContext& sc)
{
// Return the perturbation to apply to a normal for bump mapping
return Point3(0, 0, 0);
}
ULONG plDynamicEnvLayer::LocalRequirements(int subMtlNum)
{
return MTLREQ_VIEW_DEP;
}
void plDynamicEnvLayer::IDiscardTexHandle()
{
if (fTexHandle)
{
fTexHandle->DeleteThis();
fTexHandle = NULL;
}
}
void plDynamicEnvLayer::ActivateTexDisplay(BOOL onoff)
{
if (!onoff)
IDiscardTexHandle();
}
BITMAPINFO *plDynamicEnvLayer::GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono, BOOL forceW, BOOL forceH)
{
return NULL;
}
DWORD plDynamicEnvLayer::GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker)
{
// FIXME: ignore validity for now
if (fTexHandle && fIValid.InInterval(t))// && texTime == CalcFrame(t))
return fTexHandle->GetHandle();
else
{
IDiscardTexHandle();
fTexTime = 0;//CalcFrame(t);
fTexHandle = thmaker.MakeHandle(GetVPDisplayDIB(t, thmaker, fIValid));
if (fTexHandle)
return fTexHandle->GetHandle();
else
return 0;
}
}
//// MustBeUnique /////////////////////////////////////////////////////////////
// Fun stuff here. If our anchor is set to nil (i.e. "self"), then we must be
// unique for each object we're applied to. However, that means the material
// must *ALSO* be unique. Hence why this function is called by
// hsMaterialConverter::IMustBeUniqueMaterial().
bool plDynamicEnvLayer::MustBeUnique( void )
{
if( fBitmapPB->GetINode( kBmpAnchorNode ) == nil )
return true;
return false;
}

View File

@ -0,0 +1,184 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDynamicEnvLayer - Dynamic EnvironmentMap MAX Layer //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 8.22.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plDynamicEnvLayer_h
#define _plDynamicEnvLayer_h
#include "Max.h"
#include "plPlasmaMAXLayer.h"
class ClassDesc2;
class IParamBlock2;
//// Class Definition /////////////////////////////////////////////////////////
class plDynamicEnvLayer : public plPlasmaMAXLayer
{
protected:
// Parameter block
IParamBlock2 *fBitmapPB;
UVGen *fUVGen;
IMtlParams *fIMtlParams;
TexHandle *fTexHandle;
TimeValue fTexTime;
Interval fIValid;
friend class DELBitmapDlgProc;
public:
// Ref nums
enum
{
kRefUVGen,
kRefBitmap,
};
// Block ID's
enum
{
kBlkBitmap,
};
plDynamicEnvLayer();
~plDynamicEnvLayer();
void DeleteThis() { delete this; }
//From MtlBase
ParamDlg *CreateParamDlg( HWND hwMtlEdit, IMtlParams *imp );
BOOL SetDlgThing( ParamDlg* dlg );
void Update( TimeValue t, Interval& valid );
void Reset();
Interval Validity( TimeValue t );
ULONG LocalRequirements( int subMtlNum );
//From Texmap
RGBA EvalColor( ShadeContext& sc );
float EvalMono( ShadeContext& sc );
Point3 EvalNormalPerturb( ShadeContext& sc );
// For displaying textures in the viewport
BOOL SupportTexDisplay() { return TRUE; }
void ActivateTexDisplay(BOOL onoff);
BITMAPINFO *GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono=FALSE, int forceW=0, int forceH=0);
DWORD GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker);
virtual bool MustBeUnique( void );
protected:
void IDiscardTexHandle();
public:
void GetUVTransform(Matrix3 &uvtrans) { fUVGen->GetUVTransform(uvtrans); }
int GetTextureTiling() { return fUVGen->GetTextureTiling(); }
int GetUVWSource() { return fUVGen->GetUVWSource(); }
virtual int GetMapChannel() { return fUVGen->GetMapChannel(); } // only relevant if above returns UVWSRC_EXPLICIT
UVGen *GetTheUVGen() { return fUVGen; }
//TODO: Return anim index to reference index
int SubNumToRefNum( int subNum ) { return kRefBitmap; /* Only one sub*/ }
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
//From Animatable
Class_ID ClassID() { return DYNAMIC_ENV_LAYER_CLASS_ID; }
SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
void GetClassName( TSTR& s );
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message );
int NumSubs();
Animatable *SubAnim(int i);
TSTR SubAnimName(int i);
int NumRefs();
RefTargetHandle GetReference( int i );
void SetReference( int i, RefTargetHandle rtarg );
int NumParamBlocks(); // return number of ParamBlocks in this instance
IParamBlock2 *GetParamBlock(int i); // return i'th ParamBlock
IParamBlock2 *GetParamBlockByID(BlockID id); // return id'd ParamBlock
/// ParamBlock accessors
enum
{
kScalingAny,
kScalingHalf,
kScalingNone
};
// Param ID's
enum
{
// General params
kBmpTextureSize,
kBmpAnchorNode,
kBmpLastTextureSize, // Annoying, but necessary to clamp texture sizes to powers of 2
kBmpRefract
};
// Pure virtual accessors for the various bitmap related elements
virtual Bitmap *GetMaxBitmap(int index = 0) { hsAssert( false, "Function call not valid on this type of layer." ); return nil; }
virtual PBBitmap *GetPBBitmap( int index = 0 ) { hsAssert( false, "Function call not valid on this type of layer." ); return nil; }
virtual int GetNumBitmaps( void ) { return 0; }
protected:
virtual void ISetMaxBitmap(Bitmap *bitmap, int index = 0) { hsAssert( false, "Function call not valid on this type of layer." ); }
virtual void ISetPBBitmap( PBBitmap *pbbm, int index = 0 ){ hsAssert( false, "Function call not valid on this type of layer." ); }
};
#endif // _plDynamicEnvLayer_h

View File

@ -0,0 +1,266 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDynamicEnvLayer ParamBlock Functions //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 8.22.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//// PickAnchorNode ///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
class PickAnchorNode : public PickObjectProc
{
public:
plDynamicEnvLayer *fLayer;
HWND fHWnd;
int bleah;
PickAnchorNode() { fLayer = NULL; }
BOOL Pick( INode *node )
{
const char *dbgNodeName = node->GetName();
if( fLayer )
fLayer->GetParamBlockByID( plDynamicEnvLayer::kBlkBitmap )->SetValue( plDynamicEnvLayer::kBmpAnchorNode, TimeValue( 0 ), node );
return TRUE;
}
void EnterMode() { ISetButton( TRUE ); }
void ExitMode() { ISetButton( FALSE ); }
BOOL Filter( INode *node )
{
Object *obj = node->EvalWorldState( 0 ).obj;
if( obj != NULL )
{
if( obj->CanConvertToType( triObjectClassID ) ||
obj->ClassID() == Class_ID( DUMMY_CLASS_ID, 0 ) )
return TRUE;
}
return FALSE;
}
protected:
void ISetButton( BOOL checkIt )
{
ICustButton *iBut = GetICustButton( GetDlgItem( fHWnd, IDC_ANCHOR_NODE ) );
if( iBut )
{
iBut->SetCheck( checkIt );
if( fLayer )
{
if( fLayer->GetParamBlockByID( plDynamicEnvLayer::kBlkBitmap )->GetINode( plDynamicEnvLayer::kBmpAnchorNode ) == NULL )
iBut->SetText( _T( "<self>" ) );
}
}
ReleaseICustButton( iBut );
}
};
///////////////////////////////////////////////////////////////////////////////
//// ParamBlock Dialog Proc ///////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
class DELBitmapDlgProc : public ParamMap2UserDlgProc
{
PickAnchorNode fPickAnchorCallback;
/// Called to update the controls of the dialog
virtual void Update( TimeValue t, Interval &valid, IParamMap2 *map )
{
IParamBlock2 *pblock;
int i;
ParamMap2UserDlgProc::Update( t, valid, map );
pblock = map->GetParamBlock();
i = pblock->GetInt( plDynamicEnvLayer::kBmpTextureSize, t );
pblock->SetValue( plDynamicEnvLayer::kBmpLastTextureSize, t, i );
if( pblock->GetINode( plDynamicEnvLayer::kBmpAnchorNode ) == NULL )
{
ICustButton *bmSelectBtn = GetICustButton( GetDlgItem( pblock->GetMap()->GetHWnd(), IDC_ANCHOR_NODE ) );
bmSelectBtn->SetText( _T( "<self>" ) );
ReleaseICustButton( bmSelectBtn );
}
}
/// Clamp texture sizes to a power of 2
void IClampTexSizeSpinner( TimeValue t, IParamMap2 *map )
{
IParamBlock2 *pblock = map->GetParamBlock();
int lastVal = pblock->GetInt( plDynamicEnvLayer::kBmpLastTextureSize, t );
int tempVal, newVal = pblock->GetInt( plDynamicEnvLayer::kBmpTextureSize, t );
if( newVal < lastVal )
{
lastVal = newVal;
for( tempVal = 1; tempVal < newVal; tempVal <<= 1 );
newVal = tempVal >> 1;
}
else
{
lastVal = newVal;
for( tempVal = 1; tempVal < newVal; tempVal <<= 1 );
newVal = tempVal;
}
pblock->SetValue( plDynamicEnvLayer::kBmpTextureSize, t, newVal );
pblock->SetValue( plDynamicEnvLayer::kBmpLastTextureSize, t, newVal );
}
/// Main message proc
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
break;
case CC_SPINNER_CHANGE:
if( LOWORD( wParam ) == IDC_TEXSIZE_SPIN )
IClampTexSizeSpinner( t, map );
break;
case WM_COMMAND:
if( HIWORD( wParam ) == EN_CHANGE && LOWORD( wParam ) == IDC_TEXSIZE_EDIT )
IClampTexSizeSpinner( t, map );
else if( LOWORD( wParam ) == IDC_ANCHOR_NODE )
{
plDynamicEnvLayer *layer = (plDynamicEnvLayer *)map->GetParamBlock()->GetOwner();
layer->fIMtlParams->EndPickMode();
fPickAnchorCallback.fHWnd = hWnd;
fPickAnchorCallback.fLayer = layer;
layer->fIMtlParams->SetPickMode( &fPickAnchorCallback );
break;
}
break;
}
return FALSE;
}
void DeleteThis() {};
};
static DELBitmapDlgProc gDELBitmapDlgProc;
class BleahPBAccessor : public PBAccessor
{
public:
void Set(PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
plDynamicEnvLayer* layer = (plDynamicEnvLayer *)owner;
IParamBlock2 *pb = layer->GetParamBlockByID( plDynamicEnvLayer::kBlkBitmap );
switch (id)
{
case plDynamicEnvLayer::kBmpAnchorNode:
INode *newNode = (INode *)val.r;
if( newNode == NULL )
{
// Instead of displaying "none", display "<self>", since that's what nil means
// for us
ICustButton *bmSelectBtn = GetICustButton( GetDlgItem( pb->GetMap()->GetHWnd(), IDC_ANCHOR_NODE ) );
bmSelectBtn->SetText( _T( "<self>" ) );
ReleaseICustButton( bmSelectBtn );
}
break;
}
}
void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid)
{
}
};
static BleahPBAccessor gBleahPBAccessor;
///////////////////////////////////////////////////////////////////////////////
//// ParamBlock Definition ////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static ParamBlockDesc2 gBitmapParamBlk
(
plDynamicEnvLayer::kBlkBitmap, _T("bitmap"), 0, GetDynamicEnvLayerDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI, plDynamicEnvLayer::kRefBitmap,
IDD_DYNAMIC_ENVMAP_LAYER, IDS_DYNAMIC_ENVMAP_LAYER_TEX, 0, 0, &gDELBitmapDlgProc,
// General parameters
plDynamicEnvLayer::kBmpTextureSize, _T("textureSize"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_TEXSIZE_EDIT, IDC_TEXSIZE_SPIN, SPIN_AUTOSCALE,
p_range, 4, 512,
p_default, 64,
end,
plDynamicEnvLayer::kBmpAnchorNode, _T("anchorNode"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_ANCHOR_NODE,
p_prompt, IDS_SELECT_ANCHOR,
p_accessor, &gBleahPBAccessor,
end,
plDynamicEnvLayer::kBmpLastTextureSize, _T("lastTextureSize"), TYPE_INT, 0, 0,
end,
plDynamicEnvLayer::kBmpRefract, _T("refract"),TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_REFRACT,
end,
end
);

View File

@ -0,0 +1,575 @@
/*==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 "hsTypes.h"
#include "plDynamicTextLayer.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "stdmat.h"
#include "plBMSampler.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
class plDynamicTextLayerClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading = FALSE) { return TRACKED_NEW plDynamicTextLayer(); }
const TCHAR* ClassName() { return GetString(IDS_DYN_TEXT_LAYER); }
SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
Class_ID ClassID() { return DYN_TEXT_LAYER_CLASS_ID; }
const TCHAR* Category() { return TEXMAP_CAT_2D; }
const TCHAR* InternalName() { return _T("PlasmaDynamicTextLayer"); }
HINSTANCE HInstance() { return hInstance; }
};
static plDynamicTextLayerClassDesc plDynamicTextLayerDesc;
ClassDesc2* GetDynamicTextLayerDesc() { return &plDynamicTextLayerDesc; }
#include "plDynamicTextLayerBitmapPB.cpp"
ParamDlg* plDynamicTextLayer::fUVGenDlg = NULL;
plDynamicTextLayer::plDynamicTextLayer() :
fBitmapPB(NULL),
fUVGen(NULL),
fTexHandle(NULL),
fTexTime(0),
fIValid(NEVER)
{
fInitBitmap = NULL;
plDynamicTextLayerDesc.MakeAutoParamBlocks(this);
ReplaceReference(kRefUVGen, GetNewDefaultUVGen());
}
plDynamicTextLayer::~plDynamicTextLayer()
{
if( fInitBitmap )
fInitBitmap->DeleteThis();
IDiscardTexHandle();
}
//From MtlBase
void plDynamicTextLayer::Reset()
{
GetDynamicTextLayerDesc()->Reset(this, TRUE); // reset all pb2's
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
fIValid.SetEmpty();
}
void plDynamicTextLayer::Update(TimeValue t, Interval& valid)
{
if (!fIValid.InInterval(t))
{
fIValid.SetInfinite();
fUVGen->Update(t,fIValid);
fBitmapPB->GetValidity(t, fIValid);
}
// Gonna need to do this when we support animated bm's
#if 0
if (fBM)
{
if (bi.FirstFrame()!=bi.LastFrame())
ivalid.SetInstant(t);
}
#endif
valid &= fIValid;
}
Interval plDynamicTextLayer::Validity(TimeValue t)
{
//TODO: Update fIValid here
// mf horse - Hacking this in just to get animations working.
// No warranty on this not being stupid.
Interval v = FOREVER;
fBitmapPB->GetValidity(t, v);
v &= fUVGen->Validity(t);
return v;
}
ParamDlg* plDynamicTextLayer::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
fIMtlParams = imp;
IAutoMParamDlg* masterDlg = plDynamicTextLayerDesc.CreateParamDlgs(hwMtlEdit, imp, this);
fUVGenDlg = fUVGen->CreateParamDlg(hwMtlEdit, imp);
masterDlg->AddDlg(fUVGenDlg);
return masterDlg;
}
BOOL plDynamicTextLayer::SetDlgThing(ParamDlg* dlg)
{
if (dlg == fUVGenDlg)
{
fUVGenDlg->SetThing(fUVGen);
return TRUE;
}
return FALSE;
}
int plDynamicTextLayer::NumRefs()
{
return 2;
}
//From ReferenceMaker
RefTargetHandle plDynamicTextLayer::GetReference(int i)
{
switch (i)
{
case kRefUVGen: return fUVGen;
case kRefBitmap: return fBitmapPB;
default: return NULL;
}
}
void plDynamicTextLayer::SetReference(int i, RefTargetHandle rtarg)
{
Interval garbage;
switch (i)
{
case kRefUVGen:
fUVGen = (UVGen *)rtarg;
if( fUVGen )
fUVGen->Update( TimeValue( 0 ), garbage );
break;
case kRefBitmap:
fBitmapPB = (IParamBlock2 *)rtarg;
// KLUDGE: If the paramblock is being set chances are we are being created or
// loaded. In the case of load, we want to refresh our textures.
if (fBitmapPB)
RefreshBitmaps();
break;
}
}
int plDynamicTextLayer::NumParamBlocks()
{
return 1;
}
IParamBlock2* plDynamicTextLayer::GetParamBlock(int i)
{
switch (i)
{
case 0: return fBitmapPB;
default: return NULL;
}
}
IParamBlock2* plDynamicTextLayer::GetParamBlockByID(BlockID id)
{
if (fBitmapPB->ID() == id)
return fBitmapPB;
else
return NULL;
}
//From ReferenceTarget
RefTargetHandle plDynamicTextLayer::Clone(RemapDir &remap)
{
plDynamicTextLayer *mnew = TRACKED_NEW plDynamicTextLayer();
*((MtlBase*)mnew) = *((MtlBase*)this); // copy superclass stuff
mnew->ReplaceReference(kRefBitmap, remap.CloneRef(fBitmapPB));
mnew->ReplaceReference(kRefUVGen, remap.CloneRef(fUVGen));
BaseClone(this, mnew, remap);
return (RefTargetHandle)mnew;
}
int plDynamicTextLayer::NumSubs()
{
return 2;
}
Animatable* plDynamicTextLayer::SubAnim(int i)
{
//TODO: Return 'i-th' sub-anim
switch (i)
{
case kRefUVGen: return fUVGen;
case kRefBitmap: return fBitmapPB;
default: return NULL;
}
}
TSTR plDynamicTextLayer::SubAnimName(int i)
{
switch (i)
{
case kRefUVGen: return "UVGen";
case kRefBitmap: return fBitmapPB->GetLocalName();
default: return "";
}
}
RefResult plDynamicTextLayer::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message)
{
switch (message)
{
case REFMSG_CHANGE:
{
fIValid.SetEmpty();
if (hTarget == fBitmapPB)
{
// see if this message came from a changing parameter in the pblock,
// if so, limit rollout update to the changing item and update any active viewport texture
ParamID changingParam = fBitmapPB->LastNotifyParamID();
fBitmapPB->GetDesc()->InvalidateUI(changingParam);
if (changingParam != -1)
IChanged();
}
}
break;
case REFMSG_UV_SYM_CHANGE:
IDiscardTexHandle();
break;
}
return REF_SUCCEED;
}
void plDynamicTextLayer::IChanged()
{
IDiscardTexHandle();
// Texture wasn't getting updated in the viewports, and this fixes it.
// Don't know if it's the right way though.
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
// And this is so the SceneWatcher gets notified that the material on some of it's
// referenced objects changed.
NotifyDependents(FOREVER, PART_ALL, REFMSG_USER_MAT);
}
#define TEX_HDR_CHUNK 0x5000
IOResult plDynamicTextLayer::Save(ISave *isave)
{
IOResult res;
isave->BeginChunk(TEX_HDR_CHUNK);
res = MtlBase::Save(isave);
if (res != IO_OK)
return res;
isave->EndChunk();
return IO_OK;
}
IOResult plDynamicTextLayer::Load(ILoad *iload)
{
IOResult res;
while (IO_OK == (res = iload->OpenChunk()))
{
if (iload->CurChunkID() == TEX_HDR_CHUNK)
{
res = MtlBase::Load(iload);
}
iload->CloseChunk();
if (res != IO_OK)
return res;
}
return IO_OK;
}
inline Point2 CompUV(float x, float y, float z)
{
return Point2( 0.5f * ( x / z + 1.0f ), 0.5f * ( y / z + 1.0f ) );
}
Bitmap *plDynamicTextLayer::GetBitmap( TimeValue t )
{
return fInitBitmap;
}
AColor plDynamicTextLayer::EvalColor(ShadeContext& sc)
{
if (!sc.doMaps)
return AColor(0.0f, 0.0f, 0.0f, 1.0f);
AColor color;
if (sc.GetCache(this, color))
return color;
if (gbufID)
sc.SetGBufferID(gbufID);
// Evaluate the Bitmap
if( fBitmapPB->GetInt( kBmpUseInitImage ) && fInitBitmap )
{
plBMSampler mysamp( this, fInitBitmap );
color = fUVGen->EvalUVMap( sc, &mysamp, TRUE );
}
else
color.White();
// Invert color if specified
if( fBitmapPB->GetInt( kBmpInvertColor ) )
{
color.r = 1.0f - color.r;
color.g = 1.0f - color.g;
color.b = 1.0f - color.b;
}
// Discard color if specified
if( fBitmapPB->GetInt( kBmpDiscardColor ) )
color.r = color.g = color.b = 1.0f;
// Invert alpha if specified
if( fBitmapPB->GetInt( kBmpInvertAlpha ) )
color.a = 1.0f - color.a;
// Discard alpha if specified
if( fBitmapPB->GetInt( kBmpDiscardAlpha ) )
color.a = 1.0f;
sc.PutCache(this, color);
return color;
}
float plDynamicTextLayer::EvalMono(ShadeContext& sc)
{
return Intens(EvalColor(sc));
}
Point3 plDynamicTextLayer::EvalNormalPerturb(ShadeContext& sc)
{
// Return the perturbation to apply to a normal for bump mapping
return Point3(0, 0, 0);
}
ULONG plDynamicTextLayer::LocalRequirements(int subMtlNum)
{
return fUVGen->Requirements( subMtlNum );
}
void plDynamicTextLayer::IDiscardTexHandle()
{
if (fTexHandle)
{
fTexHandle->DeleteThis();
fTexHandle = NULL;
}
}
void plDynamicTextLayer::ActivateTexDisplay(BOOL onoff)
{
if (!onoff)
IDiscardTexHandle();
}
BITMAPINFO *plDynamicTextLayer::GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono, BOOL forceW, BOOL forceH)
{
// FIXME
fTexTime = 0;//CalcFrame(t);
// texValid = clipValid;
BITMAPINFO *bmi = NULL;
int xflags = 0;
// Create a bitmap to write into via Windows
BITMAPINFO tempBMI;
memset( &tempBMI.bmiHeader, 0, sizeof( BITMAPINFOHEADER ) );
tempBMI.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
tempBMI.bmiHeader.biWidth = fBitmapPB->GetInt( kBmpExportWidth );
tempBMI.bmiHeader.biHeight = -(int)fBitmapPB->GetInt( kBmpExportHeight );
tempBMI.bmiHeader.biPlanes = 1;
tempBMI.bmiHeader.biCompression = BI_RGB;
tempBMI.bmiHeader.biBitCount = 32;
DWORD *bitmapBits;
HDC winDC = CreateCompatibleDC( nil );
HBITMAP bitmap = CreateDIBSection( winDC, &tempBMI, DIB_RGB_COLORS, (void **)&bitmapBits, nil, 0 );
HBITMAP old = (HBITMAP)SelectObject( winDC, bitmap );
// Write into it now
RECT r;
SetRect( &r, 0, 0, fBitmapPB->GetInt( kBmpExportWidth ) - 1, fBitmapPB->GetInt( kBmpExportHeight ) - 1 );
HBRUSH brush = CreateSolidBrush( RGB( 255, 0, 0 ) );
FrameRect( winDC, &r, brush );
DeleteObject( brush );
SetMapMode( winDC, MM_TEXT );
SetBkMode( winDC, TRANSPARENT );
SetTextAlign( winDC, TA_TOP | TA_LEFT );
// Background letters
int nHeight = -MulDiv( 72, GetDeviceCaps( winDC, LOGPIXELSY ), 72 );
HFONT winFont = CreateFont( nHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, "Times New Roman" );
if( winFont != nil )
{
HFONT origFont = (HFONT)SelectObject( winDC, winFont );
SetTextColor( winDC, RGB( 32, 32, 32 ) );
char str2[] = "ABCDEFG";
::TextOut( winDC, 0, 0, str2, strlen( str2 ) );
SelectObject( winDC, origFont );
DeleteObject( winFont );
}
nHeight = -MulDiv( 8, GetDeviceCaps( winDC, LOGPIXELSY ), 72 );
winFont = CreateFont( nHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, "Arial" );
if( winFont != nil )
{
HFONT origFont = (HFONT)SelectObject( winDC, winFont );
SetTextColor( winDC, RGB( 255, 255, 255 ) );
char str[] = "Dynamic Text";
::TextOut( winDC, 0, 0, str, strlen( str ) );
char str3[] = "This is 8 point Arial";
::TextOut( winDC, 0, 12, str3, strlen( str3 ) );
SelectObject( winDC, origFont );
DeleteObject( winFont );
}
/// Create a MAX bitmap and copy over the data, the painful way
Bitmap *maxBmp;
BitmapInfo maxInfo;
maxInfo.SetType( BMM_TRUE_32 );
maxInfo.SetWidth( fBitmapPB->GetInt( kBmpExportWidth ) );
maxInfo.SetHeight( fBitmapPB->GetInt( kBmpExportHeight ) );
maxInfo.SetFlags( MAP_HAS_ALPHA );
maxInfo.SetCustomFlag( 0 );
maxBmp = TheManager->Create( &maxInfo );
PixelBuf l64( fBitmapPB->GetInt( kBmpExportWidth ) );
for( int y = 0; y < fBitmapPB->GetInt( kBmpExportHeight ); y++ )
{
BMM_Color_64 *p64 = l64.Ptr();
for( int x = 0; x < fBitmapPB->GetInt( kBmpExportWidth ); x++, p64++ )
{
COLORREF color = GetPixel( winDC, x, y );
if( color == RGB( 0, 0, 0 ) )
{
if( fBitmapPB->GetInt( kBmpUseInitImage ) && fInitBitmap != nil )
fInitBitmap->GetLinearPixels( x, y, 1, p64 );
else
p64->r = p64->g = p64->b = 0.f;
}
else
{
p64->r = GetRValue( color ) << 8;
p64->g = GetGValue( color ) << 8;
p64->b = GetBValue( color ) << 8;
}
p64->a = 0xffff;
}
maxBmp->PutPixels( 0, y, fBitmapPB->GetInt( kBmpExportWidth ), l64.Ptr() );
}
// Done with these now
SelectObject( winDC, old );
DeleteObject( bitmap );
DeleteObject( winDC );
// Convert to a BITMAPINFO. Go figure.
bmi = thmaker.BitmapToDIB( maxBmp, 0, xflags, forceW, forceH );
return bmi;
}
DWORD plDynamicTextLayer::GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker)
{
// FIXME: ignore validity for now
if (fTexHandle && fIValid.InInterval(t))// && texTime == CalcFrame(t))
return fTexHandle->GetHandle();
else
{
IDiscardTexHandle();
fTexTime = 0;//CalcFrame(t);
fTexHandle = thmaker.MakeHandle(GetVPDisplayDIB(t, thmaker, fIValid));
if (fTexHandle)
return fTexHandle->GetHandle();
else
return 0;
}
}
const char *plDynamicTextLayer::GetTextureName( int which )
{
PBBitmap *pbbm = fBitmapPB->GetBitmap( kBmpInitBitmap );
if( pbbm )
return pbbm->bi.Name();
return NULL;
}
void plDynamicTextLayer::ISetPBBitmap(PBBitmap *pbbm, int index /* = 0 */)
{
fBitmapPB->SetValue( (ParamID)kBmpInitBitmap, 0, pbbm );
}
PBBitmap *plDynamicTextLayer::GetPBBitmap(int index /* = 0 */)
{
return fBitmapPB->GetBitmap( (ParamID)kBmpInitBitmap );
}
//// GetSamplerInfo ///////////////////////////////////////////////////////////
// Virtual function called by plBMSampler to get various things while sampling
// the layer's image
bool plDynamicTextLayer::GetSamplerInfo( plBMSamplerData *samplerData )
{
if( fBitmapPB->GetInt( (ParamID)kBmpDiscardAlpha ) )
samplerData->fAlphaSource = plBMSamplerData::kDiscard;
else
samplerData->fAlphaSource = plBMSamplerData::kFromTexture;
return true;
}

View File

@ -0,0 +1,228 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDynamicTextLayer - Dynamic Run-time Text MAX Layer //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 1.13.2002 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plDynamicTextLayer_h
#define _plDynamicTextLayer_h
#include "Max.h"
#include "../resource.h"
#include "plPlasmaMAXLayer.h"
class ClassDesc2;
class IParamBlock2;
class DTLPBAccessor;
ClassDesc2* GetDynamicTextLayerDesc();
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
//// Class Definition /////////////////////////////////////////////////////////
class plDynamicTextLayer : public plPlasmaMAXLayer
{
protected:
friend class DTLPBAccessor;
// Parameter block
IParamBlock2 *fBitmapPB;
UVGen *fUVGen;
IMtlParams *fIMtlParams;
TexHandle *fTexHandle;
TimeValue fTexTime;
Interval fIValid;
Bitmap *fInitBitmap;
static ParamDlg *fUVGenDlg;
friend class DTLBitmapDlgProc;
public:
// Ref nums
enum
{
kRefUVGen,
kRefBitmap,
};
// Block ID's
enum
{
kBlkBitmap,
};
plDynamicTextLayer();
~plDynamicTextLayer();
void DeleteThis() { delete this; }
//From MtlBase
ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
BOOL SetDlgThing(ParamDlg* dlg);
void Update(TimeValue t, Interval& valid);
void Reset();
Interval Validity(TimeValue t);
ULONG LocalRequirements(int subMtlNum);
//From Texmap
RGBA EvalColor(ShadeContext& sc);
float EvalMono(ShadeContext& sc);
Point3 EvalNormalPerturb(ShadeContext& sc);
// For displaying textures in the viewport
BOOL SupportTexDisplay() { return TRUE; }
void ActivateTexDisplay(BOOL onoff);
BITMAPINFO *GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono=FALSE, int forceW=0, int forceH=0);
DWORD GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker);
protected:
void IChanged();
void IDiscardTexHandle();
public:
void GetUVTransform(Matrix3 &uvtrans) { fUVGen->GetUVTransform(uvtrans); }
int GetTextureTiling() { return fUVGen->GetTextureTiling(); }
int GetUVWSource() { return fUVGen->GetUVWSource(); }
virtual int GetMapChannel () { return fUVGen->GetMapChannel(); } // only relevant if above returns UVWSRC_EXPLICIT
UVGen *GetTheUVGen() { return fUVGen; }
//TODO: Return anim index to reference index
int SubNumToRefNum(int subNum) { return subNum; }
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
//From Animatable
Class_ID ClassID() { return DYN_TEXT_LAYER_CLASS_ID; }
SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_DYN_TEXT_LAYER); }
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
// TODO: Maintain the number or references here
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
int NumParamBlocks(); // return number of ParamBlocks in this instance
IParamBlock2* GetParamBlock(int i); // return i'th ParamBlock
IParamBlock2* GetParamBlockByID(BlockID id); // return id'd ParamBlock
const char *GetTextureName( int which );
virtual Bitmap* GetBitmap(TimeValue t);
/// ParamBlock accessors
enum
{
kScalingAny,
kScalingHalf,
kScalingNone
};
// Param ID's
enum
{
kBmpExportWidth,
kBmpExportHeight,
kBmpExportLastWidth, // Annoying fields, these two, but they're necessary
kBmpExportLastHeight, // for clamping the spinners to powers of 2
// Misc
kBmpDiscardColor,
kBmpInvertColor,
kBmpDiscardAlpha,
kBmpInvertAlpha,
// Static text settings
kBmpMakeStatic,
kBmpText,
kBmpFontFace,
kBmpFontSize,
kBmpLeftMargin,
kBmpTopMargin,
kBmpRightMargin,
kBmpBottomMargin,
// Initial image settings
kBmpUseInitImage,
kBmpInitBitmap,
kBmpIncludeAlphaChannel
};
// Pure virtual accessors for the various bitmap related elements
virtual Bitmap *GetMaxBitmap(int index = 0) { return fInitBitmap; }
virtual PBBitmap *GetPBBitmap( int index = 0 );
virtual int GetNumBitmaps( void ) { return 1; }
// Virtual function called by plBMSampler to get various things while sampling the layer's image
virtual bool GetSamplerInfo( plBMSamplerData *samplerData );
protected:
virtual void ISetMaxBitmap( Bitmap *bitmap, int index = 0 ) { fInitBitmap = bitmap; }
virtual void ISetPBBitmap( PBBitmap *pbbm, int index = 0 );
};
#endif // _plDynamicTextLayer_h

View File

@ -0,0 +1,320 @@
/*==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 "hsTypes.h"
#include "plDynamicTextLayer.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "stdmat.h"
#include "plBMSampler.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
///////////////////////////////////////////////////////////////////////////////
//// ParamBlock Dialog Proc ///////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
class DTLBitmapDlgProc : public ParamMap2UserDlgProc
{
/// Called to update the controls of the dialog
virtual void Update( TimeValue t, Interval &valid, IParamMap2 *map )
{
IParamBlock2 *pblock;
BitmapInfo bi;
ICustButton *bmSelectBtn;
ParamMap2UserDlgProc::Update( t, valid, map );
pblock = map->GetParamBlock();
plDynamicTextLayer *layer = (plDynamicTextLayer *)map->GetParamBlock()->GetOwner();
bmSelectBtn = GetICustButton( GetDlgItem( map->GetHWnd(), IDC_INITIMAGE ) );
PBBitmap *pbbm = pblock->GetBitmap( plDynamicTextLayer::kBmpInitBitmap );
if( pbbm )
bmSelectBtn->SetText( (TCHAR *)pbbm->bi.Filename() );
else
bmSelectBtn->SetText( _T( "None" ) );
ReleaseICustButton( bmSelectBtn );
}
/// Clamp texture sizes to a power of 2
void IClampTexSizeSpinner( TimeValue t, IParamMap2 *map )
{
}
/// Main message proc
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
break;
/// Note: the following *could* be done in the accessor, except that you end up in an
/// infinite loop updating the values. Not good.
case CC_SPINNER_CHANGE:
if( LOWORD( wParam ) == IDC_EXPORTWIDTH_SPINNER )
IClampTexSizeSpinner( t, map, true );
else if( LOWORD( wParam ) == IDC_EXPORTHEIGHT_SPINNER )
IClampTexSizeSpinner( t, map, false );
break;
case WM_COMMAND:
if( HIWORD( wParam ) == EN_CHANGE && LOWORD( wParam ) == IDC_EXPORTWIDTH )
IClampTexSizeSpinner( t, map, true );
else if( HIWORD( wParam ) == EN_CHANGE && LOWORD( wParam ) == IDC_EXPORTHEIGHT )
IClampTexSizeSpinner( t, map, false );
else if( HIWORD( wParam ) == BN_CLICKED && LOWORD( wParam ) == IDC_INITIMAGE_RELOAD )
{
// TEMP
IParamBlock2 *pblock = map->GetParamBlock();
PBBitmap *pbbm = pblock->GetBitmap( plDynamicTextLayer::kBmpInitBitmap );
if( pbbm )
{
plDynamicTextLayer *layer = (plDynamicTextLayer *)map->GetParamBlock()->GetOwner();
layer->RefreshBitmaps();
layer->IChanged();
}
return TRUE;
}
else if( LOWORD( wParam ) == IDC_INITIMAGE )
{
plPlasmaMAXLayer *layer = (plPlasmaMAXLayer *)map->GetParamBlock()->GetOwner();
if( layer == nil )
return FALSE;
BOOL selectedNewBitmap = layer->HandleBitmapSelection();
if( selectedNewBitmap )
{
IParamBlock2 *pblock = map->GetParamBlock();
ICustButton *bmSelectBtn = GetICustButton( GetDlgItem( hWnd, IDC_INITIMAGE ) );
PBBitmap *pbbm = layer->GetPBBitmap();
bmSelectBtn->SetText( pbbm != nil ? (TCHAR *)pbbm->bi.Filename() : "");
ReleaseICustButton( bmSelectBtn );
}
return TRUE;
}
break;
}
return FALSE;
}
void DeleteThis() {};
protected:
/// Clamp texture sizes to a power of 2
void IClampTexSizeSpinner( TimeValue t, IParamMap2 *map, bool clampWidth )
{
IParamBlock2 *pblock = map->GetParamBlock();
ParamID clampNew, clampOld;
ParamID otherNew, otherOld;
if( clampWidth )
{
clampNew = plDynamicTextLayer::kBmpExportWidth; clampOld = plDynamicTextLayer::kBmpExportLastWidth;
otherNew = plDynamicTextLayer::kBmpExportHeight; otherOld = plDynamicTextLayer::kBmpExportLastHeight;
}
else
{
clampNew = plDynamicTextLayer::kBmpExportHeight; clampOld = plDynamicTextLayer::kBmpExportLastHeight;
otherNew = plDynamicTextLayer::kBmpExportWidth; otherOld = plDynamicTextLayer::kBmpExportLastWidth;
}
int lastVal = pblock->GetInt( clampOld, t );
int tempVal, newVal = pblock->GetInt( clampNew, t );
if( newVal < lastVal )
{
lastVal = newVal;
for( tempVal = 1; tempVal <= newVal; tempVal <<= 1 );
newVal = tempVal >> 1;
}
else
{
lastVal = newVal;
for( tempVal = 1; tempVal < newVal; tempVal <<= 1 );
newVal = tempVal;
}
pblock->SetValue( clampNew, t, newVal );
pblock->SetValue( clampOld, t, newVal );
}
int IFloorPow2( int value )
{
int v;
for( v = 1; v <= value; v <<= 1 );
return v >> 1;
}
};
static DTLBitmapDlgProc gDTLBitmapDlgProc;
///////////////////////////////////////////////////////////////////////////////
//// Bitmap Accessor //////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
class DTLPBAccessor : public PBAccessor
{
public:
void Set(PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
if( !owner )
return;
plDynamicTextLayer *layer = (plDynamicTextLayer *)owner;
IParamBlock2 *pb = owner->GetParamBlockByID( plDynamicTextLayer::kBlkBitmap );
switch( id )
{
case plDynamicTextLayer::kBmpInitBitmap:
case plDynamicTextLayer::kBmpUseInitImage:
if (pb->GetMap())
pb->GetMap()->Invalidate( id );
layer->IChanged();
break;
}
}
void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid)
{
}
};
static DTLPBAccessor gDTLPBAccessor;
///////////////////////////////////////////////////////////////////////////////
//// ParamBlock Definition ////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static ParamBlockDesc2 gBitmapParamBlk
(
plDynamicTextLayer::kBlkBitmap, _T("bitmap"), 0, GetDynamicTextLayerDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI, plDynamicTextLayer::kRefBitmap,
IDD_DYN_TEXT_LAYER, IDS_DYN_TEXT_LAYER_PROPS, 0, 0, &gDTLBitmapDlgProc,
// Texture Color/Alpha
plDynamicTextLayer::kBmpDiscardColor, _T("discardColor"), TYPE_BOOL, 0, 0,
// p_ui, TYPE_SINGLECHEKBOX, IDC_BLEND_NO_COLOR,
end,
plDynamicTextLayer::kBmpInvertColor, _T("invertColor"), TYPE_BOOL, 0, 0,
// p_ui, TYPE_SINGLECHEKBOX, IDC_BLEND_INV_COLOR,
end,
plDynamicTextLayer::kBmpDiscardAlpha, _T("discardAlpha"), TYPE_BOOL, 0, 0,
// p_ui, TYPE_SINGLECHEKBOX, IDC_DISCARD_ALPHA,
end,
plDynamicTextLayer::kBmpInvertAlpha, _T("invertAlpha"), TYPE_BOOL, 0, 0,
// p_ui, TYPE_SINGLECHEKBOX, IDC_BLEND_INV_ALPHA,
end,
// Texture size
plDynamicTextLayer::kBmpExportWidth, _T("exportWidth"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_EXPORTWIDTH, IDC_EXPORTWIDTH_SPINNER, SPIN_AUTOSCALE,
p_range, 4, 2048,
p_default, 512,
end,
plDynamicTextLayer::kBmpExportHeight, _T("exportHeight"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_EXPORTHEIGHT, IDC_EXPORTHEIGHT_SPINNER, SPIN_AUTOSCALE,
p_range, 4, 2048,
p_default, 512,
end,
plDynamicTextLayer::kBmpExportLastWidth, _T("lastExportWidth"), TYPE_INT, 0, 0,
end,
plDynamicTextLayer::kBmpExportLastHeight, _T("lastExportHeight"), TYPE_INT, 0, 0,
end,
plDynamicTextLayer::kBmpIncludeAlphaChannel, _T("includeAlphaChannel"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_DYNTEXT_ALPHA,
p_default, FALSE,
end,
// Initial image
plDynamicTextLayer::kBmpUseInitImage, _T("useInitImage"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_USEINITIMAGE,
p_enable_ctrls, 1, plDynamicTextLayer::kBmpInitBitmap,
p_accessor, &gDTLPBAccessor,
end,
plDynamicTextLayer::kBmpInitBitmap, _T("initBitmap"), TYPE_BITMAP, P_SHORT_LABELS, 0,
p_accessor, &gDTLPBAccessor,
end,
/* plGUIButtonComponent::kRefAnimate, _T( "animate" ), TYPE_BOOL, 0, 0,
p_ui, plGUIControlBase::kRollMain, TYPE_SINGLECHEKBOX, IDC_GUI_ANIMATE,
p_default, FALSE,
p_enable_ctrls, 1, plGUIButtonComponent::kRefAnimation,
end,
// Static text settings
plDynamicTextLayer::kBmpMakeStatic, _T("makeStatic"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_DYNTEXT_MAKESTATIC,
p_default, FALSE,
p_enable_ctrls, 5, kBmpFontSize, kBmpLeftMargin, kBmpTopMargin, kBmpRightMargin, kBmpBottomMargin,
end,
plDynamicTextLayer::kBmpText,
plDynamicTextLayer::kBmpFontFace,
plDynamicTextLayer::kBmpFontSize,
plDynamicTextLayer::kBmpLeftMargin,
plDynamicTextLayer::kBmpTopMargin,
plDynamicTextLayer::kBmpRightMargin,
plDynamicTextLayer::kBmpBottomMargin,
*/
end
);

View File

@ -0,0 +1,699 @@
/*==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 "hsTypes.h"
#include "plLayerTex.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "stdmat.h"
#include "plBMSampler.h"
#include "../resource.h"
#include "plLayerTexBitmapPB.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
class plLayerTexClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading = FALSE) { return TRACKED_NEW plLayerTex(); }
const TCHAR* ClassName() { return GetString(IDS_LAYER); }
SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
Class_ID ClassID() { return LAYER_TEX_CLASS_ID; }
const TCHAR* Category() { return TEXMAP_CAT_2D; }
const TCHAR* InternalName() { return _T("PlasmaLayer"); }
HINSTANCE HInstance() { return hInstance; }
};
static plLayerTexClassDesc plLayerTexDesc;
ClassDesc2* GetLayerTexDesc() { return &plLayerTexDesc; }
ParamDlg* plLayerTex::fUVGenDlg = NULL;
// For initializing paramblock descriptor
//ParamBlockDesc2 *GetBasicBlk();
ParamBlockDesc2 *GetBitmapBlk();
//#include "plLayerTexBasicPB.cpp"
#include "plLayerTexBitmapPB.cpp"
void plLayerTex::GetClassName( TSTR &s )
{
s = GetString( IDS_LAYER );
}
plLayerTex::plLayerTex() :
fBitmapPB(NULL),
//fBasicPB(NULL),
fUVGen(NULL),
fTexHandle(NULL),
fTexTime(0),
fBM(NULL),
fIValid(NEVER)
{
#if 0
// Initialize the paramblock descriptors only once
static bool descInit = false;
if (!descInit)
{
descInit = true;
//GetBasicBlk()->SetClassDesc(GetLayerTexDesc());
GetBitmapBlk()->SetClassDesc(GetLayerTexDesc());
}
#endif
plLayerTexDesc.MakeAutoParamBlocks(this);
ReplaceReference(kRefUVGen, GetNewDefaultUVGen());
}
plLayerTex::~plLayerTex()
{
if (fBM)
fBM->DeleteThis();
IDiscardTexHandle();
}
//From MtlBase
void plLayerTex::Reset()
{
GetLayerTexDesc()->Reset(this, TRUE); // reset all pb2's
SetBitmap(NULL);
fIValid.SetEmpty();
}
void plLayerTex::Update(TimeValue t, Interval& valid)
{
if (!fIValid.InInterval(t))
{
fIValid.SetInfinite();
fUVGen->Update(t,fIValid);
fBitmapPB->GetValidity(t, fIValid);
// Interval clipValid;
// clipValid.SetInfinite();
// float temp;
// fBitmapPB->GetValue(kBmpClipU, t, temp, clipValid);
// fBitmapPB->GetValue(kBmpClipV, t, temp, clipValid);
// fBitmapPB->GetValue(kBmpClipW, t, temp, clipValid);
// fBitmapPB->GetValue(kBmpClipH, t, temp, clipValid);
}
// Gonna need to do this when we support animated bm's
#if 0
if (fBM)
{
if (bi.FirstFrame()!=bi.LastFrame())
ivalid.SetInstant(t);
}
#endif
valid &= fIValid;
}
Interval plLayerTex::Validity(TimeValue t)
{
//TODO: Update fIValid here
// mf horse - Hacking this in just to get animations working.
// No warranty on this not being stupid.
Interval v = FOREVER;
fBitmapPB->GetValidity(t, v);
//fBasicPB->GetValidity(t, v);
v &= fUVGen->Validity(t);
return v;
}
ParamDlg* plLayerTex::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
fMtlParams = imp;
IAutoMParamDlg* masterDlg = plLayerTexDesc.CreateParamDlgs(hwMtlEdit, imp, this);
fUVGenDlg = fUVGen->CreateParamDlg(hwMtlEdit, imp);
masterDlg->AddDlg(fUVGenDlg);
return masterDlg;
}
BOOL plLayerTex::SetDlgThing(ParamDlg* dlg)
{
if (dlg == fUVGenDlg)
{
fUVGenDlg->SetThing(fUVGen);
return TRUE;
}
return FALSE;
}
int plLayerTex::NumRefs()
{
return 3;
}
//From ReferenceMaker
RefTargetHandle plLayerTex::GetReference(int i)
{
switch (i)
{
case kRefUVGen: return fUVGen;
case kRefBitmap: return fBitmapPB;
//case kRefBasic: return fBasicPB;
default: return NULL;
}
}
void plLayerTex::SetReference(int i, RefTargetHandle rtarg)
{
Interval garbage;
switch (i)
{
case kRefUVGen:
fUVGen = (UVGen *)rtarg;
if( fUVGen )
fUVGen->Update( TimeValue( 0 ), garbage );
break;
case kRefBitmap:
fBitmapPB = (IParamBlock2 *)rtarg;
// KLUDGE: If the paramblock is being set chances are we are being created or
// loaded. In the case of load, we want to refresh our texture.
if (fBitmapPB)
RefreshBitmaps();
break;
}
}
int plLayerTex::NumParamBlocks()
{
return 2;
}
IParamBlock2* plLayerTex::GetParamBlock(int i)
{
switch (i)
{
case 0: return fBitmapPB;
//case 1: return fBasicPB;
default: return NULL;
}
}
IParamBlock2* plLayerTex::GetParamBlockByID(BlockID id)
{
if (fBitmapPB->ID() == id)
return fBitmapPB;
//else if (fBasicPB->ID() == id)
// return fBasicPB;
else
return NULL;
}
//From ReferenceTarget
RefTargetHandle plLayerTex::Clone(RemapDir &remap)
{
plLayerTex *mnew = TRACKED_NEW plLayerTex();
*((MtlBase*)mnew) = *((MtlBase*)this); // copy superclass stuff
//mnew->ReplaceReference(kRefBasic, remap.CloneRef(fBasicPB));
mnew->ReplaceReference(kRefBitmap, remap.CloneRef(fBitmapPB));
mnew->ReplaceReference(kRefUVGen, remap.CloneRef(fUVGen));
BaseClone(this, mnew, remap);
return (RefTargetHandle)mnew;
}
int plLayerTex::NumSubs()
{
return 3;
}
Animatable* plLayerTex::SubAnim(int i)
{
//TODO: Return 'i-th' sub-anim
switch (i)
{
case kRefUVGen: return fUVGen;
case kRefBitmap: return fBitmapPB;
//case kRefBasic: return fBasicPB;
default: return NULL;
}
}
TSTR plLayerTex::SubAnimName(int i)
{
switch (i)
{
case kRefUVGen: return "UVGen";
case kRefBitmap: return fBitmapPB->GetLocalName();
//case kRefBasic: return fBasicPB->GetLocalName();
default: return "";
}
}
RefResult plLayerTex::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message)
{
switch (message)
{
case REFMSG_CHANGE:
{
fIValid.SetEmpty();
if (hTarget == fBitmapPB)
{
// see if this message came from a changing parameter in the pblock,
// if so, limit rollout update to the changing item and update any active viewport texture
ParamID changingParam = fBitmapPB->LastNotifyParamID();
fBitmapPB->GetDesc()->InvalidateUI(changingParam);
if (changingParam != -1)
IChanged();
}
}
break;
case REFMSG_UV_SYM_CHANGE:
IDiscardTexHandle();
break;
}
return REF_SUCCEED;
}
BOOL plLayerTex::DiscardColor()
{
return fBitmapPB->GetInt(kBmpDiscardColor);
}
BOOL plLayerTex::DiscardAlpha()
{
return fBitmapPB->GetInt(kBmpDiscardAlpha);
}
void plLayerTex::IChanged()
{
IDiscardTexHandle();
// Texture wasn't getting updated in the viewports, and this fixes it.
// Don't know if it's the right way though.
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
// And this is so the SceneWatcher gets notified that the material on some of it's
// referenced objects changed.
NotifyDependents(FOREVER, PART_ALL, REFMSG_USER_MAT);
}
#define TEX_HDR_CHUNK 0x5000
#define MAX_ASS_CHUNK 0x5500
IOResult plLayerTex::Save(ISave *isave)
{
IOResult res;
isave->BeginChunk(TEX_HDR_CHUNK);
res = MtlBase::Save(isave);
if (res != IO_OK)
return res;
isave->EndChunk();
return IO_OK;
}
IOResult plLayerTex::Load(ILoad *iload)
{
IOResult res;
while (IO_OK == (res = iload->OpenChunk()))
{
if (iload->CurChunkID() == TEX_HDR_CHUNK)
{
res = MtlBase::Load(iload);
}
iload->CloseChunk();
if (res != IO_OK)
return res;
}
return IO_OK;
}
bool plLayerTex::HasAlpha()
{
return (fBM != NULL && fBM->HasAlpha() != 0);
}
Bitmap* plLayerTex::GetBitmap(TimeValue t)
{
return fBM;
}
AColor plLayerTex::EvalColor(ShadeContext& sc)
{
if (!sc.doMaps)
return AColor(0.0f, 0.0f, 0.0f, 1.0f);
AColor color;
if (sc.GetCache(this, color))
return color;
if (gbufID)
sc.SetGBufferID(gbufID);
//
// Evaluate the Bitmap
//
if (fBitmapPB->GetInt(kBmpUseBitmap) && fBM)
{
plBMSampler mysamp(this, fBM);
color = fUVGen->EvalUVMap(sc, &mysamp, FALSE);
// We'd like to pass TRUE and actually filter the image, but that seems to be
// tripping an odd crash in Max internals. *shrug*
}
else
color.White();
// Invert color if specified
if (fBitmapPB->GetInt(kBmpInvertColor))
{
color.r = 1.0f - color.r;
color.g = 1.0f - color.g;
color.b = 1.0f - color.b;
}
// Discard color if specified
if (fBitmapPB->GetInt(kBmpDiscardColor))
color.r = color.g = color.b = 1.0f;
// Invert alpha if specified
if (fBitmapPB->GetInt(kBmpInvertAlpha))
color.a = 1.0f - color.a;
// Discard alpha if specified
if (fBitmapPB->GetInt(kBmpDiscardAlpha))
color.a = 1.0f;
// If RGB output is set to alpha, show RGB as grayscale of the alpha
if (fBitmapPB->GetInt(kBmpRGBOutput) == 1)
color = AColor(color.a, color.a, color.a, 1.0f);
sc.PutCache(this, color);
return color;
}
float plLayerTex::EvalMono(ShadeContext& sc)
{
if (fBitmapPB->GetInt(kBmpMonoOutput) == 1)
return EvalColor(sc).a;
return Intens(EvalColor(sc));
}
Point3 plLayerTex::EvalNormalPerturb(ShadeContext& sc)
{
// Return the perturbation to apply to a normal for bump mapping
return Point3(0, 0, 0);
}
ULONG plLayerTex::LocalRequirements(int subMtlNum)
{
return fUVGen->Requirements(subMtlNum);
}
#if 0
int plLayerTex::ICalcFrame(TimeValue t)
{
PBBitmap *pbbm = fBitmapPB->GetBitmap(kBmpBitmap);
if (!pbbm || !pbbm->bi)
return 0;
BitmapInfo *bi = pbbm->bi;
TimeValue tm, dur, td;
int frameStart = bi->FirstFrame();
int frameEnd = bi->LastFrame();
int tpf = GetTicksPerFrame();
tm = TimeValue(float(t - startTime) * pbRate);
dur = (fend-fstart+1)*GetTicksPerFrame();
switch (endCond)
{
case END_HOLD:
if (tm <= 0)
return frameStart;
if (tm >= dur)
return frameEnd;
return tm/tpf;
case END_PINGPONG:
if (((tm >= 0) && ((tm / dur) & 1)) || ((tm < 0) && !(tm / dur)))
{
td = modt(tm, dur);
return frameStart + frameEnd - td / tpf;
}
// else fall through
case END_LOOP:
td = modt(tm, dur);
return td / tpf;
}
return 0;
}
#endif
void plLayerTex::IDiscardTexHandle()
{
if (fTexHandle)
{
fTexHandle->DeleteThis();
fTexHandle = NULL;
}
}
void plLayerTex::ActivateTexDisplay(BOOL onoff)
{
if (!onoff)
IDiscardTexHandle();
}
BITMAPINFO *plLayerTex::GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono, BOOL forceW, BOOL forceH)
{
// FIXME
fTexTime = 0;//CalcFrame(t);
// texValid = clipValid;
BITMAPINFO *bmi = NULL;
int xflags = 0;
if (fBitmapPB->GetInt(kBmpApply))
{
float clipu = fBitmapPB->GetFloat(kBmpClipU);
float clipv = fBitmapPB->GetFloat(kBmpClipV);
float clipw = fBitmapPB->GetFloat(kBmpClipW);
float cliph = fBitmapPB->GetFloat(kBmpClipH);
int discardAlpha = fBitmapPB->GetInt(kBmpDiscardAlpha);
int alphaAsRGB = (fBitmapPB->GetInt(kBmpRGBOutput) == 1);
int w = fBM->Width();
int h = fBM->Height();
Bitmap *newBM;
BitmapInfo bi;
bi.SetName(_T("y8798734"));
bi.SetType(BMM_TRUE_32);
bi.SetFlags(MAP_HAS_ALPHA);
if (fBitmapPB->GetInt(kBmpCropPlace) == 1)
{
int x0, y0, nw, nh;
int bmw = thmaker.Size();
int bmh = int(float(bmw)*float(h)/float(w));
bi.SetWidth(bmw);
bi.SetHeight(bmh);
newBM = TheManager->Create(&bi);
newBM->Fill(0,0,0,0);
nw = int(float(bmw)*clipw);
nh = int(float(bmh)*cliph);
x0 = int(float(bmw-1)*clipu);
y0 = int(float(bmh-1)*clipv);
if (nw<1) nw = 1;
if (nh<1) nh = 1;
PixelBuf row(nw);
Bitmap *tmpBM;
BitmapInfo bif2;
bif2.SetName(_T("xxxx67878"));
bif2.SetType(BMM_TRUE_32);
bif2.SetFlags(MAP_HAS_ALPHA);
bif2.SetWidth(nw);
bif2.SetHeight(nh);
tmpBM = TheManager->Create(&bif2);
tmpBM->CopyImage(fBM, COPY_IMAGE_RESIZE_LO_QUALITY, 0);
BMM_Color_64* p1 = row.Ptr();
for (int y = 0; y<nh; y++)
{
tmpBM->GetLinearPixels(0,y, nw, p1);
if (alphaAsRGB)
{
for (int ix =0; ix<nw; ix++)
p1[ix].r = p1[ix].g = p1[ix].b = p1[ix].a;
}
if (discardAlpha)
{
for (int ix = 0; ix < nw; ix++)
p1[ix].a = 0xffff;
}
newBM->PutPixels(x0, y+y0, nw, p1);
}
tmpBM->DeleteThis();
bmi = thmaker.BitmapToDIB(newBM, fUVGen->SymFlags(), xflags, forceW, forceH);
newBM->DeleteThis();
}
else
{
int x0,y0,nw,nh;
x0 = int(float(w-1)*clipu);
y0 = int(float(h-1)*clipv);
nw = int(float(w)*clipw);
nh = int(float(h)*cliph);
if (nw<1) nw = 1;
if (nh<1) nh = 1;
bi.SetWidth(nw);
bi.SetHeight(nh);
PixelBuf row(nw);
newBM = TheManager->Create(&bi);
BMM_Color_64* p1 = row.Ptr();
for (int y = 0; y<nh; y++)
{
fBM->GetLinearPixels(x0,y+y0, nw, p1);
if (alphaAsRGB)
{
for (int ix = 0; ix < nw; ix++)
p1[ix].r = p1[ix].g = p1[ix].b = p1[ix].a;
}
if (discardAlpha)
{
for (int ix = 0; ix < nw; ix++)
p1[ix].a = 0xffff;
}
newBM->PutPixels(0, y, nw, p1);
}
bmi = thmaker.BitmapToDIB(newBM, fUVGen->SymFlags(), xflags, forceW, forceH);
newBM->DeleteThis();
}
}
else
{
if (fBitmapPB->GetInt(kBmpRGBOutput) == 1)
xflags |= EX_RGB_FROM_ALPHA;
bmi = thmaker.BitmapToDIB(fBM, fUVGen->SymFlags(), xflags, forceW, forceH);
}
return bmi;
}
DWORD plLayerTex::GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker)
{
// FIXME: ignore validity for now
if (fTexHandle && fIValid.InInterval(t))// && texTime == CalcFrame(t))
return fTexHandle->GetHandle();
else
{
IDiscardTexHandle();
fTexTime = 0;//CalcFrame(t);
fTexHandle = thmaker.MakeHandle(GetVPDisplayDIB(t, thmaker, fIValid));
if (fTexHandle)
return fTexHandle->GetHandle();
else
return 0;
}
}
const char *plLayerTex::GetTextureName()
{
// if (fBitmapPB->GetInt(kBmpUseBitmap))
{
PBBitmap *pbbm = fBitmapPB->GetBitmap(kBmpBitmap);
if (pbbm)
return pbbm->bi.Name();
}
return NULL;
}
void plLayerTex::ISetPBBitmap(PBBitmap *pbbm, int index /* = 0 */)
{
fBitmapPB->SetValue(ParamID(kBmpBitmap), 0, pbbm, index);
}
PBBitmap *plLayerTex::GetPBBitmap(int index /* = 0 */)
{
return fBitmapPB->GetBitmap(ParamID(kBmpBitmap));
}
//// GetSamplerInfo ///////////////////////////////////////////////////////////
// Virtual function called by plBMSampler to get various things while sampling
// the layer's image
bool plLayerTex::GetSamplerInfo( plBMSamplerData *samplerData )
{
samplerData->fClipU = fBitmapPB->GetFloat( (ParamID)kBmpClipU );
samplerData->fClipV = fBitmapPB->GetFloat( (ParamID)kBmpClipV );
samplerData->fClipW = fBitmapPB->GetFloat( (ParamID)kBmpClipW );
samplerData->fClipH = fBitmapPB->GetFloat( (ParamID)kBmpClipH );
samplerData->fEnableCrop = fBitmapPB->GetInt( (ParamID)kBmpApply ) ? true : false;
samplerData->fCropPlacement = fBitmapPB->GetInt( (ParamID)kBmpCropPlace );
if( fBitmapPB->GetInt( (ParamID)kBmpDiscardAlpha ) )
samplerData->fAlphaSource = plBMSamplerData::kDiscard;
else if( fBitmapPB->GetInt( (ParamID)kBmpRGBOutput ) == 1 )
samplerData->fAlphaSource = plBMSamplerData::kFromRGB;
else
samplerData->fAlphaSource = plBMSamplerData::kFromTexture;
return true;
}
void plLayerTex::SetExportSize(int x, int y)
{
fBitmapPB->SetValue(kBmpExportWidth, 0, x);
fBitmapPB->SetValue(kBmpExportLastWidth, 0, x);
fBitmapPB->SetValue(kBmpExportHeight, 0, y);
fBitmapPB->SetValue(kBmpExportLastHeight, 0, y);
}

View File

@ -0,0 +1,179 @@
/*==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==*/
#ifndef __PLMAXLAYER__H
#define __PLMAXLAYER__H
#include "Max.h"
#include "plPlasmaMAXLayer.h"
class ClassDesc2;
class IParamBlock2;
class Bitmap;
ClassDesc2* GetLayerTexDesc();
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
class plLayerTex : public plPlasmaMAXLayer
{
protected:
// Parameter block
IParamBlock2 *fBitmapPB;
IParamBlock2 *fBasicPB;
UVGen *fUVGen;
IMtlParams *fMtlParams;
TexHandle *fTexHandle;
TimeValue fTexTime;
Bitmap *fBM;
static ParamDlg *fUVGenDlg;
Interval fIValid;
friend class BitmapDlgProc;
public:
// Ref nums
enum
{
kRefUVGen,
kRefBasic, // DEAD, but left in for backwards compatability
kRefBitmap,
};
// Block ID's
enum
{
kBlkBasic, // DEAD
kBlkBitmap,
};
plLayerTex();
~plLayerTex();
void DeleteThis() { delete this; }
//From MtlBase
ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
BOOL SetDlgThing(ParamDlg* dlg);
void Update(TimeValue t, Interval& valid);
void Reset();
Interval Validity(TimeValue t);
ULONG LocalRequirements(int subMtlNum);
//From Texmap
RGBA EvalColor(ShadeContext& sc);
float EvalMono(ShadeContext& sc);
Point3 EvalNormalPerturb(ShadeContext& sc);
// For displaying textures in the viewport
BOOL SupportTexDisplay() { return TRUE; }
void ActivateTexDisplay(BOOL onoff);
BITMAPINFO *GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono=FALSE, int forceW=0, int forceH=0);
DWORD GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker);
protected:
void IChanged();
void IDiscardTexHandle();
public:
void GetUVTransform(Matrix3 &uvtrans) { fUVGen->GetUVTransform(uvtrans); }
int GetTextureTiling() { return fUVGen->GetTextureTiling(); }
int GetUVWSource() { return fUVGen->GetUVWSource(); }
virtual int GetMapChannel () { return fUVGen->GetMapChannel(); } // only relevant if above returns UVWSRC_EXPLICIT
UVGen *GetTheUVGen() { return fUVGen; }
//TODO: Return anim index to reference index
int SubNumToRefNum(int subNum) { return subNum; }
virtual BOOL DiscardColor();
virtual BOOL DiscardAlpha();
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
//From Animatable
Class_ID ClassID() { return LAYER_TEX_CLASS_ID; }
SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
void GetClassName(TSTR& s);
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
// TODO: Maintain the number or references here
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
int NumParamBlocks(); // return number of ParamBlocks in this instance
IParamBlock2* GetParamBlock(int i); // return i'th ParamBlock
IParamBlock2* GetParamBlockByID(BlockID id); // return id'd ParamBlock
bool HasAlpha(); // Checks if the bitmap for this layer has an alpha channel
virtual Bitmap* GetBitmap(TimeValue t);
const char *GetTextureName();
// Accessors needed by the base class for the various bitmap related elements
virtual Bitmap *GetMaxBitmap(int index = 0) { return fBM; }
virtual PBBitmap *GetPBBitmap( int index = 0 );
virtual int GetNumBitmaps( void ) { return 1; }
// Virtual function called by plBMSampler to get various things while sampling the layer's image
virtual bool GetSamplerInfo( plBMSamplerData *samplerData );
// Backdoor for the texture find and replace util. Assumes input has the correct aspect ratio and is power of 2.
virtual void SetExportSize(int x, int y);
protected:
virtual void ISetPBBitmap( PBBitmap *pbbm, int index = 0 );
virtual void ISetMaxBitmap(Bitmap *bitmap, int index = 0) { fBM = bitmap; }
};
#endif // __PLMAXLAYER__H

View File

@ -0,0 +1,121 @@
/*==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 "hsTypes.h"
#include "plLayerTex.h"
#include "plLayerTexBasicPB.h"
class BasicDlgProc;
extern BasicDlgProc gBasicDlgProc;
static ParamBlockDesc2 gBasicParamBlk
(
plLayerTex::kBlkBasic, _T("basicLayer"), 0, GetLayerTexDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI, plLayerTex::kRefBasic,
// UI
IDD_LAYER_BASIC, IDS_LAYER_BASIC, 0, 0, &gBasicDlgProc,
// Usage
kBasicUsage, _T("usage"), TYPE_INT, 0, 0,
end,
end
);
ParamBlockDesc2 *GetBasicBlk() { return &gBasicParamBlk; }
static const char *kUsageTypes[] =
{
"None",
"Base Texture",
"Detail",
"Grime",
"Map Blend",
"Highlight/Specular",
"Alpha Mask",
"Shadow/Light Map",
"Helper Object",
"Best Guess"
};
class BasicDlgProc : public ParamMap2UserDlgProc
{
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
IParamBlock2 *pb = map->GetParamBlock();
switch (msg)
{
case WM_INITDIALOG:
{
HWND hUsage = GetDlgItem(hWnd, IDC_USAGE_TYPE);
for (int i = 0; i < kUsageNumTypes; i++)
SendMessage(hUsage, CB_ADDSTRING, 0, (LPARAM)kUsageTypes[i]);
SendMessage(hUsage, CB_SETCURSEL, pb->GetInt(kBasicUsage), 0);
}
break;
case WM_COMMAND:
switch (HIWORD(wParam))
{
case CBN_SELCHANGE:
switch (LOWORD(wParam))
{
case IDC_USAGE_TYPE:
{
int cur = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0);
if (LOWORD(wParam) == IDC_USAGE_TYPE)
pb->SetValue(kBasicUsage, t, cur);
return true;
}
break;
}
break;
}
break;
}
return false;
}
void DeleteThis() {};
};
static BasicDlgProc gBasicDlgProc;

View File

@ -0,0 +1,68 @@
/*==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==*/
#ifndef PL_LAYERTEXBASICPB_H
#define PL_LAYERTEXBASICPB_H
// Param ID's
enum
{
kBasicUsage,
};
// Usage types
enum
{
kUsageNone,
kUsageBase,
kUsageDetail,
kUsageGrime,
kUsageTransition,
kUsageHighlight,
kUsageAlphaMask,
kUsageShadowLight,
kUsageHelper,
kUsageGuess,
kUsageNumTypes
};
#endif //PL_LAYERTEXBASICPB_H

View File

@ -0,0 +1,767 @@
/*==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 "hsTypes.h"
#include "plLayerTex.h"
#include "plLayerTexBitmapPB.h"
#include "plDetailCurveCtrl.h"
#if 1
class BMTexPBAccessor;
extern BMTexPBAccessor bmtex_accessor;
class BitmapDlgProc;
extern BitmapDlgProc gBitmapDlgProc;
static ParamBlockDesc2 gBitmapParamBlk
(
plLayerTex::kBlkBitmap, _T("bitmap"), 0, GetLayerTexDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI, plLayerTex::kRefBitmap,
IDD_LAYER_TEX, IDS_LAYER_TEX, 0, 0, &gBitmapDlgProc,
// Bitmap
kBmpUseBitmap, _T("useBitmap"), TYPE_BOOL, 0, 0,
p_default, TRUE,
p_ui, TYPE_SINGLECHEKBOX, IDC_USE_BITMAP,
end,
kBmpBitmap, _T("bitmap"), TYPE_BITMAP, P_SHORT_LABELS, 0,
p_accessor, &bmtex_accessor,
end,
// Crop/Place
kBmpApply, _T("apply"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_BM_CLIP,
end,
kBmpCropPlace, _T("cropPlace"), TYPE_INT, 0, 0,
p_default, 0,
p_range, 0, 1,
p_ui, TYPE_RADIO, 2, IDC_BM_CROP,IDC_BM_PLACE,
end,
kBmpClipU, _T("clipU"), TYPE_FLOAT, P_ANIMATABLE, IDS_BITMAP_CLIPU,
p_default, 0.0,
p_range, 0.0, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_CLIP_X, IDC_CLIP_XSPIN, 0.001f,
p_accessor, &bmtex_accessor,
end,
kBmpClipV, _T("clipV"), TYPE_FLOAT, P_ANIMATABLE, IDS_BITMAP_CLIPV,
p_default, 0.0,
p_range, 0.0, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_CLIP_Y, IDC_CLIP_YSPIN, 0.001f,
p_accessor, &bmtex_accessor,
end,
kBmpClipW, _T("clipW"), TYPE_FLOAT, P_ANIMATABLE, IDS_BITMAP_CLIPW,
p_default, 1.0,
p_range, 0.0, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_CLIP_W, IDC_CLIP_WSPIN, 0.001f,
p_accessor, &bmtex_accessor,
end,
kBmpClipH, _T("clipH"), TYPE_FLOAT, P_ANIMATABLE, IDS_BITMAP_CLIPH,
p_default, 1.0,
p_range, 0.0, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_CLIP_H, IDC_CLIP_HSPIN, 0.001f,
p_accessor, &bmtex_accessor,
end,
// Texture Color/Alpha
kBmpDiscardColor, _T("discardColor"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_BLEND_NO_COLOR,
end,
kBmpInvertColor, _T("invertColor"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_BLEND_INV_COLOR,
end,
kBmpDiscardAlpha, _T("discardAlpha"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_DISCARD_ALPHA,
end,
kBmpInvertAlpha, _T("invertAlpha"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_BLEND_INV_ALPHA,
end,
// Texture Quality
kBmpNonCompressed, _T("nonCompressed"),TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_FORCE_NONCOMPRESSED,
end,
kBmpScaling, _T("scaling"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_SCALE_ALL, IDC_SCALE_HALF, IDC_SCALE_NONE,
end,
// Max Only
kBmpMonoOutput, _T("monoOutput"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 2, IDC_HSMAX_LAYER_RGBOUT, IDC_HSMAX_LAYER_ALPHAOUT,
end,
kBmpRGBOutput, _T("rgbOutput"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 2, IDC_HSMAX_LAYER_RGBOUT2, IDC_HSMAX_LAYER_ALPHAOUT2,
end,
// Mipmap
kBmpNoFilter, _T("noFilter"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_NO_FILTERING,
end,
kBmpMipBlur, _T("mipBlur"), TYPE_FLOAT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_MIPBLUR_EDIT, IDC_MIPBLUR_SPIN, 0.4,
p_range, 0.01f, 100.0f,
p_default, 1.0,
end,
kBmpMipBias, _T("mipBias"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_USE_MIPBIAS,
p_enable_ctrls, 1, kBmpMipBiasAmt,
end,
kBmpMipBiasAmt, _T("mipBiasAmt"), TYPE_FLOAT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_MIPBIAS_EDIT, IDC_MIPBIAS_SPIN, 0.7,
p_range, -100.0, 100.0,
p_default, 1.0,
end,
// Detail
kBmpUseDetail, _T("useDetail"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_USE_DETAIL,
p_default, FALSE,
p_enable_ctrls, 4, kBmpDetailStartSize, kBmpDetailStopSize, kBmpDetailStartOpac, kBmpDetailStopOpac,
p_accessor, &bmtex_accessor,
end,
kBmpDetailStartSize,_T("dropOffStart"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_DETAIL_START_SIZE_EDIT, IDC_DETAIL_START_SIZE_SPIN, 0.4,
p_range, 0, 100,
p_default, 0,
p_accessor, &bmtex_accessor,
end,
kBmpDetailStopSize, _T("dropOffStop"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_DETAIL_STOP_SIZE_EDIT, IDC_DETAIL_STOP_SIZE_SPIN, 0.4,
p_range, 0, 100,
p_default, 100,
p_accessor, &bmtex_accessor,
end,
kBmpDetailStartOpac, _T("detailMax"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_DETAIL_START_OPAC_EDIT, IDC_DETAIL_START_OPAC_SPIN, 0.4,
p_range, 0, 100,
p_default, 100,
p_accessor, &bmtex_accessor,
end,
kBmpDetailStopOpac, _T("detailMin"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_DETAIL_STOP_OPAC_EDIT, IDC_DETAIL_STOP_OPAC_SPIN, 0.4,
p_range, 0, 100,
p_default, 0,
p_accessor, &bmtex_accessor,
end,
kBmpExportWidth, _T("exportWidth"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_EXPORTWIDTH, IDC_EXPORTWIDTH_SPINNER, SPIN_AUTOSCALE,
p_range, 4, 2048,
p_default, 512,
end,
kBmpExportHeight, _T("exportHeight"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_EXPORTHEIGHT, IDC_EXPORTHEIGHT_SPINNER, SPIN_AUTOSCALE,
p_range, 4, 2048,
p_default, 512,
end,
kBmpExportLastWidth, _T("lastExportWidth"), TYPE_INT, 0, 0,
end,
kBmpExportLastHeight, _T("lastExportHeight"), TYPE_INT, 0, 0,
end,
// Keep a sysmem copy at runtime (for image examination/manipulation).
kBmpNoDiscard, _T("noDiscard"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_NO_DISCARD,
p_default, FALSE,
end,
end
);
ParamBlockDesc2 *GetBitmapBlk() { return &gBitmapParamBlk; }
class BMCropper;
class BMTexPBAccessor : public PBAccessor
{
public:
void Set(PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
plLayerTex* layer = (plLayerTex*)owner;
if(layer == NULL) return;
IParamBlock2 *pb = layer->GetParamBlockByID(plLayerTex::kBlkBitmap);
switch (id)
{
case kBmpBitmap:
if (pb->GetMap())
pb->GetMap()->Invalidate(kBmpBitmap);
// Update the bitmap saved by the layer
//layer->SetBitmap(&val.bm->bi, tabIndex);
break;
/*
case kBmpFilename:
bmt->SetMapName(val.s);
break;
case kBmpFiltering:
bmt->filterType = val.i;
if (bmt->thebm)
bmt->thebm->SetFilter(bmFilterType(val.i));
break;
*/
case kBmpClipU:
{
float u = val.f;
float w = pb->GetFloat(kBmpClipW, t);
if (u + w > 1.0f)
{
pb->SetValue(kBmpClipW, t, 1.0f-u);
if (pb->GetMap())
pb->GetMap()->Invalidate(kBmpClipW);
}
break;
}
case kBmpClipW:
{
float w = val.f;
float u = pb->GetFloat(kBmpClipU, t);
if (u + w > 1.0f)
{
pb->SetValue(kBmpClipU, t, 1.0f-w);
if (pb->GetMap())
pb->GetMap()->Invalidate(kBmpClipU);
}
break;
}
case kBmpClipV:
{
float v = val.f;
float h = pb->GetFloat(kBmpClipH, t);
if (v + h > 1.0f)
{
pb->SetValue(kBmpClipH, t, 1.0f-v);
if (pb->GetMap())
pb->GetMap()->Invalidate(kBmpClipH);
}
break;
}
case kBmpClipH:
{
float h = val.f;
float v = pb->GetFloat(kBmpClipV, t);
if (v + h > 1.0f)
{
pb->SetValue(kBmpClipV, t, 1.0f-h);
if (pb->GetMap())
pb->GetMap()->Invalidate(kBmpClipV);
}
break;
}
case kBmpDetailStartSize:
case kBmpDetailStopSize:
case kBmpDetailStartOpac:
case kBmpDetailStopOpac:
if( pb != NULL )
{
if( IIsProcSettingDetailValues( pb ) )
break; // Ignore, since we're the ones setting 'em
HWND dlg = pb->GetMap()->GetHWnd();
plDetailCurveCtrl *ctrl = GET_DETAIL_CURVE_CTRL( dlg, IDC_DETAIL_CURVE_CTRL );
if( ctrl != NULL )
{
if( id == kBmpDetailStartSize || id == kBmpDetailStartOpac )
ctrl->SetStartPoint( (float)pb->GetInt( kBmpDetailStartSize, t ) / 100.f,
(float)pb->GetInt( kBmpDetailStartOpac, t ) / 100.f );
else
ctrl->SetEndPoint( (float)pb->GetInt( kBmpDetailStopSize, t ) / 100.f,
(float)pb->GetInt( kBmpDetailStopOpac, t ) / 100.f );
}
// Make sure start is less than end
if( id == kBmpDetailStartSize )
{
int end = pb->GetInt( kBmpDetailStopSize, t );
if( val.i > end )
pb->SetValue( kBmpDetailStopSize, t, val.i );
}
else if( id == kBmpDetailStopSize )
{
int start = pb->GetInt( kBmpDetailStartSize, t );
if( val.i < start )
pb->SetValue( kBmpDetailStartSize, t, val.i );
}
}
break;
case kBmpUseDetail:
if( pb != NULL )
{
HWND dlg = pb->GetMap()->GetHWnd();
EnableWindow( GetDlgItem( dlg, IDC_DETAIL_CURVE_CTRL ), (BOOL)val.i );
}
break;
}
}
void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid)
{
}
// Gotta love hacks....
bool IIsProcSettingDetailValues( IParamBlock2 *pb );
};
static BMTexPBAccessor bmtex_accessor;
//=========================================================================================
// BMCropper
//=========================================================================================
class BMCropper : public CropCallback
{
IParamBlock2 *fPBlock;
public:
BMCropper(IParamBlock2* pblock) : fPBlock(pblock) {}
float GetInitU() { return fPBlock->GetFloat(kBmpClipU); }
float GetInitV() { return fPBlock->GetFloat(kBmpClipV); }
float GetInitW() { return fPBlock->GetFloat(kBmpClipW); }
float GetInitH() { return fPBlock->GetFloat(kBmpClipH); }
BOOL GetInitMode() { return fPBlock->GetInt(kBmpCropPlace); }
void SetValues(float u, float v, float w, float h, BOOL md);
void OnClose();
};
void BMCropper::SetValues(float u, float v, float w, float h, BOOL md)
{
TimeValue t = GetCOREInterface()->GetTime();
if (u != fPBlock->GetFloat(kBmpClipU, t))
{
fPBlock->SetValue(kBmpClipU, t, u);
fPBlock->GetMap()->Invalidate(kBmpClipU);
}
if (v != fPBlock->GetFloat(kBmpClipV, t))
{
fPBlock->SetValue(kBmpClipV, t, v);
fPBlock->GetMap()->Invalidate(kBmpClipV);
}
if (w != fPBlock->GetFloat(kBmpClipW, t))
{
fPBlock->SetValue(kBmpClipW, t, w);
fPBlock->GetMap()->Invalidate(kBmpClipW);
}
if (h != fPBlock->GetFloat(kBmpClipH, t))
{
fPBlock->SetValue(kBmpClipH, t, h);
fPBlock->GetMap()->Invalidate(kBmpClipH);
}
if (md != fPBlock->GetInt(kBmpCropPlace))
{
fPBlock->SetValue(kBmpCropPlace, t, md);
fPBlock->GetMap()->Invalidate(kBmpCropPlace);
}
}
void BMCropper::OnClose()
{
delete this;
}
class BitmapDlgProc : public ParamMap2UserDlgProc
{
friend class BMTexPBAccessor;
PBBitmap *fLastBMap;
bool fSettingDetailValues;
/// Called to update the controls of the dialog
/// Note: we're bad that we use a static here, but
virtual void Update( TimeValue t, Interval &valid, IParamMap2 *map )
{
ICustButton *bmSelectBtn;
IParamBlock2 *pblock;
int width, height;
ParamMap2UserDlgProc::Update( t, valid, map );
if( fSettingDetailValues )
{
// We're getting an update just because we changed detail values, so we
// know we don't have to do anything ourselves
return;
}
pblock = map->GetParamBlock();
// Update texture map button
bmSelectBtn = GetICustButton( GetDlgItem( map->GetHWnd(), IDC_LAYER_NAME ) );
PBBitmap *pbbm = pblock->GetBitmap( kBmpBitmap, t );
if( pbbm )
{
if( pbbm != fLastBMap )
{
bmSelectBtn->SetText( (TCHAR *)pbbm->bi.Filename() );
// Init values for clamping spinners to powers of 2
width = IFloorPow2( pbbm->bi.Width() );
map->SetRange( kBmpExportWidth, 4.f, (float)width );
height = IFloorPow2( pbbm->bi.Height() );
map->SetRange( kBmpExportHeight, 4.f, (float)height );
IClampTexSizeSpinner( t, map, true );
ISetDetailCurveNumLevels( map, t );
}
}
else if( pbbm != fLastBMap )
bmSelectBtn->SetText( _T( "None" ) );
fLastBMap = pbbm;
ReleaseICustButton( bmSelectBtn );
// Update detail curve control
HWND dlg = map->GetHWnd();
plDetailCurveCtrl *ctrl = GET_DETAIL_CURVE_CTRL( dlg, IDC_DETAIL_CURVE_CTRL );
if( ctrl == NULL )
{
// The control hasn't been created, so create it already!
HWND basis;
RECT r;
// Create the detail map control
basis = GetDlgItem( dlg, IDC_DETAIL_SAMPLE );
GetClientRect( basis, &r );
MapWindowPoints( basis, dlg, (POINT *)&r, 2 );
ctrl = TRACKED_NEW plDetailCurveCtrl( dlg, IDC_DETAIL_CURVE_CTRL, &r );
}
EnableWindow( GetDlgItem( dlg, IDC_DETAIL_CURVE_CTRL ), (BOOL)pblock->GetInt( kBmpUseDetail, t ) );
if( ctrl != NULL )
{
ctrl->SetStartPoint( (float)pblock->GetInt( kBmpDetailStartSize, t ) / 100.f,
(float)pblock->GetInt( kBmpDetailStartOpac, t ) / 100.f );
ctrl->SetEndPoint( (float)pblock->GetInt( kBmpDetailStopSize, t ) / 100.f,
(float)pblock->GetInt( kBmpDetailStopOpac, t ) / 100.f );
}
}
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static ICustButton* bmSelectBtn;
switch (msg)
{
case WM_INITDIALOG:
fLastBMap = NULL;
fSettingDetailValues = false;
break;
/// Note: the following *could* be done in the accessor, except that you end up in an
/// infinite loop updating the values. Not good.
case CC_SPINNER_CHANGE:
if( LOWORD( wParam ) == IDC_EXPORTWIDTH_SPINNER )
IClampTexSizeSpinner( t, map, true );
else if( LOWORD( wParam ) == IDC_EXPORTHEIGHT_SPINNER )
IClampTexSizeSpinner( t, map, false );
break;
// Message from the detail curve that a point got dragged
case PL_DC_POINT_DRAGGED:
{
plDetailCurveCtrl *ctrl = (plDetailCurveCtrl *)lParam;
IParamBlock2 *pblock = map->GetParamBlock();
float x, y;
fSettingDetailValues = true;
if( wParam == PL_DC_START_POINT )
{
ctrl->GetStartPoint( x, y );
pblock->SetValue( kBmpDetailStartSize, t, (int)( x * 100.f ) );
pblock->SetValue( kBmpDetailStartOpac, t, (int)( y * 100.f ) );
}
else
{
ctrl->GetEndPoint( x, y );
pblock->SetValue( kBmpDetailStopSize, t, (int)( x * 100.f ) );
pblock->SetValue( kBmpDetailStopOpac, t, (int)( y * 100.f ) );
}
map->UpdateUI( t );
fSettingDetailValues = false;
}
return 0;
case WM_COMMAND:
if( HIWORD( wParam ) == EN_CHANGE && LOWORD( wParam ) == IDC_EXPORTWIDTH )
IClampTexSizeSpinner( t, map, true );
else if( HIWORD( wParam ) == EN_CHANGE && LOWORD( wParam ) == IDC_EXPORTHEIGHT )
IClampTexSizeSpinner( t, map, false );
else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_BM_CROP_IMAGE)
{
IParamBlock2 *pblock = map->GetParamBlock();
PBBitmap *pbbm = pblock->GetBitmap(kBmpBitmap, t);
if (pbbm)
{
if (!pbbm->bm)
pbbm->bm = TheManager->Load(&pbbm->bi);
BMCropper *cropper = TRACKED_NEW BMCropper(pblock);
pbbm->bm->Display("Specify Cropping/Placement", BMM_CN, FALSE, TRUE, cropper);
}
// bm->DeleteThis();
return TRUE;
}
else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_LAYER_RELOAD)
{
// TEMP
IParamBlock2 *pblock = map->GetParamBlock();
PBBitmap *pbbm = pblock->GetBitmap(kBmpBitmap, t);
if (pbbm)
{
plLayerTex *layer = (plLayerTex*)map->GetParamBlock()->GetOwner();
layer->RefreshBitmaps();
layer->fMtlParams->MtlChanged();
layer->IChanged();
}
return TRUE;
}
else if (LOWORD(wParam) == IDC_LAYER_NAME)
{
plPlasmaMAXLayer *layer = (plPlasmaMAXLayer *)map->GetParamBlock()->GetOwner();
if (layer == nil)
return FALSE;
BOOL selectedNewBitmap = layer->HandleBitmapSelection();
if(selectedNewBitmap)
{
IParamBlock2 *pblock = map->GetParamBlock();
//plLayerTex *layer = (plLayerTex*)map->GetParamBlock()->GetOwner();
//layer->SetBitmap(&bi);
//layer->IChanged();
//BitmapInfo *bi = &layer->GetPBBitmap()->bi;
bmSelectBtn = GetICustButton(GetDlgItem(hWnd,IDC_LAYER_NAME));
PBBitmap *pbbm = layer->GetPBBitmap();
bmSelectBtn->SetText(pbbm != nil ? (TCHAR*)pbbm->bi.Filename() : "");
ReleaseICustButton(bmSelectBtn);
if (pbbm != nil)
{
// Init values for clamping spinners to powers of 2
int width = IFloorPow2( pbbm->bi.Width() );
map->SetRange( kBmpExportWidth, 4.f, (float)width );
int height = IFloorPow2( pbbm->bi.Height() );
map->SetRange( kBmpExportHeight, 4.f, (float)height );
if( width > 512 )
{
height = (int)( 512.f * (float)( (float)height / (float)width ) );
width = 512;
}
else if( height > 512 )
{
width = (int)( 512.f * (float)( (float)width / (float)height ) );
height = 512;
}
pblock->SetValue( kBmpExportWidth, t, width );
pblock->SetValue( kBmpExportLastWidth, t, width );
pblock->SetValue( kBmpExportHeight, t, height );
pblock->SetValue( kBmpExportLastHeight, t, height );
IClampTexSizeSpinner( t, map, true );
}
return TRUE;
}
else
{
return FALSE;
}
}
break;
}
return FALSE;
}
void DeleteThis() {};
void ISetDetailCurveNumLevels( IParamMap2 *map, TimeValue t )
{
/// Set the level count on the detail control
plDetailCurveCtrl *ctrl = GET_DETAIL_CURVE_CTRL( map->GetHWnd(), IDC_DETAIL_CURVE_CTRL );
if( ctrl != NULL )
{
IParamBlock2 *pblock = map->GetParamBlock();
int w = pblock->GetInt( kBmpExportWidth, t );
int h = pblock->GetInt( kBmpExportHeight, t );
int numLevels = 0;
while( w > 1 && h > 1 )
{
w >>= 1;
h >>= 1;
numLevels++;
}
ctrl->SetNumLevels( numLevels );
}
}
/// Clamp texture sizes to a power of 2
void IClampTexSizeSpinner( TimeValue t, IParamMap2 *map, bool clampWidth )
{
IParamBlock2 *pblock = map->GetParamBlock();
ParamID clampNew, clampOld;
ParamID otherNew, otherOld;
if( clampWidth )
{
clampNew = kBmpExportWidth; clampOld = kBmpExportLastWidth;
otherNew = kBmpExportHeight; otherOld = kBmpExportLastHeight;
}
else
{
clampNew = kBmpExportHeight; clampOld = kBmpExportLastHeight;
otherNew = kBmpExportWidth; otherOld = kBmpExportLastWidth;
}
int lastVal = pblock->GetInt( clampOld, t );
int tempVal, newVal = pblock->GetInt( clampNew, t );
if( newVal < lastVal )
{
lastVal = newVal;
for( tempVal = 1; tempVal <= newVal; tempVal <<= 1 );
newVal = tempVal >> 1;
}
else
{
lastVal = newVal;
for( tempVal = 1; tempVal < newVal; tempVal <<= 1 );
newVal = tempVal;
}
pblock->SetValue( clampNew, t, newVal );
pblock->SetValue( clampOld, t, newVal );
// And clamp aspect ratio
PBBitmap *pbbm = pblock->GetBitmap( kBmpBitmap, t );
if( pbbm != NULL )
{
int realWidth = pbbm->bi.Width();
int realHeight = pbbm->bi.Height();
float aspect;
if( clampWidth )
aspect = (float)realHeight / (float)realWidth;
else
aspect = (float)realWidth / (float)realHeight;
int value = newVal;
value *= aspect;
if( value < 4 )
{
// Can't be below 4!
value = 4;
pblock->SetValue( otherNew, t, value );
pblock->SetValue( otherOld, t, value );
value = value / aspect;
pblock->SetValue( clampNew, t, value );
pblock->SetValue( clampOld, t, value );
}
else
{
pblock->SetValue( otherNew, t, value );
pblock->SetValue( otherOld, t, value );
}
}
ISetDetailCurveNumLevels( map, t );
}
int IFloorPow2( int value )
{
int v;
for( v = 1; v <= value; v <<= 1 );
return v >> 1;
}
};
static BitmapDlgProc gBitmapDlgProc;
// Gotta love hacks....
bool BMTexPBAccessor::IIsProcSettingDetailValues( IParamBlock2 *pb )
{
BitmapDlgProc *proc = (BitmapDlgProc *)pb->GetMap()->GetUserDlgProc();
if( proc != NULL )
return proc->fSettingDetailValues;
return false;
}
#endif

View File

@ -0,0 +1,103 @@
/*==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==*/
#ifndef PL_LAYERTEXBITMAPPB_H
#define PL_LAYERTEXBITMAPPB_H
// Param ID's
enum
{
kBmpUseBitmap,
kBmpBitmap,
// Cropping/Placement
kBmpApply,
kBmpCropPlace,
kBmpClipU,
kBmpClipV,
kBmpClipW,
kBmpClipH,
// Misc
kBmpDiscardColor,
kBmpInvertColor,
kBmpDiscardAlpha,
kBmpInvertAlpha,
// Texture quality
kBmpNonCompressed,
kBmpScaling,
// Mipmap
kBmpNoFilter,
kBmpMipBlur,
kBmpMipBias,
kBmpMipBiasAmt,
// Max only
kBmpMonoOutput,
kBmpRGBOutput,
// Detail
kBmpUseDetail,
kBmpDetailStartSize,
kBmpDetailStopSize,
kBmpDetailStartOpac,
kBmpDetailStopOpac,
// New export size controls
kBmpExportWidth,
kBmpExportHeight,
kBmpExportLastWidth, // Annoying fields, these two, but they're necessary
kBmpExportLastHeight, // for clamping the spinners to powers of 2
// Keep a sysmem copy of the texture
kBmpNoDiscard
};
enum
{
kScalingAny,
kScalingHalf,
kScalingNone
};
#endif //PL_LAYERTEXBITMAPPB_H

View File

@ -0,0 +1,415 @@
/*==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 "plMAXCameraLayer.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "stdmat.h"
#include "plBMSampler.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
class plMAXCameraLayerClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading = FALSE) { return TRACKED_NEW plMAXCameraLayer(); }
const TCHAR* ClassName() { return GetString(IDS_MAX_CAMERA_LAYER); }
SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
Class_ID ClassID() { return MAX_CAMERA_LAYER_CLASS_ID; }
const TCHAR* Category() { return TEXMAP_CAT_COLMOD; }
const TCHAR* InternalName() { return _T("PlasmaMAXCameraLayer"); }
HINSTANCE HInstance() { return hInstance; }
};
static plMAXCameraLayerClassDesc plMAXCameraLayerDesc;
ClassDesc2* GetMAXCameraLayerDesc() { return &plMAXCameraLayerDesc; }
class MAXCameraLayerDlgProc : public ParamMap2UserDlgProc
{
public:
MAXCameraLayerDlgProc() {}
~MAXCameraLayerDlgProc() {}
void UpdateDisplay(IParamMap2 *pmap)
{
HWND hWnd = pmap->GetHWnd();
IParamBlock2 *pb = pmap->GetParamBlock();
HWND cbox;
cbox = GetDlgItem(hWnd, IDC_CAM_LAYER_UV_SRC);
SendMessage(cbox, CB_SETCURSEL, pb->GetInt(plMAXCameraLayer::kUVSource), 0);
hsBool reflect = (pb->GetInt(ParamID(plMAXCameraLayer::kExplicitCam)) == 0);
EnableWindow(GetDlgItem(hWnd, IDC_CAM_LAYER_UV_SRC), !reflect);
}
virtual void Update(TimeValue t, Interval& valid, IParamMap2* pmap) { UpdateDisplay(pmap); }
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
int id = LOWORD(wParam);
int code = HIWORD(wParam);
IParamBlock2 *pb = map->GetParamBlock();
HWND cbox = NULL;
switch (msg)
{
case WM_INITDIALOG:
int i;
for (i = 0; i < plMAXCameraLayer::kMaxUVSrc; i++)
{
cbox = GetDlgItem(hWnd, IDC_CAM_LAYER_UV_SRC);
SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)plMAXCameraLayer::kUVStrings[i]);
}
UpdateDisplay(map);
return TRUE;
case WM_COMMAND:
if (id == IDC_CAM_LAYER_UV_SRC)
{
pb->SetValue(plMAXCameraLayer::kUVSource, t, SendMessage(GetDlgItem(hWnd, id), CB_GETCURSEL, 0, 0));
return TRUE;
}
else if (id == IDC_CAM_LAYER_EXPLICIT_CAM)
{
UpdateDisplay(map);
return TRUE;
}
break;
}
return FALSE;
}
void DeleteThis() {}
};
static MAXCameraLayerDlgProc gMAXCameraLayerDlgProc;
///////////////////////////////////////////////////////////////////////////////
//// ParamBlock Definition ////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static ParamBlockDesc2 gMAXCameraLayerParamBlk
(
plMAXCameraLayer::kBlkMain, _T("CamLayer"), 0, GetMAXCameraLayerDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI, plMAXCameraLayer::kRefMain,
IDD_MAX_CAMERA_LAYER, IDS_MAX_CAMERA_LAYER_PROPS, 0, 0, &gMAXCameraLayerDlgProc,
plMAXCameraLayer::kCamera, _T("camera"), TYPE_INODE, P_CAN_CONVERT, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_CAM_LAYER_CAMERA,
p_classID, Class_ID(LOOKAT_CAM_CLASS_ID, 0),
p_prompt, IDS_CAM_LAYER_CAMERA,
end,
plMAXCameraLayer::kUVSource, _T("UVSource"), TYPE_INT, 0, 0,
p_default, 0,
end,
plMAXCameraLayer::kExplicitCam, _T("explicitCam"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_CAM_LAYER_EXPLICIT_CAM,
p_default, false,
p_enable_ctrls, 1, plMAXCameraLayer::kCamera,
end,
plMAXCameraLayer::kRootNode, _T("rootNode"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_CAM_LAYER_ROOT_NODE,
p_prompt, IDS_CAM_LAYER_ROOT_NODE,
end,
plMAXCameraLayer::kDisableColor, _T("disableColor"), TYPE_RGBA, 0, 0,
p_ui, TYPE_COLORSWATCH, IDC_CAM_LAYER_DISABLE_COLOR,
p_default, Color(0,0,0),
end,
plMAXCameraLayer::kForce, _T("force"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_CAM_LAYER_FORCE,
p_default, false,
end,
end
);
/////////////////////////////////////////////////////////////////////////////
const char *plMAXCameraLayer::kUVStrings[] = { "1", "2", "3", "4", "5", "6", "7", "8" };
const UInt8 plMAXCameraLayer::kMaxUVSrc = 8;
plMAXCameraLayer::plMAXCameraLayer() :
fParmsPB(NULL),
fIValid(NEVER)
{
plMAXCameraLayerDesc.MakeAutoParamBlocks(this);
}
plMAXCameraLayer::~plMAXCameraLayer()
{
}
//From MtlBase
void plMAXCameraLayer::Reset()
{
GetMAXCameraLayerDesc()->Reset(this, TRUE); // reset all pb2's
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
fIValid.SetEmpty();
}
void plMAXCameraLayer::Update(TimeValue t, Interval& valid)
{
if (!fIValid.InInterval(t))
{
fIValid.SetInfinite();
}
valid &= fIValid;
}
Interval plMAXCameraLayer::Validity(TimeValue t)
{
Interval v = FOREVER;
return v;
}
ParamDlg* plMAXCameraLayer::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
IAutoMParamDlg* masterDlg = plMAXCameraLayerDesc.CreateParamDlgs(hwMtlEdit, imp, this);
return masterDlg;
}
BOOL plMAXCameraLayer::SetDlgThing(ParamDlg* dlg)
{
return FALSE;
}
int plMAXCameraLayer::NumRefs()
{
return 1;
}
//From ReferenceMaker
RefTargetHandle plMAXCameraLayer::GetReference(int i)
{
switch (i)
{
case kRefMain: return fParmsPB;
default: return NULL;
}
}
void plMAXCameraLayer::SetReference(int i, RefTargetHandle rtarg)
{
Interval garbage;
switch (i)
{
case kRefMain:
fParmsPB = (IParamBlock2 *)rtarg;
break;
}
}
int plMAXCameraLayer::NumParamBlocks()
{
return 1;
}
IParamBlock2* plMAXCameraLayer::GetParamBlock(int i)
{
switch (i)
{
case 0: return fParmsPB;
default: return NULL;
}
}
IParamBlock2* plMAXCameraLayer::GetParamBlockByID(BlockID id)
{
if (fParmsPB->ID() == id)
return fParmsPB;
else
return NULL;
}
//From ReferenceTarget
RefTargetHandle plMAXCameraLayer::Clone(RemapDir &remap)
{
plMAXCameraLayer *mnew = TRACKED_NEW plMAXCameraLayer();
*((MtlBase*)mnew) = *((MtlBase*)this); // copy superclass stuff
mnew->ReplaceReference(kRefMain, remap.CloneRef(fParmsPB));
BaseClone(this, mnew, remap);
return (RefTargetHandle)mnew;
}
int plMAXCameraLayer::NumSubs()
{
return 1;
}
Animatable* plMAXCameraLayer::SubAnim(int i)
{
switch (i)
{
case kRefMain: return fParmsPB;
default: return NULL;
}
}
TSTR plMAXCameraLayer::SubAnimName(int i)
{
switch (i)
{
case kRefMain: return "Main";
default: return "";
}
}
RefResult plMAXCameraLayer::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message)
{
switch (message)
{
case REFMSG_CHANGE:
{
fIValid.SetEmpty();
if (hTarget == fParmsPB)
{
// see if this message came from a changing parameter in the pblock,
// if so, limit rollout update to the changing item
ParamID changingParam = fParmsPB->LastNotifyParamID();
fParmsPB->GetDesc()->InvalidateUI(changingParam);
if (changingParam != -1)
IChanged();
}
}
break;
}
return REF_SUCCEED;
}
void plMAXCameraLayer::IChanged()
{
// Cut and paste insanity from DynamicTextLayer.
// Texture wasn't getting updated in the viewports, and this fixes it.
// Don't know if it's the right way though.
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
// And this is so the SceneWatcher gets notified that the material on some of it's
// referenced objects changed.
NotifyDependents(FOREVER, PART_ALL, REFMSG_USER_MAT);
}
#define TEX_HDR_CHUNK 0x5000
IOResult plMAXCameraLayer::Save(ISave *isave)
{
IOResult res;
isave->BeginChunk(TEX_HDR_CHUNK);
res = MtlBase::Save(isave);
if (res != IO_OK)
return res;
isave->EndChunk();
return IO_OK;
}
IOResult plMAXCameraLayer::Load(ILoad *iload)
{
IOResult res;
while (IO_OK == (res = iload->OpenChunk()))
{
if (iload->CurChunkID() == TEX_HDR_CHUNK)
{
res = MtlBase::Load(iload);
}
iload->CloseChunk();
if (res != IO_OK)
return res;
}
return IO_OK;
}
AColor plMAXCameraLayer::EvalColor(ShadeContext& sc)
{
return AColor(0.0f, 0.0f, 0.0f, 1.0f);
}
float plMAXCameraLayer::EvalMono(ShadeContext& sc)
{
return Intens(EvalColor(sc));
}
Point3 plMAXCameraLayer::EvalNormalPerturb(ShadeContext& sc)
{
// Return the perturbation to apply to a normal for bump mapping
return Point3(0, 0, 0);
}
ULONG plMAXCameraLayer::LocalRequirements(int subMtlNum)
{
return MTLREQ_VIEW_DEP | MTLREQ_TRANSP;
}
void plMAXCameraLayer::ActivateTexDisplay(BOOL onoff)
{
}
BITMAPINFO *plMAXCameraLayer::GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono, BOOL forceW, BOOL forceH)
{
return nil;
}
DWORD plMAXCameraLayer::GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker)
{
return 0;
}
const char *plMAXCameraLayer::GetTextureName( int which )
{
return NULL;
}

View File

@ -0,0 +1,161 @@
/*==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==*/
#ifndef plMAXCameraLayer_inc
#define plMAXCameraLayer_inc
#include "Max.h"
#include "../resource.h"
#include "plPlasmaMAXLayer.h"
class ClassDesc2;
class IParamBlock2;
ClassDesc2* GetMAXCameraLayerDesc();
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
class plMAXCameraLayer : public plPlasmaMAXLayer
{
protected:
// Parameter block
IParamBlock2* fParmsPB;
Interval fIValid;
public:
// Ref nums
enum
{
kRefMain
};
// Block ID's
enum
{
kBlkMain
};
plMAXCameraLayer();
~plMAXCameraLayer();
void DeleteThis() { delete this; }
//From MtlBase
ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
BOOL SetDlgThing(ParamDlg* dlg);
void Update(TimeValue t, Interval& valid);
void Reset();
Interval Validity(TimeValue t);
ULONG LocalRequirements(int subMtlNum);
//From Texmap
RGBA EvalColor(ShadeContext& sc);
float EvalMono(ShadeContext& sc);
Point3 EvalNormalPerturb(ShadeContext& sc);
// For displaying textures in the viewport
BOOL SupportTexDisplay() { return FALSE; }
void ActivateTexDisplay(BOOL onoff);
BITMAPINFO *GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono=FALSE, int forceW=0, int forceH=0);
DWORD GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker);
protected:
void ICacheCosines();
void IChanged();
void IDiscardTexHandle();
public:
int SubNumToRefNum(int subNum) { return subNum; }
virtual BOOL DiscardColor() { return true; }
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
//From Animatable
Class_ID ClassID() { return MAX_CAMERA_LAYER_CLASS_ID; }
SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_MAX_CAMERA_LAYER); }
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
int NumParamBlocks(); // return number of ParamBlocks in this instance
IParamBlock2* GetParamBlock(int i); // return i'th ParamBlock
IParamBlock2* GetParamBlockByID(BlockID id); // return id'd ParamBlock
const char *GetTextureName( int which );
// ParamBlock accessors
enum
{
kCamera,
kUVSource,
kExplicitCam,
kRootNode,
kDisableColor,
kForce,
};
static const char *kUVStrings[];
static const UInt8 kMaxUVSrc;
// Pure virtual accessors for the various bitmap related elements
virtual Bitmap *GetMaxBitmap(int index = 0) { hsAssert(false, "Function call not valid on this type of layer."); return nil; }
virtual PBBitmap *GetPBBitmap(int index = 0) { hsAssert(false, "Function call not valid on this type of layer."); return nil; }
virtual int GetNumBitmaps(void) { return 0; }
protected:
virtual void ISetMaxBitmap(Bitmap *bitmap, int index = 0) { hsAssert(false, "Function call not valid on this type of layer."); }
virtual void ISetPBBitmap(PBBitmap *pbbm, int index = 0) { hsAssert(false, "Function call not valid on this type of layer."); }
};
#endif // plMAXCameraLayer_inc

View File

@ -0,0 +1,458 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plPlasmaMAXLayer - MAX Layer type that is the basis for all Plasma layer //
// types //
// Note: All export-side functions are contained in //
// MaxConvert/plPlasmaMaxLayerExport.cpp, for linking purposes. //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 1.13.2002 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plPlasmaMAXLayer.h"
#include "stdmat.h"
#include "istdplug.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "resource.h"
#include "../../AssetMan/PublicInterface/MaxAssInterface.h"
#include "hsUtils.h"
#include "../pnKeyedObject/hsKeyedObject.h"
#include "../pnMessage/plRefMsg.h"
#include "../plSurface/plLayerInterface.h"
#include "hsResMgr.h"
//// Derived Types List ///////////////////////////////////////////////////////
// If you create a new Plasma layer type, add a define for the class ID in
// the header and add it to the list here.
const Class_ID plPlasmaMAXLayer::fDerivedTypes[] =
{
LAYER_TEX_CLASS_ID,
STATIC_ENV_LAYER_CLASS_ID,
DYNAMIC_ENV_LAYER_CLASS_ID,
DYN_TEXT_LAYER_CLASS_ID,
ANGLE_ATTEN_LAYER_CLASS_ID,
MAX_CAMERA_LAYER_CLASS_ID
};
//// Constructor/Destructor ///////////////////////////////////////////////////
plPlasmaMAXLayer::plPlasmaMAXLayer()
{
fConversionTargets = nil;
}
plPlasmaMAXLayer::~plPlasmaMAXLayer()
{
}
//// GetPlasmaMAXLayer ////////////////////////////////////////////////////////
// Static function that checks the classID of the given texMap and, if it's a
// valid Plasma MAX Layer, returns a pointer to such.
plPlasmaMAXLayer *plPlasmaMAXLayer::GetPlasmaMAXLayer( Texmap *map )
{
if (!map)
return NULL;
int i;
for( i = 0; i < sizeof( fDerivedTypes ) / sizeof( Class_ID ); i++ )
{
if( map->ClassID() == fDerivedTypes[ i ] )
return (plPlasmaMAXLayer *)map;
}
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
//// Conversion Targets ///////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//// plLayerTargetContainer ///////////////////////////////////////////////////
// This is a helper class that just contains a passive ref list of the layers
// that are our conversion targets at export time. See, it's possible that a
// layer gets converted, added to the target list, then destroyed as the
// parent material is suddenly thrown away. In order to avoid our pointers
// from being trashed (or keeping active refs on the layers when they're not
// actually used), we have a small helper class that just keep passive refs,
// so when one of them goes away, we get a notify about it.
class plLayerTargetContainer : public hsKeyedObject
{
static UInt32 fKeyCount;
public:
hsTArray<plLayerInterface *> fLayers;
virtual hsBool MsgReceive( plMessage *msg )
{
plGenRefMsg *ref = plGenRefMsg::ConvertNoRef( msg );
if( ref != nil )
{
if( ref->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
fLayers[ ref->fWhich ] = plLayerInterface::ConvertNoRef( ref->GetRef() );
else
fLayers[ ref->fWhich ] = nil;
}
return hsKeyedObject::MsgReceive( msg );
}
plLayerTargetContainer()
{
char str[ 512 ];
sprintf( str, "plLayerTargetContainer-%d", fKeyCount++ );
hsgResMgr::ResMgr()->NewKey( str, this, plLocation::kGlobalFixedLoc );
}
};
UInt32 plLayerTargetContainer::fKeyCount = 0;
void plPlasmaMAXLayer::IAddConversionTarget( plLayerInterface *target )
{
if( fConversionTargets == nil )
{
// Create us a new container
fConversionTargets = TRACKED_NEW plLayerTargetContainer;
fConversionTargets->GetKey()->RefObject();
}
fConversionTargets->fLayers.Append( target );
hsgResMgr::ResMgr()->AddViaNotify( target->GetKey(),
new plGenRefMsg( fConversionTargets->GetKey(), plRefMsg::kOnCreate,
fConversionTargets->fLayers.GetCount() - 1, 0 ),
plRefFlags::kPassiveRef );
}
void plPlasmaMAXLayer::IClearConversionTargets( void )
{
if( fConversionTargets != nil )
{
fConversionTargets->GetKey()->UnRefObject();
fConversionTargets = nil;
}
}
int plPlasmaMAXLayer::GetNumConversionTargets( void )
{
if( fConversionTargets == nil )
return 0;
int i, count = 0;
for( i = 0; i < fConversionTargets->fLayers.GetCount(); i++ )
{
if( fConversionTargets->fLayers[ i ] != nil )
count++;
}
return count;
}
plLayerInterface *plPlasmaMAXLayer::GetConversionTarget( int index )
{
if( fConversionTargets == nil )
return nil;
int i;
for( i = 0; i < fConversionTargets->fLayers.GetCount(); i++ )
{
if( fConversionTargets->fLayers[ i ] != nil )
{
if( index == 0 )
return fConversionTargets->fLayers[ i ];
index--;
}
}
return nil;
}
///////////////////////////////////////////////////////////////////////////////
//// Asset Management, and textures ///////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void plPlasmaMAXLayer::SetBitmapAssetId(jvUniqueId& assetId, int index /* = 0 */)
{
PBBitmap *pbbm = GetPBBitmap(index);
if (pbbm && GetMaxAssInterface())
{
char buf[20];
GetMaxAssInterface()->UniqueIdToString(assetId, buf);
pbbm->bi.SetDevice(buf);
}
}
void plPlasmaMAXLayer::GetBitmapAssetId(jvUniqueId& assetId, int index /* = 0 */)
{
PBBitmap *pbbm = GetPBBitmap(index);
if (pbbm && GetMaxAssInterface())
assetId = GetMaxAssInterface()->StringToUniqueId(pbbm->bi.Device());
else
assetId.SetEmpty();
}
void plPlasmaMAXLayer::SetBitmap(BitmapInfo *bi, int index)
{
jvUniqueId targetAssetId;
GetBitmapAssetId(targetAssetId, index);
Bitmap *BM = GetMaxBitmap(index);
if (BM)
{
BM->DeleteThis();
BM = NULL;
}
if (bi)
{
if (!targetAssetId.IsEmpty())
{
// If this texture has an assetId, we will check the
// asset database and make sure we have the latest version
// of the texture file before loading it
MaxAssInterface* assInterface = GetMaxAssInterface();
if (assInterface)
{
char buf[20];
assInterface->UniqueIdToString(targetAssetId, buf);
bi->SetDevice(buf);
const char* filename = bi->Name();
// Download the latest version and retrieve the filename
char newfilename[MAX_PATH];
if (assInterface->GetLatestVersionFile(targetAssetId, newfilename, sizeof(newfilename)))
{
// If the filename has changed, we have to reset the bitmap in the ParamBlock
if(stricmp(filename, newfilename) != 0)
bi->SetName(newfilename);
}
}
}
BMMRES result;
BM = TheManager->Load(bi, &result);
if (result == BMMRES_SUCCESS)
ISetMaxBitmap(BM, index);
else
ISetMaxBitmap(NULL, index);
// The load may have failed, but we still want to set the paramblock. We
// don't want to modify the layer if we're just missing the file.
PBBitmap pbBitmap(*bi);
ISetPBBitmap(&pbBitmap, index);
}
else
{
ISetMaxBitmap(NULL, index);
ISetPBBitmap(NULL, index);
}
/*
Bitmap *BM = GetMaxBitmap(index);
if (BM)
{
BM->DeleteThis();
BM = NULL;
}
if (filename)
{
BitmapInfo bi;
bi.SetName(filename);
// If this texture has an assetId, get the latest version from AssetMan before loading it
if (assetId && !assetId->IsEmpty())
{
MaxAssInterface* maxAssInterface = GetMaxAssInterface();
if (maxAssInterface)
{
// Download the latest version and retrieve the filename
char newfilename[MAX_PATH];
if (maxAssInterface->GetLatestVersionFile(*assetId, newfilename, sizeof(newfilename)))
{
// If the filename has changed, we have to reset the bitmap in the ParamBlock
if (stricmp(filename, newfilename) != 0)
{
bi.SetName(newfilename);
}
}
}
}
ISetMaxBitmap(TheManager->Load(&bi));
PBBitmap pbBitmap(bi);
// TheManager->LoadInto(&pbBitmap.bi, &pbBitmap.bm, TRUE);
ISetPBBitmap(&pbBitmap, index);
if (assetId)
SetBitmapAssetId(*assetId, index);
}
else
{
ISetMaxBitmap(NULL, index);
ISetPBBitmap(NULL, index);
}
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
*/
}
//// RefreshBitmaps ///////////////////////////////////////////////////////////
// Makes sure the bitmap asset is the latest from AssetMan, if we're using it.
void plPlasmaMAXLayer::RefreshBitmaps()
{
int i, count = GetNumBitmaps();
for( i = 0; i < count; i++ )
{
PBBitmap *pbbm = GetPBBitmap(i);
if (pbbm)
{
SetBitmap(&pbbm->bi, i);
}
}
}
//// GetBitmapFileName ////////////////////////////////////////////////////////
// Returns the filename of the ith bitmap. Makes sure we have the latest
// version from assetMan as well, if applicable.
hsBool plPlasmaMAXLayer::GetBitmapFileName( char *destFilename, int maxLength, int index /* = 0 */ )
{
jvUniqueId targetAssetId;
GetBitmapAssetId(targetAssetId, index);
MaxAssInterface* maxAssInterface = GetMaxAssInterface();
if (maxAssInterface != nil && !targetAssetId.IsEmpty())
{
// Download the latest version and retrieve the filename
if (maxAssInterface->GetLatestVersionFile(targetAssetId, destFilename, maxLength))
return true;
}
// Normal return
if( GetPBBitmap( index ) == nil )
return false;
strncpy( destFilename, GetPBBitmap( index )->bi.Name(), maxLength );
return true;
}
BOOL plPlasmaMAXLayer::HandleBitmapSelection(int index /* = 0 */)
{
static ICustButton* bmSelectBtn;
PBBitmap *pbbm = GetPBBitmap( index );
MaxAssInterface* maxAssInterface = GetMaxAssInterface();
// If the control key is held, we want to get rid of this texture
if ((GetKeyState(VK_CONTROL) & 0x8000) && pbbm != nil)
{
char msg[512];
sprintf(msg, "Are you sure you want to change this bitmap from %s to (none)?", pbbm->bi.Name());
if (hsMessageBox(msg, "Remove texture?", hsMessageBoxYesNo) == hsMBoxYes)
{
SetBitmap(nil, index);
return TRUE;
}
return FALSE;
}
// if we have the assetman plug-in, then try to use it, unless shift is held down
else if(maxAssInterface && !(GetKeyState(VK_SHIFT) & 0x8000))
{
jvUniqueId assetId;
GetBitmapAssetId(assetId, index);
char filename[MAX_PATH];
if (maxAssInterface->OpenBitmapDlg(assetId, filename, sizeof(filename)))
{
SetBitmapAssetId(assetId, index);
BitmapInfo bi;
bi.SetName(filename);
SetBitmap(&bi, index);
return TRUE;
}
}
else
{
BitmapInfo bi;
if( pbbm != NULL )
bi.SetName( pbbm->bi.Name() );
BOOL selectedNewBitmap = TheManager->SelectFileInput(&bi,
GetCOREInterface()->GetMAXHWnd(),
_T("Select Bitmap Image File"));
if (selectedNewBitmap)
{
// Set the assetId to empty so our new, unmanaged texture will take
jvUniqueId emptyId;
SetBitmapAssetId(emptyId, index);
SetBitmap(&bi, index);
return TRUE;
}
}
return FALSE;
}

View File

@ -0,0 +1,165 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plPlasmaMAXLayer - MAX Layer type that is the basis for all Plasma layer //
// types //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 1.13.2002 mcn - Created. //
// //
//// Notes from the Author ////////////////////////////////////////////////////
// //
// This base class is actually a quite-recent addition. As a result, most //
// of the old, non-base-class-structured code is still lying around. This //
// code will be slowly converted over as time goes on; the theory was that //
// this conversion would be far more likely to occur if the base class //
// actually already existed. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plPlasmaMAXLayer_h
#define _plPlasmaMAXLayer_h
#include "Max.h"
#include "hsTypes.h"
//// Derived Type Class IDs ///////////////////////////////////////////////////
// If you create a new Plasma layer type, add a define for the class ID here
// and also add the ID to the list in plPlasmaMAXLayer.cpp.
const Class_ID LAYER_TEX_CLASS_ID( 0x4223c620, 0x183c4868 );
const Class_ID STATIC_ENV_LAYER_CLASS_ID( 0x379a0a20, 0x3d0b1244 );
const Class_ID DYNAMIC_ENV_LAYER_CLASS_ID( 0x18205c0f, 0x57ea0e10 );
const Class_ID DYN_TEXT_LAYER_CLASS_ID( 0x36e3480f, 0x120120bd );
const Class_ID ANGLE_ATTEN_LAYER_CLASS_ID( 0x6d90918, 0x6160114 );
const Class_ID MAX_CAMERA_LAYER_CLASS_ID( 0xfaf5ec7, 0x13d90d3f );
//// Class Definition /////////////////////////////////////////////////////////
class plLayerInterface;
class plMaxNode;
class plErrorMsg;
class plLayer;
class plDynamicTextMap;
class plBitmapData;
class plLocation;
class plLayerConverter;
class plLayerInterface;
class plBMSamplerData;
class jvUniqueId;
class plLayerTargetContainer;
class plPlasmaMAXLayer : public Texmap
{
friend class plLayerConverter;
protected:
static const Class_ID fDerivedTypes[];
plLayerTargetContainer *fConversionTargets;
void IAddConversionTarget( plLayerInterface *target );
void IClearConversionTargets( void );
public:
plPlasmaMAXLayer();
virtual ~plPlasmaMAXLayer();
void DeleteThis() { delete this; }
// Static that checks the classID of the given texMap and, if it's a valid Plasma MAX Layer, returns a pointer to such
static plPlasmaMAXLayer *GetPlasmaMAXLayer( Texmap *map );
// Some layers must be unique for each node they're applied to (i.e. can't be shared among nodes).
// This returns true if the layer must be unique.
virtual bool MustBeUnique( void ) { return false; }
// These let the material make an informed decision on what to do with
// the color and alpha values coming out of an EvalColor call. Something
// like an InvertColor can be handled within EvalColor, but there needs
// to be a way to tell the caller that the color returned should be completely
// ignored.
virtual BOOL DiscardColor() { return false; }
virtual BOOL DiscardAlpha() { return false; }
// Return the number of conversion targets (only valid after the MakeMesh pass)
int GetNumConversionTargets( void );
// Get an indexed conversion target
plLayerInterface *GetConversionTarget( int index );
virtual BOOL HandleBitmapSelection(int index = 0);
virtual void SetBitmap(BitmapInfo *bi, int index = 0);
virtual void SetBitmapAssetId(jvUniqueId& assetId, int index = 0);
virtual void GetBitmapAssetId(jvUniqueId& assetId, int index = 0);
// Pure virtual accessors for the various bitmap related elements
virtual Bitmap *GetMaxBitmap(int index = 0) = 0;
virtual PBBitmap *GetPBBitmap( int index = 0 ) = 0;
virtual int GetNumBitmaps( void ) = 0;
// Makes sure the textures are the latest versions (including getting
// the latest version from AssetMan)
void RefreshBitmaps();
hsBool GetBitmapFileName( char *destFilename, int maxLength, int index = 0 );
// Virtual function called by plBMSampler to get various things while sampling the layer's image
virtual bool GetSamplerInfo( plBMSamplerData *samplerData ) { return false; }
// Backdoor for the texture find and replace util. Assumes input has the correct aspect ratio and is power of 2.
virtual void SetExportSize(int x, int y) {}
protected:
virtual void ISetMaxBitmap(Bitmap *bitmap, int index = 0) = 0;
virtual void ISetPBBitmap( PBBitmap *pbbm, int index = 0 ) = 0;
};
#endif // _plPlasmaMAXLayer_h

View File

@ -0,0 +1,712 @@
/*==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 "hsTypes.h"
#include "plStaticEnvLayer.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "stdmat.h"
#include "plBMSampler.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
class plStaticEnvLayerClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading = FALSE) { return TRACKED_NEW plStaticEnvLayer(); }
const TCHAR* ClassName() { return GetString(IDS_STATIC_ENVMAP_LAYER); }
SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
Class_ID ClassID() { return STATIC_ENV_LAYER_CLASS_ID; }
const TCHAR* Category() { return TEXMAP_CAT_ENV; }
const TCHAR* InternalName() { return _T("PlasmaStaticEnvMapLayer"); }
HINSTANCE HInstance() { return hInstance; }
};
static plStaticEnvLayerClassDesc plStaticEnvLayerDesc;
ClassDesc2* GetStaticEnvLayerDesc() { return &plStaticEnvLayerDesc; }
#include "plStaticEnvLayerBitmapPB.cpp"
plStaticEnvLayer::plStaticEnvLayer() :
fBitmapPB(NULL),
fUVGen(NULL),
fTexHandle(NULL),
fTexTime(0),
fIValid(NEVER)
{
int i;
for( i = 0; i < 6; i++ )
{
fBitmaps[ i ] = NULL;
}
plStaticEnvLayerDesc.MakeAutoParamBlocks(this);
ReplaceReference(kRefUVGen, GetNewDefaultUVGen());
}
plStaticEnvLayer::~plStaticEnvLayer()
{
int i;
for( i = 0; i < 6; i++ )
{
if( fBitmaps[ i ] )
fBitmaps[ i ]->DeleteThis();
}
IDiscardTexHandle();
}
//From MtlBase
void plStaticEnvLayer::Reset()
{
GetStaticEnvLayerDesc()->Reset(this, TRUE); // reset all pb2's
for( int i = 0; i < 6; i++ )
{
SetBitmap( NULL, i );
}
fIValid.SetEmpty();
}
void plStaticEnvLayer::Update(TimeValue t, Interval& valid)
{
if (!fIValid.InInterval(t))
{
fIValid.SetInfinite();
fUVGen->Update(t,fIValid);
fBitmapPB->GetValidity(t, fIValid);
}
// Gonna need to do this when we support animated bm's
#if 0
if (fBM)
{
if (bi.FirstFrame()!=bi.LastFrame())
ivalid.SetInstant(t);
}
#endif
valid &= fIValid;
}
Interval plStaticEnvLayer::Validity(TimeValue t)
{
//TODO: Update fIValid here
// mf horse - Hacking this in just to get animations working.
// No warranty on this not being stupid.
Interval v = FOREVER;
fBitmapPB->GetValidity(t, v);
v &= fUVGen->Validity(t);
return v;
}
ParamDlg* plStaticEnvLayer::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
fIMtlParams = imp;
IAutoMParamDlg* masterDlg = plStaticEnvLayerDesc.CreateParamDlgs(hwMtlEdit, imp, this);
SELBitmapDlgProc *paramDlg = (SELBitmapDlgProc *)gBitmapParamBlk.GetUserDlgProc();
if( paramDlg )
paramDlg->fMtlParams = imp;
return masterDlg;
}
BOOL plStaticEnvLayer::SetDlgThing(ParamDlg* dlg)
{
return FALSE;
}
int plStaticEnvLayer::NumRefs()
{
return 2;
}
//From ReferenceMaker
RefTargetHandle plStaticEnvLayer::GetReference(int i)
{
switch (i)
{
case kRefUVGen: return fUVGen;
case kRefBitmap: return fBitmapPB;
default: return NULL;
}
}
void plStaticEnvLayer::SetReference(int i, RefTargetHandle rtarg)
{
Interval garbage;
switch (i)
{
case kRefUVGen:
fUVGen = (UVGen *)rtarg;
if( fUVGen )
fUVGen->Update( TimeValue( 0 ), garbage );
break;
case kRefBitmap:
fBitmapPB = (IParamBlock2 *)rtarg;
// KLUDGE: If the paramblock is being set chances are we are being created or
// loaded. In the case of load, we want to refresh our textures.
if (fBitmapPB)
RefreshBitmaps();
break;
}
}
int plStaticEnvLayer::NumParamBlocks()
{
return 1;
}
IParamBlock2* plStaticEnvLayer::GetParamBlock(int i)
{
switch (i)
{
case 0: return fBitmapPB;
default: return NULL;
}
}
IParamBlock2* plStaticEnvLayer::GetParamBlockByID(BlockID id)
{
if (fBitmapPB->ID() == id)
return fBitmapPB;
else
return NULL;
}
//From ReferenceTarget
RefTargetHandle plStaticEnvLayer::Clone(RemapDir &remap)
{
plStaticEnvLayer *mnew = TRACKED_NEW plStaticEnvLayer();
*((MtlBase*)mnew) = *((MtlBase*)this); // copy superclass stuff
mnew->ReplaceReference(kRefBitmap, remap.CloneRef(fBitmapPB));
mnew->ReplaceReference(kRefUVGen, remap.CloneRef(fUVGen));
BaseClone(this, mnew, remap);
return (RefTargetHandle)mnew;
}
int plStaticEnvLayer::NumSubs()
{
return 2;
}
Animatable* plStaticEnvLayer::SubAnim(int i)
{
//TODO: Return 'i-th' sub-anim
switch (i)
{
case kRefUVGen: return fUVGen;
case kRefBitmap: return fBitmapPB;
default: return NULL;
}
}
TSTR plStaticEnvLayer::SubAnimName(int i)
{
switch (i)
{
case kRefUVGen: return "UVGen";
case kRefBitmap: return fBitmapPB->GetLocalName();
default: return "";
}
}
RefResult plStaticEnvLayer::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message)
{
switch (message)
{
case REFMSG_CHANGE:
{
fIValid.SetEmpty();
if (hTarget == fBitmapPB)
{
// see if this message came from a changing parameter in the pblock,
// if so, limit rollout update to the changing item and update any active viewport texture
ParamID changingParam = fBitmapPB->LastNotifyParamID();
fBitmapPB->GetDesc()->InvalidateUI(changingParam);
if (changingParam != -1)
IChanged();
}
}
break;
case REFMSG_UV_SYM_CHANGE:
IDiscardTexHandle();
break;
}
return REF_SUCCEED;
}
void plStaticEnvLayer::IChanged()
{
IDiscardTexHandle();
// Texture wasn't getting updated in the viewports, and this fixes it.
// Don't know if it's the right way though.
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
// And this is so the SceneWatcher gets notified that the material on some of it's
// referenced objects changed.
NotifyDependents(FOREVER, PART_ALL, REFMSG_USER_MAT);
}
#define TEX_HDR_CHUNK 0x5000
#define MAX_ASS_CHUNK 0x5500
IOResult plStaticEnvLayer::Save(ISave *isave)
{
IOResult res;
isave->BeginChunk(TEX_HDR_CHUNK);
res = MtlBase::Save(isave);
if (res != IO_OK)
return res;
isave->EndChunk();
return IO_OK;
}
IOResult plStaticEnvLayer::Load(ILoad *iload)
{
IOResult res;
while (IO_OK == (res = iload->OpenChunk()))
{
if (iload->CurChunkID() == TEX_HDR_CHUNK)
{
res = MtlBase::Load(iload);
}
iload->CloseChunk();
if (res != IO_OK)
return res;
}
return IO_OK;
}
inline Point2 CompUV(float x, float y, float z)
{
return Point2( 0.5f * ( x / z + 1.0f ), 0.5f * ( y / z + 1.0f ) );
}
AColor plStaticEnvLayer::EvalColor(ShadeContext& sc)
{
if (!sc.doMaps)
return AColor(0.0f, 0.0f, 0.0f, 1.0f);
AColor color;
if (sc.GetCache(this, color))
return color;
if (gbufID)
sc.SetGBufferID(gbufID);
// Evaluate the Bitmap
// Point3 v = sc.VectorTo( sc.V(), REF_OBJECT );//WORLD );
Point3 v = sc.VectorTo( sc.Normal(), REF_OBJECT );
float wx,wy,wz;
Color rcol;
Bitmap *refmap = NULL;
Point3 rv;
Point2 uv;
int size;
wx = (float)fabs( v.x );
wy = (float)fabs( v.y );
wz = (float)fabs( v.z );
if( wx >= wy && wx >= wz )
{
if( v.x < 0 )
{
refmap = fBitmaps[ kLeftFace ];
uv = CompUV( -v.y, -v.z, v.x );
}
else
{
refmap = fBitmaps[ kRightFace ];
uv = CompUV( v.y, -v.z, -v.x );
}
}
else if( wy >= wx && wy >= wz )
{
if( v.y > 0 )
{
refmap = fBitmaps[ kBackFace ];
uv = CompUV( -v.x, -v.z, -v.y );
}
else
{
refmap = fBitmaps[ kFrontFace ];
uv = CompUV( v.x, -v.z, v.y );
}
}
else if( wz >= wx && wz >= wy )
{
if( v.z < 0 )
{
refmap = fBitmaps[ kBottomFace ];
uv = CompUV( -v.x, -v.y, v.z );
}
else
{
refmap = fBitmaps[ kTopFace ];
uv = CompUV( -v.x, v.y, -v.z );
}
}
if( refmap == NULL )
color.White();
else
{
if( uv.x < 0.0f )
uv.x = 0.0f;
else if( uv.x > 1.0f )
uv.x = 1.0f;
if( uv.y < 0.0f )
uv.y = 0.0f;
else if( uv.y > 1.0f )
uv.y = 1.0f;
size = refmap->Width();
int x = (int)( uv.x * (float)( size - 1 ) );
int y = (int)( ( 1.0f - uv.y ) * (float)( size - 1 ) );
BMM_Color_64 c;
refmap->GetLinearPixels( x, y, 1, &c );
color = AColor( c.r / 65535.f, c.g / 65535.f, c.b / 65535.f, c.a / 65535.f );
}
// Invert color if specified
if( fBitmapPB->GetInt( kBmpInvertColor ) )
{
color.r = 1.0f - color.r;
color.g = 1.0f - color.g;
color.b = 1.0f - color.b;
}
// Discard color if specified
if( fBitmapPB->GetInt( kBmpDiscardColor ) )
color.r = color.g = color.b = 1.0f;
// Invert alpha if specified
if( fBitmapPB->GetInt( kBmpInvertAlpha ) )
color.a = 1.0f - color.a;
// Discard alpha if specified
if( fBitmapPB->GetInt( kBmpDiscardAlpha ) )
color.a = 1.0f;
// If RGB output is set to alpha, show RGB as grayscale of the alpha
if( fBitmapPB->GetInt( kBmpRGBOutput ) == 1 )
color = AColor( color.a, color.a, color.a, 1.0f );
sc.PutCache(this, color);
return color;
}
float plStaticEnvLayer::EvalMono(ShadeContext& sc)
{
if (fBitmapPB->GetInt(kBmpMonoOutput) == 1)
return EvalColor(sc).a;
return Intens(EvalColor(sc));
}
Point3 plStaticEnvLayer::EvalNormalPerturb(ShadeContext& sc)
{
// Return the perturbation to apply to a normal for bump mapping
return Point3(0, 0, 0);
}
ULONG plStaticEnvLayer::LocalRequirements(int subMtlNum)
{
if( fBitmapPB->GetInt( kBmpUseMAXAtmosphere ) )
return MTLREQ_VIEW_DEP;
return MTLREQ_VIEW_DEP | MTLREQ_NOATMOS;
}
void plStaticEnvLayer::IDiscardTexHandle()
{
if (fTexHandle)
{
fTexHandle->DeleteThis();
fTexHandle = NULL;
}
}
void plStaticEnvLayer::ActivateTexDisplay(BOOL onoff)
{
if (!onoff)
IDiscardTexHandle();
}
BITMAPINFO *plStaticEnvLayer::GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono, BOOL forceW, BOOL forceH)
{
// FIXME
fTexTime = 0;//CalcFrame(t);
// texValid = clipValid;
BITMAPINFO *bmi = NULL;
int xflags = 0;
if (fBitmapPB->GetInt(kBmpRGBOutput) == 1)
xflags |= EX_RGB_FROM_ALPHA;
bmi = thmaker.BitmapToDIB(fBitmaps[ 0 ], fUVGen->SymFlags(), xflags, forceW, forceH);
return bmi;
}
DWORD plStaticEnvLayer::GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker)
{
// FIXME: ignore validity for now
if (fTexHandle && fIValid.InInterval(t))// && texTime == CalcFrame(t))
return fTexHandle->GetHandle();
else
{
IDiscardTexHandle();
fTexTime = 0;//CalcFrame(t);
fTexHandle = thmaker.MakeHandle(GetVPDisplayDIB(t, thmaker, fIValid));
if (fTexHandle)
return fTexHandle->GetHandle();
else
return 0;
}
}
const char *plStaticEnvLayer::GetTextureName( int which )
{
// if (fBitmapPB->GetInt(kBmpUseBitmap))
{
PBBitmap *pbbm = fBitmapPB->GetBitmap( kBmpFrontBitmap + which );
if (pbbm)
return pbbm->bi.Name();
}
return NULL;
}
//// Set/GetBaseFilename //////////////////////////////////////////////////////
void plStaticEnvLayer::SetBaseFilename( const TCHAR *name, TimeValue t )
{
fBitmapPB->SetValue( kBmpBaseFilename, t, (TCHAR *)name );
}
const TCHAR *plStaticEnvLayer::GetBaseFilename( TimeValue t )
{
Interval valid;
TCHAR *buffer;
fBitmapPB->GetValue( kBmpBaseFilename, t, buffer, valid );
return (const TCHAR *)buffer;
}
//// IGetViewTM ///////////////////////////////////////////////////////////////
Matrix3 plStaticEnvLayer::IGetViewTM( int i )
{
Matrix3 m;
m.IdentityMatrix();
switch( i )
{
case kTopFace:
m.RotateX( -PI );
break;
case kBottomFace:
break;
case kLeftFace:
m.RotateX( -.5f * PI );
m.RotateY( -.5f * PI );
break;
case kRightFace:
m.RotateX( -.5f * PI );
m.RotateY( +.5f * PI );
break;
case kFrontFace:
m.RotateX( -.5f * PI );
m.RotateY( PI );
break;
case kBackFace:
m.RotateX( -.5f * PI );
break;
}
return m;
}
//// IWriteBM /////////////////////////////////////////////////////////////////
int plStaticEnvLayer::IWriteBM( BitmapInfo *bi, Bitmap *bm, TCHAR *name )
{
bi->SetName( name );
if( bm->OpenOutput( bi ) == BMMRES_SUCCESS )
{
if( bm->Write( bi, BMM_SINGLEFRAME ) == BMMRES_SUCCESS )
{
bm->Close( bi );
return 1;
}
}
return 0;
}
//// RenderCubicMap ///////////////////////////////////////////////////////////
// Generates the 6 faces for a cubic map based on a picked node
void plStaticEnvLayer::RenderCubicMap( INode *node )
{
int res, size;
BOOL success = 0;
TSTR fname, fullname;
Bitmap *bm = NULL;
TSTR path, filename, ext, thisFilename;
BitmapInfo biOutFile;
static TCHAR suffixes[ 6 ][ 4 ] = { "_FR", "_BK", "_LF", "_RT", "_UP", "_DN" };
Interface *ip = GetCOREInterface();
size = fBitmapPB->GetInt( kBmpTextureSize, ip->GetTime() );
if( size <= 0 )
{
return;
}
thisFilename = fBitmapPB->GetStr( kBmpBaseFilename, ip->GetTime() );
if( thisFilename.isNull() )
{
return;
}
SplitFilename( thisFilename, &path, &filename, &ext );
BOOL wasHid = node->IsNodeHidden();
node->Hide( TRUE );
// Create a blank bitmap
biOutFile.SetWidth( size );
biOutFile.SetHeight( size );
biOutFile.SetType( BMM_TRUE_64 );
biOutFile.SetAspect( 1.0f );
biOutFile.SetCurrentFrame( 0 );
bm = TheManager->Create( &biOutFile );
Matrix3 nodeTM = node->GetNodeTM( ip->GetTime() );
Matrix3 tm;
INode *root = ip->GetRootNode();
bm->Display( GetString( IDS_CUBIC_RENDER_TITLE ) );
/// Set up rendering contexts
ViewParams vp;
vp.projType = PROJ_PERSPECTIVE;
vp.hither = .001f;
vp.yon = 1.0e30f;
vp.fov = PI/2.0f;
if( fBitmapPB->GetInt( kBmpUseMAXAtmosphere ) )
{
vp.nearRange = 0;
vp.farRange = fBitmapPB->GetFloat( kBmpFarDistance );
}
else
{
vp.nearRange = vp.farRange = 1.0e30f;
}
BOOL saveUseEnvMap = ip->GetUseEnvironmentMap();
ip->SetUseEnvironmentMap( false );
res = ip->OpenCurRenderer( &vp );
for( int i = 0; i < 6; i++ )
{
tm = IGetViewTM( i );
tm.PreTranslate( -nodeTM.GetTrans() );
vp.affineTM = tm;
// Construct filename
thisFilename.printf( _T( "%s\\%s%s%s" ), path, filename, suffixes[ i ], ext );
res = ip->CurRendererRenderFrame( ip->GetTime(), bm, NULL, 1.0f, &vp );
if( !res )
goto fail;
if( !IWriteBM( &biOutFile, bm, thisFilename ) )
goto fail;
}
success = 1;
fail:
ip->CloseCurRenderer();
ip->SetUseEnvironmentMap( saveUseEnvMap );
bm->DeleteThis();
node->Hide( wasHid );
if( success )
{
for(int i = 0; i < 6; i++ )
{
BitmapInfo bi;
thisFilename.printf( _T( "%s\\%s%s%s" ), path, filename, suffixes[ i ], ext );
bi.SetName( thisFilename );
PBBitmap pbBitmap( bi );
fBitmapPB->SetValue( kBmpFrontBitmap + i, ip->GetTime(), &pbBitmap );
}
fBitmapPB->GetMap()->UpdateUI( ip->GetTime() );
}
}
PBBitmap *plStaticEnvLayer::GetPBBitmap(int index /* = 0 */)
{
return fBitmapPB->GetBitmap( ParamID( kBmpFrontBitmap + index ) );
}
void plStaticEnvLayer::ISetPBBitmap( PBBitmap *pbbm, int index )
{
fBitmapPB->SetValue( ParamID( kBmpFrontBitmap + index ), 0, pbbm );
}

View File

@ -0,0 +1,253 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plStaticEnvLayer - Static EnvironmentMap MAX Layer //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 8.17.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plStaticEnvLayer_h
#define _plStaticEnvLayer_h
#include "Max.h"
#include "plPlasmaMAXLayer.h"
#include "../resource.h"
class ClassDesc2;
class IParamBlock2;
class Bitmap;
ClassDesc2* GetStaticEnvLayerDesc();
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
//// Class Definition /////////////////////////////////////////////////////////
class plStaticEnvLayer : public plPlasmaMAXLayer
{
protected:
// Parameter block
IParamBlock2 *fBitmapPB;
UVGen *fUVGen;
IMtlParams *fIMtlParams;
TexHandle *fTexHandle;
TimeValue fTexTime;
Bitmap *fBitmaps[ 6 ];
Interval fIValid;
TCHAR fBaseFileName[ MAX_PATH ];
friend class SELBitmapDlgProc;
Matrix3 IGetViewTM( int i );
int IWriteBM( BitmapInfo *bi, Bitmap *bm, TCHAR *name );
public:
// Ref nums
enum
{
kRefUVGen,
kRefBitmap,
};
// Block ID's
enum
{
kBlkBitmap,
};
// Faces
enum
{
kFrontFace,
kBackFace,
kLeftFace,
kRightFace,
kTopFace,
kBottomFace
};
plStaticEnvLayer();
~plStaticEnvLayer();
void DeleteThis() { delete this; }
//From MtlBase
ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
BOOL SetDlgThing(ParamDlg* dlg);
void Update(TimeValue t, Interval& valid);
void Reset();
Interval Validity(TimeValue t);
ULONG LocalRequirements(int subMtlNum);
//From Texmap
RGBA EvalColor(ShadeContext& sc);
float EvalMono(ShadeContext& sc);
Point3 EvalNormalPerturb(ShadeContext& sc);
// For displaying textures in the viewport
BOOL SupportTexDisplay() { return TRUE; }
void ActivateTexDisplay(BOOL onoff);
BITMAPINFO *GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono=FALSE, int forceW=0, int forceH=0);
DWORD GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker);
protected:
void IChanged();
void IDiscardTexHandle();
public:
void GetUVTransform(Matrix3 &uvtrans) { fUVGen->GetUVTransform(uvtrans); }
int GetTextureTiling() { return fUVGen->GetTextureTiling(); }
int GetUVWSource() { return fUVGen->GetUVWSource(); }
virtual int GetMapChannel () { return fUVGen->GetMapChannel(); } // only relevant if above returns UVWSRC_EXPLICIT
UVGen *GetTheUVGen() { return fUVGen; }
//TODO: Return anim index to reference index
int SubNumToRefNum(int subNum) { return subNum; }
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
//From Animatable
Class_ID ClassID() { return STATIC_ENV_LAYER_CLASS_ID; }
SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_STATIC_ENVMAP_LAYER); }
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
// TODO: Maintain the number or references here
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
int NumParamBlocks(); // return number of ParamBlocks in this instance
IParamBlock2* GetParamBlock(int i); // return i'th ParamBlock
IParamBlock2* GetParamBlockByID(BlockID id); // return id'd ParamBlock
const char *GetTextureName( int which );
void SetBaseFilename( const TCHAR *name, TimeValue t );
const TCHAR *GetBaseFilename( TimeValue t );
void RenderCubicMap( INode *node );
/// ParamBlock accessors
enum
{
kScalingAny,
kScalingHalf,
kScalingNone
};
// Param ID's
enum
{
kBmpFrontBitmap,
kBmpBackBitmap,
kBmpLeftBitmap,
kBmpRightBitmap,
kBmpTopBitmap,
kBmpBottomBitmap,
// Misc
kBmpDiscardColor,
kBmpInvertColor,
kBmpDiscardAlpha,
kBmpInvertAlpha,
// Texture quality
kBmpNonCompressed,
kBmpScaling,
// Max only
kBmpMonoOutput,
kBmpRGBOutput,
// Detail
kBmpUseDetail,
kBmpDetailStartSize,
kBmpDetailStopSize,
kBmpDetailStartOpac,
kBmpDetailStopOpac,
// Texture generation
kBmpBaseFilename,
kBmpTextureSize,
kBmpGenerateFaces,
kBmpLastTextureSize, // Annoying, but necessary to clamp texture sizes to powers of 2
kBmpUseMAXAtmosphere,
kBmpFarDistance,
// Just a hack to simulate refraction instead of reflection
kBmpRefract
};
// Pure virtual accessors for the various bitmap related elements
virtual Bitmap *GetMaxBitmap(int index = 0) { return fBitmaps[ index ]; }
virtual PBBitmap *GetPBBitmap( int index = 0 );
virtual int GetNumBitmaps( void ) { return 6; }
protected:
virtual void ISetMaxBitmap(Bitmap *bitmap, int index = 0) { fBitmaps[ index ] = bitmap; }
virtual void ISetPBBitmap( PBBitmap *pbbm, int index = 0 );
};
#endif // _plStaticEnvLayer_h

View File

@ -0,0 +1,515 @@
/*==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 "hsTypes.h"
#include "plStaticEnvLayer.h"
///////////////////////////////////////////////////////////////////////////////
//// Bitmap Accessor //////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
class SELBMTexPBAccessor : public PBAccessor
{
public:
void Set(PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
if (!owner)
return;
plStaticEnvLayer* layer = (plStaticEnvLayer*)owner;
IParamBlock2 *pb = layer->GetParamBlockByID(plStaticEnvLayer::kBlkBitmap);
switch (id)
{
case plStaticEnvLayer::kBmpFrontBitmap:
case plStaticEnvLayer::kBmpBackBitmap:
case plStaticEnvLayer::kBmpLeftBitmap:
case plStaticEnvLayer::kBmpRightBitmap:
case plStaticEnvLayer::kBmpTopBitmap:
case plStaticEnvLayer::kBmpBottomBitmap:
// Set up the enums so these would match...
if (pb->GetMap())
pb->GetMap()->Invalidate( id );
// Update the bitmap saved by the layer
//layer->SetBitmap( id, &val.bm->bi );
break;
case plStaticEnvLayer::kBmpBaseFilename:
if( pb->GetMap() )
{
pb->GetMap()->Enable( plStaticEnvLayer::kBmpGenerateFaces, ( val.s == NULL || val.s[ 0 ] == 0 ) ? FALSE : TRUE );
ICustButton *bmSelectBtn = GetICustButton( GetDlgItem( pb->GetMap()->GetHWnd(), IDC_GENERATE_FACES ) );
bmSelectBtn->SetText( _T( "Generate From Node" ) );
ReleaseICustButton( bmSelectBtn );
}
break;
}
}
void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid)
{
}
};
static SELBMTexPBAccessor bmtex_accessor;
///////////////////////////////////////////////////////////////////////////////
//// PickControlNode //////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
class PickControlNode : public PickObjectProc
{
public:
plStaticEnvLayer *fLayer;
HWND fHWnd;
PickControlNode() { fLayer = NULL; }
BOOL Pick( INode *node )
{
if( node && fLayer )
fLayer->RenderCubicMap( node );
return TRUE;
}
void EnterMode()
{
ICustButton *iBut = GetICustButton( GetDlgItem( fHWnd, IDC_GENERATE_FACES ) );
if( iBut )
{
iBut->SetCheck( TRUE );
iBut->SetText( _T( "Generate From Node" ) );
}
ReleaseICustButton( iBut );
}
void ExitMode()
{
ICustButton *iBut = GetICustButton( GetDlgItem( fHWnd, IDC_GENERATE_FACES ) );
if( iBut )
{
iBut->SetCheck( FALSE );
iBut->SetText( _T( "Generate From Node" ) );
}
ReleaseICustButton( iBut );
}
BOOL Filter( INode *node ) { return TRUE; }
};
///////////////////////////////////////////////////////////////////////////////
//// ParamBlock Dialog Proc ///////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
class SELBitmapDlgProc : public ParamMap2UserDlgProc
{
PickControlNode fPickCallback;
public:
IMtlParams *fMtlParams;
/// Called to update the controls of the dialog
virtual void Update( TimeValue t, Interval &valid, IParamMap2 *map )
{
ICustButton *bmSelectBtn;
IParamBlock2 *pblock;
int i;
long buttons[ 6 ] = { IDC_FRONT_NAME, IDC_BACK_NAME, IDC_LEFT_NAME, IDC_RIGHT_NAME, IDC_TOP_NAME, IDC_BOTTOM_NAME };
BitmapInfo bi;
ParamMap2UserDlgProc::Update( t, valid, map );
pblock = map->GetParamBlock();
for( i = plStaticEnvLayer::kBmpFrontBitmap; i <= plStaticEnvLayer::kBmpBottomBitmap; i++ )
{
bmSelectBtn = GetICustButton( GetDlgItem( map->GetHWnd(), buttons[ i ] ) );
PBBitmap *pbbm = pblock->GetBitmap( i, t );
if( pbbm )
bmSelectBtn->SetText( (TCHAR *)pbbm->bi.Filename() );
else
bmSelectBtn->SetText( _T( "None" ) );
ReleaseICustButton( bmSelectBtn );
}
plStaticEnvLayer *layer = (plStaticEnvLayer *)map->GetParamBlock()->GetOwner();
bi.SetName( layer->GetBaseFilename( t ) );
SetDlgItemText( map->GetHWnd(), IDC_BASE_FILENAME, bi.Filename() );
map->Enable( plStaticEnvLayer::kBmpGenerateFaces, ( bi.Name() == NULL || bi.Name()[ 0 ] == 0 ) ? FALSE : TRUE );
bmSelectBtn = GetICustButton( GetDlgItem( map->GetHWnd(), IDC_GENERATE_FACES ) );
bmSelectBtn->SetText( _T( "Generate From Node" ) );
ReleaseICustButton( bmSelectBtn );
i = pblock->GetInt( plStaticEnvLayer::kBmpTextureSize, t );
pblock->SetValue( plStaticEnvLayer::kBmpLastTextureSize, t, i );
}
/// Clamp texture sizes to a power of 2
void IClampTexSizeSpinner( TimeValue t, IParamMap2 *map )
{
IParamBlock2 *pblock = map->GetParamBlock();
int lastVal = pblock->GetInt( plStaticEnvLayer::kBmpLastTextureSize, t );
int tempVal, newVal = pblock->GetInt( plStaticEnvLayer::kBmpTextureSize, t );
if( newVal < lastVal )
{
lastVal = newVal;
for( tempVal = 1; tempVal < newVal; tempVal <<= 1 );
newVal = tempVal >> 1;
}
else
{
lastVal = newVal;
for( tempVal = 1; tempVal < newVal; tempVal <<= 1 );
newVal = tempVal;
}
pblock->SetValue( plStaticEnvLayer::kBmpTextureSize, t, newVal );
pblock->SetValue( plStaticEnvLayer::kBmpLastTextureSize, t, newVal );
}
/// Main message proc
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static ICustButton* bmSelectBtn;
long buttons[ 6 ] = { IDC_FRONT_NAME, IDC_BACK_NAME, IDC_LEFT_NAME, IDC_RIGHT_NAME, IDC_TOP_NAME, IDC_BOTTOM_NAME };
switch (msg)
{
case WM_INITDIALOG:
break;
case CC_SPINNER_CHANGE:
if( LOWORD( wParam ) == IDC_TEXSIZE_SPIN )
IClampTexSizeSpinner( t, map );
break;
case WM_COMMAND:
if( HIWORD( wParam ) == EN_CHANGE && LOWORD( wParam ) == IDC_TEXSIZE_EDIT )
{
IClampTexSizeSpinner( t, map );
}
else if( HIWORD( wParam ) == BN_CLICKED && LOWORD( wParam ) == IDC_LAYER_RELOAD )
{
plStaticEnvLayer *layer = (plStaticEnvLayer*)map->GetParamBlock()->GetOwner();
layer->RefreshBitmaps();
layer->IChanged();
return TRUE;
}
else if( LOWORD( wParam ) == IDC_FRONT_NAME )
return IDoLayerClicked( LOWORD( wParam ), plStaticEnvLayer::kFrontFace, map, t, hWnd );
else if( LOWORD( wParam ) == IDC_BACK_NAME )
return IDoLayerClicked( LOWORD( wParam ), plStaticEnvLayer::kBackFace, map, t, hWnd );
else if( LOWORD( wParam ) == IDC_LEFT_NAME )
return IDoLayerClicked( LOWORD( wParam ), plStaticEnvLayer::kLeftFace, map, t, hWnd );
else if( LOWORD( wParam ) == IDC_RIGHT_NAME )
return IDoLayerClicked( LOWORD( wParam ), plStaticEnvLayer::kRightFace, map, t, hWnd );
else if( LOWORD( wParam ) == IDC_TOP_NAME )
return IDoLayerClicked( LOWORD( wParam ), plStaticEnvLayer::kTopFace, map, t, hWnd );
else if( LOWORD( wParam ) == IDC_BOTTOM_NAME )
return IDoLayerClicked( LOWORD( wParam ), plStaticEnvLayer::kBottomFace, map, t, hWnd );
else if( LOWORD( wParam ) == IDC_LAYER_LOAD_GEN )
return IDoLoadGenerated( map, t, hWnd );
else if( LOWORD( wParam ) == IDC_GENERATE_FACES )
{
plStaticEnvLayer *layer = (plStaticEnvLayer*)map->GetParamBlock()->GetOwner();
fMtlParams->EndPickMode();
fPickCallback.fHWnd = hWnd;
fPickCallback.fLayer = layer;
fMtlParams->SetPickMode( &fPickCallback );
break;
}
else if( LOWORD( wParam ) == IDC_BASE_FILENAME )
return IDoSelectBaseFilename( map, t, hWnd );
break;
}
return FALSE;
}
void DeleteThis() {};
BOOL IDoSelectBaseFilename( IParamMap2 *map, TimeValue t, HWND hWnd )
{
BitmapInfo bi;
plStaticEnvLayer *layer = (plStaticEnvLayer*)map->GetParamBlock()->GetOwner();
/// Select one file
bi.SetName( layer->GetBaseFilename( t ) );
if( !TheManager->SelectFileOutput( &bi, GetCOREInterface()->GetMAXHWnd(), _T( "Choose the base filename for the rendered faces" ) ) )
return FALSE;
/// Just store the name and set the button label as such, too
SetDlgItemText( hWnd, IDC_BASE_FILENAME, bi.Filename() );
layer->SetBaseFilename( bi.Name(), t );
return TRUE;
}
BOOL IDoLoadGenerated( IParamMap2 *map, TimeValue t, HWND hWnd )
{
BitmapInfo bi;
int i;
TCHAR filename[ MAX_PATH ];
TCHAR *modPoint, faces[ 6 ][ 4 ] = { "_FR", "_BK", "_LF", "_RT", "_UP", "_DN" };
/// Select one file
PBBitmap *pbbm = map->GetParamBlock()->GetBitmap( plStaticEnvLayer::kBmpFrontBitmap, t );
if( pbbm != NULL )
bi.SetName( pbbm->bi.Name() );
if( !TheManager->SelectFileInput( &bi, GetCOREInterface()->GetMAXHWnd(), _T( "Select one of the generated face bitmaps" ) ) )
return FALSE;
/// Copy the name over and get our mod point
strcpy( filename, bi.Filename() );
modPoint = strstr( filename, "_UP" );
if( modPoint == NULL )
modPoint = strstr( filename, "_DN" );
if( modPoint == NULL )
modPoint = strstr( filename, "_LF" );
if( modPoint == NULL )
modPoint = strstr( filename, "_RT" );
if( modPoint == NULL )
modPoint = strstr( filename, "_FR" );
if( modPoint == NULL )
modPoint = strstr( filename, "_BK" );
/// Load each face
for( i = 0; i < 6; i++ )
{
memcpy( modPoint, faces[ i ], sizeof( TCHAR ) * 3 );
if( !ILoadFace( i, filename, map, t, hWnd ) )
return FALSE;
}
return TRUE;
}
BOOL ILoadFace( int whichFace, const TCHAR *fileName, IParamMap2 *map, TimeValue t, HWND hWnd )
{
long buttons[ 6 ] = { IDC_FRONT_NAME, IDC_BACK_NAME, IDC_LEFT_NAME, IDC_RIGHT_NAME, IDC_TOP_NAME, IDC_BOTTOM_NAME };
IParamBlock2 *pblock = map->GetParamBlock();
plStaticEnvLayer *layer = (plStaticEnvLayer*)map->GetParamBlock()->GetOwner();
ICustButton *bmSelectBtn;
BitmapInfo bi;
if( TheManager->GetImageInfo( &bi, fileName ) != BMMRES_SUCCESS )
return FALSE;
layer->SetBitmap( &bi, whichFace - plStaticEnvLayer::kFrontFace );
PBBitmap *pbbm = layer->GetPBBitmap( whichFace - plStaticEnvLayer::kFrontFace );
bmSelectBtn = GetICustButton( GetDlgItem( hWnd, buttons[ whichFace ] ) );
bmSelectBtn->SetText((TCHAR*)pbbm->bi.Filename());
ReleaseICustButton( bmSelectBtn );
return TRUE;
}
BOOL IDoLayerClicked( int whichBtn, int whichFace, IParamMap2 *map, TimeValue t, HWND hWnd )
{
plPlasmaMAXLayer *layer = (plPlasmaMAXLayer *)map->GetParamBlock()->GetOwner();
if (layer == nil)
return FALSE;
BOOL selectedNewBitmap = layer->HandleBitmapSelection( whichFace - plStaticEnvLayer::kFrontFace );
if(selectedNewBitmap)
{
ICustButton* bmSelectBtn;
PBBitmap *pbbm = layer->GetPBBitmap( whichFace - plStaticEnvLayer::kFrontFace );
bmSelectBtn = GetICustButton( GetDlgItem( hWnd, whichBtn ) );
bmSelectBtn->SetText(pbbm != nil ? (TCHAR*)pbbm->bi.Filename() : nil);
ReleaseICustButton(bmSelectBtn);
return TRUE;
}
else
{
return FALSE;
}
}
};
static SELBitmapDlgProc gSELBitmapDlgProc;
///////////////////////////////////////////////////////////////////////////////
//// ParamBlock Definition ////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static ParamBlockDesc2 gBitmapParamBlk
(
plStaticEnvLayer::kBlkBitmap, _T("bitmap"), 0, GetStaticEnvLayerDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI, plStaticEnvLayer::kRefBitmap,
IDD_STATIC_ENVMAP_LAYER, IDS_STATIC_ENVMAP_LAYER_TEX, 0, 0, &gSELBitmapDlgProc,
// Bitmaps
plStaticEnvLayer::kBmpFrontBitmap, _T("frontBitmap"), TYPE_BITMAP, P_SHORT_LABELS, 0,
p_accessor, &bmtex_accessor,
end,
plStaticEnvLayer::kBmpBackBitmap, _T("backBitmap"), TYPE_BITMAP, P_SHORT_LABELS, 0,
p_accessor, &bmtex_accessor,
end,
plStaticEnvLayer::kBmpLeftBitmap, _T("leftBitmap"), TYPE_BITMAP, P_SHORT_LABELS, 0,
p_accessor, &bmtex_accessor,
end,
plStaticEnvLayer::kBmpRightBitmap, _T("rightBitmap"), TYPE_BITMAP, P_SHORT_LABELS, 0,
p_accessor, &bmtex_accessor,
end,
plStaticEnvLayer::kBmpTopBitmap, _T("topBitmap"), TYPE_BITMAP, P_SHORT_LABELS, 0,
p_accessor, &bmtex_accessor,
end,
plStaticEnvLayer::kBmpBottomBitmap, _T("bottomBitmap"), TYPE_BITMAP, P_SHORT_LABELS, 0,
p_accessor, &bmtex_accessor,
end,
// Texture Color/Alpha
plStaticEnvLayer::kBmpDiscardColor, _T("discardColor"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_BLEND_NO_COLOR,
end,
plStaticEnvLayer::kBmpInvertColor, _T("invertColor"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_BLEND_INV_COLOR,
end,
plStaticEnvLayer::kBmpDiscardAlpha, _T("discardAlpha"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_DISCARD_ALPHA,
end,
plStaticEnvLayer::kBmpInvertAlpha, _T("invertAlpha"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_BLEND_INV_ALPHA,
end,
// Texture Quality
plStaticEnvLayer::kBmpNonCompressed, _T("nonCompressed"),TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_FORCE_NONCOMPRESSED,
end,
plStaticEnvLayer::kBmpScaling, _T("scaling"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_SCALE_ALL, IDC_SCALE_HALF, IDC_SCALE_NONE,
end,
// Max Only
plStaticEnvLayer::kBmpMonoOutput, _T("monoOutput"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 2, IDC_HSMAX_LAYER_RGBOUT, IDC_HSMAX_LAYER_ALPHAOUT,
end,
plStaticEnvLayer::kBmpRGBOutput, _T("rgbOutput"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 2, IDC_HSMAX_LAYER_RGBOUT2, IDC_HSMAX_LAYER_ALPHAOUT2,
end,
// Detail
plStaticEnvLayer::kBmpUseDetail, _T("useDetail"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_USE_DETAIL,
p_default, FALSE,
p_enable_ctrls, 4, plStaticEnvLayer::kBmpDetailStartSize, plStaticEnvLayer::kBmpDetailStopSize,
plStaticEnvLayer::kBmpDetailStartOpac, plStaticEnvLayer::kBmpDetailStopOpac,
end,
plStaticEnvLayer::kBmpDetailStartSize,_T("dropOffStart"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_DETAIL_START_SIZE_EDIT, IDC_DETAIL_START_SIZE_SPIN, 0.4,
p_range, 0, 100,
p_default, 0,
end,
plStaticEnvLayer::kBmpDetailStopSize, _T("dropOffStop"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_DETAIL_STOP_SIZE_EDIT, IDC_DETAIL_STOP_SIZE_SPIN, 0.4,
p_range, 0, 100,
p_default, 100,
end,
plStaticEnvLayer::kBmpDetailStartOpac, _T("detailMax"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_DETAIL_START_OPAC_EDIT, IDC_DETAIL_START_OPAC_SPIN, 0.4,
p_range, 0, 100,
p_default, 8,
end,
plStaticEnvLayer::kBmpDetailStopOpac, _T("detailMin"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_DETAIL_STOP_OPAC_EDIT, IDC_DETAIL_STOP_OPAC_SPIN, 0.4,
p_range, 0, 100,
p_default, 0,
end,
// Face generation
plStaticEnvLayer::kBmpTextureSize, _T("textureSize"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_TEXSIZE_EDIT, IDC_TEXSIZE_SPIN, SPIN_AUTOSCALE,
p_range, 4, 512,
p_default, 64,
end,
plStaticEnvLayer::kBmpBaseFilename, _T("baseFilename"), TYPE_FILENAME, 0, 0,
p_default, _T( "" ),
p_accessor, &bmtex_accessor,
end,
plStaticEnvLayer::kBmpGenerateFaces, _T("genFaces"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_GENERATE_FACES,
p_prompt, IDS_SELECT_NODE,
end,
plStaticEnvLayer::kBmpUseMAXAtmosphere, _T("useMAXAtmos"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_USEMAXFOG,
p_default, FALSE,
p_enable_ctrls, 1, plStaticEnvLayer::kBmpFarDistance,
end,
plStaticEnvLayer::kBmpFarDistance, _T("farDistance"), TYPE_FLOAT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_FARDIST_EDIT, IDC_FARDIST_SPIN, SPIN_AUTOSCALE,
p_range, 0.f, 9999999.f,
p_default, 500.f,
end,
plStaticEnvLayer::kBmpLastTextureSize, _T("lastTextureSize"), TYPE_INT, 0, 0,
end,
plStaticEnvLayer::kBmpRefract, _T("refract"),TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_REFRACT,
end,
end
);

View File

@ -0,0 +1,88 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// ParamBlock Konstants for Static EnvironmentMap MAX Layers //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 8.17.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plStaticEnvLayerBitmapPB_h
#define _plStaticEnvLayerBitmapPB_h
// Param ID's
enum
{
kBmpFrontBitmap,
kBmpBackBitmap,
kBmpLeftBitmap,
kBmpRightBitmap,
kBmpTopBitmap,
kBmpBottomBitmap,
// Misc
kBmpDiscardColor,
kBmpInvertColor,
kBmpDiscardAlpha,
kBmpInvertAlpha,
// Texture quality
kBmpNonCompressed,
kBmpScaling,
// Max only
kBmpMonoOutput,
kBmpRGBOutput,
// Detail
kBmpUseDetail,
kBmpDetailStartSize,
kBmpDetailStopSize,
kBmpDetailStartOpac,
kBmpDetailStopOpac,
};
#endif //_plStaticEnvLayerBitmapPB_h

View File

@ -0,0 +1,282 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// Export/convert-specific functionality of plAnimStealthNode //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plAnimStealthNode.h"
#include "plPassMtlBase.h"
#include "resource.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxComponent/plMaxAnimUtils.h"
#include "../MaxConvert/plConvert.h"
#include "../MaxConvert/hsMaterialConverter.h"
#include "../plSurface/hsGMaterial.h"
#include "../plSurface/plLayerAnimation.h"
#include "iparamm2.h"
//// Helpers /////////////////////////////////////////////////////////////////
static void ISearchLayerRecur( plLayerInterface *layer, const char *segName, hsTArray<plKey>& keys )
{
if( !layer )
return;
plLayerAnimation *animLayer = plLayerAnimation::ConvertNoRef(layer);
if (animLayer)
{
char *ID = animLayer->GetSegmentID();
if (ID == nil)
ID = "";
if (!strcmp(ID, segName))
{
if( keys.kMissingIndex == keys.Find(animLayer->GetKey()) )
keys.Append(animLayer->GetKey());
}
}
ISearchLayerRecur(layer->GetAttached(), segName, keys);
}
static int ISearchLayerRecur(hsGMaterial* mat, const char *segName, hsTArray<plKey>& keys)
{
if (segName == nil || strcmp( segName, ENTIRE_ANIMATION_NAME ) == 0 )
segName = "";
int i;
for( i = 0; i < mat->GetNumLayers(); i++ )
ISearchLayerRecur(mat->GetLayer(i), segName, keys);
return keys.GetCount();
}
static int GetMatAnimModKey(Mtl* mtl, plMaxNodeBase* node, const char* segName, hsTArray<plKey>& keys)
{
int retVal = 0;
int i;
//if( begin < 0 )
// begin = 0;
if( mtl->ClassID() == Class_ID(MULTI_CLASS_ID,0) )
{
for( i = 0; i < mtl->NumSubMtls(); i++ )
retVal += GetMatAnimModKey(mtl->GetSubMtl(i), node, segName, keys);
}
else
{
hsTArray<hsGMaterial*> matList;
if (node)
hsMaterialConverter::Instance().GetMaterialArray(mtl, (plMaxNode*)node, matList);
else
hsMaterialConverter::Instance().CollectConvertedMaterials(mtl, matList);
for( i = 0; i < matList.GetCount(); i++ )
{
retVal += ISearchLayerRecur(matList[i], segName, keys);
}
}
return retVal;
}
SegmentSpec *plAnimStealthNode::IGetSegmentSpec( void ) const
{
if( fCachedSegMap != nil )
{
const char *name = GetSegmentName();
if( name != nil )
{
SegmentMap::iterator i = fCachedSegMap->find( name );
if( i != fCachedSegMap->end() )
{
SegmentSpec *spec = i->second;
return spec;
}
}
}
return nil;
}
hsScalar plAnimStealthNode::GetSegStart( void ) const
{
SegmentSpec *spec = IGetSegmentSpec();
if( spec != nil )
return spec->fStart;
return 0.f;
}
hsScalar plAnimStealthNode::GetSegEnd( void ) const
{
SegmentSpec *spec = IGetSegmentSpec();
if( spec != nil )
return spec->fEnd;
return 0.f;
}
void plAnimStealthNode::GetLoopPoints( hsScalar &start, hsScalar &end ) const
{
start = GetSegStart();
end = GetSegEnd();
const char *loopName = GetLoopName();
if( loopName != nil && loopName[ 0 ] != 0 && fCachedSegMap != nil )
GetSegMapAnimTime( loopName, fCachedSegMap, SegmentSpec::kLoop, start, end );
}
void plAnimStealthNode::GetAllStopPoints( hsTArray<hsScalar> &out )
{
if( fCachedSegMap == nil )
return;
for (SegmentMap::iterator it = fCachedSegMap->begin(); it != fCachedSegMap->end(); it++)
{
SegmentSpec *spec = it->second;
if( spec->fType == SegmentSpec::kStopPoint )
{
out.Append( spec->fStart );
}
}
}
//// StuffToTimeConvert //////////////////////////////////////////////////////
// Handles converting all the settings we have that are applicable for an
// animTimeConvert and stuffing it into said ATC.
void plAnimStealthNode::StuffToTimeConvert( plAnimTimeConvert &convert, hsScalar maxLength )
{
const char *segName = GetSegmentName();
bool isEntire = ( segName == nil || strcmp( segName, ENTIRE_ANIMATION_NAME ) == 0 ) ? true : false;
if( isEntire )
{
convert.SetBegin( 0 );
convert.SetEnd( maxLength );
}
else
{
SegmentSpec *spec = IGetSegmentSpec();
convert.SetBegin( ( spec != nil ) ? spec->fStart : 0.f );
convert.SetEnd( ( spec != nil ) ? spec->fEnd : 0.f );
}
// Even if we're not looping, set the loop points. (A responder
// could tell us later to start looping.)
if( isEntire )
convert.SetLoopPoints( 0, maxLength );
else
{
hsScalar loopStart, loopEnd;
GetLoopPoints( loopStart, loopEnd );
convert.SetLoopPoints( loopStart, loopEnd );
}
convert.Loop( GetLoop() );
// Auto-start
if( GetAutoStart() )
convert.Start( 0 );
else
convert.Stop( true );
// Stuff stop points
GetAllStopPoints( convert.GetStopPoints() );
// Ease curve stuff
if( GetEaseInType() != plAnimEaseTypes::kNoEase )
{
convert.SetEase( true, GetEaseInType(), GetEaseInMin(), GetEaseInMax(), GetEaseInLength() );
}
if( GetEaseOutType() != plAnimEaseTypes::kNoEase )
{
convert.SetEase( false, GetEaseOutType(), GetEaseOutMin(), GetEaseOutMax(), GetEaseOutLength() );
}
}
//// plAnimObjInterface Functions ////////////////////////////////////////////
hsBool plAnimStealthNode::GetKeyList( INode *restrictedNode, hsTArray<plKey> &outKeys )
{
if( !fPreppedForConvert )
{
hsMessageBox( "This messages is to warn you that mcn screwed up in his attempt to create "
"a SetupProperties() pass for materials in this scene. You should probably let him know as soon as "
"possible, and also make a copy of this exact scene so that he can test with it and figure out what "
"is going wrong. Thank you.", "Mathew is Stupid Error", hsMessageBoxNormal );
}
GetMatAnimModKey( GetParentMtl(), (plMaxNode *)restrictedNode, GetSegmentName(), outKeys );
return true;
}
//// SetupProperties /////////////////////////////////////////////////////////
hsBool plAnimStealthNode::SetupProperties( plMaxNode *node, plErrorMsg *pErrMsg )
{
fPreppedForConvert = true;
plPassMtlBase *parent = GetParentMtl();
if( parent != nil && fCachedSegMap == nil )
{
fCachedSegMap = GetAnimSegmentMap( parent, nil );
}
return true;
}
//// ConvertDeInit ///////////////////////////////////////////////////////////
hsBool plAnimStealthNode::ConvertDeInit( plMaxNode *node, plErrorMsg *pErrMsg )
{
fPreppedForConvert = false;
if( fCachedSegMap != nil )
DeleteSegmentMap( fCachedSegMap );
fCachedSegMap = nil;
return true;
}

View File

@ -0,0 +1,986 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plAnimStealthNode - Stealthy hidden INode that represents a single //
// segment's worth of animation info for a material. //
// Stored as an INode so they can be "selected" //
// by components as targets of animation messages. //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plAnimStealthNode.h"
#include "plPassMtlBase.h"
#include "resource.h"
#include "../MaxComponent/plMaxAnimUtils.h"
#include "../MaxComponent/plPickNodeBase.h"
#include "iparamm2.h"
extern TCHAR *GetString( int id );
extern HINSTANCE hInstance;
//// Stealthy Class Desc /////////////////////////////////////////////////////
class plStealthClassDesc : public ClassDesc2
{
public:
int IsPublic() { return FALSE; }
void* Create(BOOL loading) { return TRACKED_NEW plAnimStealthNode(loading); }
const TCHAR* ClassName() { return GetString( IDS_STEALTH_NAME ); }
SClass_ID SuperClassID() { return HELPER_CLASS_ID; }
Class_ID ClassID() { return ANIMSTEALTH_CLASSID; }
const TCHAR* Category() { return NULL; }
const TCHAR* InternalName() { return _T("PlasmaAnimStealthInfo"); }
HINSTANCE HInstance() { return hInstance; }
};
static plStealthClassDesc sStealthClassDesc;
ClassDesc2* GetStealthClassDesc() { return &sStealthClassDesc; }
//// plStealthDlgProc /////////////////////////////////////////////////////////
// Dialog proc for the anim stealth child dialog
class plStealthDlgProc : public ParamMap2UserDlgProc
{
protected:
// Combo itemdata values
enum
{
kName, // Name of an animation/loop
kDefault, // Default combo value
kInvalid, // Invalid entry (couldn't find)
};
SegmentMap *fSegMap;
HWND fhWnd;
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void DeleteThis() { IDeleteSegMap(); }
void SetThing(ReferenceTarget *m);
void Update( TimeValue t, Interval &valid, IParamMap2 *pmap );
protected:
// Set all the controls to their stored value
void IInitControls( plAnimStealthNode *stealth, IParamBlock2 *pb);
// Deletes all the allocated memory
void IDeleteSegMap();
void ILoadLoops(IParamBlock2 *pb);
void ISetSel(HWND hCombo, const char *name);
};
const char *kAnimNameNone = ENTIRE_ANIMATION_NAME;
static plStealthDlgProc sStealthDlgProc;
//// Stealthy ParamBlock Desc ////////////////////////////////////////////////
static plEaseAccessor sEaseAccessor( plAnimStealthNode::kBlockPB, plAnimStealthNode::kPBEaseInMin,
plAnimStealthNode::kPBEaseInMax, plAnimStealthNode::kPBEaseInLength,
plAnimStealthNode::kPBEaseOutMin, plAnimStealthNode::kPBEaseOutMax,
plAnimStealthNode::kPBEaseOutLength );
ParamBlockDesc2 plAnimStealthNode::sAnimStealthPB
(
kBlockPB, _T( "animStealth" ), IDS_STEALTH_NAME, GetStealthClassDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI, kRefParamBlock,
// UI
IDD_STEALTH_ANIM, IDS_STEALTH_NAME, 0, 0, &sStealthDlgProc,
kPBName, _T("animName"), TYPE_STRING, 0, 0,
end,
kPBAutoStart, _T("autoStart"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_AUTO_START,
p_default, FALSE,
end,
kPBLoop, _T("loop"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_LOOP,
p_default, TRUE,
end,
kPBLoopName, _T("loopName"), TYPE_STRING, 0, 0,
end,
// Anim Ease
kPBEaseInType, _T("easeInType"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_PASS_ANIM_EASE_IN_NONE, IDC_PASS_ANIM_EASE_IN_CONST_ACCEL, IDC_PASS_ANIM_EASE_IN_SPLINE,
p_vals, plAnimEaseTypes::kNoEase, plAnimEaseTypes::kConstAccel, plAnimEaseTypes::kSpline,
p_default, plAnimEaseTypes::kNoEase,
end,
kPBEaseInLength, _T("easeInLength"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 99.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_PASS_ANIM_EASE_IN_TIME, IDC_PASS_ANIM_EASE_IN_TIME_SPIN, 1.0,
p_accessor, &sEaseAccessor,
end,
kPBEaseInMin, _T("easeInMin"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 99.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_PASS_ANIM_EASE_IN_MIN, IDC_PASS_ANIM_EASE_IN_MIN_SPIN, 1.0,
p_accessor, &sEaseAccessor,
end,
kPBEaseInMax, _T("easeInMax"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 99.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_PASS_ANIM_EASE_IN_MAX, IDC_PASS_ANIM_EASE_IN_MAX_SPIN, 1.0,
p_accessor, &sEaseAccessor,
end,
kPBEaseOutType, _T("easeOutType"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_PASS_ANIM_EASE_OUT_NONE, IDC_PASS_ANIM_EASE_OUT_CONST_ACCEL, IDC_PASS_ANIM_EASE_OUT_SPLINE,
p_vals, plAnimEaseTypes::kNoEase, plAnimEaseTypes::kConstAccel, plAnimEaseTypes::kSpline,
p_default, plAnimEaseTypes::kNoEase,
end,
kPBEaseOutLength, _T("easeOutLength"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 99.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_PASS_ANIM_EASE_OUT_TIME, IDC_PASS_ANIM_EASE_OUT_TIME_SPIN, 1.0,
p_accessor, &sEaseAccessor,
end,
kPBEaseOutMin, _T("easeOutMin"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 99.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_PASS_ANIM_EASE_OUT_MIN, IDC_PASS_ANIM_EASE_OUT_MIN_SPIN, 1.0,
p_accessor, &sEaseAccessor,
end,
kPBEaseOutMax, _T("easeOutMax"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 99.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_PASS_ANIM_EASE_OUT_MAX, IDC_PASS_ANIM_EASE_OUT_MAX_SPIN, 1.0,
p_accessor, &sEaseAccessor,
end,
end
);
plAnimStealthNode::plAnimStealthNode( BOOL loading ) : fClassDesc(nil), fParamBlock(nil), fParentMtl(nil)
{
fCachedSegMap = nil;
fClassDesc = &sStealthClassDesc;
fClassDesc->MakeAutoParamBlocks( this );
}
plAnimStealthNode::~plAnimStealthNode()
{
// DeleteAllRefsFromMe();
}
CreateMouseCallBack *plAnimStealthNode::GetCreateMouseCallBack()
{
return nil;
}
void plAnimStealthNode::SetParentMtl( plPassMtlBase *parent )
{
fParentMtl = parent;
}
bool plAnimStealthNode::CanConvertToStealth( INode *objNode )
{
return ( ConvertToStealth( objNode ) != nil );
}
plAnimStealthNode *plAnimStealthNode::ConvertToStealth( INode *objNode )
{
if( objNode == nil )
return nil;
Object *obj = objNode->GetObjectRef();
if( obj == nil )
return nil;
if( obj->CanConvertToType( ANIMSTEALTH_CLASSID ) )
return (plAnimStealthNode *)obj;
return nil;
}
const char *plAnimStealthNode::GetSegmentName( void ) const
{
const char *str = fParamBlock->GetStr( (ParamID)kPBName );
if( str == nil || str[ 0 ] == 0 )
return ENTIRE_ANIMATION_NAME;
return str;
}
void plAnimStealthNode::SetSegment( const char *name )
{
if( name == nil || strcmp(name, ENTIRE_ANIMATION_NAME) == 0 || name[ 0 ] == 0 )
fParamBlock->SetValue( (ParamID)kPBName, 0, "" );
else
fParamBlock->SetValue( (ParamID)kPBName, 0, (char *)name );
}
void plAnimStealthNode::SetNodeName( const char *parentName )
{
INode *node = GetINode();
if( node != nil )
{
char name[ 512 ], newName[ 512 ];
sprintf( name, "%s : %s", parentName, GetSegmentName() );
if( GetCOREInterface()->GetINodeByName( name ) != nil )
{
// For whatever reason, MakeNameUnique() doesn't ACTUALLY make a name unique!
// So we just need to more or less do it ourselves...
int i;
for( i = 1; i < 1024; i++ )
{
sprintf( newName, "%s(%d)", name, i );
if( GetCOREInterface()->GetINodeByName( newName ) == nil )
break;
}
if( i == 1024 )
{
// You've got to be kidding me...
char msg[ 2048 ];
sprintf( msg, "WARNING: For some reason, we cannot find a unique name for the node '%s'. This"
" will most likely cause export problems. Exactly how many of these do we HAVE??",
name );
hsMessageBox( msg, "WARNING!", hsMessageBoxNormal );
}
}
else
strcpy( newName, name );
node->SetName( newName );
}
}
int plAnimStealthNode::NumParamBlocks()
{
return 1;
}
IParamBlock2 *plAnimStealthNode::GetParamBlock( int i )
{
if( i == kRefParamBlock )
return fParamBlock;
return nil;
}
IParamBlock2 *plAnimStealthNode::GetParamBlockByID( BlockID id )
{
if( fParamBlock && fParamBlock->ID() == id )
return fParamBlock;
return nil;
}
RefTargetHandle plAnimStealthNode::Clone(RemapDir &remap)
{
plAnimStealthNode *obj = (plAnimStealthNode *)fClassDesc->Create( false );
// Do the base clone
BaseClone(this, obj, remap);
// Copy our references
if (fParamBlock)
obj->ReplaceReference( kRefParamBlock, fParamBlock->Clone( remap ) );
return obj;
}
void plAnimStealthNode::BuildMesh(TimeValue t)
{
}
void plAnimStealthNode::FreeCaches()
{
}
void plAnimStealthNode::GetLocalBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box)
{
box.MakeCube(Point3(0,0,0), 0);
}
void plAnimStealthNode::GetWorldBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box)
{
box.MakeCube(Point3(0,0,0), 0);
}
int plAnimStealthNode::Display(TimeValue t, INode *node, ViewExp *vpt, int flags)
{
return 0;
}
int plAnimStealthNode::HitTest(TimeValue t, INode *node, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt)
{
return 0;
}
int plAnimStealthNode::NumRefs()
{
return 1;
}
RefTargetHandle plAnimStealthNode::GetReference( int i )
{
if( i == kRefParamBlock )
return fParamBlock;
else if( i == kRefParentMtl )
return fParentMtl;
return nil;
}
void plAnimStealthNode::SetReference( int i, RefTargetHandle rtarg )
{
if( i == kRefParamBlock )
fParamBlock = (IParamBlock2 *)rtarg;
else if( i == kRefParentMtl )
fParentMtl = (plPassMtlBase *)rtarg;
}
RefResult plAnimStealthNode::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message)
{
return REF_SUCCEED;
}
IOResult plAnimStealthNode::Save(ISave* isave)
{
return IO_OK;
}
IOResult plAnimStealthNode::Load(ILoad* iload)
{
return IO_OK;
}
plPassMtlBase *plAnimStealthNode::GetParentMtl( void )
{
return fParentMtl;
}
class plGetRefs : public DependentEnumProc
{
public:
hsTArray<ReferenceMaker *> fList;
plGetRefs() { }
virtual int proc( ReferenceMaker *rmaker )
{
fList.Append( rmaker );
return DEP_ENUM_CONTINUE;
}
};
hsBool plAnimStealthNode::IsParentUsedInScene( void )
{
if( GetParentMtl() == nil )
return false;
// There are two possibilities: either a node uses us and thus has a ref to us,
// or a multi-sub uses us that a node has a ref to us.
// Note: we could do the loop as a helper function, but we only do it twice,
// so it's not *really* worth the effort...
//// NOTE: the following doesn't seem to work, but keeping here in case it ever does.
//// What really actually finds something is the enum dependents loop below
const char *mtlName = GetParentMtl()->GetName();
RefList &refList = GetRefList();
RefListItem *item = refList.FirstItem();
while( item != nil )
{
TSTR s;
item->maker->GetClassName( s );
if( item->maker->SuperClassID() == BASENODE_CLASS_ID && !CanConvertToStealth( (INode *)( item->maker ) ) )
return true; // Horray, a node has a ref to us!
else if( item->maker->ClassID() == Class_ID(MULTI_CLASS_ID,0) )
{
// Multi-sub, run the refs on that guy (we only go one up)
Mtl *multisub = (Mtl *)item->maker;
RefList &refList2 = multisub->GetRefList();
RefListItem *item2 = refList.FirstItem();
while( item2 != nil )
{
if( item2->maker->SuperClassID() == BASENODE_CLASS_ID )
return true; // Horray, a node has a ref to us!
item2 = item2->next;
}
// No go, keep trying
}
else if( item->maker->SuperClassID() == MATERIAL_CLASS_ID )
{
int q = 0;
}
item = item->next;
}
// Enum dependents
int i;
plGetRefs callback;
GetParentMtl()->EnumDependents( &callback );
for( i = 0; i < callback.fList.GetCount(); i++ )
{
ReferenceMaker *maker = callback.fList[ i ];
TSTR s;
maker->GetClassName( s );
if( maker->SuperClassID() == BASENODE_CLASS_ID && !CanConvertToStealth( (INode *)maker ) )
return true; // Horray, a node has a ref to us!
}
return false;
}
INode *plAnimStealthNode::GetINode()
{
// Go through the reflist looking for RefMakers with a ref to this component.
// There should only be one INode in this list.
RefList &refList = GetRefList();
RefListItem *item = refList.FirstItem();
while( item )
{
if( item->maker->SuperClassID() == BASENODE_CLASS_ID )
return (INode *)item->maker;
item = item->next;
}
return nil;
}
void plStealthDlgProc::Update(TimeValue t, Interval& valid, IParamMap2* pmap)
{
// Does the pmap match our pmap?
}
//// plStealthMouseOverrideProc //////////////////////////////////////////////
// Because of wonderful linking problems with the MAX libraries, we can't
// actually use CreateChildMParamMap2 like we should. So instead, we use
// CreateChildCPParamMap2. However, *that* function calls the wrong interface
// to handle untrapped mouse messages, with the result that clicking and
// dragging scrolls the command pane (where components are displayed) instead
// of the material editor pane.
// To override this, we subclass each dialog so that we can capture the mouse
// messages before MAX processes them and then reroute them appropriately.
// Note: because MAX already uses the window long of the given window, we can't
// store the old proc of the window. However, since we always use
// CreateChildCPParamMap2, and because the MAX source code shows us that it
// always uses the same dialog proc for all windows created with that function,
// we can simply store the address of that proc the first time we subclass and
// use it for restoring every time thereafter (see the following DlgProc)
static WNDPROC sOldStealthDlgProc = nil;
static INT_PTR CALLBACK plStealthMouseOverrideProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
IParamMap2 *map = (IParamMap2 *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
switch( msg )
{
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MOUSEMOVE:
{
// We don't want the COREInterface to process our mouse messages with RollupMouseMessage;
// rather, we want IMtlParams to do it just like it would if we could actually call
// CreateChildMParamMap2
IParamBlock2 *pb = map->GetParamBlock();
if( pb != nil )
{
plAnimStealthNode *stealth = (plAnimStealthNode *)pb->GetOwner();
if( stealth != nil )
{
plPassMtlBase *mtl = (plPassMtlBase *)stealth->GetParentMtl();
mtl->fIMtlParams->RollupMouseMessage( hWnd, msg, wParam, lParam );
}
}
return 0;
}
}
if( sOldStealthDlgProc != nil )
return CallWindowProc( sOldStealthDlgProc, hWnd, msg, wParam, lParam );
else
return 0;
}
BOOL plStealthDlgProc::DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
IParamBlock2 *pb = map->GetParamBlock();
plAnimStealthNode *stealth = (plAnimStealthNode *)pb->GetOwner();
switch (msg)
{
case WM_INITDIALOG:
{
// Install our override proc so we can capture mouse messages ourselves.
// Note that the first time, we grab the old proc so we can restore with that
// one every time after, since they should always be the same proc
WNDPROC old = (WNDPROC)SetWindowLongPtr( hWnd, DWLP_DLGPROC, (LONG_PTR)plStealthMouseOverrideProc );
if( sOldStealthDlgProc == nil )
sOldStealthDlgProc = old;
fhWnd = hWnd;
IInitControls( stealth, pb );
return TRUE;
}
case WM_DESTROY:
// Restore our old proc
SetWindowLongPtr( hWnd, DWLP_DLGPROC, (LONG_PTR)sOldStealthDlgProc );
break;
case WM_ENABLE:
// The entire dialog was either enabled or disabled.
break;
case WM_COMMAND:
// Loop selection changed
if( LOWORD( wParam ) == IDC_LOOPS && HIWORD( wParam ) == CBN_SELCHANGE )
{
// If a loop is selected, save it
HWND hCombo = (HWND)lParam;
int sel = SendMessage( hCombo, CB_GETCURSEL, 0, 0 );
if( sel != CB_ERR )
{
if( SendMessage( hCombo, CB_GETITEMDATA, sel, 0 ) == kName )
{
char buf[256];
SendMessage( hCombo, CB_GETLBTEXT, sel, (LPARAM)buf );
pb->SetValue( (ParamID)plAnimStealthNode::kPBLoopName, 0, buf );
}
else
pb->SetValue( (ParamID)plAnimStealthNode::kPBLoopName, 0, "" );
}
return TRUE;
}
// Auto-start or loop checkbox checked
if( LOWORD( wParam ) == IDC_LOOP && HIWORD( wParam ) == BN_CLICKED )
{
BOOL checked = ( SendMessage( (HWND)lParam, BM_GETCHECK, 0, 0 ) == BST_CHECKED );
pb->SetValue( plAnimStealthNode::kPBLoop, 0, checked );
EnableWindow( GetDlgItem( hWnd, IDC_LOOPS ), checked );
return TRUE;
}
// Refresh clicked
else if( LOWORD( wParam ) == IDC_REFRESH_ANIMS && HIWORD( wParam ) == BN_CLICKED )
{
IInitControls( stealth, pb );
return TRUE;
}
break;
}
return FALSE;
}
void plStealthDlgProc::SetThing(ReferenceTarget *m)
{
plAnimStealthNode *stealth = (plAnimStealthNode *)m;
IParamBlock2 *pb = stealth->GetParamBlockByID( plAnimStealthNode::kBlockPB );
IInitControls( stealth, pb );
}
void plStealthDlgProc::IDeleteSegMap()
{
// If we have a segment map, delete the memory associated with it
DeleteSegmentMap( fSegMap );
fSegMap = nil;
}
void plStealthDlgProc::ISetSel(HWND hCombo, const char *name)
{
// If there is a name, try and set that
if( name && strcmp( name, "" ) )
{
int idx = SendMessage( hCombo, CB_FINDSTRINGEXACT, -1, (LPARAM)name );
// If we can't find the saved name add a "not found" entry, so they know what it was
if( idx == -1 )
{
char buf[256];
sprintf( buf, "(not found) %s", name );
idx = SendMessage( hCombo, CB_ADDSTRING, 0, (LPARAM)buf );
SendMessage( hCombo, CB_SETITEMDATA, idx, kInvalid );
}
SendMessage( hCombo, CB_SETCURSEL, idx, 0 );
}
// No name, set it to none
else
{
int count = SendMessage( hCombo, CB_GETCOUNT, 0, 0 );
for( int i = 0; i < count; i++ )
{
if( SendMessage( hCombo, CB_GETITEMDATA, i, 0 ) == kDefault )
SendMessage( hCombo, CB_SETCURSEL, i, 0 );
}
}
}
void plStealthDlgProc::IInitControls( plAnimStealthNode *stealth, IParamBlock2 *pb )
{
IDeleteSegMap();
if( stealth->GetParentMtl() != nil )
{
fSegMap = GetAnimSegmentMap( stealth->GetParentMtl(), nil );
ILoadLoops( pb );
}
else
{
// ?? What should we do?
fSegMap = nil;
hsStatusMessage( "No parent material yet in plStealthDlgProc::IInitControls()...not good..." );
}
// Enable/disable the loop dropdown
EnableWindow( GetDlgItem( fhWnd, IDC_LOOPS ), pb->GetInt( (ParamID)plAnimStealthNode::kPBLoop ) );
}
void plStealthDlgProc::ILoadLoops(IParamBlock2 *pb)
{
HWND hLoops = GetDlgItem( fhWnd, IDC_LOOPS );
SendMessage( hLoops, CB_RESETCONTENT, 0, 0 );
// Add the default option
int defIdx = SendMessage( hLoops, CB_ADDSTRING, 0, (LPARAM)ENTIRE_ANIMATION_NAME );
SendMessage( hLoops, CB_SETITEMDATA, defIdx, kDefault );
const char *segName = pb->GetStr( (ParamID)plAnimStealthNode::kPBName );
if( segName == nil || fSegMap == nil )
{
// Default of "entire animation", no other loop options
SendMessage( hLoops, CB_SETCURSEL, defIdx, 0 );
return;
}
SegmentSpec *animSpec = (*fSegMap)[ segName ];
if( animSpec && fSegMap )
{
// for each segment we found:
for( SegmentMap::iterator i = fSegMap->begin(); i != fSegMap->end(); i++ )
{
SegmentSpec *spec = (*i).second;
if( spec->fType == SegmentSpec::kLoop )
{
// If the loop is contained by the animation, add it
if( (spec->fStart == -1 || spec->fStart >= animSpec->fStart) &&
(spec->fEnd == -1 || spec->fEnd <= animSpec->fEnd) )
{
// Add the name
int idx = SendMessage( hLoops, CB_ADDSTRING, 0, (LPARAM)spec->fName );
SendMessage( hLoops, CB_SETITEMDATA, idx, kName );
}
}
}
}
ISetSel( hLoops, pb->GetStr( (ParamID)plAnimStealthNode::kPBLoopName ) );
}
void plAnimStealthNode::BeginEditParams(IObjParam *ip, ULONG flags, Animatable *prev)
{
fClassDesc->BeginEditParams(ip, this, flags, prev);
}
void plAnimStealthNode::EndEditParams(IObjParam *ip, ULONG flags, Animatable *next)
{
fClassDesc->EndEditParams(ip, this, flags, next);
}
//// ReleaseDlg //////////////////////////////////////////////////////////////
void plAnimStealthNode::ReleaseDlg( void )
{
IParamMap2 *map = fParamBlock->GetMap();
fParamBlock->SetMap( nil );
if( map != nil )
DestroyChildCPParamMap2( map );
}
//// SwitchDlg ///////////////////////////////////////////////////////////////
// Switch underlying objects in the dialog (to avoid unnecessary deletion/
// recreations)
void plAnimStealthNode::SwitchDlg( plAnimStealthNode *toSwitchTo )
{
IParamMap2 *map = fParamBlock->GetMap();
fParamBlock->SetMap( nil );
toSwitchTo->fParamBlock->SetMap( map );
map->SetParamBlock( toSwitchTo->fParamBlock );
map->SetThing( (ReferenceTarget *)toSwitchTo );
map->Invalidate();
map->UpdateUI( 0 );
}
//// CreateAndEmbedDlg ///////////////////////////////////////////////////////
// Create the dialog for this object and place it inside the given dialog,
// centering it in the given control if any.
bool plAnimStealthNode::CreateAndEmbedDlg( IParamMap2 *parentMap, IMtlParams *parentParams, HWND frameCtrl )
{
IParamMap2 *map = CreateChildCPParamMap2( fParamBlock, GetCOREInterface(), hInstance,
parentMap, MAKEINTRESOURCE( IDD_STEALTH_ANIM ),
nil, &sStealthDlgProc );
fParamBlock->SetMap( map );
if( frameCtrl != nil )
{
HWND child = fParamBlock->GetMap()->GetHWnd();
RECT childFrame, centerFrame;
::GetClientRect( child, &childFrame );
::GetWindowRect( frameCtrl, &centerFrame );
::MapWindowPoints( nil, parentMap->GetHWnd(), (POINT *)&centerFrame, 2 );
int frameWidth = centerFrame.right - centerFrame.left;
int frameHeight = centerFrame.bottom - centerFrame.top;
int childWidth = childFrame.right - childFrame.left;
int childHeight = childFrame.bottom - childFrame.top;
::OffsetRect( &childFrame, ( frameWidth - childWidth ) >> 1, ( frameHeight - childHeight ) >> 1 );
::OffsetRect( &childFrame, centerFrame.left, centerFrame.top );
::SetWindowPos( child, nil, childFrame.left, childFrame.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER );
}
return true;
}
//// GetWinDlg ///////////////////////////////////////////////////////////////
// Get the actual window handle of the currently active dialog displaying us
HWND plAnimStealthNode::GetWinDlg( void ) const
{
IParamMap2 *map = fParamBlock->GetMap();
if( map != nil )
return map->GetHWnd();
return nil;
}
//// Picker Dialog for Restricted Animation Components //////////////////////////////////////////
class plPickAnimStealthNode : public plPickMtlNode
{
protected:
ParamID fTypeID;
void IAddUserType(HWND hList)
{
int type = fPB->GetInt(fTypeID);
int idx = ListBox_AddString( hList, kUseParamBlockNodeString );
if (type == plAnimObjInterface::kUseParamBlockNode && !fPB->GetINode(fNodeParamID))
ListBox_SetCurSel(hList, idx);
idx = ListBox_AddString( hList, kUseOwnerNodeString );
if (type == plAnimObjInterface::kUseOwnerNode)
ListBox_SetCurSel(hList, idx);
}
void ISetUserType(plMaxNode* node, const char* userType)
{
if( hsStrEQ( userType, kUseParamBlockNodeString ) )
{
ISetNodeValue(nil);
fPB->SetValue(fTypeID, 0, plAnimObjInterface::kUseParamBlockNode);
}
else if( hsStrEQ(userType, kUseOwnerNodeString ) )
{
ISetNodeValue(nil);
fPB->SetValue(fTypeID, 0, plAnimObjInterface::kUseOwnerNode);
}
else
fPB->SetValue(fTypeID, 0, plAnimObjInterface::kUseParamBlockNode);
}
public:
plPickAnimStealthNode(IParamBlock2* pb, ParamID nodeParamID, ParamID typeID, Mtl *mtl) :
plPickMtlNode(pb, nodeParamID, mtl), fTypeID(typeID)
{
}
};
//// plAnimObjInterface Functions ////////////////////////////////////////////
void plAnimStealthNode::PickTargetNode( IParamBlock2 *destPB, ParamID destParamID, ParamID typeID )
{
plPickAnimStealthNode pick( destPB, destParamID, typeID, (Mtl *)GetParentMtl() );
pick.DoPick();
}
const char *plAnimStealthNode::GetIfaceSegmentName( hsBool allowNil )
{
// When sending messages to material animations, they're already addressed for the right
// layer, no need for a segment name
return nil;
}
//// Parameter Access Functions //////////////////////////////////////////////
#pragma warning( push )
#pragma warning( disable:4800 ) // Forcing value to bool true or false (go figure, i'm even explicitly casting)
bool plAnimStealthNode::GetAutoStart( void ) const { return (bool)fParamBlock->GetInt( (ParamID)kPBAutoStart ); }
void plAnimStealthNode::SetAutoStart( bool b ) { fParamBlock->SetValue( (ParamID)kPBAutoStart, 0, (int)b ); };
bool plAnimStealthNode::GetLoop( void ) const { return fParamBlock->GetInt( (ParamID)kPBLoop ); }
const char *plAnimStealthNode::GetLoopName( void ) const { return fParamBlock->GetStr( (ParamID)kPBLoopName ); }
void plAnimStealthNode::SetLoop( bool b, const char *name )
{
fParamBlock->SetValue( (ParamID)kPBLoop, 0, (int)b );
if( name == nil )
fParamBlock->SetValue( (ParamID)kPBLoopName, 0, "" );
else
fParamBlock->SetValue( (ParamID)kPBLoopName, 0, (char *)name );
}
UInt8 plAnimStealthNode::GetEaseInType( void ) const { return (UInt8)fParamBlock->GetInt( (ParamID)kPBEaseInType ); }
hsScalar plAnimStealthNode::GetEaseInLength( void ) const { return (hsScalar)fParamBlock->GetFloat( (ParamID)kPBEaseInLength ); }
hsScalar plAnimStealthNode::GetEaseInMin( void ) const { return (hsScalar)fParamBlock->GetFloat( (ParamID)kPBEaseInMin ); }
hsScalar plAnimStealthNode::GetEaseInMax( void ) const { return (hsScalar)fParamBlock->GetFloat( (ParamID)kPBEaseInMax ); }
void plAnimStealthNode::SetEaseIn( UInt8 type, hsScalar length, hsScalar min, hsScalar max )
{
fParamBlock->SetValue( (ParamID)kPBEaseInType, 0, (int)type );
fParamBlock->SetValue( (ParamID)kPBEaseInLength, 0, (float)length );
fParamBlock->SetValue( (ParamID)kPBEaseInMin, 0, (float)min );
fParamBlock->SetValue( (ParamID)kPBEaseInMax, 0, (float)max );
}
UInt8 plAnimStealthNode::GetEaseOutType( void ) const { return (UInt8)fParamBlock->GetInt( (ParamID)kPBEaseOutType ); }
hsScalar plAnimStealthNode::GetEaseOutLength( void ) const { return (hsScalar)fParamBlock->GetFloat( (ParamID)kPBEaseOutLength ); }
hsScalar plAnimStealthNode::GetEaseOutMin( void ) const { return (hsScalar)fParamBlock->GetFloat( (ParamID)kPBEaseOutMin ); }
hsScalar plAnimStealthNode::GetEaseOutMax( void ) const { return (hsScalar)fParamBlock->GetFloat( (ParamID)kPBEaseOutMax ); }
void plAnimStealthNode::SetEaseOut( UInt8 type, hsScalar length, hsScalar min, hsScalar max )
{
fParamBlock->SetValue( (ParamID)kPBEaseOutType, 0, (int)type );
fParamBlock->SetValue( (ParamID)kPBEaseOutLength, 0, (float)length );
fParamBlock->SetValue( (ParamID)kPBEaseOutMin, 0, (float)min );
fParamBlock->SetValue( (ParamID)kPBEaseOutMax, 0, (float)max );
}
#pragma warning( pop ) // Forcing value to bool true or false (go figure, i'm even explicitly casting)
//// Parent Accessor Functions ///////////////////////////////////////////////
plStealthNodeAccessor &plStealthNodeAccessor::GetInstance( void )
{
static plStealthNodeAccessor instance;
return instance;
}
void plStealthNodeAccessor::ISetParent( ReferenceTarget *target, plPassMtlBase *parent )
{
if( target != nil && target->ClassID() == ANIMSTEALTH_CLASSID )
{
( (plAnimStealthNode *)target )->SetParentMtl( parent );
}
}
void plStealthNodeAccessor::TabChanged( tab_changes changeCode, Tab<PB2Value> *tab, ReferenceMaker *owner,
ParamID id, int tabIndex, int count )
{
if( changeCode == tab_insert || changeCode == tab_append )
{
if( owner->SuperClassID() != MATERIAL_CLASS_ID )
return;
plPassMtlBase *mtl = (plPassMtlBase *)owner;
while( count > 0 )
{
ISetParent( (*tab)[ tabIndex ].r, mtl );
tabIndex++;
count--;
}
}
else if( changeCode == tab_delete || changeCode == tab_ref_deleted )
{
// How are we supposed to handle this if we don't even get a stinkin pointer??
}
}
void plStealthNodeAccessor::Set( PB2Value &v, ReferenceMaker *owner, ParamID id, int tabIndex, TimeValue t )
{
// Bit of error checking
if( owner->SuperClassID() != MATERIAL_CLASS_ID )
return;
plPassMtlBase *mtl = (plPassMtlBase *)owner;
IParamBlock2 *pb = mtl->fAnimPB;
// A stealth node paramBlock value just got set. First make sure we
// un-set the old stealth's parent
ISetParent( pb->GetReferenceTarget( id, tabIndex ), nil );
// So make sure that the stealth node that was just added gets its parent mtl set properly
ISetParent( v.r, mtl );
}

View File

@ -0,0 +1,263 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plAnimStealthNode - Stealthy hidden INode that represents a single //
// segment's worth of animation info for a material. //
// Stored as an INode so they can be "selected" //
// by components as targets of animation messages. //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plAnimStealthNode_h
#define _plAnimStealthNode_h
#include "Max.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "hsTypes.h"
#include "../pnKeyedObject/plKey.h"
#include "../MaxComponent/plAnimObjInterface.h"
#include "../MaxComponent/plMaxAnimUtils.h"
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
#define ANIMSTEALTH_CLASSID Class_ID(0xd0272f8, 0x750349c9)
#define REFMSG_NOTETRACK_ADDED REFMSG_USER + 1
class plPassMtlBase;
class NoteTrack;
class plMaxNode;
class plErrorMsg;
class plAnimTimeConvert;
//// Class Def ///////////////////////////////////////////////////////////////
class plAnimStealthNode : public HelperObject, public plAnimObjInterface
{
protected:
ClassDesc2 *fClassDesc;
IParamBlock2 *fParamBlock;
plPassMtlBase *fParentMtl;
static ParamBlockDesc2 sAnimStealthPB;
hsBool fPreppedForConvert;
SegmentMap *fCachedSegMap;
SegmentSpec *IGetSegmentSpec( void ) const;
public:
// Some IDs
enum
{
kBlockPB = 0
};
enum Refs
{
kRefParamBlock,
kRefParentMtl
};
// ParamBlock IDs
enum ParamBlockIDs
{
kPBAutoStart, // Start the Animation on load (V2)
kPBLoop, // Start Looping at Begin Location
kPBName, // Name of the notetrack animation to play
kPBLoopName, // Name of the notetrack specified loop
kPBEaseInType,
kPBEaseOutType,
kPBEaseInLength,
kPBEaseOutLength,
kPBEaseInMin,
kPBEaseInMax,
kPBEaseOutMin,
kPBEaseOutMax
};
plAnimStealthNode( BOOL loading );
virtual ~plAnimStealthNode();
void DeleteThis() { delete this; }
INode *GetINode( void );
plPassMtlBase *GetParentMtl( void );
void SetParentMtl( plPassMtlBase *parent );
void SetNodeName( const char *parentName );
// Create the dialog for this object and place it inside the given dialog, centering it in the given control if any
bool CreateAndEmbedDlg( IParamMap2 *parentMap, IMtlParams *parentParams, HWND frameCtrl = nil );
// Release said dialog
void ReleaseDlg( void );
// Switch underlying objects in the dialog (to avoid unnecessary deletion/recreations)
void SwitchDlg( plAnimStealthNode *toSwitchTo );
// Get the actual window handle of the currently active dialog displaying us
HWND GetWinDlg( void ) const;
// Interesting functions
const char *GetSegmentName( void ) const;
void SetSegment( const char *name ); // nil for "entire animation"
// Conversion from stealth's INode to the actual object
static bool CanConvertToStealth( INode *objNode );
static plAnimStealthNode *ConvertToStealth( INode *objNode );
///////////////////////////////////////////////////////////////////////////////////////
// Required Max functions
//
TCHAR* GetObjectName() { return (TCHAR*)fClassDesc->ClassName(); }
void InitNodeName(TSTR& s) { s = fClassDesc->InternalName(); }
void GetClassName(TSTR& s) { s = fClassDesc->ClassName(); }
Class_ID ClassID() { return ANIMSTEALTH_CLASSID; }
RefTargetHandle Clone(RemapDir &remap);
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
RefResult NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget, PartID& partID, RefMessage message);
// allow retreival of our paramblock from other plug-ins
// and the max core
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
// We override because we don't want to be able to animate this sucker
int NumSubs() { return 0; }
Animatable *SubAnim( int i ) { return nil; }
TSTR SubAnimName( int i ) { return fClassDesc->ClassName(); }
// plug-in mouse creation callback
CreateMouseCallBack* GetCreateMouseCallBack();
void BeginEditParams(IObjParam *ip, ULONG flags, Animatable *prev);
void EndEditParams(IObjParam *ip, ULONG flags, Animatable *next);
// void SelectionSetChanged(Interface *ip, IUtil *iu);
void BuildMesh(TimeValue t);
void FreeCaches();
void GetLocalBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box);
void GetWorldBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box);
int Display(TimeValue t, INode *node, ViewExp *vpt, int flags);
int HitTest(TimeValue t, INode *node, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt);
ObjectState Eval(TimeValue t) { return ObjectState(this); }
IOResult Save(ISave* isave);
IOResult Load(ILoad* iload);
int CanConvertToType( Class_ID obtype ) { return ( obtype == ANIMSTEALTH_CLASSID ) ? 1 : 0; }
const char *GetCategory() { return fClassDesc->Category(); }
/// Parameter access
bool GetAutoStart( void ) const;
void SetAutoStart( bool b );
bool GetLoop( void ) const;
const char *GetLoopName( void ) const;
void SetLoop( bool b, const char *name );
UInt8 GetEaseInType( void ) const;
hsScalar GetEaseInLength( void ) const;
hsScalar GetEaseInMin( void ) const;
hsScalar GetEaseInMax( void ) const;
void SetEaseIn( UInt8 type, hsScalar length, hsScalar min, hsScalar max );
UInt8 GetEaseOutType( void ) const;
hsScalar GetEaseOutLength( void ) const;
hsScalar GetEaseOutMin( void ) const;
hsScalar GetEaseOutMax( void ) const;
void SetEaseOut( UInt8 type, hsScalar length, hsScalar min, hsScalar max );
// Conversion stuff
void GetAllStopPoints( hsTArray<hsScalar> &out );
hsScalar GetSegStart( void ) const;
hsScalar GetSegEnd( void ) const;
void GetLoopPoints( hsScalar &start, hsScalar &end ) const;
void StuffToTimeConvert( plAnimTimeConvert &convert, hsScalar maxLength );
// plAnimObjInterface functions
virtual void PickTargetNode( IParamBlock2 *destPB, ParamID destParamID, ParamID typeID );
virtual hsBool IsNodeRestricted( void ) { return true; }
virtual const char *GetIfaceSegmentName( hsBool allowNil );
virtual hsBool GetKeyList( INode *restrictedNode, hsTArray<plKey> &outKeys );
virtual hsBool MightRequireSeparateMaterial( void ) { return true; }
// Convert time, called on the setupProps pass for each material applied to a node in the scene
virtual hsBool SetupProperties( plMaxNode *node, plErrorMsg *pErrMsg );
virtual hsBool ConvertDeInit( plMaxNode *node, plErrorMsg *pErrMsg );
// Returns true if the parent material is applied to any node in the scene, false otherwise
hsBool IsParentUsedInScene( void );
};
//// Accessor for Parent's ParamBlock ////////////////////////////////////////
class plStealthNodeAccessor : public PBAccessor
{
protected:
void ISetParent( ReferenceTarget *target, plPassMtlBase *parent );
void IHandleSet( PB2Value &v, ReferenceMaker *owner, ParamID id, int tabIndex, TimeValue t );
public:
plStealthNodeAccessor() { }
static plStealthNodeAccessor &GetInstance( void );
virtual void Set( PB2Value &v, ReferenceMaker *owner, ParamID id, int tabIndex, TimeValue t );
virtual void TabChanged( tab_changes changeCode, Tab<PB2Value> *tab, ReferenceMaker *owner,
ParamID id, int tabIndex, int count );
};
#endif //_plAnimStealthNode_h

View File

@ -0,0 +1,676 @@
/*==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 "hsTypes.h"
#include "plBumpMtl.h"
#include "resource.h"
//extern ClassDesc2* GetMaxLayerDesc();
#include "Shaders.h"
#include "plBumpMtlBasicPB.h"
#include "iparamm2.h"
#include "Layers/plLayerTex.h"
#include "Layers/plStaticEnvLayer.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
extern HINSTANCE hInstance;
class plBumpMtlClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading) { return TRACKED_NEW plBumpMtl(loading); }
const TCHAR* ClassName() { return GetString(IDS_BUMP_MTL); }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
Class_ID ClassID() { return BUMP_MTL_CLASS_ID; }
const TCHAR* Category() { return NULL; }
const TCHAR* InternalName() { return _T("PlasmaMaterial"); }
HINSTANCE HInstance() { return hInstance; }
};
static plBumpMtlClassDesc plBumpMtlDesc;
ClassDesc2* GetBumpMtlDesc() { return &plBumpMtlDesc; }
// For initializing paramblock descriptor
ParamBlockDesc2 *GetBumpBasicPB();
ParamBlockDesc2 *GetBumpLayersPB();
#include "plBumpMtlBasicPBDec.h"
#include "plBumpMtlAnimPBDec.h"
plBumpMtl::plBumpMtl(BOOL loading) : plPassMtlBase( loading )
{
plBumpMtlDesc.MakeAutoParamBlocks( this );
fBasicPB->SetValue( kBumpBasLayer, 0, TRACKED_NEW plLayerTex );
// If we do this later (like, when the dialog loads) something blows up,
// somewhere in Max. It didn't in 4, it does in 7. This seems to fix it.
if (!loading)
IVerifyStealthPresent(ENTIRE_ANIMATION_NAME);
}
ParamDlg* plBumpMtl::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
fIMtlParams = imp;
IAutoMParamDlg* masterDlg = plBumpMtlDesc.CreateParamDlgs(hwMtlEdit, imp, this);
return (ParamDlg*)masterDlg;
}
BOOL plBumpMtl::SetDlgThing(ParamDlg* dlg)
{
return FALSE;
}
Interval plBumpMtl::Validity(TimeValue t)
{
#if 0 // mf horse
Interval valid = FOREVER;
/* for (int i = 0; i < fSubTexmap.Count(); i++)
{
if (fSubTexmap[i])
valid &= fSubTexmap[i]->Validity(t);
}
*/
// float u;
// fPBlock->GetValue(pb_spin,t,u,valid);
return valid;
#else // mf horse
const char* name = GetName();
// mf horse - Hacking in something like real validity checking
// to get material animations working. No warranty, this is just
// better than nothing.
Interval v = FOREVER;
fBasicPB->GetValidity(t, v);
if( fBasicPB->GetTexmap(kBumpBasLayer) )
v &= fBasicPB->GetTexmap(kBumpBasLayer)->Validity(t);
return v;
#endif // mf horse
}
//// GetReference ////////////////////////////////////////////////////////////
// Note: need to overload because MAX for some reason writes out the
// references by their INDEX. ARRRRGH!
RefTargetHandle plBumpMtl::GetReference( int i )
{
switch( i )
{
case kRefBasic: return fBasicPB;
case kRefAnim: return fAnimPB;
}
return plPassMtlBase::GetReference( i );
}
//// SetReference ////////////////////////////////////////////////////////////
// Note: need to overload because MAX for some reason writes out the
// references by their INDEX. ARRRRGH!
void plBumpMtl::SetReference(int i, RefTargetHandle rtarg)
{
if (i == kRefBasic)
fBasicPB = (IParamBlock2 *)rtarg;
else if (i == kRefAnim)
fAnimPB = (IParamBlock2 *)rtarg;
else
plPassMtlBase::SetReference( i, rtarg );
}
/*===========================================================================*\
| Subanim & References support
\*===========================================================================*/
int plBumpMtl::NumSubs()
{
return 3;
}
TSTR plBumpMtl::SubAnimName(int i)
{
switch (i)
{
case 0: return fBasicPB->GetLocalName();
case 1: return fAnimPB->GetLocalName();
case 2: return "Base Layer";
}
return "";
}
Animatable* plBumpMtl::SubAnim(int i)
{
switch (i)
{
case 0: return fBasicPB;
case 1: return fAnimPB;
case 2: return fBasicPB->GetTexmap(kBumpBasLayer);
break;
}
return NULL;
}
int plBumpMtl::NumParamBlocks()
{
return 2;
}
IParamBlock2* plBumpMtl::GetParamBlock(int i)
{
return (IParamBlock2*)GetReference(i);
}
IParamBlock2* plBumpMtl::GetParamBlockByID(BlockID id)
{
if (fBasicPB->ID() == id)
return fBasicPB;
else if (fAnimPB->ID() == id)
return fAnimPB;
return NULL;
}
RefResult plBumpMtl::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message)
{
return plPassMtlBase::NotifyRefChanged( changeInt, hTarget, partID, message );
}
////////////////////////////////////////////////////////////////////////////////
// Subtexmap access
int plBumpMtl::NumSubTexmaps()
{
return 1;
}
Texmap* plBumpMtl::GetSubTexmap(int i)
{
if (i == 0)
return fBasicPB->GetTexmap(kBumpBasLayer);
return NULL;
}
void plBumpMtl::SetSubTexmap(int i, Texmap *m)
{
if (i == 0)
fBasicPB->SetValue(kBumpBasLayer, 0, m);
}
TSTR plBumpMtl::GetSubTexmapSlotName(int i)
{
if (i == 0)
return "Base";
return "";
}
TSTR plBumpMtl::GetSubTexmapTVName(int i)
{
return GetSubTexmapSlotName(i);
}
/*===========================================================================*\
| Updating and cloning
\*===========================================================================*/
RefTargetHandle plBumpMtl::Clone(RemapDir &remap)
{
plBumpMtl *mnew = TRACKED_NEW plBumpMtl(FALSE);
plPassMtlBase::ICloneBase( mnew, remap );
return (RefTargetHandle)mnew;
}
void plBumpMtl::ICloneRefs( plPassMtlBase *target, RemapDir &remap )
{
target->ReplaceReference(kRefBasic, remap.CloneRef(fBasicPB));
target->ReplaceReference(kRefAnim, remap.CloneRef(fAnimPB));
}
void plBumpMtl::NotifyChanged()
{
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
}
void plBumpMtl::Update(TimeValue t, Interval& valid)
{
// mf horse - Hacking in something like real validity checking
// to get material animations working. No warranty, this is just
// better than nothing.
if (!fIValid.InInterval(t))
{
fIValid.SetInfinite();
if( fBasicPB->GetTexmap(kBumpBasLayer) )
fBasicPB->GetTexmap(kBumpBasLayer)->Update(t, fIValid);
// fLayersPB->GetValue(kMtlLayLayer1On, t, fMapOn[0], fIValid);
/*
for (int i = 0; i < fSubTexmap.Count(); i++)
{
if (fSubTexmap[i])
fSubTexmap[i]->Update(t,fIValid);
}
*/
}
valid &= fIValid;
}
/*===========================================================================*\
| Determine the characteristics of the material
\*===========================================================================*/
void plBumpMtl::SetAmbient(Color c, TimeValue t) {}
void plBumpMtl::SetDiffuse(Color c, TimeValue t) {}
void plBumpMtl::SetSpecular(Color c, TimeValue t) {}
void plBumpMtl::SetShininess(float v, TimeValue t) {}
Color plBumpMtl::GetAmbient(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plBumpMtl::GetDiffuse(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plBumpMtl::GetSpecular(int mtlNum, BOOL backFace) { return Color(0,0,0); }
float plBumpMtl::GetXParency(int mtlNum, BOOL backFace)
{
return 0.f;
}
float plBumpMtl::GetShininess(int mtlNum, BOOL backFace) { return 0.0f; }
float plBumpMtl::GetShinStr(int mtlNum, BOOL backFace) { return 0.0f; }
float plBumpMtl::WireSize(int mtlNum, BOOL backFace) { return 0.0f; }
/////////////////////////////////////////////////////////////////
void plBumpMtl::SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb)
{
#if 0
if (texHandleValid.InInterval(t)) {
mtl->texture.SetCount(numTexHandlesUsed);
for (int i=0; i<numTexHandlesUsed; i++) {
if (texHandle[i]) {
mtl->texture[i].textHandle = texHandle[i]->GetHandle();
Texmap *tx = (*maps)[useSubForTex[i]].map;
cb.GetGfxTexInfoFromTexmap(t, mtl->texture[i], tx );
SetTexOps(mtl,i,texOpsType[i]);
}
}
return;
}
#endif
#if 0 // WTF?!?!?!?
Texmap *tx[2];
int diffChan = stdIDToChannel[ ID_DI ];
int opacChan = stdIDToChannel[ ID_OP ];
tx[0] = (*maps)[diffChan].IsActive()?(*maps)[diffChan].map:NULL;
tx[1] = (*maps)[opacChan].IsActive()?(*maps)[opacChan].map:NULL;
#endif
int nsupport = cb.NumberTexturesSupported();
#if 0
BITMAPINFO *bmi[NTEXHANDLES];
int nmaps=0;
for (int i=0; i<NTEXHANDLES; i++) {
if (tx[i]) nmaps ++;
bmi[i] = NULL;
}
mtl->texture.SetCount(nmaps);
if (nmaps==0)
return;
for (i=0; i<nmaps; i++)
mtl->texture[i].textHandle = NULL;
texHandleValid.SetInfinite();
Interval valid;
BOOL needDecal = FALSE;
int ntx = 0;
int op;
int forceW = 0;
int forceH = 0;
if (tx[0]) {
cb.GetGfxTexInfoFromTexmap(t, mtl->texture[0], tx[0]);
TextureInfo &ti = mtl->texture[0];
if (ti.tiling[0]==GW_TEX_NO_TILING||ti.tiling[1]==GW_TEX_NO_TILING)
needDecal = TRUE;
op = needDecal?TXOP_ALPHABLEND:TXOP_MODULATE;
bmi[0] = tx[0]->GetVPDisplayDIB(t,cb,valid,FALSE);
if (bmi[0]) {
texHandleValid &= valid;
useSubForTex[0] = diffChan;
ntx = 1;
forceW = bmi[0]->bmiHeader.biWidth;
forceH = bmi[0]->bmiHeader.biHeight;
}
}
if (tx[1]) {
cb.GetGfxTexInfoFromTexmap(t, mtl->texture[ntx], tx[1]);
if (nsupport>ntx) {
bmi[1] = tx[1]->GetVPDisplayDIB(t,cb,valid,TRUE);
if (bmi[1]) {
texHandleValid &= valid;
StuffAlpha(bmi[1], (*maps)[opacChan].amount, GetOpacity(t),ntx?whiteCol:pShader->GetDiffuseClr(t));
texHandle[ntx] = cb.MakeHandle(bmi[1]);
bmi[1] = NULL;
mtl->texture[ntx].textHandle = texHandle[ntx]->GetHandle();
SetTexOps(mtl,ntx,TXOP_OPACITY);
useSubForTex[ntx] = opacChan;
ntx++;
}
}
else {
if (!needDecal) {
TextureInfo ti;
// if (SameUV(mtl->texture[0],mtl->texture[1])) {
// Not really correct to combine channels for different UV's but what the heck.
bmi[1] = tx[1]->GetVPDisplayDIB(t,cb,valid,TRUE, forceW, forceH);
if (bmi[1]) {
texHandleValid &= valid;
StuffAlphaInto(bmi[1], bmi[0], (*maps)[opacChan].amount, GetOpacity(t));
op = TXOP_OPACITY;
free(bmi[1]);
bmi[1] = NULL;
}
// }
}
}
}
if (bmi[0]) {
texHandle[0] = cb.MakeHandle(bmi[0]);
bmi[0] = NULL;
mtl->texture[0].textHandle = texHandle[0]->GetHandle();
SetTexOps(mtl,0,op);
}
mtl->texture.SetCount(ntx);
numTexHandlesUsed = ntx;
#endif
}
/*===========================================================================*\
| Actual shading takes place
\*===========================================================================*/
void plBumpMtl::GetInterpVtxValue(int channel, ShadeContext &sc, Point3 &val)
{
Mesh *mesh = sc.globContext->GetRenderInstance(sc.NodeID())->mesh;
if (mesh != nil)
{
Face *maxFace = &mesh->faces[ sc.FaceNumber() ];
UVVert *map = mesh->mapVerts(channel);
if (map != nil)
{
Point3 p0 = map[maxFace->getVert( 0 )];
Point3 p1 = map[maxFace->getVert( 1 )];
Point3 p2 = map[maxFace->getVert( 2 )];
Point3 interp = sc.BarycentricCoords();
val.x = interp.x * p0.x + interp.y * p1.x + interp.z * p2.x;
val.y = interp.x * p0.y + interp.y * p1.y + interp.z * p2.y;
val.z = interp.x * p0.z + interp.y * p1.z + interp.z * p2.z;
return;
}
}
// No value defined... set default.
if (channel == MAP_SHADING)
val.x = val.y = val.z = 0.0f;
else
val.x = val.y = val.z = 1.0f;
}
void plBumpMtl::Shade(ShadeContext& sc)
{
// Get the background color
Color backColor, backTrans;
sc.GetBGColor(backColor, backTrans);
ShadeWithBackground(sc, backColor);
}
//// Requirements ////////////////////////////////////////////////////////////
// Tells MAX what we need to render ourselves properly, such as translucency,
// two-sidedness, etc. Flags are in imtl.h in the MAX SDK.
ULONG plBumpMtl::Requirements( int subMtlNum )
{
ULONG req = 0;
req = Mtl::Requirements( subMtlNum );
// Uncomment this to get the background color fed to our ShadeWithBackground()
// (slower processing tho)
//req |= MTLREQ_BGCOL;
req |= MTLREQ_UV;
req |= MTLREQ_TRANSP;
if (req & MTLREQ_FACEMAP)
{
int i = 0;
}
return req;
}
void plBumpMtl::ShadeWithBackground(ShadeContext &sc, Color background, bool useVtxAlpha /* = true */)
{
#if 1
// old
#if 0
Color lightCol,rescol, diffIllum0;
RGBA mval;
Point3 N0,P;
BOOL bumped = FALSE;
int i;
if (gbufID)
sc.SetGBufferID(gbufID);
if (sc.mode == SCMODE_SHADOW) {
float opac = 0.0;
for (i=0; i < NumSubTexmaps(); i++) {
if (SubTexmapOn(i)) {
hsMaxLayerBase *hsmLay = (hsMaxLayerBase *)GetSubTexmap(i);
opac += hsmLay->GetOpacity(t);
}
}
float f = 1.0f - opac;
sc.out.t = Color(f,f,f);
return;
}
N0 = sc.Normal();
P = sc.P();
#endif
TimeValue t = sc.CurTime();
Color color(0, 0, 0);
float alpha = 0.0;
// Evaluate Base layer
Texmap *map = fBasicPB->GetTexmap(kBumpBasLayer);
if (map && ( map->ClassID() == LAYER_TEX_CLASS_ID
|| map->ClassID() == STATIC_ENV_LAYER_CLASS_ID ) )
{
plLayerTex *layer = (plLayerTex*)map;
AColor evalColor = layer->EvalColor(sc);
color = evalColor;
alpha = evalColor.a;
}
#if 1
AColor black;
black.Black();
AColor white;
white.White();
SIllumParams ip;
//
// Shading setup
//
// Setup the parameters for the shader
ip.amb = black;
ip.diff = white;
ip.diffIllum = black;
ip.specIllum = black;
ip.N = sc.Normal();
ip.V = sc.V();
//
// Specularity
//
ip.spec = black;
ip.sh_str = 0;
ip.ph_exp = 0;
ip.shine = 0;
ip.softThresh = 0;
//
// Do the shading
Shader *myShader = GetShader(SHADER_BLINN);
myShader->Illum(sc, ip);
ip.diffIllum.ClampMinMax();
ip.specIllum.ClampMinMax();
ip.diffIllum = ip.amb * sc.ambientLight + ip.diff * ip.diffIllum;
// AColor returnColor = AColor(opac * ip.diffIllum + ip.specIllum, opac)
#endif
float vtxAlpha = 1.0f;
if (useVtxAlpha && GetOutputBlend() == plPassMtlBase::kBlendAlpha)
{
Point3 p;
GetInterpVtxValue(MAP_ALPHA, sc, p);
vtxAlpha = p.x;
}
alpha *= vtxAlpha;
// MAX will do the additive/alpha/no blending for us based on what Requirements()
// we tell it. However, since MAX's formula is bgnd*sc.out.t + sc.out.c,
// we have to multiply our output color by the alpha.
// If we ever need a more complicated blending function, you can request the
// background color via Requirements() (otherwise it's just black) and then do
// the blending yourself; however, if the transparency isn't set, the shadows
// will be opaque, so be careful.
Color outC = ip.diffIllum + ip.specIllum;
sc.out.c = ( outC * alpha );
sc.out.t = Color( 1.f - alpha, 1.f - alpha, 1.f - alpha );
#endif
}
float plBumpMtl::EvalDisplacement(ShadeContext& sc)
{
return 0.0f;
}
Interval plBumpMtl::DisplacementValidity(TimeValue t)
{
Interval iv;
iv.SetInfinite();
return iv;
}
bool plBumpMtl::HasAlpha()
{
return ((plLayerTex *)fBasicPB->GetTexmap(kBumpBasLayer))->HasAlpha();
}
// Massive list of inherited accessor functions for ParamBlock data
// Advanced Block
int plBumpMtl::GetBasicWire() { return 0; }
int plBumpMtl::GetMeshOutlines() { return 0; }
int plBumpMtl::GetTwoSided() { return 0; }
int plBumpMtl::GetSoftShadow() { return 0; }
int plBumpMtl::GetNoProj() { return 0; }
int plBumpMtl::GetVertexShade() { return 0; }
int plBumpMtl::GetNoShade() { return 0; }
int plBumpMtl::GetNoFog() { return 0; }
int plBumpMtl::GetWhite() { return 0; }
int plBumpMtl::GetZOnly() { return 0; }
int plBumpMtl::GetZClear() { return 0; }
int plBumpMtl::GetZNoRead() { return 0; }
int plBumpMtl::GetZNoWrite() { return 0; }
int plBumpMtl::GetZInc() { return 0; }
int plBumpMtl::GetAlphaTestHigh() { return 0; }
// Animation block
char * plBumpMtl::GetAnimName() { return fAnimPB->GetStr(kPBAnimName); }
int plBumpMtl::GetAutoStart() { return fAnimPB->GetInt(kPBAnimAutoStart); }
int plBumpMtl::GetLoop() { return fAnimPB->GetInt(kPBAnimLoop); }
char * plBumpMtl::GetAnimLoopName() { return fAnimPB->GetStr(kPBAnimLoopName); }
// Basic block
int plBumpMtl::GetColorLock() { return 0; }
Color plBumpMtl::GetAmbColor() { return Color(0,0,0); }
Color plBumpMtl::GetColor() { return Color(0,0,0); }
int plBumpMtl::GetOpacity() { return 100; }
int plBumpMtl::GetEmissive() { return 0; }
int plBumpMtl::GetUseSpec() { return 0; }
int plBumpMtl::GetShine() { return 0; }
Color plBumpMtl::GetSpecularColor() { return Color(0,0,0); }
int plBumpMtl::GetDiffuseColorLock() { return 0; }
Color plBumpMtl::GetRuntimeColor() { return fBasicPB->GetColor(kBumpBasRunColor); }
Control *plBumpMtl::GetPreshadeColorController() { return nil; }
Control *plBumpMtl::GetAmbColorController() { return nil; }
Control *plBumpMtl::GetOpacityController() { return nil; }
Control *plBumpMtl::GetSpecularColorController() { return nil; }
Control *plBumpMtl::GetRuntimeColorController() { return fBasicPB->GetController(ParamID(kBumpBasRunColor)); }
// Layer block
Texmap *plBumpMtl::GetBaseLayer() { return fBasicPB->GetTexmap(kBumpBasLayer); }
int plBumpMtl::GetTopLayerOn() { return 0; }
Texmap *plBumpMtl::GetTopLayer() { return nil; }
int plBumpMtl::GetLayerBlend() { return 0; }
int plBumpMtl::GetOutputAlpha() { return 0; }
int plBumpMtl::GetOutputBlend() { return fBasicPB->GetInt( kBumpBasSpecular ) ? plPassMtlBase::kBlendAdd : plPassMtlBase::kBlendAlpha; }

View File

@ -0,0 +1,194 @@
/*==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==*/
#ifndef PL_BUMPMTL_H
#define PL_BUMPMTL_H
#include "Max.h"
#include "iparamb2.h"
#include "../resource.h"
#include "plPassMtlBase.h"
#define BUMP_MTL_CLASS_ID Class_ID(0x4dbf7b0a, 0x92226de)
extern TCHAR *GetString(int id);
class plBumpMtl : public plPassMtlBase
{
protected:
virtual void ICloneRefs( plPassMtlBase *target, RemapDir &remap );
public:
enum RefIDs
{
kRefBasic,
kRefAnim,
};
enum BlockIDs
{
kBlkBasic,
kBlkAnim,
};
plBumpMtl(BOOL loading);
void DeleteThis() { delete this; }
//From Animatable
Class_ID ClassID() { return BUMP_MTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_BUMP_MTL); }
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void NotifyChanged();
BOOL SupportsMultiMapsInViewport() { return FALSE; }
void SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb);
// Shade and displacement calculation
static void GetInterpVtxValue(int channel, ShadeContext &sc, Point3 &interpVal);
void Shade(ShadeContext& sc);
void ShadeWithBackground(ShadeContext &sc, Color background, bool useVtxAlpha = true);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
virtual RefTargetHandle GetReference( int i );
virtual void SetReference( int i, RefTargetHandle rtarg );
// SubTexmap access methods
int NumSubTexmaps();
Texmap* GetSubTexmap(int i);
void SetSubTexmap(int i, Texmap *m);
TSTR GetSubTexmapSlotName(int i);
TSTR GetSubTexmapTVName(int i);
BOOL SetDlgThing(ParamDlg* dlg);
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
// void SetParamDlg(ParamDlg *dlg);
// void SetNumSubTexmaps(int num);
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
ULONG Requirements( int subMtlNum );
virtual bool HasAlpha();
// Massive list of inherited accessor functions for ParamBlock data
// Advanced Block
virtual int GetBasicWire();
virtual int GetMeshOutlines();
virtual int GetTwoSided();
virtual int GetSoftShadow();
virtual int GetNoProj();
virtual int GetVertexShade();
virtual int GetNoShade();
virtual int GetNoFog();
virtual int GetWhite();
virtual int GetZOnly();
virtual int GetZClear();
virtual int GetZNoRead();
virtual int GetZNoWrite();
virtual int GetZInc();
virtual int GetAlphaTestHigh();
// Animation block
virtual char * GetAnimName();
virtual int GetAutoStart();
virtual int GetLoop();
virtual char * GetAnimLoopName();
// Basic block
virtual int GetColorLock();
virtual Color GetAmbColor();
virtual Color GetColor();
virtual int GetOpacity();
virtual int GetEmissive();
virtual int GetUseSpec();
virtual int GetShine();
virtual Color GetSpecularColor();
virtual Control *GetPreshadeColorController();
virtual Control *GetAmbColorController();
virtual Control *GetOpacityController();
virtual Control *GetSpecularColorController();
virtual int GetDiffuseColorLock();
virtual Color GetRuntimeColor();
virtual Control *GetRuntimeColorController();
// Layer block
virtual Texmap *GetBaseLayer();
virtual int GetTopLayerOn();
virtual Texmap *GetTopLayer();
virtual int GetLayerBlend();
virtual int GetOutputAlpha();
virtual int GetOutputBlend();
};
#endif //PL_BUMPMTL_H

View File

@ -0,0 +1,53 @@
/*==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==*/
#ifndef PL_BUMPMTLANIMPB_H
#define PL_BUMPMTLANIMPB_H
enum
{
kBumpAnimName,
kBumpAnimAutoStart,
kBumpAnimLoop,
kBumpAnimLoopName,
};
#endif

View File

@ -0,0 +1,109 @@
/*==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 "plBumpMtl.h"
#include "plPassBaseParamIDs.h"
#include "resource.h"
#include "iparamm2.h"
#include "plPassAnimDlgProc.h"
#include "plAnimStealthNode.h"
using namespace plPassBaseParamIDs;
static ParamBlockDesc2 gBumpAnimPB
(
plBumpMtl::kBlkAnim, _T("anim"), IDS_PASS_ANIM, GetBumpMtlDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI + P_CALLSETS_ON_LOAD, plBumpMtl::kRefAnim,
// UI
IDD_PASS_ANIM, IDS_PASS_ANIM, 0, 0, &plPassAnimDlgProc::Get(),
#ifdef MCN_UPGRADE_OLD_ANIM_BLOCKS
// THE FOLLOWING ARE ALL OLD PARAMETERS AND SHOULD NO LONGER BE USED. The only reason
// they're here is so we can convert old paramBlocks into the new plAnimStealthNode format
kPBAnimName, _T("animName"), TYPE_STRING, 0, 0,
end,
kPBAnimAutoStart, _T("autoStart"), TYPE_BOOL, 0, 0,
end,
kPBAnimLoop, _T("loop"), TYPE_BOOL, 0, 0,
end,
kPBAnimLoopName, _T("loopName"), TYPE_STRING, 0, 0,
end,
// Anim Ease
kPBAnimEaseInType, _T("easeInType"), TYPE_INT, 0, 0,
end,
kPBAnimEaseInLength, _T("easeInLength"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseInMin, _T("easeInMin"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseInMax, _T("easeInMax"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutType, _T("easeOutType"), TYPE_INT, 0, 0,
end,
kPBAnimEaseOutLength, _T("easeOutLength"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutMin, _T("easeOutMin"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutMax, _T("easeOutMax"), TYPE_FLOAT, 0, 0,
end,
#endif // MCN_UPGRADE_OLD_ANIM_BLOCKS
kPBAnimUseGlobal, _T("UseGlobal"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_MTL_USE_GLOBAL,
end,
kPBAnimGlobalName, _T("GlobalName"), TYPE_STRING, 0, 0,
p_default, _T(""),
end,
kPBAnimStealthNodes, _T( "testing" ), TYPE_REFTARG_TAB, 0, 0, 0,
p_accessor, &plStealthNodeAccessor::GetInstance(),
end,
end
);
ParamBlockDesc2 *GetBumpAnimPB() { return &gBumpAnimPB; }

View File

@ -0,0 +1,54 @@
/*==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==*/
#ifndef PL_BUMPMTLBASICPB_H
#define PL_BUMPMTLBASICPB_H
// Param ID's
enum
{
kBumpBasSpecular,
kBumpBasRunColor,
kBumpBasLayer
};
#endif //PL_BUMPMTLBASICPB_H

View File

@ -0,0 +1,108 @@
/*==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 "plBumpMtl.h"
#include "plBumpMtlBasicPB.h"
#include "resource.h"
#include "iparamm2.h"
class BumpBasicDlgProc;
extern BumpBasicDlgProc gBumpBasicDlgProc;
static ParamBlockDesc2 gBumpBasicPB
(
plBumpMtl::kBlkBasic, _T("basic"), IDS_PASS_BASIC, GetBumpMtlDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI, plBumpMtl::kRefBasic,
// UI
IDD_BUMP_BASIC, IDS_PASS_BASIC, 0, 0, &gBumpBasicDlgProc,
kBumpBasLayer, _T("bumpLayer"), TYPE_TEXMAP, 0, IDS_BASIC_AMB,
p_ui, TYPE_TEXMAPBUTTON, IDC_LAYER1,
p_subtexno, 0,
end,
kBumpBasRunColor, _T("runtimeColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_RUNCOLOR,
// p_ui, TYPE_COLORSWATCH, IDC_LAYER_RUNCOLOR,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_INTEN_EDIT, IDC_INTEN_SPIN,
IDC_DUMMY_EDIT1, IDC_DUMMY_SPIN1, IDC_DUMMY_EDIT2, IDC_DUMMY_SPIN2,
SPIN_AUTOSCALE,
p_default, Color(1,0,0),
end,
// Specularity
kBumpBasSpecular, _T("useSpec"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_SPECULAR,
end,
end
);
ParamBlockDesc2 *GetBumpBasicPB() { return &gBumpBasicPB; }
class BumpBasicDlgProc : public ParamMap2UserDlgProc
{
#if 1
protected:
public:
BumpBasicDlgProc() {}
~BumpBasicDlgProc() { }
#endif
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
IParamBlock2 *pb = map->GetParamBlock();
switch (msg)
{
case WM_INITDIALOG:
{
}
return TRUE;
}
return FALSE;
}
void DeleteThis() {}
};
static BumpBasicDlgProc gBumpBasicDlgProc;

View File

@ -0,0 +1,715 @@
/*==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 "hsUtils.h"
#include "plClothingMtl.h"
#include "resource.h"
#include "Shaders.h"
#include "iparamm2.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "plBMSampler.h"
#include "stdmat.h"
#include "Layers/plLayerTex.h"
#include "Layers/plLayerTexBitmapPB.h"
#include "../../Plasma/PubUtilLib/plAvatar/plClothingLayout.h"
extern HINSTANCE hInstance;
class plClothingMtlClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading) { return TRACKED_NEW plClothingMtl(loading); }
const TCHAR* ClassName() { return GetString(IDS_CLOTHING_MTL); }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
Class_ID ClassID() { return CLOTHING_MTL_CLASS_ID; }
const TCHAR* Category() { return NULL; }
const TCHAR* InternalName() { return _T("ClothingMaterial"); }
HINSTANCE HInstance() { return hInstance; }
};
static plClothingMtlClassDesc plClothingMtlDesc;
ClassDesc2* GetClothingMtlDesc() { return &plClothingMtlDesc; }
// For initializing paramblock descriptor
ParamBlockDesc2 *GetClothingPB();
#include "plClothingMtlPBDec.h"
const UINT32 plClothingMtl::ButtonConstants[] =
{
IDC_CLOTHING_TEXTURE1,
IDC_CLOTHING_TEXTURE2,
IDC_CLOTHING_TEXTURE3,
IDC_CLOTHING_TEXTURE4
};
const UINT32 plClothingMtl::TextConstants[] =
{
IDC_CLOTHING_TILE1_NAME,
IDC_CLOTHING_TILE1_SIZE,
IDC_CLOTHING_TILE2_NAME,
IDC_CLOTHING_TILE2_SIZE,
IDC_CLOTHING_TILE3_NAME,
IDC_CLOTHING_TILE3_SIZE,
IDC_CLOTHING_TILE4_NAME,
IDC_CLOTHING_TILE4_SIZE
};
const char *plClothingMtl::LayerStrings[] =
{
"Base",
"Skin",
"Skin Blend (1)",
"Skin Blend (2)",
"Skin Blend (3)",
"Skin Blend (4)",
"Skin Blend (5)",
"Skin Blend (6)",
"Tint 1",
"Tint 2"
};
const UInt8 plClothingMtl::LayerToPBIdx[] =
{
kTexmapBase,
kTexmapSkin,
kTexmapSkinBlend1,
kTexmapSkinBlend2,
kTexmapSkinBlend3,
kTexmapSkinBlend4,
kTexmapSkinBlend5,
kTexmapSkinBlend6,
kTexmap,
kTexmap2
};
plClothingMtl::plClothingMtl(BOOL loading) : fBasicPB(NULL)
{
plClothingMtlDesc.MakeAutoParamBlocks(this);
Reset();
int i;
for (i = 0; i < plClothingMtl::kMaxTiles; i++)
{
plLayerTex *tex = TRACKED_NEW plLayerTex;
fBasicPB->SetValue(ParamID(kTexmap), 0, tex, i);
}
fBasicPB->SetValue(ParamID(kThumbnail), 0, TRACKED_NEW plLayerTex);
}
void plClothingMtl::Reset()
{
fIValid.SetEmpty();
}
ParamDlg* plClothingMtl::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
fIMtlParams = imp;
IAutoMParamDlg* masterDlg = plClothingMtlDesc.CreateParamDlgs(hwMtlEdit, imp, this);
return (ParamDlg*)masterDlg;
}
BOOL plClothingMtl::SetDlgThing(ParamDlg* dlg)
{
return FALSE;
}
Interval plClothingMtl::Validity(TimeValue t)
{
// mf horse - Hacking in something like real validity checking
// to get material animations working. No warranty, this is just
// better than nothing.
Interval v = FOREVER;
fBasicPB->GetValidity(t, v);
return v;
}
/*===========================================================================*\
| Subanim & References support
\*===========================================================================*/
/*
int plClothingMtl::NumSubs()
{
return 2;
}
TSTR plClothingMtl::SubAnimName(int i)
{
switch (i)
{
case 0: return fBasicPB->GetLocalName();
case 1: return "Texmap";
}
return "";
}
Animatable* plClothingMtl::SubAnim(int i)
{
switch (i)
{
case 0: return fBasicPB;
case 1: return fBasicPB->GetTexmap(kTexmap);
}
return NULL;
}
*/
int plClothingMtl::NumRefs()
{
return 1;
}
RefTargetHandle plClothingMtl::GetReference(int i)
{
switch (i)
{
case kRefBasic: return fBasicPB;
}
return NULL;
}
void plClothingMtl::SetReference(int i, RefTargetHandle rtarg)
{
if (i == kRefBasic)
fBasicPB = (IParamBlock2 *)rtarg;
}
int plClothingMtl::NumParamBlocks()
{
return 1;
}
IParamBlock2* plClothingMtl::GetParamBlock(int i)
{
return (IParamBlock2*)GetReference(i);
}
IParamBlock2* plClothingMtl::GetParamBlockByID(BlockID id)
{
if (fBasicPB->ID() == id)
return fBasicPB;
return NULL;
}
RefResult plClothingMtl::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message)
{
switch (message)
{
case REFMSG_CHANGE:
fIValid.SetEmpty();
// see if this message came from a changing parameter in the pblock,
// if so, limit rollout update to the changing item
if (hTarget == fBasicPB)
{
IParamBlock2 *pb = (IParamBlock2*)hTarget;
ParamID changingParam = pb->LastNotifyParamID();
pb->GetDesc()->InvalidateUI(changingParam);
// And let the SceneWatcher know that the material on some of it's
// referenced objects changed.
NotifyDependents(FOREVER, PART_ALL, REFMSG_USER_MAT);
}
break;
}
return REF_SUCCEED;
}
////////////////////////////////////////////////////////////////////////////////
// Subtexmap access
int plClothingMtl::NumSubTexmaps()
{
return plClothingElement::kLayerMax * kMaxTiles + 1; // add one for the thumbnail
}
Texmap* plClothingMtl::GetSubTexmap(int i)
{
if (i >= 0 && i < plClothingElement::kLayerMax * kMaxTiles)
return fBasicPB->GetTexmap(ParamID(LayerToPBIdx[i / kMaxTiles]), 0, i % kMaxTiles);
if (i == plClothingElement::kLayerMax * kMaxTiles)
return fBasicPB->GetTexmap(ParamID(kThumbnail));
return NULL;
}
void plClothingMtl::SetSubTexmap(int i, Texmap *m)
{
if (i >= 0 && i < plClothingElement::kLayerMax * kMaxTiles)
fBasicPB->SetValue(ParamID(LayerToPBIdx[i / kMaxTiles]), 0, m, i % kMaxTiles);
if (i == plClothingElement::kLayerMax * kMaxTiles)
fBasicPB->SetValue(kThumbnail, 0, m);
}
TSTR plClothingMtl::GetSubTexmapSlotName(int i)
{
if (i >= 0 && i < plClothingElement::kLayerMax * kMaxTiles)
return "Texmap";
if (i == plClothingElement::kLayerMax * kMaxTiles)
return "Thumbnail";
return "";
}
TSTR plClothingMtl::GetSubTexmapTVName(int i)
{
return GetSubTexmapSlotName(i);
}
DllExport Texmap *plClothingMtl::GetTexmap(int index, int layer)
{
return fBasicPB->GetTexmap(ParamID(LayerToPBIdx[layer]), 0, index);
}
/*===========================================================================*\
| Standard IO
\*===========================================================================*/
#define MTL_HDR_CHUNK 0x4000
IOResult plClothingMtl::Save(ISave *isave)
{
IOResult res;
isave->BeginChunk(MTL_HDR_CHUNK);
res = MtlBase::Save(isave);
if (res!=IO_OK) return res;
isave->EndChunk();
return IO_OK;
}
IOResult plClothingMtl::Load(ILoad *iload)
{
IOResult res;
int id;
while (IO_OK==(res=iload->OpenChunk()))
{
switch(id = iload->CurChunkID())
{
case MTL_HDR_CHUNK:
res = MtlBase::Load(iload);
break;
}
iload->CloseChunk();
if (res!=IO_OK)
return res;
}
return IO_OK;
}
/*===========================================================================*\
| Updating and cloning
\*===========================================================================*/
RefTargetHandle plClothingMtl::Clone(RemapDir &remap)
{
plClothingMtl *mnew = TRACKED_NEW plClothingMtl(FALSE);
*((MtlBase*)mnew) = *((MtlBase*)this);
mnew->ReplaceReference(kRefBasic, remap.CloneRef(fBasicPB));
BaseClone(this, mnew, remap);
mnew->fIValid.SetEmpty();
return (RefTargetHandle)mnew;
}
void plClothingMtl::NotifyChanged()
{
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
}
void plClothingMtl::Update(TimeValue t, Interval& valid)
{
//StdUVGen *gen = (StdUVGen *)fUVGen;
//gen->SetUScl(1.0f, t);
//gen->SetVScl(1.0f, t);
//gen->Update(t, fIValid);
valid &= fIValid;
}
/*===========================================================================*\
| Determine the characteristics of the material
\*===========================================================================*/
void plClothingMtl::SetAmbient(Color c, TimeValue t) {}
void plClothingMtl::SetDiffuse(Color c, TimeValue t) {}
void plClothingMtl::SetSpecular(Color c, TimeValue t) {}
void plClothingMtl::SetShininess(float v, TimeValue t) {}
Color plClothingMtl::GetAmbient(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plClothingMtl::GetDiffuse(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plClothingMtl::GetSpecular(int mtlNum, BOOL backFace) { return Color(0,0,0); }
float plClothingMtl::GetXParency(int mtlNum, BOOL backFace)
{
/*
int opacity = fBasicPB->GetInt( kOpacity, 0 );
float alpha = 1.0f - ( (float)opacity / 100.0f );
return alpha;
*/
return 0;
}
float plClothingMtl::GetShininess(int mtlNum, BOOL backFace) { return 0.0f; }
float plClothingMtl::GetShinStr(int mtlNum, BOOL backFace) { return 0.0f; }
float plClothingMtl::WireSize(int mtlNum, BOOL backFace) { return 0.0f; }
/////////////////////////////////////////////////////////////////
void plClothingMtl::SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb)
{
}
/*===========================================================================*\
| Actual shading takes place
\*===========================================================================*/
void plClothingMtl::Shade(ShadeContext& sc)
{
// Get the background color
Color backColor, backTrans;
sc.GetBGColor(backColor, backTrans);
ShadeWithBackground(sc, backColor);
}
//// Requirements ////////////////////////////////////////////////////////////
// Tells MAX what we need to render ourselves properly, such as translucency,
// two-sidedness, etc. Flags are in imtl.h in the MAX SDK.
ULONG plClothingMtl::Requirements( int subMtlNum )
{
ULONG req = 0;
req = Mtl::Requirements( subMtlNum );
// Uncomment this to get the background color fed to our ShadeWithBackground()
// (slower processing tho)
// req |= MTLREQ_BGCOL;
//int blendType = fBasicPB->GetInt( kBlend );
//if( blendType == kBlendAdd )
// req |= MTLREQ_ADDITIVE_TRANSP | MTLREQ_TRANSP;
//else if( blendType == kBlendAlpha )
// req |= MTLREQ_TRANSP;
//else if( fBasicPB->GetInt( kOpacity, 0 ) != 100 )
// req |= MTLREQ_TRANSP;
return req;
}
void plClothingMtl::ShadeWithBackground(ShadeContext &sc, Color background)
{
#if 1
TimeValue t = sc.CurTime();
Color color(0, 0, 0);
float alpha = 0.0;
// Evaluate Base layer
Texmap *map = fBasicPB->GetTexmap(kTexmap);
if (map && map->ClassID() == LAYER_TEX_CLASS_ID)
{
plLayerTex *layer = (plLayerTex*)map;
AColor evalColor = layer->EvalColor(sc);
color = evalColor;
alpha = evalColor.a;
}
#if 1
AColor black;
black.Black();
AColor white;
white.White();
SIllumParams ip;
//if( fBasicPB->GetInt( kNormal ) == kEmissive )
//{
// Emissive objects don't get shaded
// ip.diffIllum = fBasicPB->GetColor(kColorAmb, t) * color;
// ip.diffIllum.ClampMinMax();
// ip.specIllum = black;
//}
//else
{
//
// Shading setup
//
// Setup the parameters for the shader
ip.amb = black;
ip.diff = white; //fBasicPB->GetColor(kColor, t) * color;
ip.spec = white;
ip.diffIllum = black;
ip.specIllum = black;
ip.N = sc.Normal();
ip.V = sc.V();
//
// Specularity
//
ip.sh_str = 0;
ip.ph_exp = 0;
ip.shine = 0;
ip.softThresh = 0;
// Do the shading
Shader *myShader = GetShader(SHADER_BLINN);
myShader->Illum(sc, ip);
ip.diffIllum.ClampMinMax();
ip.specIllum.ClampMinMax();
ip.diffIllum = ip.amb * sc.ambientLight + ip.diff * ip.diffIllum;
}
// AColor returnColor = AColor(opac * ip.diffIllum + ip.specIllum, opac)
#endif
// Get opacity and combine with alpha
float opac = 1.0f; //float(fBasicPB->GetInt(kOpacity, t)) / 100.0f;
//float opac = 1.0f;
alpha *= opac;
// MAX will do the additive/alpha/no blending for us based on what Requirements()
// we tell it. However, since MAX's formula is bgnd*sc.out.t + sc.out.c,
// we have to multiply our output color by the alpha.
// If we ever need a more complicated blending function, you can request the
// background color via Requirements() (otherwise it's just black) and then do
// the blending yourself; however, if the transparency isn't set, the shadows
// will be opaque, so be careful.
Color outC = ip.diffIllum + ip.specIllum;
sc.out.c = ( outC * alpha );
sc.out.t = Color( 1.f - alpha, 1.f - alpha, 1.f - alpha );
#endif
}
float plClothingMtl::EvalDisplacement(ShadeContext& sc)
{
return 0.0f;
}
Interval plClothingMtl::DisplacementValidity(TimeValue t)
{
Interval iv;
iv.SetInfinite();
return iv;
}
plClothingElement *plClothingMtl::FindElementByName(char *name)
{
int i;
for (i = 0; i < fElements.GetCount(); i++)
{
if (!strcmp(fElements.Get(i)->fName, name))
return fElements.Get(i);
}
return nil;
}
void plClothingMtl::InitTilesets()
{
hsAssert(fElements.GetCount() == 0, "Tilesets already initialized");
fElements.Reset();
fTilesets.SetCountAndZero(plClothingLayout::kMaxTileset);
plClothingElement::GetElements(fElements);
/*
plClothingTileset *tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("shirt");
tileset->AddElement(FindElementByName("shirt-chest"));
tileset->AddElement(FindElementByName("shirt-sleeve"));
fTilesets[plClothingLayout::kSetShirt] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("face");
tileset->AddElement(FindElementByName("face"));
fTilesets[plClothingLayout::kSetFace] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("eye");
tileset->AddElement(FindElementByName("eyeball"));
fTilesets[plClothingLayout::kSetEye] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("shoe");
tileset->AddElement(FindElementByName("shoe-top"));
tileset->AddElement(FindElementByName("shoe-bottom"));
fTilesets[plClothingLayout::kSetShoe] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("pants");
tileset->AddElement(FindElementByName("pants"));
fTilesets[plClothingLayout::kSetPants] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("hand");
tileset->AddElement(FindElementByName("hand-LOD"));
tileset->AddElement(FindElementByName("hand-square"));
tileset->AddElement(FindElementByName("hand-wide"));
fTilesets[plClothingLayout::kSetHand] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("playerbook");
tileset->AddElement(FindElementByName("playerbook"));
fTilesets[plClothingLayout::kSetPlayerBook] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("backpack");
tileset->AddElement(FindElementByName("backpack"));
fTilesets[plClothingLayout::kSetBackpack] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("glasses");
tileset->AddElement(FindElementByName("glasses-front"));
tileset->AddElement(FindElementByName("glasses-side"));
fTilesets[plClothingLayout::kSetGlasses] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("KI");
tileset->AddElement(FindElementByName("KI"));
fTilesets[plClothingLayout::kSetKI] = tileset;
*/
plClothingTileset *tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("Torso");
tileset->AddElement(FindElementByName("Chest"));
tileset->AddElement(FindElementByName("Arm"));
fTilesets[plClothingLayout::kSetShirt] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("Head");
tileset->AddElement(FindElementByName("Eye"));
tileset->AddElement(FindElementByName("Extra Hair"));
tileset->AddElement(FindElementByName("Face"));
tileset->AddElement(FindElementByName("Hat"));
fTilesets[plClothingLayout::kSetFace] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("Foot");
tileset->AddElement(FindElementByName("Foot"));
fTilesets[plClothingLayout::kSetShoe] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("Legs");
tileset->AddElement(FindElementByName("Legs"));
fTilesets[plClothingLayout::kSetPants] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("Hand");
tileset->AddElement(FindElementByName("Finger"));
tileset->AddElement(FindElementByName("LOD"));
tileset->AddElement(FindElementByName("Palm"));
fTilesets[plClothingLayout::kSetHand] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("Player Book");
tileset->AddElement(FindElementByName("Player Book"));
fTilesets[plClothingLayout::kSetPlayerBook] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("Glasses");
tileset->AddElement(FindElementByName("Glasses"));
fTilesets[plClothingLayout::kSetGlasses] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("KI");
tileset->AddElement(FindElementByName("KI"));
fTilesets[plClothingLayout::kSetKI] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("(unused)");
fTilesets[plClothingLayout::kSetEye] = tileset;
tileset = TRACKED_NEW plClothingTileset();
tileset->SetName("(unused)");
fTilesets[plClothingLayout::kSetBackpack] = tileset;
}
void plClothingMtl::ReleaseTilesets()
{
while (fElements.GetCount() > 0)
delete fElements.Pop();
while (fTilesets.GetCount() > 0)
delete fTilesets.Pop();
}
/////////////////////////////////////////////////////////////////////////////////
plClothingTileset::plClothingTileset() : fName(nil)
{
fElements.Reset();
}
plClothingTileset::~plClothingTileset()
{
delete [] fName;
}
void plClothingTileset::AddElement(plClothingElement *element)
{
fElements.Append(element);
}
void plClothingTileset::SetName(char *name)
{
delete fName; fName = hsStrcpy(name);
}

View File

@ -0,0 +1,217 @@
/*==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==*/
#ifndef PL_CLOTHINGMTL_H
#define PL_CLOTHINGMTL_H
#include "Max.h"
#include "iparamb2.h"
#include "../resource.h"
#include "hsTemplates.h"
class Bitmap;
class plClothingItem;
class plMaxNode;
class plClothingElement;
#define CLOTHING_MTL_CLASS_ID Class_ID(0x792c6de4, 0x1f952b65)
extern TCHAR *GetString(int id);
class plClothingTileset
{
public:
char *fName;
hsTArray<plClothingElement *> fElements;
plClothingTileset();
~plClothingTileset();
void SetName(char *name);
void AddElement(plClothingElement *element);
};
class plClothingMtl : public Mtl
{
protected:
IParamBlock2 *fBasicPB;
Interval fIValid;
public:
IMtlParams *fIMtlParams;
static const char *LayerStrings[];
static const UInt8 LayerToPBIdx[];
enum
{
kRefBasic,
};
enum
{
kBlkBasic,
};
enum // Param block indicies
{
kTileset,
kTexmap,
kDescription,
kThumbnail,
kLayer,
kTexmapSkin,
kTexmap2,
kDefault,
kCustomTextSpecs,
kTexmapBase,
kTexmapSkinBlend1,
kTexmapSkinBlend2,
kTexmapSkinBlend3,
kTexmapSkinBlend4,
kTexmapSkinBlend5,
kTexmapSkinBlend6,
kDefaultTint1,
kDefaultTint2,
kForcedAcc,
};
enum
{
kMaxTiles = 4,
};
enum
{
kBlendNone,
kBlendAlpha,
//kBlendAdd,
};
static const UINT32 ButtonConstants[kMaxTiles];
static const UINT32 TextConstants[kMaxTiles * 2];
hsTArray<plClothingTileset *> fTilesets;
hsTArray<plClothingElement *> fElements;
virtual void InitTilesets();
virtual void ReleaseTilesets();
plClothingElement *FindElementByName(char *name);
int GetTilesetIndex() { return fBasicPB->GetInt(ParamID(kTileset)); }
DllExport Texmap *GetTexmap(int index, int layer);
Texmap *GetThumbnail() { return fBasicPB->GetTexmap(ParamID(kThumbnail)); }
char *GetDescription() { return fBasicPB->GetStr(ParamID(kDescription)); }
char *GetCustomText() { return fBasicPB->GetStr(ParamID(kCustomTextSpecs)); }
hsBool GetDefault() { return fBasicPB->GetInt(ParamID(kDefault)) != 0; }
Color GetDefaultTint1() { return fBasicPB->GetColor(plClothingMtl::kDefaultTint1); }
Color GetDefaultTint2() { return fBasicPB->GetColor(plClothingMtl::kDefaultTint2); }
char *GetForcedAccessoryName() { return fBasicPB->GetStr(ParamID(kForcedAcc)); }
plClothingMtl(BOOL loading);
void DeleteThis() { delete this; }
//From Animatable
Class_ID ClassID() { return CLOTHING_MTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_CLOTHING_MTL); }
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void Reset();
void NotifyChanged();
BOOL SupportsMultiMapsInViewport() { return FALSE; }
void SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb);
// Shade and displacement calculation
void Shade(ShadeContext& sc);
void ShadeWithBackground(ShadeContext &sc, Color background);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
// SubTexmap access methods
int NumSubTexmaps();
Texmap* GetSubTexmap(int i);
void SetSubTexmap(int i, Texmap *m);
TSTR GetSubTexmapSlotName(int i);
TSTR GetSubTexmapTVName(int i);
BOOL SetDlgThing(ParamDlg* dlg);
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs() { return 0; }
Animatable* SubAnim(int i) { return nil; }
TSTR SubAnimName(int i) { return ""; }
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
ULONG Requirements( int subMtlNum );
};
#endif //PL_ClothingMTL_H

View File

@ -0,0 +1,442 @@
/*==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 "plClothingMtl.h"
#include "../../AssetMan/PublicInterface/AssManBaseTypes.h"
#include "max.h"
class plClothingEditBox
{
protected:
int fCtrlID;
int fPBEditID;
plClothingEditBox() {};
void IGetText(IParamBlock2 *pb, HWND hCtrl)
{
// Get the previous value
const char *oldVal = pb->GetStr(fPBEditID);
if (!oldVal)
oldVal = "";
// Get the text from the edit and store it in the paramblock
int len = GetWindowTextLength(hCtrl)+1;
if (len > 1)
{
char *buf = TRACKED_NEW char[len];
GetWindowText(hCtrl, buf, len);
// If the old value is different from the current one, update
if (strcmp(oldVal, buf))
pb->SetValue(fPBEditID, 0, buf);
delete [] buf;
}
else
{
// If the old value wasn't empty, update
if (*oldVal != '\0')
pb->SetValue(fPBEditID, 0, "");
}
}
public:
plClothingEditBox(int ctrlID, int pbEditID) : fCtrlID(ctrlID), fPBEditID(pbEditID) {}
void UpdateText(IParamBlock2 *pb, HWND hWnd)
{
const char *str = pb->GetStr(fPBEditID);
SetDlgItemText(hWnd, fCtrlID, (str != nil ? str : ""));
}
BOOL ProcessMsg(IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// If this isn't a message we process, return
if (!(msg == WM_INITDIALOG || msg == WM_DESTROY ||
(msg == WM_COMMAND && LOWORD(wParam) == fCtrlID)))
return FALSE;
IParamBlock2 *pb = map->GetParamBlock();
// Initializing the dialog, set the text box
if (msg == WM_INITDIALOG)
{
UpdateText(pb, hWnd);
return FALSE;
}
// Being destroyed, but we may not have gotten the text from the edit box
// (EN_KILLFOCUS seems to be sent after the window isn't recieving any more messages)
if (msg == WM_DESTROY)
{
IGetText(pb, GetDlgItem(hWnd, fCtrlID));
return FALSE;
}
int notification = HIWORD(wParam);
HWND hCtrl = (HWND)lParam;
// Disable Max accelerators when the edit box gets focus
if (notification == EN_SETFOCUS)
{
//plMaxAccelerators::Disable();
DisableAccelerators();
return TRUE;
}
// The edit control is losing focus, get it's contents
else if (notification == EN_KILLFOCUS)
{
IGetText(pb, hCtrl);
//plMaxAccelerators::Enable();
EnableAccelerators();
return TRUE;
}
return FALSE;
}
};
class ClothingBasicDlgProc;
extern ClothingBasicDlgProc gClothingBasicDlgProc;
static ParamBlockDesc2 gClothingMtlPB
(
plClothingMtl::kBlkBasic, _T("Clothing"), IDS_PASS_BASIC, GetClothingMtlDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI + P_CALLSETS_ON_LOAD, plClothingMtl::kRefBasic,
// UI
IDD_CLOTHING, IDS_PASS_BASIC, 0, 0, &gClothingBasicDlgProc,
plClothingMtl::kTileset, _T("tileset"), TYPE_INT, 0, 0,
p_default, 0,
end,
plClothingMtl::kTexmap, _T("texmap"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kDescription, _T("ItemDescription"), TYPE_STRING, 0, 0,
p_ui, TYPE_EDITBOX, IDC_CLOTHING_DESCRIPTION,
end,
plClothingMtl::kThumbnail, _T("Thumbnail"), TYPE_TEXMAP, 0, 0,
end,
plClothingMtl::kLayer, _T("Layer"), TYPE_INT, 0, 0,
p_default, plClothingElement::kLayerTint1,
end,
plClothingMtl::kTexmapSkin, _T("SkinLayer"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmap2, _T("TintLayer2"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kDefault, _T("Default"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_CLOTHING_DEFAULT,
p_default, 0,
end,
plClothingMtl::kCustomTextSpecs, _T("TextSpecs"), TYPE_STRING, 0, 0,
end,
plClothingMtl::kTexmapBase, _T("BaseLayer"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmapSkinBlend1, _T("SkinBlend(1)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmapSkinBlend2, _T("SkinBlend(2)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmapSkinBlend3, _T("SkinBlend(3)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmapSkinBlend4, _T("SkinBlend(4)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmapSkinBlend5, _T("SkinBlend(5)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmapSkinBlend6, _T("SkinBlend(6)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kDefaultTint1, _T("DefaultTint1"), TYPE_RGBA, 0, 0,
p_ui, TYPE_COLORSWATCH, IDC_CLOTHING_TINT1,
p_default, Color(1,1,1),
end,
plClothingMtl::kDefaultTint2, _T("DefaultTint2"), TYPE_RGBA, 0, 0,
p_ui, TYPE_COLORSWATCH, IDC_CLOTHING_TINT2,
p_default, Color(1,1,1),
end,
plClothingMtl::kForcedAcc, _T("ForcedAcc"), TYPE_STRING, 0, 0,
p_ui, TYPE_EDITBOX, IDC_CLOTHING_FORCED_ACC,
end,
end
);
class ClothingBasicDlgProc : public ParamMap2UserDlgProc
{
protected:
plClothingEditBox fCustomText;
public:
ClothingBasicDlgProc() : fCustomText(IDC_CLOTHING_CUSTOM_TEXT_SPECS, plClothingMtl::kCustomTextSpecs) {}
~ClothingBasicDlgProc() {}
void UpdateDisplay(IParamMap2 *pmap)
{
HWND hWnd = pmap->GetHWnd();
IParamBlock2 *pb = pmap->GetParamBlock();
plClothingMtl *mtl = (plClothingMtl *)pb->GetOwner();
HWND cbox = NULL;
plPlasmaMAXLayer *layer;
PBBitmap *pbbm;
ICustButton *bmSelectBtn;
char buff[256];
// Setup the tiles
int i, j;
int layerSet = pb->GetInt(ParamID(plClothingMtl::kLayer));
int layerIdx = plClothingMtl::LayerToPBIdx[layerSet];
for (j = 0; j < plClothingMtl::kMaxTiles; j++)
{
layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(layerIdx), 0, j);
pbbm = (layer == nil ? nil : layer->GetPBBitmap());
bmSelectBtn = GetICustButton(GetDlgItem(hWnd, plClothingMtl::ButtonConstants[j]));
bmSelectBtn->SetText(pbbm ? (TCHAR*)pbbm->bi.Filename() : "(none)");
ReleaseICustButton(bmSelectBtn);
}
// And the thumbnail...
layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(plClothingMtl::kThumbnail));
if (layer == nil)
{
layer = TRACKED_NEW plLayerTex;
pb->SetValue(ParamID(plClothingMtl::kThumbnail), 0, layer);
}
pbbm = layer->GetPBBitmap();
if (pbbm)
{
bmSelectBtn = GetICustButton(GetDlgItem(hWnd, IDC_CLOTHING_THUMBNAIL));
bmSelectBtn->SetText((TCHAR*)pbbm->bi.Filename());
ReleaseICustButton(bmSelectBtn);
}
int setIdx = pb->GetInt(ParamID(plClothingMtl::kTileset));
ComboBox_SetCurSel(GetDlgItem(hWnd, IDC_CLOTHING_TILESET), setIdx);
ComboBox_SetCurSel(GetDlgItem(hWnd, IDC_CLOTHING_LAYER), pb->GetInt(ParamID(plClothingMtl::kLayer)));
mtl->InitTilesets();
plClothingTileset *tileset = mtl->fTilesets.Get(setIdx);
for (i = 0; i < tileset->fElements.GetCount(); i++)
{
plClothingElement *element = tileset->fElements.Get(i);
SendMessage(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i]),
WM_SETTEXT, NULL, (LPARAM)element->fName);
sprintf(buff, "(%d, %d)", element->fWidth, element->fHeight);
SendMessage(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i + 1]),
WM_SETTEXT, NULL, (LPARAM)buff);
ShowWindow(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i]), SW_SHOW);
ShowWindow(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i + 1]), SW_SHOW);
ShowWindow(GetDlgItem(hWnd, plClothingMtl::ButtonConstants[i]), SW_SHOW);
}
for (i = tileset->fElements.GetCount(); i < plClothingMtl::kMaxTiles; i++)
{
ShowWindow(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i]), SW_HIDE);
ShowWindow(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i + 1]), SW_HIDE);
ShowWindow(GetDlgItem(hWnd, plClothingMtl::ButtonConstants[i]), SW_HIDE);
}
mtl->ReleaseTilesets();
fCustomText.UpdateText(pb, hWnd);
}
virtual void Update(TimeValue t, Interval& valid, IParamMap2* pmap) { UpdateDisplay(pmap); }
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// Check if it is for our edit box
if (fCustomText.ProcessMsg(map, hWnd, msg, wParam, lParam))
return TRUE;
int id = LOWORD(wParam);
int code = HIWORD(wParam);
IParamBlock2 *pb = map->GetParamBlock();
plClothingMtl *mtl = (plClothingMtl *)pb->GetOwner();
HWND cbox = NULL;
plPlasmaMAXLayer *layer;
PBBitmap *pbbm;
ICustButton *bmSelectBtn;
int layerIdx = plClothingMtl::LayerToPBIdx[pb->GetInt(ParamID(plClothingMtl::kLayer))];
switch (msg)
{
case WM_INITDIALOG:
int j;
mtl->InitTilesets();
cbox = GetDlgItem(hWnd, IDC_CLOTHING_TILESET);
for (j = 0; j < mtl->fTilesets.GetCount(); j++)
SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)mtl->fTilesets.Get(j)->fName);
mtl->ReleaseTilesets();
cbox = GetDlgItem(hWnd, IDC_CLOTHING_LAYER);
for (j = 0; j < plClothingElement::kLayerMax; j++)
ComboBox_AddString(cbox, plClothingMtl::LayerStrings[j]);
return TRUE;
case WM_COMMAND:
if (id == IDC_CLOTHING_TILESET)
{
int setIdx = SendMessage(GetDlgItem(hWnd, id), CB_GETCURSEL, 0, 0);
pb->SetValue(plClothingMtl::kTileset, t, setIdx);
return TRUE;
}
if (id == IDC_CLOTHING_LAYER)
{
pb->SetValue(plClothingMtl::kLayer, t, ComboBox_GetCurSel(GetDlgItem(hWnd, id)));
return TRUE;
}
if (id == IDC_CLOTHING_THUMBNAIL)
{
layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(plClothingMtl::kThumbnail));
if (layer == nil)
return FALSE;
BitmapInfo bi;
bi.SetName(layer->GetPBBitmap() == nil ? "" : layer->GetPBBitmap()->bi.Name());
BOOL selectedNewBitmap = layer->HandleBitmapSelection();
if (selectedNewBitmap)
{
pbbm = layer->GetPBBitmap();
bmSelectBtn = GetICustButton(GetDlgItem(hWnd, IDC_CLOTHING_THUMBNAIL));
bmSelectBtn->SetText(pbbm != nil ? (TCHAR*)pbbm->bi.Filename() : "(none)");
ReleaseICustButton(bmSelectBtn);
}
return TRUE;
}
int buttonIdx = -1;
if (id == IDC_CLOTHING_TEXTURE1) buttonIdx = 0;
else if (id == IDC_CLOTHING_TEXTURE2) buttonIdx = 1;
else if (id == IDC_CLOTHING_TEXTURE3) buttonIdx = 2;
else if (id == IDC_CLOTHING_TEXTURE4) buttonIdx = 3;
if (buttonIdx != -1)
{
layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(layerIdx), 0, buttonIdx);
if (layer == nil)
{ // First time we've set a layer on this spot
layer = TRACKED_NEW plLayerTex;
pb->SetValue(ParamID(layerIdx), 0, layer, buttonIdx);
}
jvUniqueId oldId;
layer->GetBitmapAssetId(oldId);
BitmapInfo bi;
bi.SetName(layer->GetPBBitmap() == nil ? "" : layer->GetPBBitmap()->bi.Name());
BOOL selectedNewBitmap = layer->HandleBitmapSelection();
if (selectedNewBitmap)
{
// Check if it's ok, and undo if not.
hsBool choiceOk = true;
pbbm = layer->GetPBBitmap();
if (pbbm != nil)
{
mtl->InitTilesets();
plClothingTileset *tileset = mtl->fTilesets.Get(pb->GetInt(plClothingMtl::kTileset));
plClothingElement *element = tileset->fElements.Get(buttonIdx);
float targRatio = (float)element->fWidth / (float)element->fHeight;
float ratio = (float)pbbm->bi.Width() / (float)pbbm->bi.Height();
if (targRatio != ratio)
{
choiceOk = false;
hsMessageBox("That image's width/height ratio does not match the one for this tile. "
"Restoring the old selection.", "Invalid image", hsMessageBoxNormal);
}
else if (pbbm->bi.Width() < element->fWidth)
{
choiceOk = false;
hsMessageBox("The chosen image is too small for that tile slot. "
"Restoring the old selection.", "Invalid image", hsMessageBoxNormal);
}
mtl->ReleaseTilesets();
}
if (!choiceOk)
{
layer->SetBitmapAssetId(oldId);
layer->SetBitmap(&bi);
}
else
{
bmSelectBtn = GetICustButton(GetDlgItem(hWnd, plClothingMtl::ButtonConstants[buttonIdx]));
bmSelectBtn->SetText(pbbm != nil ? (TCHAR*)pbbm->bi.Filename() : "(none)");
ReleaseICustButton(bmSelectBtn);
}
}
}
return TRUE;
}
return FALSE;
}
void DeleteThis() {}
};
static ClothingBasicDlgProc gClothingBasicDlgProc;

View File

@ -0,0 +1,584 @@
/*==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 "hsTypes.h"
#include "plCompositeMtl.h"
#include "plPassMtl.h"
//#include "plCompositeMtlPB.h"
#include "plCompositeMtlDlg.h"
class plCompositeClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading) { return TRACKED_NEW plCompositeMtl(loading); }
const TCHAR* ClassName() { return GetString(IDS_COMP_MTL); }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
Class_ID ClassID() { return COMP_MTL_CLASS_ID; }
const TCHAR* Category() { return NULL; }
const TCHAR* InternalName() { return _T("PlasmaComposite"); }
HINSTANCE HInstance() { return hInstance; }
};
static plCompositeClassDesc plCompositeMtlDesc;
ClassDesc2* GetCompMtlDesc() { return &plCompositeMtlDesc; }
#include "plCompositeMtlPBDec.h"
const char *plCompositeMtl::BlendStrings[] = // Make sure these match up in order with the Blend enum (in the header)
{
"Vertex Alpha",
"Inverse Vtx Alpha",
"Vertex Illum Red",
"Inv. Vtx Illum Red",
"Vertex Illum Green",
"Inv. Vtx Illum Green",
"Vertex Illum Blue",
"Inv. Vtx Illum Blue"
};
plCompositeMtl::plCompositeMtl(BOOL loading) : fPassesPB(NULL)
{
plCompositeMtlDesc.MakeAutoParamBlocks(this);
if (!loading)
Reset();
int i;
for (i = 0; i < NSUBMTLS; i++)
{
plPassMtl *newMtl = TRACKED_NEW plPassMtl(false);
fPassesPB->SetValue(kCompPasses, 0, newMtl, i);
GetCOREInterface()->AssignNewName(fPassesPB->GetMtl(kCompPasses, 0, i));
}
}
void plCompositeMtl::Reset()
{
fIValid.SetEmpty();
}
ParamDlg* plCompositeMtl::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
fMtlDlg = TRACKED_NEW plCompositeMtlDlg(hwMtlEdit, imp, this);
return fMtlDlg;
}
void plCompositeMtl::SetParamDlg(ParamDlg *dlg)
{
fMtlDlg = (plCompositeMtlDlg*)dlg;
}
BOOL plCompositeMtl::SetDlgThing(ParamDlg* dlg)
{
if (dlg == fMtlDlg)
{
fMtlDlg->SetThing(this);
return TRUE;
}
return FALSE;
}
Interval plCompositeMtl::Validity(TimeValue t)
{
Interval valid = FOREVER;
/* for (int i = 0; i < fSubTexmap.Count(); i++)
{
if (fSubTexmap[i])
valid &= fSubTexmap[i]->Validity(t);
}
*/
// float u;
// fPBlock->GetValue(pb_spin,t,u,valid);
return valid;
}
// The index for a face on a composite material is really just a bitmask for all the submaterials. This function only
// computes it... The mesh creator will ask it to be created if it's needed.
int plCompositeMtl::ComputeMaterialIndex(float opac[][2], int vertCount)
{
int index = 0;
int i;//, j;
int bitmask = 1;
for (i = NumSubMtls() - 1, bitmask <<= i; i >= 0; i--, bitmask >>= 1)
{
index |= bitmask;
/*
if (i == 0)
index |= bitmask; // it's not opaqued out, so include the base layer
else if (fPassesPB->GetInt(kCompOn, 0, i - 1)) // is the checkbox ticked? (ie, are we using it?)
{
bool transparent = true;
for (j = 0; j < vertCount; j++)
{
if (opac[j][i - 1] != 0.0)
transparent = false;
}
if (transparent)
continue; // totally transparent for this face, skip it
index |= bitmask; // include this material
bool opaque = true;
for (j = 0; j < vertCount; j++)
{
if (opac[j][i - 1] < 1.0)
opaque = false;
}
if (opaque && !((plPassMtlBase *)fPassesPB->GetMtl(kCompPasses, 0, i))->HasAlpha())
break; // This material is totally opaque, no sense including anything underneath it
}
*/
}
return index;
}
int plCompositeMtl::GetBlendStyle(int index)
{
return fPassesPB->GetInt(kCompBlend, 0, index - 1);
}
// Determines whether all materials are only blending on one channel (and possibly its inverse) and therefore
// it's ok to overwrite the vertex alpha exported for the span using this material.
// Returns: -1 if we use multiple sources, otherwise the source we all agree on
int plCompositeMtl::CanWriteAlpha()
{
int blend[3];
blend[0] = ((((plPassMtlBase *)GetSubMtl(0))->GetOutputBlend() == plPassMtlBase::kBlendNone) ? -1 : kCompBlendVertexAlpha);
blend[1] = (fPassesPB->GetInt(kCompOn, 0, 0) ? RemoveInverse(GetBlendStyle(1)) : -1);
blend[2] = (fPassesPB->GetInt(kCompOn, 0, 1) ? RemoveInverse(GetBlendStyle(2)) : -1);
int source = blend[0];
int i;
for (i = 1; i < 3; i++)
{
if (source < 0)
{
source = blend[i];
continue;
}
if (source >= 0 && blend[i] >= 0 && blend[i] != source)
return -1;
}
return source;
}
/*===========================================================================*\
| Subanim & References support
\*===========================================================================*/
int plCompositeMtl::NumSubs()
{
return NumSubMtls();
}
TSTR plCompositeMtl::SubAnimName(int i)
{
return GetSubMtlSlotName(i);
}
Animatable* plCompositeMtl::SubAnim(int i)
{
return GetSubMtl(i);
}
int plCompositeMtl::NumRefs()
{
return 1;
}
RefTargetHandle plCompositeMtl::GetReference(int i)
{
if (i == kRefPasses)
return fPassesPB;
return NULL;
}
void plCompositeMtl::SetReference(int i, RefTargetHandle rtarg)
{
if (i == kRefPasses)
fPassesPB = (IParamBlock2 *)rtarg;
}
int plCompositeMtl::NumParamBlocks()
{
return 1;
}
IParamBlock2 *plCompositeMtl::GetParamBlock(int i)
{
if (i == kRefPasses)
return fPassesPB;
return NULL;
}
IParamBlock2 *plCompositeMtl::GetParamBlockByID(BlockID id)
{
if (fPassesPB->ID() == id)
return fPassesPB;
return NULL;
}
RefResult plCompositeMtl::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message )
{
switch (message)
{
case REFMSG_CHANGE:
fIValid.SetEmpty();
if (hTarget == fPassesPB)
{
ParamID changingParam = fPassesPB->LastNotifyParamID();
fPassesPB->GetDesc()->InvalidateUI(changingParam);
}
break;
}
return REF_SUCCEED;
}
////////////////////////////////////////////////////////////////////////////////
// Subtexmap access
int plCompositeMtl::NumSubMtls()
{
// return fPassesPB->GetInt(kMultCount);
return NSUBMTLS;
}
Mtl *plCompositeMtl::GetSubMtl(int i)
{
if (i < NumSubMtls())
return fPassesPB->GetMtl(kCompPasses, 0, i);
return NULL;
}
void plCompositeMtl::SetSubMtl(int i, Mtl *m)
{
if (i < NumSubMtls())
fPassesPB->SetValue(kCompPasses, 0, m, i);
}
TSTR plCompositeMtl::GetSubMtlSlotName(int i)
{
TSTR str;
str.printf("Pass %d", i+1);
return str;
}
TSTR plCompositeMtl::GetSubMtlTVName(int i)
{
return GetSubMtlSlotName(i);
}
/*===========================================================================*\
| Standard IO
\*===========================================================================*/
#define MTL_HDR_CHUNK 0x4000
IOResult plCompositeMtl::Save(ISave *isave)
{
IOResult res;
isave->BeginChunk(MTL_HDR_CHUNK);
res = MtlBase::Save(isave);
if (res!=IO_OK) return res;
isave->EndChunk();
return IO_OK;
}
IOResult plCompositeMtl::Load(ILoad *iload)
{
IOResult res;
int id;
while (IO_OK==(res=iload->OpenChunk()))
{
switch(id = iload->CurChunkID())
{
case MTL_HDR_CHUNK:
res = MtlBase::Load(iload);
break;
}
iload->CloseChunk();
if (res!=IO_OK)
return res;
}
return IO_OK;
}
/*===========================================================================*\
| Updating and cloning
\*===========================================================================*/
RefTargetHandle plCompositeMtl::Clone(RemapDir &remap)
{
plCompositeMtl *mnew = TRACKED_NEW plCompositeMtl(FALSE);
*((MtlBase*)mnew) = *((MtlBase*)this);
mnew->ReplaceReference(kRefPasses, remap.CloneRef(fPassesPB));
mnew->fIValid.SetEmpty();
BaseClone(this, mnew, remap);
return (RefTargetHandle)mnew;
}
void plCompositeMtl::NotifyChanged()
{
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
}
void plCompositeMtl::Update(TimeValue t, Interval& valid)
{
if (!fIValid.InInterval(t))
{
fIValid.SetInfinite();
// fPassesPB->GetValue(kMtlLayLayer1On, t, fMapOn[0], fIValid);
for (int i = 0; i < NumSubMtls(); i++)
{
if (GetSubMtl(i))
GetSubMtl(i)->Update(t, fIValid);
}
}
valid &= fIValid;
}
/*===========================================================================*\
| Determine the characteristics of the material
\*===========================================================================*/
void plCompositeMtl::SetAmbient(Color c, TimeValue t) {}
void plCompositeMtl::SetDiffuse(Color c, TimeValue t) {}
void plCompositeMtl::SetSpecular(Color c, TimeValue t) {}
void plCompositeMtl::SetShininess(float v, TimeValue t) {}
Color plCompositeMtl::GetAmbient(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plCompositeMtl::GetDiffuse(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plCompositeMtl::GetSpecular(int mtlNum, BOOL backFace) { return Color(0,0,0); }
float plCompositeMtl::GetXParency(int mtlNum, BOOL backFace) { return 0.0f; }
float plCompositeMtl::GetShininess(int mtlNum, BOOL backFace) { return 0.0f; }
float plCompositeMtl::GetShinStr(int mtlNum, BOOL backFace) { return 0.0f; }
float plCompositeMtl::WireSize(int mtlNum, BOOL backFace) { return 0.0f; }
/*===========================================================================*\
| Actual shading takes place
\*===========================================================================*/
void plCompositeMtl::Shade(ShadeContext& sc)
{
// Get the background color
Color backColor, backTrans;
//sc.GetBGColor(backColor, backTrans);
backColor.Black();
backTrans.White();
Point3 vtxIllum, vtxAlpha;
plPassMtl::GetInterpVtxValue(MAP_ALPHA, sc, vtxAlpha);
plPassMtl::GetInterpVtxValue(MAP_SHADING, sc, vtxIllum);
int count = NumSubMtls();
for (int i = 0; i < count; i++)
{
if (i > 0 && fPassesPB->GetInt(kCompOn, 0, i - 1) == 0) // Material is unchecked, skip it.
continue;
Mtl *mtl = GetSubMtl(i);
if (mtl == NULL || mtl->ClassID() != PASS_MTL_CLASS_ID)
continue;
float opacity;
if (i == 0)
{
opacity = 1.0f;
}
else
{
int blendMethod = fPassesPB->GetInt(kCompBlend, 0, i - 1);
switch(blendMethod)
{
case kCompBlendVertexAlpha:
case kCompBlendInverseVtxAlpha:
opacity = vtxAlpha.x;
break;
case kCompBlendVertexIllumRed:
case kCompBlendInverseVtxIllumRed:
opacity = vtxIllum.x;
break;
case kCompBlendVertexIllumGreen:
case kCompBlendInverseVtxIllumGreen:
opacity = vtxIllum.y;
break;
case kCompBlendVertexIllumBlue:
case kCompBlendInverseVtxIllumBlue:
opacity = vtxIllum.z;
break;
default:
opacity = 1.0f;
break;
}
if (IsInverseBlend(blendMethod))
opacity = 1 - opacity;
}
plPassMtl *passMtl = (plPassMtl*)mtl;
passMtl->ShadeWithBackground(sc, backColor, false); // Don't include the vtx alpha, that's OUR job
float currTrans = (1 - (1 - sc.out.t.r) * opacity);
backTrans *= currTrans;
backColor = backColor * currTrans + sc.out.c * opacity;
}
sc.out.t = backTrans;
sc.out.c = backColor;
}
float plCompositeMtl::EvalDisplacement(ShadeContext& sc)
{
return 0.0f;
}
Interval plCompositeMtl::DisplacementValidity(TimeValue t)
{
Interval iv;
iv.SetInfinite();
return iv;
}
/*
void plCompositeMtl::SetNumSubMtls(int num)
{
TimeValue t = GetCOREInterface()->GetTime();
int curNum = fPassesPB->GetInt(kMultCount);
fPassesPB->SetValue(kMultCount, 0, num);
fPassesPB->SetCount(kMultPasses, num);
fPassesPB->SetCount(kMultOn, num);
for (int i = curNum; i < num; i++)
{
plPassMtl *newMtl = TRACKED_NEW plPassMtl(false);
fPassesPB->SetValue(kMultPasses, t, newMtl, i);
fPassesPB->SetValue(kMultOn, t, TRUE, i);
GetCOREInterface()->AssignNewName(fPassesPB->GetMtl(kMultPasses, t, i));
}
}
*/
void plCompositeMtl::SetOpacityVal(float *target, UVVert *alpha, UVVert *illum, int method)
{
if (method == kCompBlendVertexAlpha || method == kCompBlendInverseVtxAlpha)
{
if (alpha == NULL)
*target = 1.0f;
else
*target = alpha->x;
}
else if (method == kCompBlendVertexIllumRed || method == kCompBlendInverseVtxIllumRed)
{
if (illum == NULL)
*target = 1.0f;
else
*target = illum->x;
}
else if (method == kCompBlendVertexIllumGreen || method == kCompBlendInverseVtxIllumGreen)
{
if (illum == NULL)
*target = 1.0f;
else
*target = illum->y;
}
else if (method == kCompBlendVertexIllumBlue || method == kCompBlendInverseVtxIllumBlue)
{
if (illum == NULL)
*target = 1.0f;
else
*target = illum->z;
}
else
{
*target = 1.0f;
}
if (method == kCompBlendInverseVtxAlpha ||
method == kCompBlendInverseVtxIllumRed ||
method == kCompBlendInverseVtxIllumGreen ||
method == kCompBlendInverseVtxIllumBlue)
{
*target = 1.0f - *target;
}
}
/*
int plCompositeMtl::UVChannelsNeeded(bool makeAlphaLayer)
{
if (makeAlphaLayer)
return 1;
// Otherwise, we do have vertex alpha... can we get by without taking up a UV channel?
int channels = 0;
int i;
for (i = 0; i < NumSubMtls() - 1; i++)
{
if (!fPassesPB->GetInt(kCompOn, 0, i))
continue; // The material is unchecked, no need to see if it needs a channel
int method = fPassesPB->GetInt(kCompBlend, 0, i);
if (!(method == kCompBlendVertexAlpha || method1 == kCompBlendInverseVtxAlpha))
{
channels = 1;
break;
}
}
return channels;
}
*/

View File

@ -0,0 +1,170 @@
/*==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==*/
#ifndef __PLCOMPMTL__H
#define __PLCOMPMTL__H
#include "Max.h"
#include "../resource.h"
#include "istdplug.h"
#include "iparamb2.h"
#include "iparamm2.h"
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
#define COMP_MTL_CLASS_ID Class_ID(0x237c422d, 0x64ab6371)
class plCompositeMtlDlg;
class plCompositeMtl : public Mtl
{
protected:
IParamBlock2 *fPassesPB;
Interval fIValid;
plCompositeMtlDlg *fMtlDlg;
public:
enum
{
kCompPasses,
kCompOn,
kCompBlend,
kCompUVChannels,
kCompLayerCounts
};
// Make sure to pair up each blend mode with an inverse after it
// (This way we check for an inverse blend by doing an odd/even check.)
enum BlendMethod // These should match up in order with the blend strings
{
kCompBlendVertexAlpha,
kCompBlendInverseVtxAlpha,
kCompBlendVertexIllumRed,
kCompBlendInverseVtxIllumRed,
kCompBlendVertexIllumGreen,
kCompBlendInverseVtxIllumGreen,
kCompBlendVertexIllumBlue,
kCompBlendInverseVtxIllumBlue,
kCompNumBlendMethods
};
static const char *BlendStrings[];
enum { kRefPasses };
enum { kBlkPasses };
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void Reset();
void NotifyChanged();
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
// Shade and displacement calculation
void Shade(ShadeContext& sc);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
// SubTexmap access methods
int NumSubMtls();
Mtl* GetSubMtl(int i);
void SetSubMtl(int i, Mtl *m);
TSTR GetSubMtlSlotName(int i);
TSTR GetSubMtlTVName(int i);
BOOL SetDlgThing(ParamDlg* dlg);
plCompositeMtl(BOOL loading);
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
//From Animatable
Class_ID ClassID() { return COMP_MTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_COMP_MTL); }
RefTargetHandle Clone(RemapDir &remap);
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
void DeleteThis() { delete this; }
void SetParamDlg(ParamDlg *dlg);
int ComputeMaterialIndex(float opac[][2], int vertCount);
int GetBlendStyle(int index);
int CanWriteAlpha();
bool IsInverseBlend(int blend) const { return blend & 1; }
int RemoveInverse(int blend) { return blend - (blend & 1); }
//void SetNumSubMtls(int num);
void SetOpacityVal(float *pt, UVVert *alphas, UVVert *illums, int method);
//DllExport int UVChannelsNeeded(bool makeAlphaLayer);
};
#endif // __PLCOMPMTL__H

View File

@ -0,0 +1,293 @@
/*==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 "hsTypes.h"
#include "max.h"
#include "MaxIcon.h"
#include "resource.h"
#include "plCompositeMtl.h"
//#include "plCompositeMtlPB.h"
//#include "plMaxLayer.h"
#include "plCompositeMtlDlg.h"
struct LayerID
{
int layerID;
int activeID;
int blendID;
};
static LayerID kLayerID[] =
{
{ IDC_TEX1, 0, 0 },
{ IDC_TEX2, IDC_TEXON2, IDC_COMBO2 },
{ IDC_TEX3, IDC_TEXON3, IDC_COMBO3 }
};
//-----------------------------------------------------------------------------
// Constructor and destructor
//-----------------------------------------------------------------------------
plCompositeMtlDlg::plCompositeMtlDlg(HWND hwMtlEdit, IMtlParams *imp, plCompositeMtl *m)
{
fDADMgr.Init(this);
fhMtlEdit = hwMtlEdit;
fhRollup = NULL;
fMtl = m;
fPBlock = fMtl->GetParamBlockByID(plCompositeMtl::kBlkPasses);
ip = imp;
valid = FALSE;
for (int i = 0; i < NSUBMTLS; i++)
fLayerBtns[i] = NULL;
curTime = imp->GetTime();
fhRollup = ip->AddRollupPage(
hInstance,
MAKEINTRESOURCE(IDD_COMPOSITE),
ForwardProc,
"Composite Parameters",
(LPARAM)this);
}
plCompositeMtlDlg::~plCompositeMtlDlg()
{
fMtl->SetParamDlg(NULL);
for (int i = 0; i < NSUBMTLS; i++)
{
ReleaseICustButton(fLayerBtns[i]);
fLayerBtns[i] = NULL;
}
SetWindowLong(fhRollup, GWL_USERDATA, NULL);
ip->DeleteRollupPage(fhRollup);
fhRollup = NULL;
}
//-----------------------------------------------------------------------------
// Functions inheirited from ParamDlg
//-----------------------------------------------------------------------------
void plCompositeMtlDlg::SetThing(ReferenceTarget *m)
{
assert(m->SuperClassID() == MATERIAL_CLASS_ID);
assert(m->ClassID() == COMP_MTL_CLASS_ID);
// Bad?
if (fMtl)
fMtl->SetParamDlg(NULL);
fMtl = (plCompositeMtl *)m;
if (fMtl)
fMtl->SetParamDlg(this);
LoadDialog();
IUpdateMtlDisplay();
}
void plCompositeMtlDlg::SetTime(TimeValue t)
{
if (t != curTime)
{
curTime = t;
Interval v;
fMtl->Update(ip->GetTime(),v);
LoadDialog();
IUpdateMtlDisplay();
}
}
void plCompositeMtlDlg::ReloadDialog()
{
Interval v;
fMtl->Update(ip->GetTime(), v);
LoadDialog();
}
void plCompositeMtlDlg::ActivateDlg(BOOL onOff)
{
}
int plCompositeMtlDlg::FindSubMtlFromHWND(HWND hwnd)
{
for (int i = 0; i < NSUBMTLS; i++)
{
if (hwnd == fLayerBtns[i]->GetHwnd())
return i;
}
return -1;
}
BOOL plCompositeMtlDlg::ForwardProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
plCompositeMtlDlg *theDlg;
if (msg == WM_INITDIALOG)
{
theDlg = (plCompositeMtlDlg*)lParam;
theDlg->fhRollup = hDlg;
SetWindowLong(hDlg, GWL_USERDATA, lParam);
}
else
{
if ((theDlg = (plCompositeMtlDlg *)GetWindowLong(hDlg, GWL_USERDATA)) == NULL)
return FALSE;
}
return theDlg->LayerPanelProc(hDlg,msg,wParam,lParam);
}
//----------------------------------------------------------------------------
// Layer panel processor
//----------------------------------------------------------------------------
BOOL plCompositeMtlDlg::LayerPanelProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
int id = LOWORD(wParam);
int code = HIWORD(wParam);
int i;
switch (msg)
{
case WM_INITDIALOG:
{
for (i = 0; i < NSUBMTLS; i++)
{
fLayerBtns[i] = GetICustButton(GetDlgItem(hDlg, kLayerID[i].layerID));
fLayerBtns[i]->SetDADMgr(&fDADMgr);
if (i > 0) // the first material doesn't get one, nyah nyah!
{
HWND cbox = NULL;
int j;
for (j = 0; j < plCompositeMtl::kCompNumBlendMethods; j++)
{
cbox = GetDlgItem(hDlg, kLayerID[i].blendID);
SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)plCompositeMtl::BlendStrings[j]);
}
SendMessage(cbox, CB_SETCURSEL, 0, 0);
}
}
// TEMP testing
UpdateLayerDisplay();
IUpdateMtlDisplay();
}
return TRUE;
case WM_DESTROY:
for (i = 0; i < NSUBMTLS; i++)
{
ReleaseICustButton(fLayerBtns[i]);
fLayerBtns[i] = NULL;
}
break;
case WM_COMMAND:
{
for (i = 0; i < NSUBMTLS; i++)
{
if (id == kLayerID[i].activeID)
{
bool checked = SendMessage(GetDlgItem(hDlg, id), BM_GETCHECK, 0, 0) == BST_CHECKED;
fPBlock->SetValue(plCompositeMtl::kCompOn, curTime, checked, i - 1);
return TRUE;
}
if (id == kLayerID[i].layerID)
{
PostMessage(fhMtlEdit, WM_SUB_MTL_BUTTON, i, (LPARAM)fMtl);
return TRUE;
}
if (id == kLayerID[i].blendID)
{
fPBlock->SetValue(plCompositeMtl::kCompBlend, curTime, SendMessage(GetDlgItem(hDlg, id), CB_GETCURSEL, 0, 0), i - 1);
return TRUE;
}
}
}
// IUpdateMtlDisplay();
break;
}
return FALSE;
}
void plCompositeMtlDlg::UpdateLayerDisplay()
{
int i;
for (i = 0; i < NSUBMTLS; i++)
{
Mtl *m = fPBlock->GetMtl(plCompositeMtl::kCompPasses, curTime, i);
TSTR nm;
if (m)
nm = m->GetName();
else
nm = "None";
fLayerBtns[i]->SetText(nm.data());
ShowWindow(GetDlgItem(fhRollup, kLayerID[i].layerID), SW_SHOW);
ShowWindow(GetDlgItem(fhRollup, kLayerID[i].activeID), SW_SHOW);
if (i > 0)
{
int check = (fPBlock->GetInt(plCompositeMtl::kCompOn, curTime, i - 1) == 0 ? BST_UNCHECKED : BST_CHECKED);
SendMessage(GetDlgItem(fhRollup, kLayerID[i].activeID), BM_SETCHECK, (WPARAM)check, 0);
int selection = fPBlock->GetInt(plCompositeMtl::kCompBlend, curTime, i - 1);
SendMessage(GetDlgItem(fhRollup, kLayerID[i].blendID), CB_SETCURSEL, (WPARAM)selection, 0);
}
}
}
void plCompositeMtlDlg::LoadDialog()
{
if (fMtl)
{
fPBlock = fMtl->GetParamBlockByID(plCompositeMtl::kBlkPasses);
if (fhRollup)
UpdateLayerDisplay();
}
}

View File

@ -0,0 +1,102 @@
/*==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==*/
#ifndef PL_COMPMTLDLG_H
#define PL_COMPMTLDLG_H
#define NSUBMTLS 3
class plCompositeMtlDlg : public ParamDlg
{
protected:
IParamBlock2 *fPBlock;
HWND fhMtlEdit; // Window handle of the materials editor dialog
HWND fhRollup; // Our rollup panel
IMtlParams *ip;
plCompositeMtl *fMtl; // current mtl being edited.
TimeValue curTime;
int isActive;
BOOL valid;
// int offset;
ICustButton *fLayerBtns[NSUBMTLS];
MtlDADMgr fDADMgr; // For drag-drop sub-materials
public:
// Constructor and destructor
plCompositeMtlDlg(HWND hwMtlEdit, IMtlParams *imp, plCompositeMtl *m);
~plCompositeMtlDlg();
// Functions inherited from ParamDLg:
Class_ID ClassID() { return COMP_MTL_CLASS_ID; }
void SetThing(ReferenceTarget *m);
ReferenceTarget* GetThing() { return (ReferenceTarget*)fMtl; }
void SetTime(TimeValue t);
void ReloadDialog();
void ActivateDlg(BOOL onOff);
void DeleteThis() { delete this; }
int FindSubMtlFromHWND(HWND hw);
static BOOL CALLBACK ForwardProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL LayerPanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
void UpdateLayerDisplay();
void LoadDialog();
/*
// Lower-level crap
void Invalidate(); // Called by ParamMtl
BOOL IsActive() { return isActive; }
private:
void ClampOffset();
void SetNumMats();
void UpdateLayers();
void UpdateControlFor(int np);
void VScroll(int code, short int cpos );
*/
protected:
void IUpdateMtlDisplay() { if (ip) ip->MtlChanged(); }
};
#endif

View File

@ -0,0 +1,81 @@
/*==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==*/
#ifndef PL_COMPOSITE_MTL_PB_H
#define PL_COMPOSITE_MTL_PB_H
enum
{
kCompPasses,
kCompOn,
kCompBlend,
kCompUVChannels,
kCompLayerCounts
};
// Make sure to pair up each blend mode with an inverse after it
// (This way we check for an inverse blend by doing an odd/even check.)
enum BlendMethod // These should match up in order with the blend strings
{
kCompBlendVertexAlpha,
kCompBlendInverseVtxAlpha,
kCompBlendVertexIllumRed,
kCompBlendInverseVtxIllumRed,
kCompBlendVertexIllumGreen,
kCompBlendInverseVtxIllumGreen,
kCompBlendVertexIllumBlue,
kCompBlendInverseVtxIllumBlue,
kCompNumBlendMethods
};
static char *BlendStrings[] = // Make sure these match up in order with the Blend enum
{
"Vertex Alpha",
"Inverse Vtx Alpha",
"Vertex Illum Red",
"Inv. Vtx Illum Red",
"Vertex Illum Green",
"Inv. Vtx Illum Green",
"Vertex Illum Blue",
"Inv. Vtx Illum Blue"
};
#endif //PL_COMPOSITE_MTL_PB_H

View File

@ -0,0 +1,67 @@
/*==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 "plCompositeMtl.h"
//#include "plCompositeMtlPB.h"
ClassDesc2* GetCompMtlDesc();
static ParamBlockDesc2 gCompositeMtlPB
(
plCompositeMtl::kBlkPasses, _T("composite"), 0, GetCompMtlDesc(),
P_AUTO_CONSTRUCT, plCompositeMtl::kRefPasses,
plCompositeMtl::kCompPasses, _T("passes"), TYPE_MTL_TAB, 3, 0, 0,
end,
plCompositeMtl::kCompOn, _T("passOn"), TYPE_BOOL_TAB, 2, 0, 0,
p_default, TRUE,
end,
plCompositeMtl::kCompBlend, _T("BlendMethod"), TYPE_INT_TAB, 2, 0, 0,
p_default, 0,
end,
plCompositeMtl::kCompUVChannels, _T("UVChannels"), TYPE_INT_TAB, 2, 0, 0,
p_default, 0,
end,
plCompositeMtl::kCompLayerCounts, _T("LayerCounts"), TYPE_INT_TAB, 3, 0, 0,
p_default, 0,
end,
end
);

View File

@ -0,0 +1,800 @@
/*==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 "hsTypes.h"
#include "plDecalMtl.h"
#include "resource.h"
//extern ClassDesc2* GetMaxLayerDesc();
#include "Shaders.h"
#include "../MaxComponent/plMaxAnimUtils.h"
#include "plPassBaseParamIDs.h"
#include "plDecalMtlBasicPB.h"
#include "plDecalMtlLayersPB.h"
#include "iparamm2.h"
#include "Layers/plLayerTex.h"
#include "Layers/plStaticEnvLayer.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
extern HINSTANCE hInstance;
class plDecalMtlClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading) { return TRACKED_NEW plDecalMtl(loading); }
const TCHAR* ClassName() { return GetString(IDS_DECAL_MTL); }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
Class_ID ClassID() { return DECAL_MTL_CLASS_ID; }
const TCHAR* Category() { return NULL; }
const TCHAR* InternalName() { return _T("PlasmaMaterial"); }
HINSTANCE HInstance() { return hInstance; }
};
static plDecalMtlClassDesc plDecalMtlDesc;
ClassDesc2* GetDecalMtlDesc() { return &plDecalMtlDesc; }
// For initializing paramblock descriptor
ParamBlockDesc2 *GetDecalBasicPB();
ParamBlockDesc2 *GetDecalAdvPB();
ParamBlockDesc2 *GetDecalLayersPB();
#include "plDecalMtlAdvPBDec.h"
#include "plDecalMtlBasicPBDec.h"
#include "plDecalMtlLayersPBDec.h"
#include "plDecalMtlAnimPBDec.h"
plDecalMtl::plDecalMtl(BOOL loading) : plPassMtlBase( loading )
{
plDecalMtlDesc.MakeAutoParamBlocks( this );
fLayersPB->SetValue( kDecalLayBase, 0, TRACKED_NEW plLayerTex );
fLayersPB->SetValue( kDecalLayTop, 0, TRACKED_NEW plLayerTex );
// If we do this later (like, when the dialog loads) something blows up,
// somewhere in Max. It didn't in 4, it does in 7. This seems to fix it.
if (!loading)
IVerifyStealthPresent(ENTIRE_ANIMATION_NAME);
}
ParamDlg* plDecalMtl::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
fIMtlParams = imp;
IAutoMParamDlg* masterDlg = plDecalMtlDesc.CreateParamDlgs(hwMtlEdit, imp, this);
return (ParamDlg*)masterDlg;
}
BOOL plDecalMtl::SetDlgThing(ParamDlg* dlg)
{
return FALSE;
}
Interval plDecalMtl::Validity(TimeValue t)
{
#if 0 // mf horse
Interval valid = FOREVER;
/* for (int i = 0; i < fSubTexmap.Count(); i++)
{
if (fSubTexmap[i])
valid &= fSubTexmap[i]->Validity(t);
}
*/
// float u;
// fPBlock->GetValue(pb_spin,t,u,valid);
return valid;
#else // mf horse
const char* name = GetName();
// mf horse - Hacking in something like real validity checking
// to get material animations working. No warranty, this is just
// better than nothing.
Interval v = FOREVER;
fBasicPB->GetValidity(t, v);
fAdvPB->GetValidity(t, v);
if( fLayersPB->GetTexmap(kDecalLayBase) )
v &= fLayersPB->GetTexmap(kDecalLayBase)->Validity(t);
if( fLayersPB->GetTexmap(kDecalLayTop) )
v &= fLayersPB->GetTexmap(kDecalLayTop)->Validity(t);
return v;
#endif // mf horse
}
//// GetReference ////////////////////////////////////////////////////////////
// Note: need to overload because MAX for some reason writes out the
// references by their INDEX. ARRRRGH!
RefTargetHandle plDecalMtl::GetReference( int i )
{
switch( i )
{
case kRefBasic: return fBasicPB;
case kRefAdv: return fAdvPB;
case kRefLayers: return fLayersPB;
case kRefAnim: return fAnimPB;
}
return plPassMtlBase::GetReference( i );
}
//// SetReference ////////////////////////////////////////////////////////////
// Note: need to overload because MAX for some reason writes out the
// references by their INDEX. ARRRRGH!
void plDecalMtl::SetReference(int i, RefTargetHandle rtarg)
{
if (i == kRefBasic)
fBasicPB = (IParamBlock2 *)rtarg;
else if (i == kRefAdv)
fAdvPB = (IParamBlock2 *)rtarg;
else if (i == kRefLayers)
fLayersPB = (IParamBlock2 *)rtarg;
else if (i == kRefAnim)
fAnimPB = (IParamBlock2 *)rtarg;
else
plPassMtlBase::SetReference( i, rtarg );
}
/*===========================================================================*\
| Subanim & References support
\*===========================================================================*/
int plDecalMtl::NumSubs()
{
return 6;
}
TSTR plDecalMtl::SubAnimName(int i)
{
switch (i)
{
case 0: return fBasicPB->GetLocalName();
case 1: return fAdvPB->GetLocalName();
case 2: return fLayersPB->GetLocalName();
case 3: return fAnimPB->GetLocalName();
case 4: return "Base Layer";
case 5: return "Top Layer";
}
return "";
}
Animatable* plDecalMtl::SubAnim(int i)
{
switch (i)
{
case 0: return fBasicPB;
case 1: return fAdvPB;
case 2: return fLayersPB;
case 3: return fAnimPB;
case 4: return fLayersPB->GetTexmap(kDecalLayBase);
case 5:
if (fLayersPB->GetInt(kDecalLayTopOn))
return fLayersPB->GetTexmap(kDecalLayTop);
break;
}
return NULL;
}
int plDecalMtl::NumParamBlocks()
{
return 4;
}
IParamBlock2* plDecalMtl::GetParamBlock(int i)
{
return (IParamBlock2*)GetReference(i);
}
IParamBlock2* plDecalMtl::GetParamBlockByID(BlockID id)
{
if (fBasicPB->ID() == id)
return fBasicPB;
else if (fAdvPB->ID() == id)
return fAdvPB;
else if (fLayersPB->ID() == id)
return fLayersPB;
else if (fAnimPB->ID() == id)
return fAnimPB;
return NULL;
}
RefResult plDecalMtl::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message)
{
return plPassMtlBase::NotifyRefChanged( changeInt, hTarget, partID, message );
}
////////////////////////////////////////////////////////////////////////////////
// Subtexmap access
int plDecalMtl::NumSubTexmaps()
{
return 2;
}
Texmap* plDecalMtl::GetSubTexmap(int i)
{
if (i == 0)
return fLayersPB->GetTexmap(kDecalLayBase);
else if (i == 1)
return fLayersPB->GetTexmap(kDecalLayTop);
return NULL;
}
void plDecalMtl::SetSubTexmap(int i, Texmap *m)
{
if (i == 0)
fLayersPB->SetValue(kDecalLayBase, 0, m);
else if (i == 1)
fLayersPB->SetValue(kDecalLayTop, 0, m);
}
TSTR plDecalMtl::GetSubTexmapSlotName(int i)
{
if (i == 0)
return "Base";
else if (i == 1)
return "Top";
return "";
}
TSTR plDecalMtl::GetSubTexmapTVName(int i)
{
return GetSubTexmapSlotName(i);
}
int plDecalMtl::SubTexmapOn(int i)
{
if (i == 0)
return 1;
else if (i == 1 && fLayersPB->GetInt(kDecalLayTopOn))
return 1;
return 0;
}
/*===========================================================================*\
| Updating and cloning
\*===========================================================================*/
RefTargetHandle plDecalMtl::Clone(RemapDir &remap)
{
plDecalMtl *mnew = TRACKED_NEW plDecalMtl(FALSE);
plPassMtlBase::ICloneBase( mnew, remap );
return (RefTargetHandle)mnew;
}
void plDecalMtl::ICloneRefs( plPassMtlBase *target, RemapDir &remap )
{
target->ReplaceReference(kRefBasic, remap.CloneRef(fBasicPB));
target->ReplaceReference(kRefAdv, remap.CloneRef(fAdvPB));
target->ReplaceReference(kRefLayers, remap.CloneRef(fLayersPB));
target->ReplaceReference(kRefAnim, remap.CloneRef(fAnimPB));
}
void plDecalMtl::NotifyChanged()
{
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
}
void plDecalMtl::Update(TimeValue t, Interval& valid)
{
// mf horse - Hacking in something like real validity checking
// to get material animations working. No warranty, this is just
// better than nothing.
if (!fIValid.InInterval(t))
{
fIValid.SetInfinite();
if( fLayersPB->GetTexmap(kDecalLayBase) )
fLayersPB->GetTexmap(kDecalLayBase)->Update(t, fIValid);
if( fLayersPB->GetTexmap(kDecalLayTop) )
fLayersPB->GetTexmap(kDecalLayTop)->Update(t, fIValid);
// fLayersPB->GetValue(kMtlLayLayer1On, t, fMapOn[0], fIValid);
/*
for (int i = 0; i < fSubTexmap.Count(); i++)
{
if (fSubTexmap[i])
fSubTexmap[i]->Update(t,fIValid);
}
*/
}
// Our wonderful way of version handling--if the runtimeColor is (-1,-1,-1), we know it's
// just been initialized, so set it to the static color (this lets us do the right thing for
// loading old paramBlocks)
if( fBasicPB )
{
Color run = fBasicPB->GetColor( kDecalBasRunColor, 0 );
if( run == Color(-1,-1,-1) )
{
fBasicPB->SetValue( kDecalBasRunColor, 0, fBasicPB->GetColor( kDecalBasColor, 0 ) );
}
// Also, if shineStr is anything other than -1, then it must be an old paramblock and we need
// to convert to our new specColor (we know this because the original valid range was 0-100)
int shine = fBasicPB->GetInt( kDecalBasShineStr, 0 );
if( shine != -1 )
{
fBasicPB->SetValue( kDecalBasSpecColor, 0, Color( (float)shine / 100.f, (float)shine / 100.f, (float)shine / 100.f ) );
fBasicPB->SetValue( kDecalBasShineStr, 0, (int)-1 );
}
}
valid &= fIValid;
}
/*===========================================================================*\
| Determine the characteristics of the material
\*===========================================================================*/
void plDecalMtl::SetAmbient(Color c, TimeValue t) {}
void plDecalMtl::SetDiffuse(Color c, TimeValue t) {}
void plDecalMtl::SetSpecular(Color c, TimeValue t) {}
void plDecalMtl::SetShininess(float v, TimeValue t) {}
Color plDecalMtl::GetAmbient(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plDecalMtl::GetDiffuse(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plDecalMtl::GetSpecular(int mtlNum, BOOL backFace) { return Color(0,0,0); }
float plDecalMtl::GetXParency(int mtlNum, BOOL backFace)
{
int opacity = fBasicPB->GetInt( kDecalBasOpacity, 0 );
float alpha = 1.0f - ( (float)opacity / 100.0f );
return alpha;
}
float plDecalMtl::GetShininess(int mtlNum, BOOL backFace) { return 0.0f; }
float plDecalMtl::GetShinStr(int mtlNum, BOOL backFace) { return 0.0f; }
float plDecalMtl::WireSize(int mtlNum, BOOL backFace) { return 0.0f; }
/////////////////////////////////////////////////////////////////
void plDecalMtl::SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb)
{
#if 0
if (texHandleValid.InInterval(t)) {
mtl->texture.SetCount(numTexHandlesUsed);
for (int i=0; i<numTexHandlesUsed; i++) {
if (texHandle[i]) {
mtl->texture[i].textHandle = texHandle[i]->GetHandle();
Texmap *tx = (*maps)[useSubForTex[i]].map;
cb.GetGfxTexInfoFromTexmap(t, mtl->texture[i], tx );
SetTexOps(mtl,i,texOpsType[i]);
}
}
return;
}
#endif
#if 0 // WTF?!?!?!?
Texmap *tx[2];
int diffChan = stdIDToChannel[ ID_DI ];
int opacChan = stdIDToChannel[ ID_OP ];
tx[0] = (*maps)[diffChan].IsActive()?(*maps)[diffChan].map:NULL;
tx[1] = (*maps)[opacChan].IsActive()?(*maps)[opacChan].map:NULL;
#endif
int nsupport = cb.NumberTexturesSupported();
#if 0
BITMAPINFO *bmi[NTEXHANDLES];
int nmaps=0;
for (int i=0; i<NTEXHANDLES; i++) {
if (tx[i]) nmaps ++;
bmi[i] = NULL;
}
mtl->texture.SetCount(nmaps);
if (nmaps==0)
return;
for (i=0; i<nmaps; i++)
mtl->texture[i].textHandle = NULL;
texHandleValid.SetInfinite();
Interval valid;
BOOL needDecal = FALSE;
int ntx = 0;
int op;
int forceW = 0;
int forceH = 0;
if (tx[0]) {
cb.GetGfxTexInfoFromTexmap(t, mtl->texture[0], tx[0]);
TextureInfo &ti = mtl->texture[0];
if (ti.tiling[0]==GW_TEX_NO_TILING||ti.tiling[1]==GW_TEX_NO_TILING)
needDecal = TRUE;
op = needDecal?TXOP_ALPHABLEND:TXOP_MODULATE;
bmi[0] = tx[0]->GetVPDisplayDIB(t,cb,valid,FALSE);
if (bmi[0]) {
texHandleValid &= valid;
useSubForTex[0] = diffChan;
ntx = 1;
forceW = bmi[0]->bmiHeader.biWidth;
forceH = bmi[0]->bmiHeader.biHeight;
}
}
if (tx[1]) {
cb.GetGfxTexInfoFromTexmap(t, mtl->texture[ntx], tx[1]);
if (nsupport>ntx) {
bmi[1] = tx[1]->GetVPDisplayDIB(t,cb,valid,TRUE);
if (bmi[1]) {
texHandleValid &= valid;
StuffAlpha(bmi[1], (*maps)[opacChan].amount, GetOpacity(t),ntx?whiteCol:pShader->GetDiffuseClr(t));
texHandle[ntx] = cb.MakeHandle(bmi[1]);
bmi[1] = NULL;
mtl->texture[ntx].textHandle = texHandle[ntx]->GetHandle();
SetTexOps(mtl,ntx,TXOP_OPACITY);
useSubForTex[ntx] = opacChan;
ntx++;
}
}
else {
if (!needDecal) {
TextureInfo ti;
// if (SameUV(mtl->texture[0],mtl->texture[1])) {
// Not really correct to combine channels for different UV's but what the heck.
bmi[1] = tx[1]->GetVPDisplayDIB(t,cb,valid,TRUE, forceW, forceH);
if (bmi[1]) {
texHandleValid &= valid;
StuffAlphaInto(bmi[1], bmi[0], (*maps)[opacChan].amount, GetOpacity(t));
op = TXOP_OPACITY;
free(bmi[1]);
bmi[1] = NULL;
}
// }
}
}
}
if (bmi[0]) {
texHandle[0] = cb.MakeHandle(bmi[0]);
bmi[0] = NULL;
mtl->texture[0].textHandle = texHandle[0]->GetHandle();
SetTexOps(mtl,0,op);
}
mtl->texture.SetCount(ntx);
numTexHandlesUsed = ntx;
#endif
}
/*===========================================================================*\
| Actual shading takes place
\*===========================================================================*/
void plDecalMtl::Shade(ShadeContext& sc)
{
// Get the background color
Color backColor, backTrans;
sc.GetBGColor(backColor, backTrans);
ShadeWithBackground(sc, backColor);
}
//// Requirements ////////////////////////////////////////////////////////////
// Tells MAX what we need to render ourselves properly, such as translucency,
// two-sidedness, etc. Flags are in imtl.h in the MAX SDK.
ULONG plDecalMtl::Requirements( int subMtlNum )
{
ULONG req = 0;
req = Mtl::Requirements( subMtlNum );
// Uncomment this to get the background color fed to our ShadeWithBackground()
// (slower processing tho)
// req |= MTLREQ_BGCOL;
req |= MTLREQ_UV;
int blendType = fLayersPB->GetInt( kDecalLayOutputBlend );
if( blendType == kBlendAdd )
req |= MTLREQ_ADDITIVE_TRANSP | MTLREQ_TRANSP;
else if( blendType == kBlendAlpha )
req |= MTLREQ_TRANSP;
else if( fBasicPB->GetInt( kDecalBasOpacity, 0 ) != 100 )
req |= MTLREQ_TRANSP;
if( fAdvPB->GetInt( kPBAdvTwoSided ) )
req |= MTLREQ_2SIDE;
return req;
}
void plDecalMtl::ShadeWithBackground(ShadeContext &sc, Color background)
{
#if 1
// old
#if 0
Color lightCol,rescol, diffIllum0;
RGBA mval;
Point3 N0,P;
BOOL bumped = FALSE;
int i;
if (gbufID)
sc.SetGBufferID(gbufID);
if (sc.mode == SCMODE_SHADOW) {
float opac = 0.0;
for (i=0; i < NumSubTexmaps(); i++) {
if (SubTexmapOn(i)) {
hsMaxLayerBase *hsmLay = (hsMaxLayerBase *)GetSubTexmap(i);
opac += hsmLay->GetOpacity(t);
}
}
float f = 1.0f - opac;
sc.out.t = Color(f,f,f);
return;
}
N0 = sc.Normal();
P = sc.P();
#endif
TimeValue t = sc.CurTime();
Color color(0, 0, 0);
float alpha = 0.0;
// Evaluate Base layer
Texmap *map = fLayersPB->GetTexmap(kDecalLayBase);
if (map && ( map->ClassID() == LAYER_TEX_CLASS_ID
|| map->ClassID() == STATIC_ENV_LAYER_CLASS_ID ) )
{
plLayerTex *layer = (plLayerTex*)map;
AColor evalColor = layer->EvalColor(sc);
color = evalColor;
alpha = evalColor.a;
}
// Evaluate Top layer, if it's on
if (fLayersPB->GetInt(kDecalLayTopOn))
{
Texmap *map = fLayersPB->GetTexmap(kDecalLayTop);
if (map && ( map->ClassID() == LAYER_TEX_CLASS_ID
|| map->ClassID() == STATIC_ENV_LAYER_CLASS_ID ) )
{
plLayerTex *layer = (plLayerTex*)map;
AColor evalColor = layer->EvalColor(sc);
// Blend layers
int blendType = fLayersPB->GetInt(kDecalLayBlend);
switch (blendType)
{
case kBlendAdd:
color += evalColor * evalColor.a;
break;
case kBlendAlpha:
color = (1.0f - evalColor.a) * color + evalColor.a * evalColor;
alpha = 1 - (1 - evalColor.a) * (1 - alpha);
break;
case kBlendMult:
color *= evalColor;
break;
default: // No blend...
color = evalColor;
alpha = 1.0;
break;
}
}
}
#if 1
AColor black;
black.Black();
AColor white;
white.White();
SIllumParams ip;
if (fBasicPB->GetInt(kDecalBasEmissive))
{
// Emissive objects don't get shaded
ip.diffIllum = fBasicPB->GetColor(kDecalBasColorAmb, t) * color;
ip.diffIllum.ClampMinMax();
ip.specIllum = black;
}
else
{
//
// Shading setup
//
// Setup the parameters for the shader
ip.amb = fBasicPB->GetColor(kDecalBasColorAmb, t);
ip.diff = fBasicPB->GetColor(kDecalBasColor, t) * color;
ip.diffIllum = black;
ip.specIllum = black;
ip.N = sc.Normal();
ip.V = sc.V();
//
// Specularity
//
if (fBasicPB->GetInt(kDecalBasUseSpec, t))
{
ip.sh_str = 1.f;
ip.spec = fBasicPB->GetColor( kDecalBasSpecColor, t );
ip.ph_exp = (float)pow(2.0f,float(fBasicPB->GetInt(kDecalBasShine, t)) / 10.0f);
ip.shine = float(fBasicPB->GetInt(kDecalBasShine, t)) / 100.0f;
}
else
{
ip.sh_str = 0;
ip.ph_exp = 0;
ip.shine = 0;
ip.spec = black;
}
ip.softThresh = 0;
//
// Do the shading
Shader *myShader = GetShader(SHADER_BLINN);
myShader->Illum(sc, ip);
// Override shader parameters
if (fAdvPB->GetInt(kPBAdvNoShade))
{
ip.diffIllum = black;
ip.specIllum = black;
}
if (fAdvPB->GetInt(kPBAdvWhite))
{
ip.diffIllum = white;
ip.specIllum = black;
}
ip.diffIllum.ClampMinMax();
ip.specIllum.ClampMinMax();
ip.diffIllum = ip.amb * sc.ambientLight + ip.diff * ip.diffIllum;
}
// AColor returnColor = AColor(opac * ip.diffIllum + ip.specIllum, opac)
#endif
// Get opacity and combine with alpha
float opac = float(fBasicPB->GetInt(kDecalBasOpacity, t)) / 100.0f;
alpha *= opac;
// MAX will do the additive/alpha/no blending for us based on what Requirements()
// we tell it. However, since MAX's formula is bgnd*sc.out.t + sc.out.c,
// we have to multiply our output color by the alpha.
// If we ever need a more complicated blending function, you can request the
// background color via Requirements() (otherwise it's just black) and then do
// the blending yourself; however, if the transparency isn't set, the shadows
// will be opaque, so be careful.
Color outC = ip.diffIllum + ip.specIllum;
sc.out.c = ( outC * alpha );
sc.out.t = Color( 1.f - alpha, 1.f - alpha, 1.f - alpha );
#endif
}
float plDecalMtl::EvalDisplacement(ShadeContext& sc)
{
return 0.0f;
}
Interval plDecalMtl::DisplacementValidity(TimeValue t)
{
Interval iv;
iv.SetInfinite();
return iv;
}
bool plDecalMtl::HasAlpha()
{
return ((plLayerTex *)fLayersPB->GetTexmap(kDecalLayBase))->HasAlpha();
}
// Massive list of inherited accessor functions for ParamBlock data
// Advanced Block
int plDecalMtl::GetBasicWire() { return fAdvPB->GetInt(kPBAdvWire); }
int plDecalMtl::GetMeshOutlines() { return fAdvPB->GetInt(kPBAdvMeshOutlines); }
int plDecalMtl::GetTwoSided() { return fAdvPB->GetInt(kPBAdvTwoSided); }
int plDecalMtl::GetSoftShadow() { return fAdvPB->GetInt(kPBAdvSoftShadow); }
int plDecalMtl::GetNoProj() { return fAdvPB->GetInt(kPBAdvNoProj); }
int plDecalMtl::GetVertexShade() { return fAdvPB->GetInt(kPBAdvVertexShade); }
int plDecalMtl::GetNoShade() { return fAdvPB->GetInt(kPBAdvNoShade); }
int plDecalMtl::GetNoFog() { return fAdvPB->GetInt(kPBAdvNoFog); }
int plDecalMtl::GetWhite() { return fAdvPB->GetInt(kPBAdvWhite); }
int plDecalMtl::GetZOnly() { return fAdvPB->GetInt(kPBAdvZOnly); }
int plDecalMtl::GetZClear() { return fAdvPB->GetInt(kPBAdvZClear); }
int plDecalMtl::GetZNoRead() { return fAdvPB->GetInt(kPBAdvZNoRead); }
int plDecalMtl::GetZNoWrite() { return fAdvPB->GetInt(kPBAdvZNoWrite); }
int plDecalMtl::GetZInc() { return fAdvPB->GetInt(kPBAdvZInc); }
int plDecalMtl::GetAlphaTestHigh() { return fAdvPB->GetInt(kPBAdvAlphaTestHigh); }
// Animation block
char * plDecalMtl::GetAnimName() { return fAnimPB->GetStr(kPBAnimName); }
int plDecalMtl::GetAutoStart() { return fAnimPB->GetInt(kPBAnimAutoStart); }
int plDecalMtl::GetLoop() { return fAnimPB->GetInt(kPBAnimLoop); }
char * plDecalMtl::GetAnimLoopName() { return fAnimPB->GetStr(kPBAnimLoopName); }
int plDecalMtl::GetEaseInType() { return fAnimPB->GetInt(kPBAnimEaseInType); }
float plDecalMtl::GetEaseInNormLength() { return fAnimPB->GetFloat(kPBAnimEaseInLength); }
float plDecalMtl::GetEaseInMinLength() { return fAnimPB->GetFloat(kPBAnimEaseInMin); }
float plDecalMtl::GetEaseInMaxLength() { return fAnimPB->GetFloat(kPBAnimEaseInMax); }
int plDecalMtl::GetEaseOutType() { return fAnimPB->GetInt(kPBAnimEaseOutType); }
float plDecalMtl::GetEaseOutNormLength() { return fAnimPB->GetFloat(kPBAnimEaseOutLength); }
float plDecalMtl::GetEaseOutMinLength() { return fAnimPB->GetFloat(kPBAnimEaseOutMin); }
float plDecalMtl::GetEaseOutMaxLength() { return fAnimPB->GetFloat(kPBAnimEaseOutMax); }
int plDecalMtl::GetUseGlobal() { return fAnimPB->GetInt(ParamID(kPBAnimUseGlobal)); }
char * plDecalMtl::GetGlobalVarName() { return fAnimPB->GetStr(ParamID(kPBAnimGlobalName)); }
// Basic block
int plDecalMtl::GetColorLock() { return fBasicPB->GetInt(kDecalBasColorLock); }
Color plDecalMtl::GetAmbColor() { return fBasicPB->GetColor(kDecalBasColorAmb); }
Color plDecalMtl::GetColor() { return fBasicPB->GetColor(kDecalBasColor); }
int plDecalMtl::GetOpacity() { return fBasicPB->GetInt(kDecalBasOpacity); }
int plDecalMtl::GetEmissive() { return fBasicPB->GetInt(kDecalBasEmissive); }
int plDecalMtl::GetUseSpec() { return fBasicPB->GetInt(kDecalBasUseSpec); }
int plDecalMtl::GetShine() { return fBasicPB->GetInt(kDecalBasShine); }
Color plDecalMtl::GetSpecularColor() { return fBasicPB->GetColor(kDecalBasSpecColor); }
Control *plDecalMtl::GetPreshadeColorController() { return fBasicPB->GetController(ParamID(kDecalBasColor)); }
Control *plDecalMtl::GetAmbColorController() { return fBasicPB->GetController(ParamID(kDecalBasColorAmb)); }
Control *plDecalMtl::GetOpacityController() { return fBasicPB->GetController(ParamID(kDecalBasOpacity)); }
Control *plDecalMtl::GetSpecularColorController() { return fBasicPB->GetController(ParamID(kDecalBasSpecColor)); }
int plDecalMtl::GetDiffuseColorLock() { return fBasicPB->GetInt(kDecalBasDiffuseLock); }
Color plDecalMtl::GetRuntimeColor() { return fBasicPB->GetColor(kDecalBasRunColor); }
Control *plDecalMtl::GetRuntimeColorController() { return fBasicPB->GetController(ParamID(kDecalBasRunColor)); }
// Layer block
Texmap *plDecalMtl::GetBaseLayer() { return fLayersPB->GetTexmap(kDecalLayBase); }
int plDecalMtl::GetTopLayerOn() { return fLayersPB->GetInt(kDecalLayTopOn); }
Texmap *plDecalMtl::GetTopLayer() { return fLayersPB->GetTexmap(kDecalLayTop); }
int plDecalMtl::GetLayerBlend() { return fLayersPB->GetInt(kDecalLayBlend); }
int plDecalMtl::GetOutputAlpha() { return fLayersPB->GetInt(kDecalLayOutputAlpha); }
int plDecalMtl::GetOutputBlend() { return fLayersPB->GetInt(kDecalLayOutputBlend); }

View File

@ -0,0 +1,209 @@
/*==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==*/
#ifndef PL_DECALMTL_H
#define PL_DECALMTL_H
#include "Max.h"
#include "iparamb2.h"
#include "../resource.h"
#include "plPassMtlBase.h"
#define DECAL_MTL_CLASS_ID Class_ID(0x691d2257, 0x419d629e)
extern TCHAR *GetString(int id);
class plDecalMtl : public plPassMtlBase
{
protected:
virtual void ICloneRefs( plPassMtlBase *target, RemapDir &remap );
public:
enum
{
kRefBasic,
kRefLayers,
kRefAdv,
kRefAnim,
};
enum Blocks
{
kBlkBasic,
kBlkLayers,
kBlkAdv,
kBlkAnim,
};
plDecalMtl(BOOL loading);
void DeleteThis() { delete this; }
//From Animatable
Class_ID ClassID() { return DECAL_MTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_DECAL_MTL); }
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void NotifyChanged();
BOOL SupportsMultiMapsInViewport() { return FALSE; }
void SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb);
// Shade and displacement calculation
void Shade(ShadeContext& sc);
void ShadeWithBackground(ShadeContext &sc, Color background);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
virtual RefTargetHandle GetReference( int i );
virtual void SetReference( int i, RefTargetHandle rtarg );
// SubTexmap access methods
int NumSubTexmaps();
Texmap* GetSubTexmap(int i);
void SetSubTexmap(int i, Texmap *m);
TSTR GetSubTexmapSlotName(int i);
TSTR GetSubTexmapTVName(int i);
int SubTexmapOn(int i);
BOOL SetDlgThing(ParamDlg* dlg);
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
// void SetParamDlg(ParamDlg *dlg);
// void SetNumSubTexmaps(int num);
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
ULONG Requirements( int subMtlNum );
virtual bool HasAlpha();
// Massive list of inherited accessor functions for ParamBlock data
// Advanced Block
virtual int GetBasicWire();
virtual int GetMeshOutlines();
virtual int GetTwoSided();
virtual int GetSoftShadow();
virtual int GetNoProj();
virtual int GetVertexShade();
virtual int GetNoShade();
virtual int GetNoFog();
virtual int GetWhite();
virtual int GetZOnly();
virtual int GetZClear();
virtual int GetZNoRead();
virtual int GetZNoWrite();
virtual int GetZInc();
virtual int GetAlphaTestHigh();
// Animation block
virtual char * GetAnimName();
virtual int GetAutoStart();
virtual int GetLoop();
virtual char * GetAnimLoopName();
virtual int GetEaseInType();
virtual float GetEaseInMinLength();
virtual float GetEaseInMaxLength();
virtual float GetEaseInNormLength();
virtual int GetEaseOutType();
virtual float GetEaseOutMinLength();
virtual float GetEaseOutMaxLength();
virtual float GetEaseOutNormLength();
virtual int GetUseGlobal();
virtual char * GetGlobalVarName();
// Basic block
virtual int GetColorLock();
virtual Color GetAmbColor();
virtual Color GetColor();
virtual int GetOpacity();
virtual int GetEmissive();
virtual int GetUseSpec();
virtual int GetShine();
virtual Color GetSpecularColor();
virtual Control *GetPreshadeColorController();
virtual Control *GetAmbColorController();
virtual Control *GetOpacityController();
virtual Control *GetSpecularColorController();
virtual int GetDiffuseColorLock();
virtual Color GetRuntimeColor();
virtual Control *GetRuntimeColorController();
// Layer block
virtual Texmap *GetBaseLayer();
virtual int GetTopLayerOn();
virtual Texmap *GetTopLayer();
virtual int GetLayerBlend();
virtual int GetOutputAlpha();
virtual int GetOutputBlend();
};
#endif //PL_DECALMTL_H

View File

@ -0,0 +1,83 @@
/*==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==*/
#ifndef PL_DECALMTLADVPB_H
#define PL_DECALMTLADVPB_H
// Param ID's
enum
{
// Specular
kDecalAdvUseSpec, // Not used anymore, feel free to replace with new fields as necessary
kDecalAdvSpecType, // ditto
kDecalAdvShine, // ...
kDecalAdvShineStr, // ...
// Misc
kDecalAdvWire,
kDecalAdvMeshOutlines,
kDecalAdvTwoSided,
// Shading
kDecalAdvSoftShadow,
kDecalAdvNoProj,
kDecalAdvVertexShade,
kDecalAdvNoShade,
kDecalAdvNoFog,
kDecalAdvWhite,
// Z
kDecalAdvZOnly,
kDecalAdvZClear,
kDecalAdvZNoRead,
kDecalAdvZNoWrite,
kDecalAdvZInc,
};
// Specular types
enum
{
kSpecTypeAlpha,
kSpecTypeColor,
kSpecTypeHighlight
};
#endif //PL_DECALMTLADVPB_H

View File

@ -0,0 +1,111 @@
/*==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 "plDecalMtl.h"
#include "plPassBaseParamIDs.h"
using namespace plPassBaseParamIDs;
static ParamBlockDesc2 gDecalAdvPB
(
plDecalMtl::kBlkAdv, _T("advanced"), IDS_PASS_ADV, GetDecalMtlDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI, plDecalMtl::kRefAdv,
// UI
IDD_PASS_ADV, IDS_PASS_ADV, 0, APPENDROLL_CLOSED, NULL,
// Misc Properties
kPBAdvWire, _T("basicWire"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_MISC_WIRE,
end,
kPBAdvMeshOutlines, _T("meshOutlines"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_MISC_MESHOUTLINES,
end,
kPBAdvTwoSided, _T("twoSided"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_MISC_TWOSIDED,
end,
// Shade properties
kPBAdvSoftShadow, _T("softShadow"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_SOFTSHADOW,
end,
kPBAdvNoProj, _T("noProj"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_NO_PROJ,
end,
kPBAdvVertexShade, _T("vertexShade"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_VERTEXSHADE,
end,
kPBAdvNoShade, _T("noShade"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_NOSHADE,
end,
kPBAdvNoFog, _T("noFog"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_NO_FOG,
end,
kPBAdvWhite, _T("white"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_WHITE,
end,
// Z Properties
kPBAdvZOnly, _T("zOnly"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZONLY,
end,
kPBAdvZClear, _T("zClear"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZCLEAR,
end,
kPBAdvZNoRead, _T("zNoRead"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZNOREAD,
end,
kPBAdvZNoWrite, _T("zNoWrite"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZNOWRITE,
p_default, TRUE,
end,
kPBAdvZInc, _T("zInc"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_INC,
p_default, TRUE,
end,
kPBAdvAlphaTestHigh, _T("aTestHigh"), TYPE_BOOL, 0, 0,
p_default, FALSE,
end,
end
);
ParamBlockDesc2 *GetDecalAdvPB() { return &gDecalAdvPB; }

View File

@ -0,0 +1,63 @@
/*==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==*/
#ifndef PL_DECALMTLANIMPB_H
#define PL_DECALMTLANIMPB_H
enum
{
kDecalAnimName,
kDecalAnimAutoStart,
kDecalAnimLoop,
kDecalAnimLoopName,
kDecalEaseInType, // Not used, but reserved
kDecalEaseOutType, //
kDecalEaseInLength, //
kDecalEaseOutLength, //
kDecalEaseInMin, //
kDecalEaseInMax, //
kDecalEaseOutMin, //
kDecalEaseOutMax, //
kDecalAnimUseGlobal, //
kDecalAnimGlobalName, //
};
#endif

View File

@ -0,0 +1,109 @@
/*==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 "plDecalMtl.h"
#include "plPassBaseParamIDs.h"
#include "resource.h"
#include "iparamm2.h"
#include "plPassAnimDlgProc.h"
#include "plAnimStealthNode.h"
using namespace plPassBaseParamIDs;
static ParamBlockDesc2 gDecalAnimPB
(
plDecalMtl::kBlkAnim, _T("anim"), IDS_PASS_ANIM, GetDecalMtlDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI + P_CALLSETS_ON_LOAD, plDecalMtl::kRefAnim,
// UI
IDD_PASS_ANIM, IDS_PASS_ANIM, 0, 0, &plPassAnimDlgProc::Get(),
#ifdef MCN_UPGRADE_OLD_ANIM_BLOCKS
// THE FOLLOWING ARE ALL OLD PARAMETERS AND SHOULD NO LONGER BE USED. The only reason
// they're here is so we can convert old paramBlocks into the new plAnimStealthNode format
kPBAnimName, _T("animName"), TYPE_STRING, 0, 0,
end,
kPBAnimAutoStart, _T("autoStart"), TYPE_BOOL, 0, 0,
end,
kPBAnimLoop, _T("loop"), TYPE_BOOL, 0, 0,
end,
kPBAnimLoopName, _T("loopName"), TYPE_STRING, 0, 0,
end,
// Anim Ease
kPBAnimEaseInType, _T("easeInType"), TYPE_INT, 0, 0,
end,
kPBAnimEaseInLength, _T("easeInLength"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseInMin, _T("easeInMin"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseInMax, _T("easeInMax"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutType, _T("easeOutType"), TYPE_INT, 0, 0,
end,
kPBAnimEaseOutLength, _T("easeOutLength"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutMin, _T("easeOutMin"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutMax, _T("easeOutMax"), TYPE_FLOAT, 0, 0,
end,
#endif // MCN_UPGRADE_OLD_ANIM_BLOCKS
kPBAnimUseGlobal, _T("UseGlobal"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_MTL_USE_GLOBAL,
end,
kPBAnimGlobalName, _T("GlobalName"), TYPE_STRING, 0, 0,
p_default, _T(""),
end,
kPBAnimStealthNodes, _T( "testing" ), TYPE_REFTARG_TAB, 0, 0, 0,
p_accessor, &plStealthNodeAccessor::GetInstance(),
end,
end
);
ParamBlockDesc2 *GetDecalAnimPB() { return &gDecalAnimPB; }

View File

@ -0,0 +1,68 @@
/*==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==*/
#ifndef PL_DECALMTLBASICPB_H
#define PL_DECALMTLBASICPB_H
// Param ID's
enum
{
kDecalBasColorLock,
kDecalBasColorAmb,
kDecalBasColor,
kDecalBasOpacity,
kDecalBasEmissive,
// Specular
kDecalBasUseSpec,
kDecalBasShine,
kDecalBasShineStr,
// New color stuff
kDecalBasDiffuseLock,
kDecalBasRunColor,
kDecalBasSpecColor
};
#endif //PL_DECALMTLBASICPB_H

View File

@ -0,0 +1,252 @@
/*==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 "plDecalMtl.h"
#include "plDecalMtlBasicPB.h"
#include "resource.h"
#include "iparamm2.h"
class DecalBasicPBAccessor;
extern DecalBasicPBAccessor basicAccessor;
class DecalBasicDlgProc;
extern DecalBasicDlgProc gDecalBasicDlgProc;
static ParamBlockDesc2 gDecalBasicPB
(
plDecalMtl::kBlkBasic, _T("basic"), IDS_PASS_BASIC, GetDecalMtlDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI, plDecalMtl::kRefBasic,
// UI
IDD_PASS_BASIC, IDS_PASS_BASIC, 0, 0, &gDecalBasicDlgProc,
// Color
kDecalBasColorLock, _T("colorLock"), TYPE_BOOL, 0, 0,
p_ui, TYPE_CHECKBUTTON, IDC_LOCK_AD,
p_accessor, &basicAccessor,
end,
kDecalBasColorAmb, _T("ambColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_AMB,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_COLOR_AMB,
p_accessor, &basicAccessor,
end,
kDecalBasColor, _T("color"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_COLOR,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_COLOR,
p_default, Color(1,1,1),
p_accessor, &basicAccessor,
end,
kDecalBasRunColor, _T("runtimeColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_RUNCOLOR,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_RUNCOLOR,
p_default, Color(1,1,1),
p_accessor, &basicAccessor,
end,
kDecalBasDiffuseLock, _T("diffuseLock"), TYPE_BOOL, 0, 0,
p_ui, TYPE_CHECKBUTTON, IDC_LOCK_COLORS,
p_accessor, &basicAccessor,
p_default, TRUE,
end,
// Opacity
kDecalBasOpacity, _T("opacity"), TYPE_INT, P_ANIMATABLE, IDS_BASIC_OPAC,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_TR_EDIT, IDC_TR_SPIN, 0.4,
p_range, 0, 100,
p_default, 100,
end,
kDecalBasEmissive, _T("emissive"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_LAYER_EMISSIVE_CB,
end,
// Specularity
kDecalBasUseSpec, _T("useSpec"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_SPECULAR,
p_enable_ctrls, 2, kDecalBasShine, kDecalBasShineStr,
end,
kDecalBasShine, _T("shine"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_SH_EDIT, IDC_SH_SPIN, 0.4,
p_range, 0, 100,
end,
kDecalBasSpecColor, _T("specularColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_SPECCOLOR,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_SPECCOLOR,
p_default, Color(0,0,0),
end,
// OBSOLETE--here so we can upgrade it to color if necessary
kDecalBasShineStr, _T("shineStr"), TYPE_INT, 0, 0,
p_range, -1, 100,
p_default, -1,
end,
end
);
ParamBlockDesc2 *GetDecalBasicPB() { return &gDecalBasicPB; }
class DecalBasicPBAccessor : public PBAccessor
{
bool fColorLocked;
public:
DecalBasicPBAccessor() : fColorLocked( false ) {}
void Set(PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
plDecalMtl* mtl = (plDecalMtl*)owner;
IParamBlock2 *pb = mtl->GetParamBlockByID(plDecalMtl::kBlkBasic);
switch (id)
{
case kDecalBasColorLock:
if (val.i)
pb->SetValue(kDecalBasColor, t, pb->GetColor(kDecalBasColorAmb, t));
break;
case kDecalBasDiffuseLock:
if (val.i)
pb->SetValue(kDecalBasRunColor, t, pb->GetColor(kDecalBasColor, t));
break;
case kDecalBasColor:
case kDecalBasColorAmb:
case kDecalBasRunColor:
ISyncLockedColors( id, pb, val, t );
break;
}
}
void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid)
{
}
void ISyncLockedColors( ParamID settingID, IParamBlock2 *pb, PB2Value &val, TimeValue t )
{
int i, numToSet = 0;
ParamID toSet[ 2 ];
if( fColorLocked )
return;
fColorLocked = true;
if( settingID == kDecalBasColorAmb && pb->GetInt( kDecalBasColorLock, t ) )
{
toSet[ numToSet++ ] = kDecalBasColor;
if( pb->GetInt( kDecalBasDiffuseLock, t ) )
toSet[ numToSet++ ] = kDecalBasRunColor;
}
else if( settingID == kDecalBasRunColor && pb->GetInt( kDecalBasDiffuseLock, t ) )
{
toSet[ numToSet++ ] = kDecalBasColor;
if( pb->GetInt( kDecalBasColorLock, t ) )
toSet[ numToSet++ ] = kDecalBasColorAmb;
}
else if( settingID == kDecalBasColor )
{
if( pb->GetInt( kDecalBasColorLock, t ) )
toSet[ numToSet++ ] = kDecalBasColorAmb;
if( pb->GetInt( kDecalBasDiffuseLock, t ) )
toSet[ numToSet++ ] = kDecalBasRunColor;
}
for( i = 0; i < numToSet; i++ )
{
pb->SetValue( toSet[ i ], t, *val.p );
pb->GetMap()->Invalidate( toSet[ i ] );
}
fColorLocked = false;
}
};
static DecalBasicPBAccessor basicAccessor;
class DecalBasicDlgProc : public ParamMap2UserDlgProc
{
#if 1
protected:
HIMAGELIST hLockButtons;
void LoadLockButtons()
{
static bool loaded = false;
if (loaded)
return;
loaded = true;
HINSTANCE hInst = hInstance;
hLockButtons = ImageList_Create(16, 15, TRUE, 2, 0);
HBITMAP hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BUTTONS));
HBITMAP hMask = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_MASKBUTTONS));
ImageList_Add(hLockButtons, hBitmap, hMask);
DeleteObject(hBitmap);
DeleteObject(hMask);
}
void ISetLock(HWND hButton)
{
LoadLockButtons();
ICustButton *iBut = GetICustButton(hButton);
iBut->SetImage(hLockButtons,0,1,0,1,16,15);
iBut->SetType(CBT_CHECK);
ReleaseICustButton(iBut);
}
public:
DecalBasicDlgProc() : hLockButtons(NULL) {}
~DecalBasicDlgProc() { if (hLockButtons) ImageList_Destroy(hLockButtons); }
#endif
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
IParamBlock2 *pb = map->GetParamBlock();
switch (msg)
{
case WM_INITDIALOG:
{
ISetLock(GetDlgItem(hWnd, IDC_LOCK_AD));
ISetLock(GetDlgItem(hWnd, IDC_LOCK_COLORS));
}
return TRUE;
}
return FALSE;
}
void DeleteThis() {}
};
static DecalBasicDlgProc gDecalBasicDlgProc;

View File

@ -0,0 +1,56 @@
/*==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==*/
#ifndef PL_DECALMTLLAYERSPB_H
#define PL_DECALMTLLAYERSPB_H
enum
{
// Layers
kDecalLayBase,
kDecalLayOutputBlend,
kDecalLayTopOn,
kDecalLayTop,
kDecalLayBlend,
kDecalLayOutputAlpha,
};
#endif //PL_DECALMTLLAYERSPB_H

View File

@ -0,0 +1,103 @@
/*==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 "plDecalMtl.h"
#include "plDecalMtlLayersPB.h"
#include "resource.h"
#include "iparamm2.h"
#include "Layers/plLayerTex.h"
class DecalMtlLayersAccessor;
extern DecalMtlLayersAccessor gLayersAccessor;
class LayersDlgProc;
extern LayersDlgProc gLayersDlgProc;
static ParamBlockDesc2 gDecalMtlLayersPB
(
plDecalMtl::kBlkLayers, _T("layers"), IDS_PASS_LAYERS, GetDecalMtlDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI, plDecalMtl::kRefLayers,
// UI
IDD_PASS_LAYERS, IDS_PASS_LAYERS, 0, 0, NULL,
kDecalLayBase, _T("baseLayer"), TYPE_TEXMAP, 0, IDS_BASIC_AMB,
p_ui, TYPE_TEXMAPBUTTON, IDC_LAYER1,
p_subtexno, 0,
end,
kDecalLayOutputBlend, _T("outputBlend"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_OUTPUTB_NONE, IDC_OUTPUTB_ALPHA, IDC_OUTPUTB_ADD,
p_vals, plPassMtlBase::kBlendNone, plPassMtlBase::kBlendAlpha, plPassMtlBase::kBlendAdd,
p_default, plPassMtlBase::kBlendNone,
end,
kDecalLayTopOn, _T("topLayerOn"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_TOP_ON,
p_default, FALSE,
p_enable_ctrls, 3, kDecalLayTop, kDecalLayBlend, kDecalLayOutputAlpha,
end,
kDecalLayTop, _T("topLayer"), TYPE_TEXMAP, 0, 0,
p_ui, TYPE_TEXMAPBUTTON, IDC_LAYER2,
p_subtexno, 1,
end,
kDecalLayBlend, _T("layerBlend"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_LAYER_ALPHA, IDC_LAYER_ADD, IDC_LAYER_MULTIPLY,
p_vals, plPassMtlBase::kBlendAlpha, plPassMtlBase::kBlendAdd, plPassMtlBase::kBlendMult,
p_default, plPassMtlBase::kBlendAdd,
end,
kDecalLayOutputAlpha, _T("ouputAlpha"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_OUTPUTA_DISCARD, IDC_OUTPUTA_ADD, IDC_OUTPUTA_MULT,
p_vals, plPassMtlBase::kAlphaDiscard, plPassMtlBase::kAlphaAdd, plPassMtlBase::kAlphaMultiply,
p_default, plPassMtlBase::kAlphaDiscard,
end,
end
);
ParamBlockDesc2 *GetDecalLayersPB() { return &gDecalMtlLayersPB; }

View File

@ -0,0 +1,386 @@
/*==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 "hsTypes.h"
#include "plMultipassMtl.h"
#include "plPassMtl.h"
#include "plMultipassMtlPB.h"
#include "plMultipassMtlDlg.h"
class plMultipassClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading) { return TRACKED_NEW plMultipassMtl(loading); }
const TCHAR* ClassName() { return GetString(IDS_MULTI_MTL); }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
Class_ID ClassID() { return MULTIMTL_CLASS_ID; }
const TCHAR* Category() { return NULL; }
const TCHAR* InternalName() { return _T("PlasmaMultipass"); }
HINSTANCE HInstance() { return hInstance; }
};
static plMultipassClassDesc plMultipassMtlDesc;
ClassDesc2* GetMultiMtlDesc() { return &plMultipassMtlDesc; }
#include "plMultipassMtlPB.cpp"
plMultipassMtl::plMultipassMtl(BOOL loading) : fPassesPB(NULL)
{
plMultipassMtlDesc.MakeAutoParamBlocks(this);
if (!loading)
Reset();
SetNumSubMtls(1);
}
void plMultipassMtl::Reset()
{
fIValid.SetEmpty();
}
ParamDlg* plMultipassMtl::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
fMtlDlg = TRACKED_NEW plMultipassMtlDlg(hwMtlEdit, imp, this);
return fMtlDlg;
}
void plMultipassMtl::SetParamDlg(ParamDlg *dlg)
{
fMtlDlg = (plMultipassMtlDlg*)dlg;
}
BOOL plMultipassMtl::SetDlgThing(ParamDlg* dlg)
{
if (dlg == fMtlDlg)
{
fMtlDlg->SetThing(this);
return TRUE;
}
return FALSE;
}
Interval plMultipassMtl::Validity(TimeValue t)
{
Interval valid = FOREVER;
/* for (int i = 0; i < fSubTexmap.Count(); i++)
{
if (fSubTexmap[i])
valid &= fSubTexmap[i]->Validity(t);
}
*/
// float u;
// fPBlock->GetValue(pb_spin,t,u,valid);
return valid;
}
/*===========================================================================*\
| Subanim & References support
\*===========================================================================*/
int plMultipassMtl::NumSubs()
{
return NumSubMtls();
}
TSTR plMultipassMtl::SubAnimName(int i)
{
return GetSubMtlSlotName(i);
}
Animatable* plMultipassMtl::SubAnim(int i)
{
return GetSubMtl(i);
}
int plMultipassMtl::NumRefs()
{
return 1;
}
RefTargetHandle plMultipassMtl::GetReference(int i)
{
if (i == kRefPasses)
return fPassesPB;
return NULL;
}
void plMultipassMtl::SetReference(int i, RefTargetHandle rtarg)
{
if (i == kRefPasses)
fPassesPB = (IParamBlock2 *)rtarg;
}
int plMultipassMtl::NumParamBlocks()
{
return 1;
}
IParamBlock2 *plMultipassMtl::GetParamBlock(int i)
{
if (i == kRefPasses)
return fPassesPB;
return NULL;
}
IParamBlock2 *plMultipassMtl::GetParamBlockByID(BlockID id)
{
if (fPassesPB->ID() == id)
return fPassesPB;
return NULL;
}
RefResult plMultipassMtl::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message )
{
switch (message)
{
case REFMSG_CHANGE:
fIValid.SetEmpty();
if (hTarget == fPassesPB)
{
ParamID changingParam = fPassesPB->LastNotifyParamID();
fPassesPB->GetDesc()->InvalidateUI(changingParam);
}
break;
}
return REF_SUCCEED;
}
////////////////////////////////////////////////////////////////////////////////
// Subtexmap access
int plMultipassMtl::NumSubMtls()
{
return fPassesPB->GetInt(kMultCount);
}
Mtl *plMultipassMtl::GetSubMtl(int i)
{
if (i < NumSubMtls())
return fPassesPB->GetMtl(kMultPasses, 0, i);
return NULL;
}
void plMultipassMtl::SetSubMtl(int i, Mtl *m)
{
if (i < NumSubMtls())
fPassesPB->SetValue(kMultPasses, 0, m, i);
}
TSTR plMultipassMtl::GetSubMtlSlotName(int i)
{
TSTR str;
str.printf("Pass %d", i+1);
return str;
}
TSTR plMultipassMtl::GetSubMtlTVName(int i)
{
return GetSubMtlSlotName(i);
}
/*===========================================================================*\
| Standard IO
\*===========================================================================*/
#define MTL_HDR_CHUNK 0x4000
IOResult plMultipassMtl::Save(ISave *isave)
{
IOResult res;
isave->BeginChunk(MTL_HDR_CHUNK);
res = MtlBase::Save(isave);
if (res!=IO_OK) return res;
isave->EndChunk();
return IO_OK;
}
IOResult plMultipassMtl::Load(ILoad *iload)
{
IOResult res;
int id;
while (IO_OK==(res=iload->OpenChunk()))
{
switch(id = iload->CurChunkID())
{
case MTL_HDR_CHUNK:
res = MtlBase::Load(iload);
break;
}
iload->CloseChunk();
if (res!=IO_OK)
return res;
}
return IO_OK;
}
/*===========================================================================*\
| Updating and cloning
\*===========================================================================*/
RefTargetHandle plMultipassMtl::Clone(RemapDir &remap)
{
plMultipassMtl *mnew = TRACKED_NEW plMultipassMtl(FALSE);
*((MtlBase*)mnew) = *((MtlBase*)this);
mnew->ReplaceReference(kRefPasses, remap.CloneRef(fPassesPB));
mnew->fIValid.SetEmpty();
BaseClone(this, mnew, remap);
return (RefTargetHandle)mnew;
}
void plMultipassMtl::NotifyChanged()
{
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
}
void plMultipassMtl::Update(TimeValue t, Interval& valid)
{
if (!fIValid.InInterval(t))
{
fIValid.SetInfinite();
// fPassesPB->GetValue(kMtlLayLayer1On, t, fMapOn[0], fIValid);
for (int i = 0; i < NumSubMtls(); i++)
{
if (GetSubMtl(i))
GetSubMtl(i)->Update(t, fIValid);
}
}
valid &= fIValid;
}
/*===========================================================================*\
| Determine the characteristics of the material
\*===========================================================================*/
void plMultipassMtl::SetAmbient(Color c, TimeValue t) {}
void plMultipassMtl::SetDiffuse(Color c, TimeValue t) {}
void plMultipassMtl::SetSpecular(Color c, TimeValue t) {}
void plMultipassMtl::SetShininess(float v, TimeValue t) {}
Color plMultipassMtl::GetAmbient(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plMultipassMtl::GetDiffuse(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plMultipassMtl::GetSpecular(int mtlNum, BOOL backFace) { return Color(0,0,0); }
float plMultipassMtl::GetXParency(int mtlNum, BOOL backFace) { return 0.0f; }
float plMultipassMtl::GetShininess(int mtlNum, BOOL backFace) { return 0.0f; }
float plMultipassMtl::GetShinStr(int mtlNum, BOOL backFace) { return 0.0f; }
float plMultipassMtl::WireSize(int mtlNum, BOOL backFace) { return 0.0f; }
/*===========================================================================*\
| Actual shading takes place
\*===========================================================================*/
void plMultipassMtl::Shade(ShadeContext& sc)
{
// Get the background color
Color backColor, backTrans;
backColor.Black();
backTrans.White();
int count = NumSubMtls();
for (int i = 0; i < count; i++)
{
if (fPassesPB->GetInt(kMultOn, 0, i) == 0)
continue;
// Call each pass' shade function with the previous color
Mtl *mtl = GetSubMtl(i);
//backTrans = Color(0,0,0);
if (mtl->ClassID() == PASS_MTL_CLASS_ID)
{
plPassMtl *passMtl = (plPassMtl*)mtl;
passMtl->ShadeWithBackground(sc, backColor);
backTrans *= sc.out.t;
backColor = backColor * sc.out.t + sc.out.c;
}
}
sc.out.t = backTrans;
sc.out.c = backColor;
}
float plMultipassMtl::EvalDisplacement(ShadeContext& sc)
{
return 0.0f;
}
Interval plMultipassMtl::DisplacementValidity(TimeValue t)
{
Interval iv;
iv.SetInfinite();
return iv;
}
void plMultipassMtl::SetNumSubMtls(int num)
{
TimeValue t = GetCOREInterface()->GetTime();
int curNum = fPassesPB->GetInt(kMultCount);
fPassesPB->SetValue(kMultCount, 0, num);
fPassesPB->SetCount(kMultPasses, num);
fPassesPB->SetCount(kMultOn, num);
fPassesPB->SetCount(kMultLayerCounts, num);
for (int i = curNum; i < num; i++)
{
plPassMtl *newMtl = TRACKED_NEW plPassMtl(false);
fPassesPB->SetValue(kMultPasses, t, newMtl, i);
fPassesPB->SetValue(kMultOn, t, TRUE, i);
GetCOREInterface()->AssignNewName(fPassesPB->GetMtl(kMultPasses, t, i));
}
}

View File

@ -0,0 +1,136 @@
/*==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==*/
#ifndef __PLMAXMTL__H
#define __PLMAXMTL__H
#include "Max.h"
#include "../resource.h"
#include "istdplug.h"
#include "iparamb2.h"
#include "iparamm2.h"
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
#define MULTIMTL_CLASS_ID Class_ID(0x3f687a, 0x28c62bd7)
class plMultipassMtlDlg;
class plMultipassMtl : public Mtl
{
protected:
IParamBlock2 *fPassesPB;
Interval fIValid;
plMultipassMtlDlg *fMtlDlg;
public:
enum { kRefPasses };
enum { kBlkPasses };
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void Reset();
void NotifyChanged();
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
// Shade and displacement calculation
void Shade(ShadeContext& sc);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
// SubTexmap access methods
int NumSubMtls();
Mtl* GetSubMtl(int i);
void SetSubMtl(int i, Mtl *m);
TSTR GetSubMtlSlotName(int i);
TSTR GetSubMtlTVName(int i);
BOOL SetDlgThing(ParamDlg* dlg);
plMultipassMtl(BOOL loading);
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
//From Animatable
Class_ID ClassID() { return MULTIMTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_MULTI_MTL); }
RefTargetHandle Clone(RemapDir &remap);
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
void DeleteThis() { delete this; }
void SetParamDlg(ParamDlg *dlg);
void SetNumSubMtls(int num);
};
#endif // __PLMAXMTL__H

View File

@ -0,0 +1,342 @@
/*==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 "hsTypes.h"
#include "max.h"
#include "MaxIcon.h"
#include "resource.h"
#include "plMultipassMtl.h"
#include "plMultipassMtlPB.h"
//#include "plMaxLayer.h"
#include "plMultipassMtlDlg.h"
struct LayerID
{
int layerID;
int activeID;
};
static LayerID kLayerID[] =
{
{ IDC_TEX1, IDC_TEXON1 },
{ IDC_TEX2, IDC_TEXON2 },
{ IDC_TEX3, IDC_TEXON3 },
{ IDC_TEX4, IDC_TEXON4 },
{ IDC_TEX5, IDC_TEXON5 },
{ IDC_TEX6, IDC_TEXON6 },
{ IDC_TEX7, IDC_TEXON7 },
{ IDC_TEX8, IDC_TEXON8 },
{ IDC_TEX9, IDC_TEXON9 },
{ IDC_TEX10, IDC_TEXON10 },
};
//-----------------------------------------------------------------------------
// Constructor and destructor
//-----------------------------------------------------------------------------
plMultipassMtlDlg::plMultipassMtlDlg(HWND hwMtlEdit, IMtlParams *imp, plMultipassMtl *m)
{
fDADMgr.Init(this);
fhMtlEdit = hwMtlEdit;
fhRollup = NULL;
fMtl = m;
fPBlock = fMtl->GetParamBlockByID(plMultipassMtl::kBlkPasses);
ip = imp;
valid = FALSE;
for (int i = 0; i < NSUBMTLS; i++)
fLayerBtns[i] = NULL;
curTime = imp->GetTime();
fhRollup = ip->AddRollupPage(
hInstance,
MAKEINTRESOURCE(IDD_MULTIPASS),
ForwardProc,
"Multipass Parameters",
(LPARAM)this);
}
plMultipassMtlDlg::~plMultipassMtlDlg()
{
fMtl->SetParamDlg(NULL);
for (int i = 0; i < NSUBMTLS; i++)
{
ReleaseICustButton(fLayerBtns[i]);
fLayerBtns[i] = NULL;
}
SetWindowLong(fhRollup, GWL_USERDATA, NULL);
ip->DeleteRollupPage(fhRollup);
fhRollup = NULL;
}
//-----------------------------------------------------------------------------
// Functions inheirited from ParamDlg
//-----------------------------------------------------------------------------
void plMultipassMtlDlg::SetThing(ReferenceTarget *m)
{
assert(m->SuperClassID() == MATERIAL_CLASS_ID);
assert(m->ClassID() == MULTIMTL_CLASS_ID);
// Bad?
if (fMtl)
fMtl->SetParamDlg(NULL);
fMtl = (plMultipassMtl *)m;
if (fMtl)
fMtl->SetParamDlg(this);
LoadDialog();
IUpdateMtlDisplay();
}
void plMultipassMtlDlg::SetTime(TimeValue t)
{
if (t != curTime)
{
curTime = t;
Interval v;
fMtl->Update(ip->GetTime(),v);
LoadDialog();
IUpdateMtlDisplay();
}
}
void plMultipassMtlDlg::ReloadDialog()
{
Interval v;
fMtl->Update(ip->GetTime(), v);
LoadDialog();
}
void plMultipassMtlDlg::ActivateDlg(BOOL onOff)
{
}
int plMultipassMtlDlg::FindSubMtlFromHWND(HWND hwnd)
{
for (int i = 0; i < NSUBMTLS; i++)
{
if (hwnd == fLayerBtns[i]->GetHwnd())
return i;
}
return -1;
}
BOOL plMultipassMtlDlg::ForwardProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
plMultipassMtlDlg *theDlg;
if (msg == WM_INITDIALOG)
{
theDlg = (plMultipassMtlDlg*)lParam;
theDlg->fhRollup = hDlg;
SetWindowLong(hDlg, GWL_USERDATA, lParam);
}
else
{
if ((theDlg = (plMultipassMtlDlg *)GetWindowLong(hDlg, GWL_USERDATA)) == NULL)
return FALSE;
}
return theDlg->LayerPanelProc(hDlg,msg,wParam,lParam);
}
//----------------------------------------------------------------------------
// Layer panel processor
//----------------------------------------------------------------------------
BOOL plMultipassMtlDlg::LayerPanelProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
int id = LOWORD(wParam);
int code = HIWORD(wParam);
int i;
switch (msg)
{
case WM_INITDIALOG:
{
int nLayers = fPBlock->GetInt(kMultCount);
for (i = 0; i < NSUBMTLS; i++)
{
fLayerBtns[i] = GetICustButton(GetDlgItem(hDlg, kLayerID[i].layerID));
fLayerBtns[i]->SetDADMgr(&fDADMgr);
/* if (i < nLayers)
{
SetCheckBox(hDlg, kLayerID[i].activeID, fPBlock->GetInt(kMtlLayerOn, curTime, i));
}
*/
fNumTexSpin = SetupIntSpinner(hDlg, IDC_LAYER_SPIN, IDC_LAYER_EDIT, 1, 10, nLayers);
}
// TEMP testing
UpdateLayerDisplay();
IUpdateMtlDisplay();
}
return TRUE;
case WM_DESTROY:
for (i = 0; i < NSUBMTLS; i++)
{
ReleaseICustButton(fLayerBtns[i]);
fLayerBtns[i] = NULL;
}
ReleaseISpinner(fNumTexSpin);
fNumTexSpin = NULL;
break;
case CC_SPINNER_CHANGE:
if (id == IDC_LAYER_SPIN && !code)
{
IGetSpinnerVal();
return TRUE;
}
break;
case CC_SPINNER_BUTTONUP:
if (id == IDC_LAYER_SPIN && code)
{
IGetSpinnerVal();
return TRUE;
}
break;
case WM_COMMAND:
{
for (i = 0; i < NSUBMTLS; i++)
{
if (id == kLayerID[i].activeID)
{
// fMtl->EnableMap(i,GetCheckBox(hwndDlg, id));
bool checked = SendMessage(GetDlgItem(hDlg, id), BM_GETCHECK, 0, 0) == BST_CHECKED;
fPBlock->SetValue(kMultOn, curTime, checked, i);
return TRUE;
}
if (id == kLayerID[i].layerID)
{
PostMessage(fhMtlEdit, WM_SUB_MTL_BUTTON, i, (LPARAM)fMtl);
return TRUE;
}
}
}
// IUpdateMtlDisplay();
break;
}
return FALSE;
}
void plMultipassMtlDlg::UpdateLayerDisplay()
{
int numlayers = fPBlock->GetInt(kMultCount);
fNumTexSpin->SetValue(numlayers, FALSE);
int i;
for (i = 0; i < numlayers && i < NSUBMTLS; i++)
{
Mtl *m = fPBlock->GetMtl(kMultPasses, curTime, i);
TSTR nm;
if (m)
nm = m->GetName();
else
nm = "None";
fLayerBtns[i]->SetText(nm.data());
ShowWindow(GetDlgItem(fhRollup, kLayerID[i].layerID), SW_SHOW);
ShowWindow(GetDlgItem(fhRollup, kLayerID[i].activeID), SW_SHOW);
SetCheckBox(fhRollup, kLayerID[i].activeID, fPBlock->GetInt(kMultOn, curTime, i));
}
for (i = numlayers; i < NSUBMTLS; i++)
{
ShowWindow(GetDlgItem(fhRollup, kLayerID[i].layerID), SW_HIDE);
ShowWindow(GetDlgItem(fhRollup, kLayerID[i].activeID), SW_HIDE);
}
}
void plMultipassMtlDlg::LoadDialog()
{
if (fMtl)
{
fPBlock = fMtl->GetParamBlockByID(plMultipassMtl::kBlkPasses);
if (fhRollup)
UpdateLayerDisplay();
}
}
bool plMultipassMtlDlg::ISetNumLayers(int num)
{
if (num >= 1 && num <= NSUBMTLS)
{
fMtl->SetNumSubMtls(num);
UpdateLayerDisplay();
// IUpdateMtlDisplay();
return true;
}
return false;
}
void plMultipassMtlDlg::IGetSpinnerVal()
{
ISpinnerControl *spin = GetISpinner(GetDlgItem(fhRollup, IDC_LAYER_SPIN));
if (!spin)
return;
// If new number of layers is invalid, set to current num
if (!ISetNumLayers(spin->GetIVal()))
{
int nLayers = fPBlock->GetInt(kMultCount);
spin->SetValue(nLayers, FALSE);
}
ReleaseISpinner(spin);
}

View File

@ -0,0 +1,105 @@
/*==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==*/
#ifndef PL_MAXMTLDLG_H
#define PL_MAXMTLDLG_H
#define NSUBMTLS 10
class plMultipassMtlDlg : public ParamDlg
{
protected:
IParamBlock2 *fPBlock;
HWND fhMtlEdit; // Window handle of the materials editor dialog
HWND fhRollup; // Our rollup panel
IMtlParams *ip;
plMultipassMtl *fMtl; // current mtl being edited.
TimeValue curTime;
int isActive;
BOOL valid;
// int offset;
ISpinnerControl *fNumTexSpin;
ICustButton *fLayerBtns[NSUBMTLS];
MtlDADMgr fDADMgr; // For drag-drop sub-materials
public:
// Constructor and destructor
plMultipassMtlDlg(HWND hwMtlEdit, IMtlParams *imp, plMultipassMtl *m);
~plMultipassMtlDlg();
// Functions inherited from ParamDLg:
Class_ID ClassID() { return MULTIMTL_CLASS_ID; }
void SetThing(ReferenceTarget *m);
ReferenceTarget* GetThing() { return (ReferenceTarget*)fMtl; }
void SetTime(TimeValue t);
void ReloadDialog();
void ActivateDlg(BOOL onOff);
void DeleteThis() { delete this; }
int FindSubMtlFromHWND(HWND hw);
static BOOL CALLBACK ForwardProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL LayerPanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
void UpdateLayerDisplay();
void LoadDialog();
/*
// Lower-level crap
void Invalidate(); // Called by ParamMtl
BOOL IsActive() { return isActive; }
private:
void ClampOffset();
void SetNumMats();
void UpdateLayers();
void UpdateControlFor(int np);
void VScroll(int code, short int cpos );
*/
protected:
void IUpdateMtlDisplay() { if (ip) ip->MtlChanged(); }
bool ISetNumLayers(int num);
void IGetSpinnerVal();
};
#endif

View File

@ -0,0 +1,66 @@
/*==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 "hsTypes.h"
#include "plMultipassMtl.h"
#include "plMultipassMtlPB.h"
ClassDesc2* GetMultiMtlDesc();
static ParamBlockDesc2 gMultipassMtlPB
(
plMultipassMtl::kBlkPasses, _T("multipass"), 0, GetMultiMtlDesc(),
P_AUTO_CONSTRUCT, plMultipassMtl::kRefPasses,
kMultCount, _T("numPasses"), TYPE_INT, 0, 0,
p_default, 0,
end,
kMultPasses, _T("passes"), TYPE_MTL_TAB, 0, 0, 0,
end,
kMultOn, _T("passOn"), TYPE_BOOL_TAB, 0, 0, 0,
p_default, TRUE,
end,
kMultLayerCounts, _T("LayerCounts"), TYPE_INT_TAB, 0, 0, 0,
p_default, 0,
end,
end
);

View File

@ -0,0 +1,53 @@
/*==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==*/
#ifndef PL_MULTIPASS_MTL_PB_H
#define PL_MULTIPASS_MTL_PB_H
enum
{
kMultCount,
kMultPasses,
kMultOn,
kMultLayerCounts
};
#endif //PL_MULTIPASS_MTL_PB_H

View File

@ -0,0 +1,143 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plNoteTrackWatcher - Dummy object to watch for notetrack additions or //
// removals from the main material that owns it. //
// All of this is required because MAX will notify //
// an object's dependents about notetrack actions but //
// NOT the object itself, and the Add/DeleteNoteTrack //
// functions are non-virtual. ARRRGH! //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plNoteTrackWatcher.h"
#include "plPassMtlBase.h"
#include "iparamm2.h"
#include "resource.h"
//// Watcher Class Desc //////////////////////////////////////////////////////
plNoteTrackWatcher::plNoteTrackWatcher( plPassMtlBase *parentMtl ) : fParentMtl(nil)
{
fNoteTrackCount = parentMtl->NumNoteTracks();
MakeRefByID( FOREVER, kRefParentMtl, parentMtl );
}
plNoteTrackWatcher::~plNoteTrackWatcher()
{
if( fParentMtl != nil )
{
fParentMtl->fNTWatcher = nil;
DeleteReference( kRefParentMtl );
}
DeleteAllRefsFromMe();
}
BOOL plNoteTrackWatcher::IsRealDependency( ReferenceTarget *rtarg )
{
if( rtarg == fParentMtl )
return false;
return true;
}
int plNoteTrackWatcher::NumRefs()
{
return 1;
}
RefTargetHandle plNoteTrackWatcher::GetReference( int i )
{
if( i == kRefParentMtl )
return fParentMtl;
return nil;
}
void plNoteTrackWatcher::SetReference( int i, RefTargetHandle rtarg )
{
if( i == kRefParentMtl )
fParentMtl = (plPassMtlBase *)rtarg;
}
RefResult plNoteTrackWatcher::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message)
{
switch( message )
{
case REFMSG_SUBANIM_STRUCTURE_CHANGED:
if( hTarget == fParentMtl && fParentMtl != nil )
{
// Structure of parent material changed--did it gain or lose a notetrack?
int oldCount = fNoteTrackCount;
fNoteTrackCount = fParentMtl->NumNoteTracks();
if( oldCount != fNoteTrackCount )
{
// Is it an addition?
if( fNoteTrackCount > oldCount )
// Yes, notify parent.
fParentMtl->NoteTrackAdded();
else
// Deletion, also notify parent
fParentMtl->NoteTrackRemoved();
}
}
break;
case REFMSG_NODE_NAMECHANGE:
if( hTarget == fParentMtl )
{
fParentMtl->NameChanged();
}
break;
case REFMSG_TARGET_DELETED:
fParentMtl = nil;
break;
}
return REF_SUCCEED;
}

View File

@ -0,0 +1,104 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plNoteTrackWatcher - Dummy object to watch for notetrack additions or //
// removals from the main material that owns it. //
// All of this is required because MAX will notify //
// an object's dependents about notetrack actions but //
// NOT the object itself, and the Add/DeleteNoteTrack //
// functions are non-virtual. ARRRGH! //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plNoteTrackWatcher_h
#define _plNoteTrackWatcher_h
#include "Max.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "hsTypes.h"
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
#define NTWATCHER_CLASSID Class_ID(0x313f531e, 0xa5f132f)
#define REFMSG_NOTETRACK_ADDED REFMSG_USER + 1
class plPassMtlBase;
class NoteTrack;
//// Class Def ///////////////////////////////////////////////////////////////
class plNoteTrackWatcher : public ReferenceMaker
{
protected:
plPassMtlBase *fParentMtl;
// For tracking notetrack additions to the parent
int fNoteTrackCount;
public:
enum Refs
{
kRefParentMtl = 0
};
plNoteTrackWatcher( plPassMtlBase *parentMtl );
virtual ~plNoteTrackWatcher();
void DeleteThis() { delete this; }
Class_ID ClassID() { return NTWATCHER_CLASSID; }
SClass_ID SuperClassID() { return REF_MAKER_CLASS_ID; }
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
RefResult NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget, PartID& partID, RefMessage message);
virtual BOOL IsRealDependency( ReferenceTarget *rtarg );
};
#endif //_plNoteTrackWatcher_h

View File

@ -0,0 +1,636 @@
/*==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 "hsTypes.h"
#include "plParticleMtl.h"
#include "resource.h"
//extern ClassDesc2* GetMaxLayerDesc();
#include "Shaders.h"
#include "iparamm2.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "plBMSampler.h"
#include "stdmat.h"
#include "Layers/plLayerTex.h"
#include "Layers/plLayerTexBitmapPB.h"
extern HINSTANCE hInstance;
class plParticleMtlClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading) { return TRACKED_NEW plParticleMtl(loading); }
const TCHAR* ClassName() { return GetString(IDS_PARTICLE_MTL); }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
Class_ID ClassID() { return PARTICLE_MTL_CLASS_ID; }
const TCHAR* Category() { return NULL; }
const TCHAR* InternalName() { return _T("ParticleMaterial"); }
HINSTANCE HInstance() { return hInstance; }
};
static plParticleMtlClassDesc plParticleMtlDesc;
ClassDesc2* GetParticleMtlDesc() { return &plParticleMtlDesc; }
// For initializing paramblock descriptor
ParamBlockDesc2 *GetParticlePB();
#include "plParticleMtlPBDec.h"
const char *plParticleMtl::NormalStrings[] = // Make sure these match up in order with the Normal enum (in the header)
{
"Normal: View Facing",
"Normal: Up",
"Normal: Nearest Light",
"Normal: From Center",
"Normal: Vel x Up x Vel",
"Emissive"
};
plParticleMtl::plParticleMtl(BOOL loading) : fBasicPB(NULL)//, fBM(NULL), fUVGen(NULL)
{
#if 0 // This wasn't working on load
// Initialize the paramblock descriptors only once
static bool descInit = false;
if (!descInit)
{
descInit = true;
GetParticlePB()->SetClassDesc(GetParticleMtlDesc());
}
#endif
plParticleMtlDesc.MakeAutoParamBlocks(this);
// if (!loading)
{
Reset();
plLayerTex *tex = TRACKED_NEW plLayerTex;
//tex->GetParamBlockByID(kBlkBasic)->SetValue(kBmpUseBitmap, 0, 1);
fBasicPB->SetValue(kTexmap, 0, tex);
}
//fUVGen = GetNewDefaultUVGen();
}
void plParticleMtl::Reset()
{
fIValid.SetEmpty();
}
ParamDlg* plParticleMtl::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
fIMtlParams = imp;
IAutoMParamDlg* masterDlg = plParticleMtlDesc.CreateParamDlgs(hwMtlEdit, imp, this);
return (ParamDlg*)masterDlg;
}
BOOL plParticleMtl::SetDlgThing(ParamDlg* dlg)
{
return FALSE;
}
Interval plParticleMtl::Validity(TimeValue t)
{
#if 0 // mf horse
Interval valid = FOREVER;
/* for (int i = 0; i < fSubTexmap.Count(); i++)
{
if (fSubTexmap[i])
valid &= fSubTexmap[i]->Validity(t);
}
*/
// float u;
// fPBlock->GetValue(pb_spin,t,u,valid);
return valid;
#else // mf horse
const char* name = GetName();
// mf horse - Hacking in something like real validity checking
// to get material animations working. No warranty, this is just
// better than nothing.
Interval v = FOREVER;
fBasicPB->GetValidity(t, v);
return v;
#endif // mf horse
}
/*===========================================================================*\
| Subanim & References support
\*===========================================================================*/
int plParticleMtl::NumSubs()
{
return 2;
}
TSTR plParticleMtl::SubAnimName(int i)
{
switch (i)
{
case 0: return fBasicPB->GetLocalName();
case 1: return "Texmap";
}
return "";
}
Animatable* plParticleMtl::SubAnim(int i)
{
switch (i)
{
case 0: return fBasicPB;
case 1: return fBasicPB->GetTexmap(kTexmap);
}
return NULL;
}
int plParticleMtl::NumRefs()
{
return 1;
}
RefTargetHandle plParticleMtl::GetReference(int i)
{
switch (i)
{
case kRefBasic: return fBasicPB;
}
return NULL;
}
void plParticleMtl::SetReference(int i, RefTargetHandle rtarg)
{
if (i == kRefBasic)
fBasicPB = (IParamBlock2 *)rtarg;
}
int plParticleMtl::NumParamBlocks()
{
return 1;
}
IParamBlock2* plParticleMtl::GetParamBlock(int i)
{
return (IParamBlock2*)GetReference(i);
}
IParamBlock2* plParticleMtl::GetParamBlockByID(BlockID id)
{
if (fBasicPB->ID() == id)
return fBasicPB;
return NULL;
}
RefResult plParticleMtl::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message)
{
switch (message)
{
case REFMSG_CHANGE:
fIValid.SetEmpty();
// see if this message came from a changing parameter in the pblock,
// if so, limit rollout update to the changing item
if (hTarget == fBasicPB)
{
IParamBlock2 *pb = (IParamBlock2*)hTarget;
ParamID changingParam = pb->LastNotifyParamID();
pb->GetDesc()->InvalidateUI(changingParam);
// And let the SceneWatcher know that the material on some of it's
// referenced objects changed.
NotifyDependents(FOREVER, PART_ALL, REFMSG_USER_MAT);
}
break;
}
return REF_SUCCEED;
}
////////////////////////////////////////////////////////////////////////////////
// Subtexmap access
int plParticleMtl::NumSubTexmaps()
{
return 1;
}
Texmap* plParticleMtl::GetSubTexmap(int i)
{
if (i == 0)
return fBasicPB->GetTexmap(kTexmap);
return NULL;
}
void plParticleMtl::SetSubTexmap(int i, Texmap *m)
{
if (i == 0)
fBasicPB->SetValue(kTexmap, 0, m);
}
TSTR plParticleMtl::GetSubTexmapSlotName(int i)
{
if (i == 0)
return "Texmap";
return "";
}
TSTR plParticleMtl::GetSubTexmapTVName(int i)
{
return GetSubTexmapSlotName(i);
}
/*===========================================================================*\
| Standard IO
\*===========================================================================*/
#define MTL_HDR_CHUNK 0x4000
IOResult plParticleMtl::Save(ISave *isave)
{
IOResult res;
isave->BeginChunk(MTL_HDR_CHUNK);
res = MtlBase::Save(isave);
if (res!=IO_OK) return res;
isave->EndChunk();
return IO_OK;
}
IOResult plParticleMtl::Load(ILoad *iload)
{
IOResult res;
int id;
while (IO_OK==(res=iload->OpenChunk()))
{
switch(id = iload->CurChunkID())
{
case MTL_HDR_CHUNK:
res = MtlBase::Load(iload);
break;
}
iload->CloseChunk();
if (res!=IO_OK)
return res;
}
return IO_OK;
}
/*===========================================================================*\
| Updating and cloning
\*===========================================================================*/
RefTargetHandle plParticleMtl::Clone(RemapDir &remap)
{
plParticleMtl *mnew = TRACKED_NEW plParticleMtl(FALSE);
*((MtlBase*)mnew) = *((MtlBase*)this);
mnew->ReplaceReference(kRefBasic, remap.CloneRef(fBasicPB));
BaseClone(this, mnew, remap);
mnew->fIValid.SetEmpty();
return (RefTargetHandle)mnew;
}
void plParticleMtl::NotifyChanged()
{
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
}
void plParticleMtl::Update(TimeValue t, Interval& valid)
{
//StdUVGen *gen = (StdUVGen *)fUVGen;
//gen->SetUScl(1.0f, t);
//gen->SetVScl(1.0f, t);
//gen->Update(t, fIValid);
valid &= fIValid;
}
/*===========================================================================*\
| Determine the characteristics of the material
\*===========================================================================*/
void plParticleMtl::SetAmbient(Color c, TimeValue t) {}
void plParticleMtl::SetDiffuse(Color c, TimeValue t) {}
void plParticleMtl::SetSpecular(Color c, TimeValue t) {}
void plParticleMtl::SetShininess(float v, TimeValue t) {}
Color plParticleMtl::GetAmbient(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plParticleMtl::GetDiffuse(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plParticleMtl::GetSpecular(int mtlNum, BOOL backFace) { return Color(0,0,0); }
float plParticleMtl::GetXParency(int mtlNum, BOOL backFace)
{
int opacity = fBasicPB->GetInt( kOpacity, 0 );
float alpha = 1.0f - ( (float)opacity / 100.0f );
return alpha;
}
float plParticleMtl::GetShininess(int mtlNum, BOOL backFace) { return 0.0f; }
float plParticleMtl::GetShinStr(int mtlNum, BOOL backFace) { return 0.0f; }
float plParticleMtl::WireSize(int mtlNum, BOOL backFace) { return 0.0f; }
/////////////////////////////////////////////////////////////////
void plParticleMtl::SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb)
{
#if 0
if (texHandleValid.InInterval(t)) {
mtl->texture.SetCount(numTexHandlesUsed);
for (int i=0; i<numTexHandlesUsed; i++) {
if (texHandle[i]) {
mtl->texture[i].textHandle = texHandle[i]->GetHandle();
Texmap *tx = (*maps)[useSubForTex[i]].map;
cb.GetGfxTexInfoFromTexmap(t, mtl->texture[i], tx );
SetTexOps(mtl,i,texOpsType[i]);
}
}
return;
}
#endif
#if 0 // WTF?!?!?!?
Texmap *tx[2];
int diffChan = stdIDToChannel[ ID_DI ];
int opacChan = stdIDToChannel[ ID_OP ];
tx[0] = (*maps)[diffChan].IsActive()?(*maps)[diffChan].map:NULL;
tx[1] = (*maps)[opacChan].IsActive()?(*maps)[opacChan].map:NULL;
#endif
int nsupport = cb.NumberTexturesSupported();
#if 0
BITMAPINFO *bmi[NTEXHANDLES];
int nmaps=0;
for (int i=0; i<NTEXHANDLES; i++) {
if (tx[i]) nmaps ++;
bmi[i] = NULL;
}
mtl->texture.SetCount(nmaps);
if (nmaps==0)
return;
for (i=0; i<nmaps; i++)
mtl->texture[i].textHandle = NULL;
texHandleValid.SetInfinite();
Interval valid;
BOOL needDecal = FALSE;
int ntx = 0;
int op;
int forceW = 0;
int forceH = 0;
if (tx[0]) {
cb.GetGfxTexInfoFromTexmap(t, mtl->texture[0], tx[0]);
TextureInfo &ti = mtl->texture[0];
if (ti.tiling[0]==GW_TEX_NO_TILING||ti.tiling[1]==GW_TEX_NO_TILING)
needDecal = TRUE;
op = needDecal?TXOP_ALPHABLEND:TXOP_MODULATE;
bmi[0] = tx[0]->GetVPDisplayDIB(t,cb,valid,FALSE);
if (bmi[0]) {
texHandleValid &= valid;
useSubForTex[0] = diffChan;
ntx = 1;
forceW = bmi[0]->bmiHeader.biWidth;
forceH = bmi[0]->bmiHeader.biHeight;
}
}
if (tx[1]) {
cb.GetGfxTexInfoFromTexmap(t, mtl->texture[ntx], tx[1]);
if (nsupport>ntx) {
bmi[1] = tx[1]->GetVPDisplayDIB(t,cb,valid,TRUE);
if (bmi[1]) {
texHandleValid &= valid;
StuffAlpha(bmi[1], (*maps)[opacChan].amount, GetOpacity(t),ntx?whiteCol:pShader->GetDiffuseClr(t));
texHandle[ntx] = cb.MakeHandle(bmi[1]);
bmi[1] = NULL;
mtl->texture[ntx].textHandle = texHandle[ntx]->GetHandle();
SetTexOps(mtl,ntx,TXOP_OPACITY);
useSubForTex[ntx] = opacChan;
ntx++;
}
}
else {
if (!needDecal) {
TextureInfo ti;
// if (SameUV(mtl->texture[0],mtl->texture[1])) {
// Not really correct to combine channels for different UV's but what the heck.
bmi[1] = tx[1]->GetVPDisplayDIB(t,cb,valid,TRUE, forceW, forceH);
if (bmi[1]) {
texHandleValid &= valid;
StuffAlphaInto(bmi[1], bmi[0], (*maps)[opacChan].amount, GetOpacity(t));
op = TXOP_OPACITY;
free(bmi[1]);
bmi[1] = NULL;
}
// }
}
}
}
if (bmi[0]) {
texHandle[0] = cb.MakeHandle(bmi[0]);
bmi[0] = NULL;
mtl->texture[0].textHandle = texHandle[0]->GetHandle();
SetTexOps(mtl,0,op);
}
mtl->texture.SetCount(ntx);
numTexHandlesUsed = ntx;
#endif
}
/*===========================================================================*\
| Actual shading takes place
\*===========================================================================*/
void plParticleMtl::Shade(ShadeContext& sc)
{
// Get the background color
Color backColor, backTrans;
sc.GetBGColor(backColor, backTrans);
ShadeWithBackground(sc, backColor);
}
//// Requirements ////////////////////////////////////////////////////////////
// Tells MAX what we need to render ourselves properly, such as translucency,
// two-sidedness, etc. Flags are in imtl.h in the MAX SDK.
ULONG plParticleMtl::Requirements( int subMtlNum )
{
ULONG req = 0;
req = Mtl::Requirements( subMtlNum );
// Uncomment this to get the background color fed to our ShadeWithBackground()
// (slower processing tho)
// req |= MTLREQ_BGCOL;
int blendType = fBasicPB->GetInt( kBlend );
if( blendType == kBlendAdd )
req |= MTLREQ_ADDITIVE_TRANSP | MTLREQ_TRANSP;
else if( blendType == kBlendAlpha )
req |= MTLREQ_TRANSP;
else if( fBasicPB->GetInt( kOpacity, 0 ) != 100 )
req |= MTLREQ_TRANSP;
return req;
}
void plParticleMtl::ShadeWithBackground(ShadeContext &sc, Color background)
{
#if 1
TimeValue t = sc.CurTime();
Color color(0, 0, 0);
float alpha = 0.0;
// Evaluate Base layer
Texmap *map = fBasicPB->GetTexmap(kTexmap);
if (map && map->ClassID() == LAYER_TEX_CLASS_ID)
{
plLayerTex *layer = (plLayerTex*)map;
AColor evalColor = layer->EvalColor(sc);
color = evalColor;
alpha = evalColor.a;
}
#if 1
AColor black;
black.Black();
AColor white;
white.White();
SIllumParams ip;
if( fBasicPB->GetInt( kNormal ) == kEmissive )
{
// Emissive objects don't get shaded
ip.diffIllum = fBasicPB->GetColor(kColorAmb, t) * color;
ip.diffIllum.ClampMinMax();
ip.specIllum = black;
}
else
{
//
// Shading setup
//
// Setup the parameters for the shader
ip.amb = black;
ip.diff = fBasicPB->GetColor(kColor, t) * color;
ip.spec = white;
ip.diffIllum = black;
ip.specIllum = black;
ip.N = sc.Normal();
ip.V = sc.V();
//
// Specularity
//
ip.sh_str = 0;
ip.ph_exp = 0;
ip.shine = 0;
ip.softThresh = 0;
// Do the shading
Shader *myShader = GetShader(SHADER_BLINN);
myShader->Illum(sc, ip);
ip.diffIllum.ClampMinMax();
ip.specIllum.ClampMinMax();
ip.diffIllum = ip.amb * sc.ambientLight + ip.diff * ip.diffIllum;
}
// AColor returnColor = AColor(opac * ip.diffIllum + ip.specIllum, opac)
#endif
// Get opacity and combine with alpha
float opac = float(fBasicPB->GetInt(kOpacity, t)) / 100.0f;
//float opac = 1.0f;
alpha *= opac;
// MAX will do the additive/alpha/no blending for us based on what Requirements()
// we tell it. However, since MAX's formula is bgnd*sc.out.t + sc.out.c,
// we have to multiply our output color by the alpha.
// If we ever need a more complicated blending function, you can request the
// background color via Requirements() (otherwise it's just black) and then do
// the blending yourself; however, if the transparency isn't set, the shadows
// will be opaque, so be careful.
Color outC = ip.diffIllum + ip.specIllum;
sc.out.c = ( outC * alpha );
sc.out.t = Color( 1.f - alpha, 1.f - alpha, 1.f - alpha );
#endif
}
float plParticleMtl::EvalDisplacement(ShadeContext& sc)
{
return 0.0f;
}
Interval plParticleMtl::DisplacementValidity(TimeValue t)
{
Interval iv;
iv.SetInfinite();
return iv;
}
Control *plParticleMtl::GetAmbColorController() { return fBasicPB->GetController(ParamID(kColorAmb)); }
Control *plParticleMtl::GetColorController() { return fBasicPB->GetController(ParamID(kColor)); }
Control *plParticleMtl::GetOpacityController() { return fBasicPB->GetController(ParamID(kOpacity)); }
Control *plParticleMtl::GetWidthController() { return fBasicPB->GetController(ParamID(kWidth)); }
Control *plParticleMtl::GetHeightController() { return fBasicPB->GetController(ParamID(kHeight)); }

View File

@ -0,0 +1,198 @@
/*==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==*/
#ifndef PL_PARTICLEMTL_H
#define PL_PARTICLEMTL_H
#include "Max.h"
//#include "istdplug.h"
#include "iparamb2.h"
//#include "iparamm2.h"
#include "../resource.h"
class Bitmap;
#define PARTICLE_MTL_CLASS_ID Class_ID(0x26df05ff, 0x60660749)
extern TCHAR *GetString(int id);
class plParticleMtl : public Mtl
{
protected:
IParamBlock2 *fBasicPB;
Interval fIValid;
public:
IMtlParams *fIMtlParams;
enum
{
kRefBasic,
};
enum
{
kBlkBasic,
};
enum // Param block indicies
{
kOpacity,
kColor,
kWidth,
kHeight,
kXTiles,
kYTiles,
kNormal,
kBlend,
kOrientation,
kBitmap,
kTexmap,
kColorAmb,
kNoFilter
};
enum
{
kBlendNone,
kBlendAlpha,
kBlendAdd
};
enum
{
kOrientVelocity,
kOrientUp,
kOrientVelStretch,
kOrientVelFlow
};
enum
{
kNormalViewFacing,
kNormalUp,
kNormalNearestLight,
kNormalFromCenter,
kNormalVelUpVel,
kEmissive,
kNumNormalOptions
};
static const char *NormalStrings[];
plParticleMtl(BOOL loading);
void DeleteThis() { delete this; }
//From Animatable
Class_ID ClassID() { return PARTICLE_MTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_PARTICLE_MTL); }
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void Reset();
void NotifyChanged();
BOOL SupportsMultiMapsInViewport() { return FALSE; }
void SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb);
// Shade and displacement calculation
void Shade(ShadeContext& sc);
void ShadeWithBackground(ShadeContext &sc, Color background);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
// SubTexmap access methods
int NumSubTexmaps();
Texmap* GetSubTexmap(int i);
void SetSubTexmap(int i, Texmap *m);
TSTR GetSubTexmapSlotName(int i);
TSTR GetSubTexmapTVName(int i);
BOOL SetDlgThing(ParamDlg* dlg);
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
// void SetParamDlg(ParamDlg *dlg);
// void SetNumSubTexmaps(int num);
DllExport Control *GetAmbColorController();
DllExport Control *GetColorController();
DllExport Control *GetOpacityController();
DllExport Control *GetWidthController();
DllExport Control *GetHeightController();
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
ULONG Requirements( int subMtlNum );
};
#endif //PL_PARTICLEMTL_H

View File

@ -0,0 +1,250 @@
/*==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 "plParticleMtl.h"
class PartMtlPBAccessor;
extern PartMtlPBAccessor partMtl_accessor;
class ParticleBasicDlgProc;
extern ParticleBasicDlgProc gParticleBasicDlgProc;
#define PL_PARTICLE_MTL_MIN_TILES 1
#define PL_PARTICLE_MTL_MAX_TILES 16
static ParamBlockDesc2 gParticleMtlPB
(
plParticleMtl::kBlkBasic, _T("particle"), IDS_PASS_BASIC, GetParticleMtlDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI + P_CALLSETS_ON_LOAD, plParticleMtl::kRefBasic,
// UI
IDD_PARTICLE, IDS_PASS_BASIC, 0, 0, &gParticleBasicDlgProc,
plParticleMtl::kOpacity, _T("opacity"), TYPE_INT, P_ANIMATABLE, IDS_PARTICLE_OPACITY,
p_default, 100,
p_range, 0, 100,
p_ui, TYPE_SPINNER, EDITTYPE_INT,
IDC_PARTICLE_OPACITY, IDC_PARTICLE_OPACITY_SPIN, 1.0,
end,
plParticleMtl::kColorAmb, _T("ambColor"), TYPE_RGBA, P_ANIMATABLE, IDS_PARTICLE_AMB_COLOR,
p_ui, TYPE_COLORSWATCH, IDC_PARTICLE_AMB_COLOR,
p_default, Color(0,0,0),
end,
plParticleMtl::kColor, _T("color"), TYPE_RGBA, P_ANIMATABLE, IDS_PARTICLE_COLOR,
p_ui, TYPE_COLORSWATCH, IDC_PARTICLE_COLOR,
p_default, Color(1,1,1),
end,
plParticleMtl::kWidth, _T("width"), TYPE_FLOAT, P_ANIMATABLE, IDS_PARTICLE_WIDTH,
p_default, 1.0,
p_range, 0.01, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_PARTICLE_WIDTH, IDC_PARTICLE_WIDTH_SPIN, 1.0,
end,
plParticleMtl::kHeight, _T("height"), TYPE_FLOAT, P_ANIMATABLE, IDS_PARTICLE_HEIGHT,
p_default, 1.0,
p_range, 0.01, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_PARTICLE_HEIGHT, IDC_PARTICLE_HEIGHT_SPIN, 1.0,
end,
plParticleMtl::kXTiles, _T("xTiling"), TYPE_INT, 0, 0,
p_default, 1,
p_range, PL_PARTICLE_MTL_MIN_TILES, PL_PARTICLE_MTL_MAX_TILES,
p_ui, TYPE_SPINNER, EDITTYPE_POS_INT,
IDC_PARTICLE_XTILE, IDC_PARTICLE_XTILE_SPIN, 1.0,
p_accessor, &partMtl_accessor,
end,
plParticleMtl::kYTiles, _T("yTiling"), TYPE_INT, 0, 0,
p_default, 1,
p_range, PL_PARTICLE_MTL_MIN_TILES, PL_PARTICLE_MTL_MAX_TILES,
p_ui, TYPE_SPINNER, EDITTYPE_POS_INT,
IDC_PARTICLE_YTILE, IDC_PARTICLE_YTILE_SPIN, 1.0,
p_accessor, &partMtl_accessor,
end,
plParticleMtl::kNormal, _T("normal"), TYPE_INT, 0, 0,
p_default, 0,
end,
plParticleMtl::kBlend, _T("texBlend"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 2, IDC_PARTICLE_BLEND_ALPHA, IDC_PARTICLE_BLEND_ADD,
p_vals, plParticleMtl::kBlendAlpha, plParticleMtl::kBlendAdd,
p_default, plParticleMtl::kBlendAlpha,
end,
plParticleMtl::kOrientation, _T("layerBlend"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 4, IDC_PARTICLE_ORIENT_VELOCITY, IDC_PARTICLE_ORIENT_UP, IDC_PARTICLE_ORIENT_VELSTRETCH, IDC_PARTICLE_ORIENT_VELFLOW,
p_vals, plParticleMtl::kOrientVelocity, plParticleMtl::kOrientUp, plParticleMtl::kOrientVelStretch, plParticleMtl::kOrientVelFlow,
p_default, plParticleMtl::kOrientVelocity,
end,
plParticleMtl::kBitmap, _T("bitmap"), TYPE_BITMAP, P_SHORT_LABELS, 0,
///p_ui, TYPE_BITMAPBUTTON, IDC_PARTICLE_TEXTURE,
//p_accessor, &partMtl_accessor,
end,
plParticleMtl::kTexmap, _T("texmap"), TYPE_TEXMAP, 0, 0,
// p_ui, TYPE_TEXMAPBUTTON, IDC_LAYER2,
end,
plParticleMtl::kNoFilter, _T("noFilter"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_PARTICLE_NOFILTER,
p_default, FALSE,
end,
end
);
class PartMtlPBAccessor : public PBAccessor
{
public:
void Set(PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
plParticleMtl* mtl = (plParticleMtl *)owner;
//plLayerTex *layer;
switch (id)
{
case plParticleMtl::kBitmap:
break;
case plParticleMtl::kXTiles:
case plParticleMtl::kYTiles:
if (val.i < PL_PARTICLE_MTL_MIN_TILES)
val.i = PL_PARTICLE_MTL_MIN_TILES;
if (val.i > PL_PARTICLE_MTL_MAX_TILES)
val.i = PL_PARTICLE_MTL_MAX_TILES;
break;
}
}
void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid)
{
}
};
static PartMtlPBAccessor partMtl_accessor;
class ParticleBasicDlgProc : public ParamMap2UserDlgProc
{
public:
ParticleBasicDlgProc() {}
~ParticleBasicDlgProc() {}
void UpdateDisplay(IParamMap2 *pmap)
{
HWND hWnd = pmap->GetHWnd();
IParamBlock2 *pb = pmap->GetParamBlock();
HWND cbox = GetDlgItem(hWnd, IDC_PARTICLE_NORMAL);
plPlasmaMAXLayer *layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(plParticleMtl::kTexmap));
PBBitmap *pbbm;
ICustButton *bmSelectBtn;
SendMessage(cbox, CB_SETCURSEL, pb->GetInt(plParticleMtl::kNormal), 0);
pbbm = (layer == nil ? nil : layer->GetPBBitmap());
bmSelectBtn = GetICustButton(GetDlgItem(hWnd,IDC_PARTICLE_TEXTURE));
bmSelectBtn->SetText(pbbm ? (TCHAR*)pbbm->bi.Filename() : "(none)");
ReleaseICustButton(bmSelectBtn);
}
virtual void Update(TimeValue t, Interval& valid, IParamMap2* pmap) { UpdateDisplay(pmap); }
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
int id = LOWORD(wParam);
int code = HIWORD(wParam);
IParamBlock2 *pb = map->GetParamBlock();
HWND cbox = NULL;
plPlasmaMAXLayer *layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(plParticleMtl::kTexmap));
switch (msg)
{
case WM_INITDIALOG:
int j;
for (j = 0; j < plParticleMtl::kNumNormalOptions; j++)
{
cbox = GetDlgItem(hWnd, IDC_PARTICLE_NORMAL);
SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)plParticleMtl::NormalStrings[j]);
}
UpdateDisplay(map);
return TRUE;
case WM_COMMAND:
if (id == IDC_PARTICLE_NORMAL)
{
pb->SetValue(plParticleMtl::kNormal, t, SendMessage(GetDlgItem(hWnd, id), CB_GETCURSEL, 0, 0));
return TRUE;
}
else if (id == IDC_PARTICLE_TEXTURE)
{
if (layer == nil)
return FALSE;
layer->HandleBitmapSelection();
UpdateDisplay(map);
return TRUE;
}
else if (id == IDC_PARTICLE_NOFILTER)
{
if (!layer)
return FALSE;
if( pb->GetInt(plParticleMtl::kNoFilter) )
{
layer->GetParamBlockByID( plLayerTex::kBlkBitmap )->SetValue(kBmpNoFilter, t, 1);
}
else
{
layer->GetParamBlockByID( plLayerTex::kBlkBitmap )->SetValue(kBmpNoFilter, t, 0);
}
return TRUE;
}
break;
}
return FALSE;
}
void DeleteThis() {}
};
static ParticleBasicDlgProc gParticleBasicDlgProc;

View File

@ -0,0 +1,321 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plPassAnimDlgProc - Base Animation Dlg Proc for plPassMtlBase //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plPassAnimDlgProc.h"
#include "plPassBaseParamIDs.h"
#include "../MaxComponent/plNotetrackAnim.h"
#include "resource.h"
#include "iparamm2.h"
#include "plAnimStealthNode.h"
#include "../MaxComponent/plMaxAnimUtils.h"
#include "../MaxComponent/plAnimComponent.h"
#include "../MaxExport/plErrorMsg.h"
const char *kPassNameNone = ENTIRE_ANIMATION_NAME;
#include "plAnimStealthNode.h"
using namespace plPassBaseParamIDs;
plPassAnimDlgProc::plPassAnimDlgProc()
{
fCurrParamMap = nil;
fInitingNames = false;
}
plPassAnimDlgProc::~plPassAnimDlgProc()
{
if( fCurrParamMap != nil )
{
plPassMtlBase *mtl = (plPassMtlBase *)( fCurrParamMap->GetParamBlock()->GetOwner() );
mtl->RegisterChangeCallback( this );
}
}
plPassAnimDlgProc &plPassAnimDlgProc::Get( void )
{
static plPassAnimDlgProc instance;
return instance;
}
void plPassAnimDlgProc::Update(TimeValue t, Interval& valid, IParamMap2* pmap)
{
/* plAnimStealthNode *testStealth = (plAnimStealthNode *)pmap->GetParamBlock()->GetINode( (ParamID)kPBAnimTESTING );
if( testStealth != nil )
{
IParamBlock2 *pb = testStealth->GetParamBlockByID( plAnimStealthNode::kBlockPB );
if( pb && pb->GetMap() && pb->GetMap()->GetUserDlgProc() )
pb->GetMap()->GetUserDlgProc()->Update( t, valid, pmap );
}
*/
HWND hWnd = pmap->GetHWnd();
IParamBlock2 *pb = pmap->GetParamBlock();
plAnimComponentProc::SetBoxToAgeGlobal(GetDlgItem(hWnd, IDC_MTL_GLOBAL_NAME), pb->GetStr(ParamID(kPBAnimGlobalName)));
}
BOOL plPassAnimDlgProc::DlgProc(TimeValue t, IParamMap2 *pMap, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if( fCurrParamMap != pMap )
{
if( fCurrParamMap != nil )
{
plPassMtlBase *mtl = (plPassMtlBase *)( fCurrParamMap->GetParamBlock()->GetOwner() );
mtl->UnregisterChangeCallback( this );
}
fCurrParamMap = pMap;
if( fCurrParamMap != nil )
{
plPassMtlBase *mtl = (plPassMtlBase *)( fCurrParamMap->GetParamBlock()->GetOwner() );
mtl->RegisterChangeCallback( this );
}
}
IParamBlock2 *pb = pMap->GetParamBlock();
plPassMtlBase *mtl = (plPassMtlBase*)pb->GetOwner();
HWND gWnd = GetDlgItem(hWnd, IDC_MTL_GLOBAL_NAME);
char buff[512];
switch (msg)
{
case WM_DESTROY:
if( fCurrParamMap != nil )
{
plPassMtlBase *mtl = (plPassMtlBase *)( fCurrParamMap->GetParamBlock()->GetOwner() );
mtl->RegisterChangeCallback( this );
fCurrParamMap = nil;
}
break;
case WM_INITDIALOG:
{
fhWnd = hWnd;
fCurrStealth = nil;
IInitControls(mtl, pb);
plAnimComponentProc::FillAgeGlobalComboBox(gWnd, pb->GetStr(ParamID(kPBAnimGlobalName)));
plAnimComponentProc::SetBoxToAgeGlobal(gWnd, pb->GetStr(ParamID(kPBAnimGlobalName)));
IEnableGlobal(hWnd, pb->GetInt( (ParamID)kPBAnimUseGlobal ) );
bool stopPoints = false;
if( DoesHaveStopPoints( pb->GetOwner() ) )
{
stopPoints = true;
break;
}
IEnableEaseStopPoints( pMap, stopPoints );
}
return TRUE;
case WM_COMMAND:
// Anim name selection changed
if (LOWORD(wParam) == IDC_NAMES && HIWORD(wParam) == CBN_SELCHANGE)
{
IUpdateSegmentSel( pMap );
return TRUE;
}
// Refresh clicked
else if (LOWORD(wParam) == IDC_REFRESH_ANIMS && HIWORD(wParam) == BN_CLICKED)
{
IInitControls(mtl, pb);
return TRUE;
}
else if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_MTL_GLOBAL_NAME)
{
ComboBox_GetLBText(gWnd, ComboBox_GetCurSel(gWnd), buff);
pb->SetValue(ParamID(kPBAnimGlobalName), 0, _T(buff));
}
else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_MTL_USE_GLOBAL)
{
IEnableGlobal(hWnd, pb->GetInt( (ParamID)kPBAnimUseGlobal ) );
}
break;
}
return FALSE;
}
void plPassAnimDlgProc::SegmentListChanged( void )
{
if( fCurrParamMap != nil )
ILoadNames( fCurrParamMap->GetParamBlock() );
}
void plPassAnimDlgProc::IUpdateSegmentSel( IParamMap2 *thisMap, hsBool clear )
{
plAnimStealthNode *newStealth;
HWND hAnims = GetDlgItem( fhWnd, IDC_NAMES );
// Get current selection
if( clear )
newStealth = nil;
else
{
int sel = SendDlgItemMessage( fhWnd, IDC_NAMES, CB_GETCURSEL, 0, 0 );
if( sel == CB_ERR )
{
// Somehow we don't have a selection...fine, just destroy
newStealth = nil;
}
else
{
newStealth = (plAnimStealthNode *)SendDlgItemMessage( fhWnd, IDC_NAMES, CB_GETITEMDATA, sel, 0 );
}
}
// Did we really not change?
if( newStealth == fCurrStealth )
return;
if( fCurrStealth != nil && newStealth != nil )
{
fCurrStealth->SwitchDlg( newStealth );
}
else
{
// Destroy the old
if( fCurrStealth != nil )
fCurrStealth->ReleaseDlg();
// Show the new
if( newStealth != nil )
IExposeStealthNode( newStealth, thisMap );
}
// And update!
fCurrStealth = newStealth;
}
void plPassAnimDlgProc::IExposeStealthNode( HelperObject *node, IParamMap2 *thisMap )
{
if( node->ClassID() != ANIMSTEALTH_CLASSID )
return;
// Get our stealth pointer
plAnimStealthNode *stealth = (plAnimStealthNode *)node;
// Create the paramMap-based dialog for us
IParamBlock2 *pb = thisMap->GetParamBlock();
plPassMtlBase *mtl = (plPassMtlBase *)pb->GetOwner();
if( !stealth->CreateAndEmbedDlg( thisMap, mtl->fIMtlParams, GetDlgItem( fhWnd, IDC_PLACEHOLDER ) ) )
{
}
}
void plPassAnimDlgProc::SetThing(ReferenceTarget *m)
{
plPassMtlBase *mtl = (plPassMtlBase*)m;
IInitControls(mtl, mtl->fAnimPB );
}
void plPassAnimDlgProc::IInitControls(Animatable *anim, IParamBlock2 *pb)
{
ILoadNames( pb );
IEnableGlobal( fhWnd, pb->GetInt( ParamID( kPBAnimUseGlobal ) ) );
}
void plPassAnimDlgProc::ILoadNames(IParamBlock2 *pb )
{
// The following is to prevent IGetNumStealths() from re-calling us
if( fInitingNames )
return;
fInitingNames = true;
HWND hAnims = GetDlgItem(fhWnd, IDC_NAMES);
SendMessage(hAnims, CB_RESETCONTENT, 0, 0);
plPassMtlBase *mtl = (plPassMtlBase *)pb->GetOwner();
// Loop through our stealth nodes and add them all to the combo,
// since that's what we're selecting...erm, yeah
int i, count = mtl->IGetNumStealths( true );
for( i = 0; i < count; i++ )
{
plAnimStealthNode *stealth = mtl->IGetStealth( i, false );
if( stealth != nil )
{
int idx = SendMessage( hAnims, CB_ADDSTRING, 0, (LPARAM)stealth->GetSegmentName() );
SendMessage( hAnims, CB_SETITEMDATA, idx, (LPARAM)stealth );
}
}
SendMessage( hAnims, CB_SETCURSEL, 0, 0 );
IUpdateSegmentSel( pb->GetMap() );
fInitingNames = false;
}
void plPassAnimDlgProc::IEnableGlobal(HWND hWnd, hsBool enable)
{
Edit_Enable(GetDlgItem(hWnd, IDC_MTL_GLOBAL_NAME), enable);
ComboBox_Enable(GetDlgItem(hWnd, IDC_NAMES), !enable);
HWND stealthWnd = ( fCurrStealth != nil ) ? fCurrStealth->GetWinDlg() : nil;
if( stealthWnd != nil )
EnableWindow( stealthWnd, !enable );
}
void plPassAnimDlgProc::IEnableEaseStopPoints( IParamMap2 *pm, bool enable )
{
pm->Enable( (ParamID)kPBAnimEaseInMin, enable );
pm->Enable( (ParamID)kPBAnimEaseInMax, enable );
pm->Enable( (ParamID)kPBAnimEaseOutMin, enable );
pm->Enable( (ParamID)kPBAnimEaseOutMax, enable );
}

View File

@ -0,0 +1,100 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plPassAnimDlgProc - Base Animation Dlg Proc for plPassMtlBase //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plPassAnimDlgProc_h
#define _plPassAnimDlgProc_h
#include "plPassMtlBase.h"
#include "iparamm2.h"
class plAnimStealthNode;
class IParamMap2;
class plPassAnimDlgProc : public ParamMap2UserDlgProc, public plMtlChangeCallback
{
protected:
// Combo itemdata values
enum
{
kName, // Name of an animation/loop
kDefault, // Default combo value
kInvalid, // Invalid entry (couldn't find)
};
plAnimStealthNode *fCurrStealth;
IParamMap2 *fCurrParamMap;
bool fInitingNames;
HWND fhWnd;
public:
plPassAnimDlgProc();
virtual ~plPassAnimDlgProc();
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void DeleteThis() {}
void SetThing(ReferenceTarget *m);
virtual void Update(TimeValue t, Interval& valid, IParamMap2* pmap);
void SegmentListChanged( void );
static plPassAnimDlgProc &Get( void );
protected:
// Set all the controls to their stored value
void IInitControls(Animatable *anim, IParamBlock2 *pb);
void IEnableGlobal(HWND hWnd, hsBool enable);
void ILoadNames( IParamBlock2 *pb );
void IExposeStealthNode( HelperObject *stealth, IParamMap2 *thisMap );
void IUpdateSegmentSel( IParamMap2 *thisMap, hsBool clear = false );
void IEnableEaseStopPoints( IParamMap2 *pm, bool enable );
};
#endif //_plPassAnimDlgProc_h

View File

@ -0,0 +1,116 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plPassBaseParamIDs - Common ParamIDs for all plPassMtlBase-derived mtls //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plPassBaseParamIDs_h
#define _plPassBaseParamIDs_h
#define MCN_UPGRADE_OLD_ANIM_BLOCKS
namespace plPassBaseParamIDs
{
enum AdvancedIDs
{
// Specular
kPBAdvUseSpec, // Not used anymore, feel free to replace with new fields as necessary
kPBAdvSpecType, // ditto
kPBAdvShine, // ...
kPBAdvShineStr, // ...
// Misc
kPBAdvWire,
kPBAdvMeshOutlines,
kPBAdvTwoSided,
// Shading
kPBAdvSoftShadow,
kPBAdvNoProj,
kPBAdvVertexShade,
kPBAdvNoShade,
kPBAdvNoFog,
kPBAdvWhite,
// Z
kPBAdvZOnly,
kPBAdvZClear,
kPBAdvZNoRead,
kPBAdvZNoWrite,
kPBAdvZInc,
// Alpha test
kPBAdvAlphaTestHigh
};
enum SpecularTypes
{
kSpecTypeAlpha,
kSpecTypeColor,
kSpecTypeHighlight
};
enum AnimationIDs
{
kPBAnimName,
kPBAnimAutoStart,
kPBAnimLoop,
kPBAnimLoopName,
kPBAnimEaseInType,
kPBAnimEaseOutType,
kPBAnimEaseInLength,
kPBAnimEaseOutLength,
kPBAnimEaseInMin,
kPBAnimEaseInMax,
kPBAnimEaseOutMin,
kPBAnimEaseOutMax,
kPBAnimUseGlobal,
kPBAnimGlobalName,
kPBAnimStealthNodes
};
}
#endif //_plPassBaseParamIDs_h

View File

@ -0,0 +1,862 @@
/*==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 "hsTypes.h"
#include "plPassMtl.h"
#include "resource.h"
//extern ClassDesc2* GetMaxLayerDesc();
#include "Shaders.h"
#include "../MaxComponent/plMaxAnimUtils.h"
#include "plPassBaseParamIDs.h"
#include "plPassMtlBasicPB.h"
#include "plPassMtlLayersPB.h"
#include "iparamm2.h"
#include "Layers/plLayerTex.h"
#include "Layers/plStaticEnvLayer.h"
#include "hsBitVector.h"
extern HINSTANCE hInstance;
class plPassMtlClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading) { return TRACKED_NEW plPassMtl(loading); }
const TCHAR* ClassName() { return GetString(IDS_PASS_MTL); }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
Class_ID ClassID() { return PASS_MTL_CLASS_ID; }
const TCHAR* Category() { return NULL; }
const TCHAR* InternalName() { return _T("PlasmaMaterial"); }
HINSTANCE HInstance() { return hInstance; }
};
static plPassMtlClassDesc plPassMtlDesc;
ClassDesc2* GetPassMtlDesc() { return &plPassMtlDesc; }
// For initializing paramblock descriptor
ParamBlockDesc2 *GetPassBasicPB();
ParamBlockDesc2 *GetPassAdvPB();
ParamBlockDesc2 *GetPassLayersPB();
#include "plPassMtlAdvPBDec.h"
#include "plPassMtlBasicPBDec.h"
#include "plPassMtlLayersPBDec.h"
#include "plPassMtlAnimPBDec.h"
#include "plAnimStealthNode.h"
plPassMtl::plPassMtl(BOOL loading) : plPassMtlBase( loading )
{
plPassMtlDesc.MakeAutoParamBlocks( this );
fLayersPB->SetValue( kPassLayBase, 0, TRACKED_NEW plLayerTex );
fLayersPB->SetValue( kPassLayTop, 0, TRACKED_NEW plLayerTex );
// If we do this later (like, when the dialog loads) something blows up,
// somewhere in Max. It didn't in 4, it does in 7. This seems to fix it.
if (!loading)
IVerifyStealthPresent(ENTIRE_ANIMATION_NAME);
}
plPassMtl::~plPassMtl()
{
}
ParamDlg* plPassMtl::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
fIMtlParams = imp;
IAutoMParamDlg* masterDlg = plPassMtlDesc.CreateParamDlgs(hwMtlEdit, imp, this);
return (ParamDlg*)masterDlg;
}
BOOL plPassMtl::SetDlgThing(ParamDlg* dlg)
{
return FALSE;
}
Interval plPassMtl::Validity(TimeValue t)
{
#if 0 // mf horse
Interval valid = FOREVER;
/* for (int i = 0; i < fSubTexmap.Count(); i++)
{
if (fSubTexmap[i])
valid &= fSubTexmap[i]->Validity(t);
}
*/
// float u;
// fPBlock->GetValue(pb_spin,t,u,valid);
return valid;
#else // mf horse
const char* name = GetName();
// mf horse - Hacking in something like real validity checking
// to get material animations working. No warranty, this is just
// better than nothing.
Interval v = FOREVER;
fBasicPB->GetValidity(t, v);
fAdvPB->GetValidity(t, v);
if( fLayersPB->GetTexmap(kPassLayBase) )
v &= fLayersPB->GetTexmap(kPassLayBase)->Validity(t);
if( fLayersPB->GetTexmap(kPassLayTop) )
v &= fLayersPB->GetTexmap(kPassLayTop)->Validity(t);
return v;
#endif // mf horse
}
//// GetReference ////////////////////////////////////////////////////////////
// Note: need to overload because MAX for some reason writes out the
// references by their INDEX. ARRRRGH!
RefTargetHandle plPassMtl::GetReference( int i )
{
switch( i )
{
case kRefBasic: return fBasicPB;
case kRefAdv: return fAdvPB;
case kRefLayers: return fLayersPB;
case kRefAnim: return fAnimPB;
}
return plPassMtlBase::GetReference( i );
}
//// SetReference ////////////////////////////////////////////////////////////
// Note: need to overload because MAX for some reason writes out the
// references by their INDEX. ARRRRGH!
void plPassMtl::SetReference(int i, RefTargetHandle rtarg)
{
if (i == kRefBasic)
fBasicPB = (IParamBlock2 *)rtarg;
else if (i == kRefAdv)
fAdvPB = (IParamBlock2 *)rtarg;
else if (i == kRefLayers)
fLayersPB = (IParamBlock2 *)rtarg;
else if (i == kRefAnim)
fAnimPB = (IParamBlock2 *)rtarg;
else
plPassMtlBase::SetReference( i, rtarg );
}
/*===========================================================================*\
| Subanim & References support
\*===========================================================================*/
int plPassMtl::NumSubs()
{
return 6;
}
TSTR plPassMtl::SubAnimName(int i)
{
switch (i)
{
case 0: return fBasicPB->GetLocalName();
case 1: return fAdvPB->GetLocalName();
case 2: return fLayersPB->GetLocalName();
case 3: return fAnimPB->GetLocalName();
case 4: return "Base Layer";
case 5: return "Top Layer";
}
return "";
}
Animatable* plPassMtl::SubAnim(int i)
{
switch (i)
{
case 0: return fBasicPB;
case 1: return fAdvPB;
case 2: return fLayersPB;
case 3: return fAnimPB;
case 4: return fLayersPB->GetTexmap(kPassLayBase);
case 5:
if (fLayersPB->GetInt(kPassLayTopOn))
return fLayersPB->GetTexmap(kPassLayTop);
break;
}
return NULL;
}
int plPassMtl::NumParamBlocks()
{
return 4;
}
IParamBlock2* plPassMtl::GetParamBlock(int i)
{
return (IParamBlock2*)GetReference(i);
}
IParamBlock2* plPassMtl::GetParamBlockByID(BlockID id)
{
if (fBasicPB->ID() == id)
return fBasicPB;
else if (fAdvPB->ID() == id)
return fAdvPB;
else if (fLayersPB->ID() == id)
return fLayersPB;
else if (fAnimPB->ID() == id)
return fAnimPB;
return NULL;
}
RefResult plPassMtl::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message)
{
return plPassMtlBase::NotifyRefChanged( changeInt, hTarget, partID, message );
}
////////////////////////////////////////////////////////////////////////////////
// Subtexmap access
int plPassMtl::NumSubTexmaps()
{
return 2;
}
Texmap* plPassMtl::GetSubTexmap(int i)
{
if (i == 0)
return fLayersPB->GetTexmap(kPassLayBase);
else if (i == 1)
return fLayersPB->GetTexmap(kPassLayTop);
return NULL;
}
void plPassMtl::SetSubTexmap(int i, Texmap *m)
{
if (i == 0)
fLayersPB->SetValue(kPassLayBase, 0, m);
else if (i == 1)
fLayersPB->SetValue(kPassLayTop, 0, m);
}
TSTR plPassMtl::GetSubTexmapSlotName(int i)
{
if (i == 0)
return "Base";
else if (i == 1)
return "Top";
return "";
}
TSTR plPassMtl::GetSubTexmapTVName(int i)
{
return GetSubTexmapSlotName(i);
}
int plPassMtl::SubTexmapOn(int i)
{
if (i == 0)
return 1;
else if (i == 1 && fLayersPB->GetInt(kPassLayTopOn))
return 1;
return 0;
}
/*===========================================================================*\
| Updating and cloning
\*===========================================================================*/
RefTargetHandle plPassMtl::Clone(RemapDir &remap)
{
plPassMtl *mnew = TRACKED_NEW plPassMtl(FALSE);
plPassMtlBase::ICloneBase( mnew, remap );
return (RefTargetHandle)mnew;
}
void plPassMtl::ICloneRefs( plPassMtlBase *target, RemapDir &remap )
{
target->ReplaceReference(kRefBasic, remap.CloneRef(fBasicPB));
target->ReplaceReference(kRefAdv, remap.CloneRef(fAdvPB));
target->ReplaceReference(kRefLayers, remap.CloneRef(fLayersPB));
target->ReplaceReference(kRefAnim, remap.CloneRef(fAnimPB));
}
void plPassMtl::NotifyChanged()
{
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
}
void plPassMtl::Update(TimeValue t, Interval& valid)
{
// mf horse - Hacking in something like real validity checking
// to get material animations working. No warranty, this is just
// better than nothing.
if (!fIValid.InInterval(t))
{
fIValid.SetInfinite();
if( fLayersPB->GetTexmap(kPassLayBase) )
fLayersPB->GetTexmap(kPassLayBase)->Update(t, fIValid);
if( fLayersPB->GetTexmap(kPassLayTop) )
fLayersPB->GetTexmap(kPassLayTop)->Update(t, fIValid);
// fLayersPB->GetValue(kMtlLayLayer1On, t, fMapOn[0], fIValid);
/*
for (int i = 0; i < fSubTexmap.Count(); i++)
{
if (fSubTexmap[i])
fSubTexmap[i]->Update(t,fIValid);
}
*/
}
// Our wonderful way of version handling--if the runtimeColor is (-1,-1,-1), we know it's
// just been initialized, so set it to the static color (this lets us do the right thing for
// loading old paramBlocks)
if( fBasicPB )
{
Color run = fBasicPB->GetColor( kPassBasRunColor, 0 );
if( run == Color(-1,-1,-1) )
{
fBasicPB->SetValue( kPassBasRunColor, 0, fBasicPB->GetColor( kPassBasColor, 0 ) );
}
// Also, if shineStr is anything other than -1, then it must be an old paramblock and we need
// to convert to our new specColor (we know this because the original valid range was 0-100)
int shine = fBasicPB->GetInt( kPassBasShineStr, 0 );
if( shine != -1 )
{
fBasicPB->SetValue( kPassBasSpecColor, 0, Color( (float)shine / 100.f, (float)shine / 100.f, (float)shine / 100.f ) );
fBasicPB->SetValue( kPassBasShineStr, 0, (int)-1 );
}
}
valid &= fIValid;
}
/*===========================================================================*\
| Determine the characteristics of the material
\*===========================================================================*/
void plPassMtl::SetAmbient(Color c, TimeValue t) {}
void plPassMtl::SetDiffuse(Color c, TimeValue t) {}
void plPassMtl::SetSpecular(Color c, TimeValue t) {}
void plPassMtl::SetShininess(float v, TimeValue t) {}
Color plPassMtl::GetAmbient(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plPassMtl::GetDiffuse(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plPassMtl::GetSpecular(int mtlNum, BOOL backFace) { return Color(0,0,0); }
float plPassMtl::GetXParency(int mtlNum, BOOL backFace)
{
int opacity = fBasicPB->GetInt( kPassBasOpacity, 0 );
float alpha = 1.0f - ( (float)opacity / 100.0f );
return alpha;
}
float plPassMtl::GetShininess(int mtlNum, BOOL backFace) { return 0.0f; }
float plPassMtl::GetShinStr(int mtlNum, BOOL backFace) { return 0.0f; }
float plPassMtl::WireSize(int mtlNum, BOOL backFace) { return 0.0f; }
/////////////////////////////////////////////////////////////////
void plPassMtl::SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb)
{
#if 0
if (texHandleValid.InInterval(t)) {
mtl->texture.SetCount(numTexHandlesUsed);
for (int i=0; i<numTexHandlesUsed; i++) {
if (texHandle[i]) {
mtl->texture[i].textHandle = texHandle[i]->GetHandle();
Texmap *tx = (*maps)[useSubForTex[i]].map;
cb.GetGfxTexInfoFromTexmap(t, mtl->texture[i], tx );
SetTexOps(mtl,i,texOpsType[i]);
}
}
return;
}
#endif
#if 0 // WTF?!?!?!?
Texmap *tx[2];
int diffChan = stdIDToChannel[ ID_DI ];
int opacChan = stdIDToChannel[ ID_OP ];
tx[0] = (*maps)[diffChan].IsActive()?(*maps)[diffChan].map:NULL;
tx[1] = (*maps)[opacChan].IsActive()?(*maps)[opacChan].map:NULL;
#endif
int nsupport = cb.NumberTexturesSupported();
#if 0
BITMAPINFO *bmi[NTEXHANDLES];
int nmaps=0;
for (int i=0; i<NTEXHANDLES; i++) {
if (tx[i]) nmaps ++;
bmi[i] = NULL;
}
mtl->texture.SetCount(nmaps);
if (nmaps==0)
return;
for (i=0; i<nmaps; i++)
mtl->texture[i].textHandle = NULL;
texHandleValid.SetInfinite();
Interval valid;
BOOL needDecal = FALSE;
int ntx = 0;
int op;
int forceW = 0;
int forceH = 0;
if (tx[0]) {
cb.GetGfxTexInfoFromTexmap(t, mtl->texture[0], tx[0]);
TextureInfo &ti = mtl->texture[0];
if (ti.tiling[0]==GW_TEX_NO_TILING||ti.tiling[1]==GW_TEX_NO_TILING)
needDecal = TRUE;
op = needDecal?TXOP_ALPHABLEND:TXOP_MODULATE;
bmi[0] = tx[0]->GetVPDisplayDIB(t,cb,valid,FALSE);
if (bmi[0]) {
texHandleValid &= valid;
useSubForTex[0] = diffChan;
ntx = 1;
forceW = bmi[0]->bmiHeader.biWidth;
forceH = bmi[0]->bmiHeader.biHeight;
}
}
if (tx[1]) {
cb.GetGfxTexInfoFromTexmap(t, mtl->texture[ntx], tx[1]);
if (nsupport>ntx) {
bmi[1] = tx[1]->GetVPDisplayDIB(t,cb,valid,TRUE);
if (bmi[1]) {
texHandleValid &= valid;
StuffAlpha(bmi[1], (*maps)[opacChan].amount, GetOpacity(t),ntx?whiteCol:pShader->GetDiffuseClr(t));
texHandle[ntx] = cb.MakeHandle(bmi[1]);
bmi[1] = NULL;
mtl->texture[ntx].textHandle = texHandle[ntx]->GetHandle();
SetTexOps(mtl,ntx,TXOP_OPACITY);
useSubForTex[ntx] = opacChan;
ntx++;
}
}
else {
if (!needDecal) {
TextureInfo ti;
// if (SameUV(mtl->texture[0],mtl->texture[1])) {
// Not really correct to combine channels for different UV's but what the heck.
bmi[1] = tx[1]->GetVPDisplayDIB(t,cb,valid,TRUE, forceW, forceH);
if (bmi[1]) {
texHandleValid &= valid;
StuffAlphaInto(bmi[1], bmi[0], (*maps)[opacChan].amount, GetOpacity(t));
op = TXOP_OPACITY;
free(bmi[1]);
bmi[1] = NULL;
}
// }
}
}
}
if (bmi[0]) {
texHandle[0] = cb.MakeHandle(bmi[0]);
bmi[0] = NULL;
mtl->texture[0].textHandle = texHandle[0]->GetHandle();
SetTexOps(mtl,0,op);
}
mtl->texture.SetCount(ntx);
numTexHandlesUsed = ntx;
#endif
}
/*===========================================================================*\
| Actual shading takes place
\*===========================================================================*/
void plPassMtl::GetInterpVtxValue(int channel, ShadeContext &sc, Point3 &val)
{
Mesh *mesh = sc.globContext->GetRenderInstance(sc.NodeID())->mesh;
if (mesh != nil)
{
Face *maxFace = &mesh->faces[ sc.FaceNumber() ];
UVVert *map = mesh->mapVerts(channel);
if (map != nil)
{
Point3 p0 = map[maxFace->getVert( 0 )];
Point3 p1 = map[maxFace->getVert( 1 )];
Point3 p2 = map[maxFace->getVert( 2 )];
Point3 interp = sc.BarycentricCoords();
val.x = interp.x * p0.x + interp.y * p1.x + interp.z * p2.x;
val.y = interp.x * p0.y + interp.y * p1.y + interp.z * p2.y;
val.z = interp.x * p0.z + interp.y * p1.z + interp.z * p2.z;
return;
}
}
// No value defined... set default.
if (channel == MAP_SHADING)
val.x = val.y = val.z = 0.0f;
else
val.x = val.y = val.z = 1.0f;
}
void plPassMtl::Shade(ShadeContext& sc)
{
// Get the background color
Color backColor, backTrans;
sc.GetBGColor(backColor, backTrans);
ShadeWithBackground(sc, backColor);
}
//// Requirements ////////////////////////////////////////////////////////////
// Tells MAX what we need to render ourselves properly, such as translucency,
// two-sidedness, etc. Flags are in imtl.h in the MAX SDK.
ULONG plPassMtl::Requirements( int subMtlNum )
{
ULONG req = 0;
req = Mtl::Requirements( subMtlNum );
// Uncomment this to get the background color fed to our ShadeWithBackground()
// (slower processing tho)
//req |= MTLREQ_BGCOL;
req |= MTLREQ_UV;
int blendType = fLayersPB->GetInt( kPassLayOutputBlend );
if( blendType == kBlendAdd )
req |= MTLREQ_ADDITIVE_TRANSP | MTLREQ_TRANSP;
else if( blendType == kBlendAlpha )
req |= MTLREQ_TRANSP;
else if( fBasicPB->GetInt( kPassBasOpacity, 0 ) != 100 )
req |= MTLREQ_TRANSP;
if( fAdvPB->GetInt( kPBAdvTwoSided ) )
req |= MTLREQ_2SIDE;
if (req & MTLREQ_FACEMAP)
{
int i = 0;
}
return req;
}
void plPassMtl::ShadeWithBackground(ShadeContext &sc, Color background, bool useVtxAlpha /* = true */)
{
#if 1
// old
#if 0
Color lightCol,rescol, diffIllum0;
RGBA mval;
Point3 N0,P;
BOOL bumped = FALSE;
int i;
if (gbufID)
sc.SetGBufferID(gbufID);
if (sc.mode == SCMODE_SHADOW) {
float opac = 0.0;
for (i=0; i < NumSubTexmaps(); i++) {
if (SubTexmapOn(i)) {
hsMaxLayerBase *hsmLay = (hsMaxLayerBase *)GetSubTexmap(i);
opac += hsmLay->GetOpacity(t);
}
}
float f = 1.0f - opac;
sc.out.t = Color(f,f,f);
return;
}
N0 = sc.Normal();
P = sc.P();
#endif
TimeValue t = sc.CurTime();
Color color(0, 0, 0);
float alpha = 0.0;
// Evaluate Base layer
Texmap *map = fLayersPB->GetTexmap(kPassLayBase);
if (map && ( map->ClassID() == LAYER_TEX_CLASS_ID
|| map->ClassID() == STATIC_ENV_LAYER_CLASS_ID ) )
{
plLayerTex *layer = (plLayerTex*)map;
AColor evalColor = layer->EvalColor(sc);
color = evalColor;
alpha = evalColor.a;
}
// Evaluate Top layer, if it's on
if (fLayersPB->GetInt(kPassLayTopOn))
{
Texmap *map = fLayersPB->GetTexmap(kPassLayTop);
if (map && ( map->ClassID() == LAYER_TEX_CLASS_ID
|| map->ClassID() == STATIC_ENV_LAYER_CLASS_ID
|| map->ClassID() == ANGLE_ATTEN_LAYER_CLASS_ID) )
{
plPlasmaMAXLayer *layer = (plPlasmaMAXLayer*)map;
AColor evalColor = layer->EvalColor(sc);
// Blend layers
if( !layer->DiscardColor() )
{
int blendType = fLayersPB->GetInt(kPassLayBlend);
switch (blendType)
{
case kBlendAdd:
color += evalColor * evalColor.a;
break;
case kBlendAlpha:
color = (1.0f - evalColor.a) * color + evalColor.a * evalColor;
break;
case kBlendMult:
color *= evalColor;
break;
default: // No blend...
color = evalColor;
break;
}
}
if( !layer->DiscardAlpha() )
{
int alphaType = fLayersPB->GetInt(kPassLayOutputBlend);
switch( alphaType )
{
case kAlphaMultiply:
alpha *= evalColor.a;
break;
case kAlphaAdd:
alpha += evalColor.a;
break;
case kAlphaDiscard:
default:
break;
}
}
}
}
#if 1
AColor black;
black.Black();
AColor white;
white.White();
SIllumParams ip;
if (fBasicPB->GetInt(kPassBasEmissive))
{
// Emissive objects don't get shaded
ip.diffIllum = fBasicPB->GetColor(kPassBasColorAmb, t) * color;
ip.diffIllum.ClampMinMax();
ip.specIllum = black;
}
else
{
//
// Shading setup
//
// Setup the parameters for the shader
ip.amb = fBasicPB->GetColor(kPassBasColorAmb, t);
ip.diff = fBasicPB->GetColor(kPassBasColor, t) * color;
ip.diffIllum = black;
ip.specIllum = black;
ip.N = sc.Normal();
ip.V = sc.V();
//
// Specularity
//
if (fBasicPB->GetInt(kPassBasUseSpec, t))
{
ip.sh_str = 1.f;
ip.spec = fBasicPB->GetColor( kPassBasSpecColor, t );
ip.ph_exp = (float)pow(2.0f,float(fBasicPB->GetInt(kPassBasShine, t)) / 10.0f);
ip.shine = float(fBasicPB->GetInt(kPassBasShine, t)) / 100.0f;
}
else
{
ip.spec = black;
ip.sh_str = 0;
ip.ph_exp = 0;
ip.shine = 0;
}
ip.softThresh = 0;
//
// Do the shading
Shader *myShader = GetShader(SHADER_BLINN);
myShader->Illum(sc, ip);
// Override shader parameters
if (fAdvPB->GetInt(kPBAdvNoShade))
{
ip.diffIllum = black;
ip.specIllum = black;
}
if (fAdvPB->GetInt(kPBAdvWhite))
{
ip.diffIllum = white;
ip.specIllum = black;
}
ip.specIllum.ClampMinMax();
ip.diffIllum = ip.amb * sc.ambientLight + ip.diff * ip.diffIllum;
ip.diffIllum.ClampMinMax();
}
// AColor returnColor = AColor(opac * ip.diffIllum + ip.specIllum, opac)
#endif
// Get opacity and combine with alpha
float opac = float(fBasicPB->GetInt(kPassBasOpacity, t)) / 100.0f;
alpha *= opac;
float vtxAlpha = 1.0f;
if (useVtxAlpha && GetOutputBlend() == plPassMtlBase::kBlendAlpha)
{
Point3 p;
GetInterpVtxValue(MAP_ALPHA, sc, p);
vtxAlpha = p.x;
}
alpha *= vtxAlpha;
// MAX will do the additive/alpha/no blending for us based on what Requirements()
// we tell it. However, since MAX's formula is bgnd*sc.out.t + sc.out.c,
// we have to multiply our output color by the alpha.
// If we ever need a more complicated blending function, you can request the
// background color via Requirements() (otherwise it's just black) and then do
// the blending yourself; however, if the transparency isn't set, the shadows
// will be opaque, so be careful.
Color outC = ip.diffIllum + ip.specIllum;
sc.out.c = ( outC * alpha );
sc.out.t = Color( 1.f - alpha, 1.f - alpha, 1.f - alpha );
#endif
}
float plPassMtl::EvalDisplacement(ShadeContext& sc)
{
return 0.0f;
}
Interval plPassMtl::DisplacementValidity(TimeValue t)
{
Interval iv;
iv.SetInfinite();
return iv;
}
bool plPassMtl::HasAlpha()
{
return ((plLayerTex *)fLayersPB->GetTexmap(kPassLayBase))->HasAlpha();
}
// Massive list of inherited accessor functions for ParamBlock data
// Advanced Block
int plPassMtl::GetBasicWire() { return fAdvPB->GetInt(kPBAdvWire); }
int plPassMtl::GetMeshOutlines() { return fAdvPB->GetInt(kPBAdvMeshOutlines); }
int plPassMtl::GetTwoSided() { return fAdvPB->GetInt(kPBAdvTwoSided); }
int plPassMtl::GetSoftShadow() { return fAdvPB->GetInt(kPBAdvSoftShadow); }
int plPassMtl::GetNoProj() { return fAdvPB->GetInt(kPBAdvNoProj); }
int plPassMtl::GetVertexShade() { return fAdvPB->GetInt(kPBAdvVertexShade); }
int plPassMtl::GetNoShade() { return fAdvPB->GetInt(kPBAdvNoShade); }
int plPassMtl::GetNoFog() { return fAdvPB->GetInt(kPBAdvNoFog); }
int plPassMtl::GetWhite() { return fAdvPB->GetInt(kPBAdvWhite); }
int plPassMtl::GetZOnly() { return fAdvPB->GetInt(kPBAdvZOnly); }
int plPassMtl::GetZClear() { return fAdvPB->GetInt(kPBAdvZClear); }
int plPassMtl::GetZNoRead() { return fAdvPB->GetInt(kPBAdvZNoRead); }
int plPassMtl::GetZNoWrite() { return fAdvPB->GetInt(kPBAdvZNoWrite); }
int plPassMtl::GetZInc() { return fAdvPB->GetInt(kPBAdvZInc); }
int plPassMtl::GetAlphaTestHigh() { return fAdvPB->GetInt(kPBAdvAlphaTestHigh); }
// Animation block
char * plPassMtl::GetAnimName() { return fAnimPB->GetStr(kPBAnimName); }
int plPassMtl::GetAutoStart() { return fAnimPB->GetInt(kPBAnimAutoStart); }
int plPassMtl::GetLoop() { return fAnimPB->GetInt(kPBAnimLoop); }
char * plPassMtl::GetAnimLoopName() { return fAnimPB->GetStr(kPBAnimLoopName); }
int plPassMtl::GetEaseInType() { return fAnimPB->GetInt(kPBAnimEaseInType); }
float plPassMtl::GetEaseInNormLength() { return fAnimPB->GetFloat(kPBAnimEaseInLength); }
float plPassMtl::GetEaseInMinLength() { return fAnimPB->GetFloat(kPBAnimEaseInMin); }
float plPassMtl::GetEaseInMaxLength() { return fAnimPB->GetFloat(kPBAnimEaseInMax); }
int plPassMtl::GetEaseOutType() { return fAnimPB->GetInt(kPBAnimEaseOutType); }
float plPassMtl::GetEaseOutNormLength() { return fAnimPB->GetFloat(kPBAnimEaseOutLength); }
float plPassMtl::GetEaseOutMinLength() { return fAnimPB->GetFloat(kPBAnimEaseOutMin); }
float plPassMtl::GetEaseOutMaxLength() { return fAnimPB->GetFloat(kPBAnimEaseOutMax); }
int plPassMtl::GetUseGlobal() { return fAnimPB->GetInt(ParamID(kPBAnimUseGlobal)); }
char * plPassMtl::GetGlobalVarName() { return fAnimPB->GetStr(ParamID(kPBAnimGlobalName)); }
// Basic block
int plPassMtl::GetColorLock() { return fBasicPB->GetInt(kPassBasColorLock); }
Color plPassMtl::GetAmbColor() { return fBasicPB->GetColor(kPassBasColorAmb); }
Color plPassMtl::GetColor() { return fBasicPB->GetColor(kPassBasColor); }
int plPassMtl::GetOpacity() { return fBasicPB->GetInt(kPassBasOpacity); }
int plPassMtl::GetEmissive() { return fBasicPB->GetInt(kPassBasEmissive); }
int plPassMtl::GetUseSpec() { return fBasicPB->GetInt(kPassBasUseSpec); }
int plPassMtl::GetShine() { return fBasicPB->GetInt(kPassBasShine); }
Color plPassMtl::GetSpecularColor() { return fBasicPB->GetColor(kPassBasSpecColor); }
int plPassMtl::GetDiffuseColorLock() { return fBasicPB->GetInt(kPassBasDiffuseLock); }
Color plPassMtl::GetRuntimeColor() { return fBasicPB->GetColor(kPassBasRunColor); }
Control *plPassMtl::GetPreshadeColorController() { return fBasicPB->GetController(ParamID(kPassBasColor)); }
Control *plPassMtl::GetAmbColorController() { return fBasicPB->GetController(ParamID(kPassBasColorAmb)); }
Control *plPassMtl::GetOpacityController() { return fBasicPB->GetController(ParamID(kPassBasOpacity)); }
Control *plPassMtl::GetSpecularColorController() { return fBasicPB->GetController(ParamID(kPassBasSpecColor)); }
Control *plPassMtl::GetRuntimeColorController() { return fBasicPB->GetController(ParamID(kPassBasRunColor)); }
// Layer block
Texmap *plPassMtl::GetBaseLayer() { return fLayersPB->GetTexmap(kPassLayBase); }
int plPassMtl::GetTopLayerOn() { return fLayersPB->GetInt(kPassLayTopOn); }
Texmap *plPassMtl::GetTopLayer() { return fLayersPB->GetTexmap(kPassLayTop); }
int plPassMtl::GetLayerBlend() { return fLayersPB->GetInt(kPassLayBlend); }
int plPassMtl::GetOutputAlpha() { return fLayersPB->GetInt(kPassLayOutputAlpha); }
int plPassMtl::GetOutputBlend() { return fLayersPB->GetInt(kPassLayOutputBlend); }

View File

@ -0,0 +1,213 @@
/*==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==*/
#ifndef PL_PASSMTL_H
#define PL_PASSMTL_H
#include "Max.h"
//#include "istdplug.h"
#include "iparamb2.h"
//#include "iparamm2.h"
#include "../resource.h"
#include "plPassMtlBase.h"
#include "hsTemplates.h"
#define PASS_MTL_CLASS_ID Class_ID(0x42b6718f, 0x2d579b35)
extern TCHAR *GetString(int id);
class plPassMtl : public plPassMtlBase
{
protected:
virtual void ICloneRefs( plPassMtlBase *target, RemapDir &remap );
public:
enum RefIDs
{
kRefBasic,
kRefAdv,
kRefLayers,
kRefAnim,
};
enum Blocks
{
kBlkBasic,
kBlkAdv,
kBlkLayers,
kBlkAnim,
};
plPassMtl(BOOL loading);
virtual ~plPassMtl();
void DeleteThis() { delete this; }
//From Animatable
Class_ID ClassID() { return PASS_MTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_PASS_MTL); }
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void NotifyChanged();
BOOL SupportsMultiMapsInViewport() { return FALSE; }
void SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb);
// Shade and displacement calculation
static void GetInterpVtxValue(int channel, ShadeContext &sc, Point3 &interpVal);
void Shade(ShadeContext& sc);
void ShadeWithBackground(ShadeContext &sc, Color background, bool useVtxAlpha = true);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
virtual RefTargetHandle GetReference( int i );
virtual void SetReference( int i, RefTargetHandle rtarg );
// SubTexmap access methods
int NumSubTexmaps();
Texmap* GetSubTexmap(int i);
void SetSubTexmap(int i, Texmap *m);
TSTR GetSubTexmapSlotName(int i);
TSTR GetSubTexmapTVName(int i);
int SubTexmapOn(int i);
BOOL SetDlgThing(ParamDlg* dlg);
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
// void SetParamDlg(ParamDlg *dlg);
// void SetNumSubTexmaps(int num);
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
ULONG Requirements( int subMtlNum );
virtual bool HasAlpha();
// Massive list of inherited accessor functions for ParamBlock data
// Advanced Block
virtual int GetBasicWire();
virtual int GetMeshOutlines();
virtual int GetTwoSided();
virtual int GetSoftShadow();
virtual int GetNoProj();
virtual int GetVertexShade();
virtual int GetNoShade();
virtual int GetNoFog();
virtual int GetWhite();
virtual int GetZOnly();
virtual int GetZClear();
virtual int GetZNoRead();
virtual int GetZNoWrite();
virtual int GetZInc();
virtual int GetAlphaTestHigh();
// Animation block
virtual char * GetAnimName();
virtual int GetAutoStart();
virtual int GetLoop();
virtual char * GetAnimLoopName();
virtual int GetEaseInType();
virtual float GetEaseInMinLength();
virtual float GetEaseInMaxLength();
virtual float GetEaseInNormLength();
virtual int GetEaseOutType();
virtual float GetEaseOutMinLength();
virtual float GetEaseOutMaxLength();
virtual float GetEaseOutNormLength();
virtual int GetUseGlobal();
virtual char * GetGlobalVarName();
// Basic block
virtual int GetColorLock();
virtual Color GetAmbColor();
virtual Color GetColor();
virtual int GetOpacity();
virtual int GetEmissive();
virtual int GetUseSpec();
virtual int GetShine();
virtual Color GetSpecularColor();
virtual Control *GetPreshadeColorController();
virtual Control *GetAmbColorController();
virtual Control *GetOpacityController();
virtual Control *GetSpecularColorController();
virtual int GetDiffuseColorLock();
virtual Color GetRuntimeColor();
virtual Control *GetRuntimeColorController();
// Layer block
virtual Texmap *GetBaseLayer();
virtual int GetTopLayerOn();
virtual Texmap *GetTopLayer();
virtual int GetLayerBlend();
virtual int GetOutputAlpha();
virtual int GetOutputBlend();
};
#endif //PL_PASSMTL_H

View File

@ -0,0 +1,75 @@
/*==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==*/
#ifndef PL_PASSMTLADVPB_H
#define PL_PASSMTLADVPB_H
// Param ID's
enum
{
// Specular
kPassAdvUseSpec, // Not used anymore, feel free to replace with new fields as necessary
kPassAdvSpecType, // ditto
kPassAdvShine, // ...
kPassAdvShineStr, // ...
// Misc
kPassAdvWire,
kPassAdvMeshOutlines,
kPassAdvTwoSided,
// Shading
kPassAdvSoftShadow,
kPassAdvNoProj,
kPassAdvVertexShade,
kPassAdvNoShade,
kPassAdvNoFog,
kPassAdvWhite,
// Z
kPassAdvZOnly,
kPassAdvZClear,
kPassAdvZNoRead,
kPassAdvZNoWrite,
kPassAdvZInc,
};
#endif //PL_PASSMTLADVPB_H

View File

@ -0,0 +1,110 @@
/*==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 "plPassMtl.h"
#include "plPassBaseParamIDs.h"
using namespace plPassBaseParamIDs;
static ParamBlockDesc2 gPassAdvPB
(
plPassMtl::kBlkAdv, _T("advanced"), IDS_PASS_ADV, GetPassMtlDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI, plPassMtl::kRefAdv,
// UI
IDD_PASS_ADV, IDS_PASS_ADV, 0, APPENDROLL_CLOSED, NULL,
// Misc Properties
kPBAdvWire, _T("basicWire"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_MISC_WIRE,
end,
kPBAdvMeshOutlines, _T("meshOutlines"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_MISC_MESHOUTLINES,
end,
kPBAdvTwoSided, _T("twoSided"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_MISC_TWOSIDED,
end,
// Shade properties
kPBAdvSoftShadow, _T("softShadow"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_SOFTSHADOW,
end,
kPBAdvNoProj, _T("noProj"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_NO_PROJ,
end,
kPBAdvVertexShade, _T("vertexShade"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_VERTEXSHADE,
end,
kPBAdvNoShade, _T("noShade"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_NOSHADE,
end,
kPBAdvNoFog, _T("noFog"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_NO_FOG,
end,
kPBAdvWhite, _T("white"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_WHITE,
end,
// Z Properties
kPBAdvZOnly, _T("zOnly"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZONLY,
end,
kPBAdvZClear, _T("zClear"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZCLEAR,
end,
kPBAdvZNoRead, _T("zNoRead"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZNOREAD,
end,
kPBAdvZNoWrite, _T("zNoWrite"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZNOWRITE,
end,
kPBAdvZInc, _T("zInc"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_INC,
end,
kPBAdvAlphaTestHigh, _T("aTestHigh"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_ALPHA_TEST_HIGH,
p_default, FALSE,
end,
end
);
ParamBlockDesc2 *GetPassAdvPB() { return &gPassAdvPB; }

View File

@ -0,0 +1,101 @@
/*==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==*/
#ifndef PL_PASSMTLANIMPB_H
#define PL_PASSMTLANIMPB_H
enum { kPassAnimMain, kPassAnimEase };
#define WM_ROLLOUT_OPEN WM_USER+1
class plAnimEaseDlgProc : public ParamMap2UserDlgProc
{
protected:
void EnableStopPoints(IParamMap2 *pm, bool enable)
{
pm->Enable(kPassEaseInMin, enable);
pm->Enable(kPassEaseInMax, enable);
pm->Enable(kPassEaseOutMin, enable);
pm->Enable(kPassEaseOutMax, enable);
}
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
IParamBlock2 *pb = map->GetParamBlock();
bool stopPoints = false;
if (DoesHaveStopPoints(pb->GetOwner()))
{
stopPoints = true;
break;
}
EnableStopPoints(map, stopPoints);
// If we're doing an ease, set the ease rollup to open
// if (pb->GetInt(kPassEaseInType) != plAnimEaseTypes::kNoEase ||
// pb->GetInt(kPassEaseOutType) != plAnimEaseTypes::kNoEase)
// PostMessage(hWnd, WM_ROLLOUT_OPEN, 0, 0);
}
return TRUE;
// Max doesn't know about the rollup until after WM_CREATE, so we get
// around it by posting a message
//case WM_ROLLOUT_OPEN:
// {
// IRollupWindow *rollup = GetCOREInterface(MTLEDIT_INTERFACE)->GetCommandPanelRollup();
// int idx = rollup->GetPanelIndex(hWnd);
// rollup->SetPanelOpen(idx, TRUE);
// }
// return TRUE;
}
return FALSE;
}
void DeleteThis() {}
};
#endif

View File

@ -0,0 +1,111 @@
/*==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 "plPassMtl.h"
#include "plPassBaseParamIDs.h"
#include "resource.h"
#include "iparamm2.h"
#include "plPassAnimDlgProc.h"
#include "plAnimStealthNode.h"
using namespace plPassBaseParamIDs;
static ParamBlockDesc2 gPassAnimPB
(
plPassMtl::kBlkAnim, _T("anim"), IDS_PASS_ANIM, GetPassMtlDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI + P_CALLSETS_ON_LOAD, plPassMtl::kRefAnim,
// UI
IDD_PASS_ANIM, IDS_PASS_ANIM, 0, 0, &plPassAnimDlgProc::Get(),
#ifdef MCN_UPGRADE_OLD_ANIM_BLOCKS
// THE FOLLOWING ARE ALL OLD PARAMETERS AND SHOULD NO LONGER BE USED. The only reason
// they're here is so we can convert old paramBlocks into the new plAnimStealthNode format
kPBAnimName, _T("animName"), TYPE_STRING, 0, 0,
end,
kPBAnimAutoStart, _T("autoStart"), TYPE_BOOL, 0, 0,
end,
kPBAnimLoop, _T("loop"), TYPE_BOOL, 0, 0,
end,
kPBAnimLoopName, _T("loopName"), TYPE_STRING, 0, 0,
end,
// Anim Ease
kPBAnimEaseInType, _T("easeInType"), TYPE_INT, 0, 0,
end,
kPBAnimEaseInLength, _T("easeInLength"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseInMin, _T("easeInMin"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseInMax, _T("easeInMax"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutType, _T("easeOutType"), TYPE_INT, 0, 0,
end,
kPBAnimEaseOutLength, _T("easeOutLength"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutMin, _T("easeOutMin"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutMax, _T("easeOutMax"), TYPE_FLOAT, 0, 0,
end,
#endif // MCN_UPGRADE_OLD_ANIM_BLOCKS
kPBAnimUseGlobal, _T("UseGlobal"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_MTL_USE_GLOBAL,
end,
kPBAnimGlobalName, _T("GlobalName"), TYPE_STRING, 0, 0,
p_default, _T(""),
end,
kPBAnimStealthNodes, _T( "testing" ), TYPE_REFTARG_TAB, 0, 0, 0,
p_accessor, &plStealthNodeAccessor::GetInstance(),
end,
end
);
ParamBlockDesc2 *GetPassAnimPB() { return &gPassAnimPB; }

View File

@ -0,0 +1,676 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plPassMtlBase - Base class for all Plasma MAX materials //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "hsBitVector.h"
#include "Max.h"
#include "iparamb2.h"
#include "notify.h"
#include "notetrck.h"
#include "plPassMtlBase.h"
#include "plPassBaseParamIDs.h"
#include "plNoteTrackWatcher.h"
#include "plAnimStealthNode.h"
#include "../MaxComponent/plMaxAnimUtils.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
// For converting from a MAX Mtl
#include "plPassMtl.h"
#include "plBumpMtl.h"
#include "plDecalMtl.h"
using namespace plPassBaseParamIDs;
IMtlParams *plPassMtlBase::fIMtlParams = nil;
//// plPostLoadHandler ///////////////////////////////////////////////////////
// Small class to keep track of all the materials to update after load
class plPostLoadHandler
{
static bool fLoading;
static hsTArray<plPassMtlBase *> fPostLoads;
public:
static bool IsLoading() { return fLoading; }
static void PostLoadFixupFunction( void *param, NotifyInfo *info )
{
fLoading = false;
for( int i = 0; i < fPostLoads.GetCount(); i++ )
fPostLoads[ i ]->PostLoadAnimPBFixup();
fPostLoads.Reset();
UnRegisterNotification( PostLoadFixupFunction, param, NOTIFY_FILE_POST_OPEN );
UnRegisterNotification( PostLoadFixupFunction, param, NOTIFY_FILE_POST_MERGE );
}
static void AddPostLoad( plPassMtlBase *mtl )
{
fLoading = true;
if( fPostLoads.GetCount() == 0 )
{
RegisterNotification( PostLoadFixupFunction, mtl, NOTIFY_FILE_POST_OPEN );
RegisterNotification( PostLoadFixupFunction, mtl, NOTIFY_FILE_POST_MERGE );
}
mtl->SetLoadingFlag( true );
fPostLoads.Append( mtl );
}
static void RemovePostLoad( plPassMtlBase *mtl )
{
for( int i = 0; i < fPostLoads.GetCount(); i++ )
{
if( fPostLoads[ i ] == mtl )
{
fPostLoads.Remove( i );
break;
}
}
}
};
hsTArray<plPassMtlBase *> plPostLoadHandler::fPostLoads;
bool plPostLoadHandler::fLoading = false;
plPassMtlBase::plPassMtlBase( BOOL loading ) : fNTWatcher( nil ), fBasicPB(NULL), fAdvPB(NULL), fLayersPB(NULL), fAnimPB(NULL),
fLoading( loading )
{
fNTWatcher = TRACKED_NEW plNoteTrackWatcher( this );
Reset();
}
plPassMtlBase::~plPassMtlBase()
{
if( fLoading )
plPostLoadHandler::RemovePostLoad( this );
// Force the watcher's parent pointer to nil, otherwise the de-ref will attempt to re-delete us
fNTWatcher->SetReference( plNoteTrackWatcher::kRefParentMtl, nil );
delete fNTWatcher;
fNTWatcher = nil;
// Manually delete our notetrack refs, otherwise there'll be hell to pay
for( int i = 0; i < fNotetracks.GetCount(); i++ )
{
if( fNotetracks[ i ] != nil )
DeleteReference( kRefNotetracks + i );
}
}
void plPassMtlBase::Reset( void )
{
fIValid.SetEmpty();
}
//// Stealth Accessors ///////////////////////////////////////////////////////
int plPassMtlBase::GetNumStealths( void )
{
return IGetNumStealths( true );
}
plAnimStealthNode *plPassMtlBase::GetStealth( int index )
{
return IGetStealth( index, false );
}
int plPassMtlBase::IGetNumStealths( hsBool update )
{
if( update )
IUpdateAnimNodes();
return fAnimPB->Count( (ParamID)kPBAnimStealthNodes );
}
plAnimStealthNode *plPassMtlBase::IGetStealth( int index, hsBool update )
{
if( update )
IUpdateAnimNodes();
return (plAnimStealthNode *)fAnimPB->GetReferenceTarget( (ParamID)kPBAnimStealthNodes, 0, index );
}
plAnimStealthNode *plPassMtlBase::IFindStealth( const char *segmentName )
{
int i;
for( i = 0; i < fAnimPB->Count( (ParamID)kPBAnimStealthNodes ); i++ )
{
plAnimStealthNode *node = (plAnimStealthNode *)fAnimPB->GetReferenceTarget( (ParamID)kPBAnimStealthNodes, 0, i );
const char *name = node->GetSegmentName();
if( node != nil && strcmp( name, segmentName ) == 0 )
{
return node;
}
}
return nil;
}
//// IVerifyStealthPresent ///////////////////////////////////////////////////
// Ensures that we have a stealth for the given segment.
plAnimStealthNode *plPassMtlBase::IVerifyStealthPresent( const char *animName )
{
// If we're in the middle of loading, don't check
if (plPostLoadHandler::IsLoading())
return nil;
plAnimStealthNode *stealth = IFindStealth( animName );
if( stealth == nil )
{
// New segment, add a new stealth node
stealth = (plAnimStealthNode *)GetCOREInterface()->CreateInstance( HELPER_CLASS_ID, ANIMSTEALTH_CLASSID );
INode *node = GetCOREInterface()->CreateObjectNode( stealth );
stealth->SetSegment( ( strcmp(animName, ENTIRE_ANIMATION_NAME) != 0 ) ? animName : nil );
stealth->SetNodeName( GetName() );
node->Freeze( true );
// Skip the attach, since we might not find a valid INode. This will leave the node attached to the scene
// root, which is fine. Since we just care about it being SOMEWHERE in the scene hierarchy
/*
if( fAnimPB->Count( (ParamID)kPBAnimStealthNodes ) > 0 )
{
plAnimStealthNode *first = (plAnimStealthNode *)fAnimPB->GetReferenceTarget( (ParamID)kPBAnimStealthNodes, 0, 0 );
first->GetINode()->AttachChild( node );
}
*/
fAnimPB->Append( (ParamID)kPBAnimStealthNodes, 1, (ReferenceTarget **)&stealth );
const char *realName = stealth->GetSegmentName();
fStealthsChanged = true;
}
else
{
// Exists already, we're ok
stealth->SetParentMtl( this );
}
return stealth;
}
//// Change Callbacks ////////////////////////////////////////////////////////
void plPassMtlBase::RegisterChangeCallback( plMtlChangeCallback *callback )
{
if( fChangeCallbacks.Find( callback ) == fChangeCallbacks.kMissingIndex )
fChangeCallbacks.Append( callback );
}
void plPassMtlBase::UnregisterChangeCallback( plMtlChangeCallback *callback )
{
int idx = fChangeCallbacks.Find( callback );
if( idx != fChangeCallbacks.kMissingIndex )
fChangeCallbacks.Remove( idx );
}
//// IUpdateAnimNodes ////////////////////////////////////////////////////////
// Updates the list of stealth nodes in the anim paramBlock to match our
// list of anim segments.
void plPassMtlBase::IUpdateAnimNodes( void )
{
// Our beautiful hack, to make sure we don't update until we actually are loaded
if( fLoading )
return;
SegmentMap *segMap = GetAnimSegmentMap( this, nil );
hsTArray<plAnimStealthNode *> goodNodes;
// Keep track of whether we change anything
fStealthsChanged = false;
// Verify one for "entire animation"
plAnimStealthNode *stealth = IVerifyStealthPresent( ENTIRE_ANIMATION_NAME );
goodNodes.Append( stealth );
// Verify segment nodes
if( segMap != nil )
{
for( SegmentMap::iterator i = segMap->begin(); i != segMap->end(); i++ )
{
SegmentSpec *spec = (*i).second;
if( spec->fType == SegmentSpec::kAnim )
{
plAnimStealthNode *stealth = IVerifyStealthPresent( spec->fName );
goodNodes.Append( stealth );
}
}
DeleteSegmentMap( segMap );
}
// Remove nodes that no longer have segments
int idx;
for( idx = 0; idx < fAnimPB->Count( (ParamID)kPBAnimStealthNodes ); )
{
plAnimStealthNode *node = (plAnimStealthNode *)fAnimPB->GetReferenceTarget( (ParamID)kPBAnimStealthNodes, 0, idx );
if( node != nil && goodNodes.Find( node ) == goodNodes.kMissingIndex )
{
fAnimPB->Delete( (ParamID)kPBAnimStealthNodes, idx, 1 );
// GetCOREInterface()->DeleteNode( node->GetINode() );
fStealthsChanged = true;
}
else
idx++;
}
if( fStealthsChanged )
{
// Yup, our list of stealths got updated. Notify everyone of such.
for( idx = 0; idx < fChangeCallbacks.GetCount(); idx++ )
fChangeCallbacks[ idx ]->SegmentListChanged();
}
}
//// NameChanged /////////////////////////////////////////////////////////////
// Notify from NTWatcher so we can update the names of our stealth nodes
void plPassMtlBase::NameChanged( void )
{
for( int idx = 0; idx < fAnimPB->Count( (ParamID)kPBAnimStealthNodes ); idx++ )
{
plAnimStealthNode *node = (plAnimStealthNode *)fAnimPB->GetReferenceTarget( (ParamID)kPBAnimStealthNodes, 0, idx );
if( node != nil )
node->SetNodeName( GetName() );
}
}
//// NoteTrackAdded/Removed //////////////////////////////////////////////////
// Notifies from NTWatcher so we can update our list of stealths
void plPassMtlBase::NoteTrackAdded( void )
{
int i;
// Make a ref to our new notetrack
for( i = 0; i < NumNoteTracks(); i++ )
{
NoteTrack *track = GetNoteTrack( i );
if( fNotetracks.Find( track ) == fNotetracks.kMissingIndex )
{
MakeRefByID( FOREVER, kRefNotetracks + fNotetracks.GetCount(), track );
break;
}
}
for( i = 0; i < fChangeCallbacks.GetCount(); i++ )
fChangeCallbacks[ i ]->NoteTrackListChanged();
IUpdateAnimNodes();
}
void plPassMtlBase::NoteTrackRemoved( void )
{
int i;
hsBitVector stillThere;
// Make a ref to our new notetrack
for( i = 0; i < NumNoteTracks(); i++ )
{
NoteTrack *track = GetNoteTrack( i );
int idx = fNotetracks.Find( track );
if( idx != fNotetracks.kMissingIndex )
stillThere.Set( idx );
}
for( i = 0; i < fNotetracks.GetCount(); i++ )
{
if( !stillThere.IsBitSet( i ) && fNotetracks[ i ] != nil )
{
// DeleteReference( kRefNotetracks + i );
SetReference( kRefNotetracks + i, nil );
}
}
for( i = 0; i < fChangeCallbacks.GetCount(); i++ )
fChangeCallbacks[ i ]->NoteTrackListChanged();
IUpdateAnimNodes();
}
//////////////////////////////////////////////////////////////////////////////
//// MAX Ref Stuff ///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// NumRefs /////////////////////////////////////////////////////////////////
int plPassMtlBase::NumRefs()
{
return 4 + fNotetracks.GetCount();
}
//// GetReference ////////////////////////////////////////////////////////////
RefTargetHandle plPassMtlBase::GetReference( int i )
{
if( i >= kRefNotetracks && i < kRefNotetracks + fNotetracks.GetCount() )
return fNotetracks[ i - kRefNotetracks ];
return NULL;
}
//// SetReference ////////////////////////////////////////////////////////////
void plPassMtlBase::SetReference(int i, RefTargetHandle rtarg)
{
if( i >= kRefNotetracks )
{
fNotetracks.ExpandAndZero(i - kRefNotetracks + 1);
fNotetracks[i - kRefNotetracks] = (NoteTrack*)rtarg;
}
}
//// NotifyRefChanged ////////////////////////////////////////////////////////
RefResult plPassMtlBase::NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget,
PartID &partID, RefMessage message )
{
switch( message )
{
case REFMSG_CHANGE:
fIValid.SetEmpty();
// see if this message came from a changing parameter in the pblock,
// if so, limit rollout update to the changing item
if (hTarget == fBasicPB || hTarget == fAdvPB || hTarget == fLayersPB || hTarget == fAnimPB)
{
IParamBlock2 *pb = (IParamBlock2*)hTarget;
ParamID changingParam = pb->LastNotifyParamID();
pb->GetDesc()->InvalidateUI( changingParam );
// And let the SceneWatcher know that the material on some of it's
// referenced objects changed.
NotifyDependents( FOREVER, PART_ALL, REFMSG_USER_MAT );
}
else
{
// Was it a notetrack ref?
if( fNotetracks.Find( (NoteTrack *)hTarget ) != fNotetracks.kMissingIndex )
{
// Yup, so update our notetrack list
IUpdateAnimNodes();
}
}
break;
case REFMSG_TARGET_DELETED:
NoteTrackRemoved();
break;
}
return REF_SUCCEED;
}
//////////////////////////////////////////////////////////////////////////////
//// Standard IO (or non-standard, as the case may be) ///////////////////////
//////////////////////////////////////////////////////////////////////////////
//// PostLoadAnimPBFixup /////////////////////////////////////////////////////
// Takes the old version of the anim paramblock and translates it into the
// new version.
// Note that there's an interesting (?) side effect of this: for new materials,
// we'll incorrectly detect them as the "old" format and fix-up them as well.
// This means that we'll end up with the same defaults for (Entire Animation)
// that we had for the old materials. We can easily change the defaults by
// changing the defaults for the old paramblock though.
// Also, we go ahead and re-work the stealth parent pointers here, since it
// appears to be the ONLY time we can do it and have it reliably work. ARRGH!
//
// History of the options that we CAN'T do and why (and hence why this):
// - ParamBlock accessor doesn't work. For some reason, the accessor isn't
// always called on load, even with P_CALLSETS_ON_LOAD specified
// - Doing it on Load() doesn't work, because neither the ParamBlocks are
// guaranteed to be fully loaded (with their tabs filled) nor are the
// notetracks necessarily attached yet
// - Notetracks can also possibly be attached BEFORE load, which doesn't
// do us a damned bit of good, so we need to make sure we're fully
// loaded before we run this function. Unfortunately, the only time
// we're guaranteed THAT is by a FILE_POST_OPEN notify. (post-load
// callbacks don't work because they're called right after our object
// is loaded but not necessarily before the notetracks are attached)
void plPassMtlBase::PostLoadAnimPBFixup( void )
{
SetLoadingFlag( false );
#ifdef MCN_UPGRADE_OLD_ANIM_BLOCKS
if( fAnimPB->Count( (ParamID)kPBAnimStealthNodes ) == 0 )
{
// Yup, old style. So our update process looks like this:
// 1) Create stealths for all our segments as we are now
// 2) Set the parameters on all of them to our old defaults (no autostart,
// loop on entire, no ease).
// 3) Copy the old paramblock values to the single stealth indicated by
// the old PB
// Step 1...
IUpdateAnimNodes();
// Step 2...
for( int i = 0; i < fAnimPB->Count( (ParamID)kPBAnimStealthNodes ); i++ )
{
plAnimStealthNode *node = (plAnimStealthNode *)fAnimPB->GetReferenceTarget( (ParamID)kPBAnimStealthNodes, 0, i );
const char *name = node->GetSegmentName();
node->SetAutoStart( false );
node->SetLoop( true, ENTIRE_ANIMATION_NAME );
node->SetEaseIn( plAnimEaseTypes::kNoEase, 1.f, 1.f, 1.f );
node->SetEaseOut( plAnimEaseTypes::kNoEase, 1.f, 1.f, 1.f );
}
// Step 3...
const char *oldSel = (const char *)fAnimPB->GetStr( (ParamID)kPBAnimName );
if( oldSel == nil )
oldSel = ENTIRE_ANIMATION_NAME;
plAnimStealthNode *myNew = IFindStealth( oldSel );
if( myNew != nil )
{
#pragma warning( push ) // Forcing value to bool true or false (go figure, i'm even explicitly casting)
#pragma warning( disable:4800 ) // Forcing value to bool true or false (go figure, i'm even explicitly casting)
myNew->SetAutoStart( (bool)fAnimPB->GetInt( (ParamID)kPBAnimAutoStart ) );
myNew->SetLoop( (bool)fAnimPB->GetInt( (ParamID)kPBAnimLoop ),
(char *)fAnimPB->GetStr( (ParamID)kPBAnimLoopName ) );
myNew->SetEaseIn( (UInt8)fAnimPB->GetInt( (ParamID)kPBAnimEaseInType ),
(hsScalar)fAnimPB->GetFloat( (ParamID)kPBAnimEaseInLength ),
(hsScalar)fAnimPB->GetFloat( (ParamID)kPBAnimEaseInMin ),
(hsScalar)fAnimPB->GetFloat( (ParamID)kPBAnimEaseInMax ) );
myNew->SetEaseOut( (UInt8)fAnimPB->GetInt( (ParamID)kPBAnimEaseOutType ),
(hsScalar)fAnimPB->GetFloat( (ParamID)kPBAnimEaseOutLength ),
(hsScalar)fAnimPB->GetFloat( (ParamID)kPBAnimEaseOutMin ),
(hsScalar)fAnimPB->GetFloat( (ParamID)kPBAnimEaseOutMax ) );
#pragma warning( pop )
}
}
#endif // MCN_UPGRADE_OLD_ANIM_BLOCKS
// Make sure the parent is set tho. Note: we have to do this because, for some *(#$&(* reason,
// when we're loading a file, MAX can somehow add the stealths to our tab list WITHOUT calling
// the accessor for it (and the tab is empty on the CallSetsOnLoad() pass, for some reason).
for( int i = 0; i < fAnimPB->Count( (ParamID)kPBAnimStealthNodes ); i++ )
{
plAnimStealthNode *node = (plAnimStealthNode *)fAnimPB->GetReferenceTarget( (ParamID)kPBAnimStealthNodes, 0, i );
node->SetParentMtl( this );
}
}
#define MTL_HDR_CHUNK 0x4000
//// Load ////////////////////////////////////////////////////////////////////
// Our actual MAX load function
IOResult plPassMtlBase::Load(ILoad *iload)
{
plPostLoadHandler::AddPostLoad( this );
IOResult res;
int id;
while (IO_OK==(res=iload->OpenChunk()))
{
switch(id = iload->CurChunkID())
{
case MTL_HDR_CHUNK:
res = MtlBase::Load(iload);
break;
}
iload->CloseChunk();
if (res!=IO_OK)
return res;
}
return IO_OK;
}
//// Save ////////////////////////////////////////////////////////////////////
// The MAX flip-side
IOResult plPassMtlBase::Save(ISave *isave)
{
IOResult res;
isave->BeginChunk(MTL_HDR_CHUNK);
res = MtlBase::Save(isave);
if (res!=IO_OK) return res;
isave->EndChunk();
return IO_OK;
}
//// ICloneBase //////////////////////////////////////////////////////////////
void plPassMtlBase::ICloneBase( plPassMtlBase *target, RemapDir &remap )
{
*((MtlBase*)target) = *((MtlBase*)this);
ICloneRefs( target, remap );
for( int idx = 0; idx < fAnimPB->Count( (ParamID)kPBAnimStealthNodes ); idx++ )
{
IParamBlock2 *pb = target->fAnimPB;
plAnimStealthNode *stealth = (plAnimStealthNode *)fAnimPB->GetReferenceTarget( (ParamID)kPBAnimStealthNodes, 0, idx );
pb->SetValue( (ParamID)kPBAnimStealthNodes, 0, remap.CloneRef( stealth ), idx );
stealth = (plAnimStealthNode *)pb->GetReferenceTarget( (ParamID)kPBAnimStealthNodes, 0, idx );
INode *node = GetCOREInterface()->CreateObjectNode( stealth );
stealth->SetNodeName( GetName() );
node->Freeze( true );
}
BaseClone(this, target, remap);
target->fIValid.SetEmpty();
}
//// ConvertToPassMtl ////////////////////////////////////////////////////////
// Static convert to our plPassMtlBase type, if possible
plPassMtlBase *plPassMtlBase::ConvertToPassMtl( Mtl *mtl )
{
if( mtl == nil )
return nil;
if( mtl->ClassID() == PASS_MTL_CLASS_ID
|| mtl->ClassID() == BUMP_MTL_CLASS_ID
|| mtl->ClassID() == DECAL_MTL_CLASS_ID )
{
return (plPassMtlBase *)mtl;
}
return nil;
}
//// SetupProperties /////////////////////////////////////////////////////////
hsBool plPassMtlBase::SetupProperties( plMaxNode *node, plErrorMsg *pErrMsg )
{
hsBool ret = true;
// Call SetupProperties on all our animStealths if we have any
int i, count = IGetNumStealths();
for( i = 0; i < count; i++ )
{
if( !IGetStealth( i, false )->SetupProperties( node, pErrMsg ) )
ret = false;
}
return ret;
}
//// ConvertDeInit ///////////////////////////////////////////////////////////
hsBool plPassMtlBase::ConvertDeInit( plMaxNode *node, plErrorMsg *pErrMsg )
{
hsBool ret = true;
// Call ConvertDeInit on all our animStealths if we have any
int i, count = IGetNumStealths();
for( i = 0; i < count; i++ )
{
if( !IGetStealth( i, false )->ConvertDeInit( node, pErrMsg ) )
ret = false;
}
return ret;
}

View File

@ -0,0 +1,301 @@
/*==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==*/
#ifndef PL_PASSMTLBASE_H
#define PL_PASSMTLBASE_H
#include "hsTemplates.h"
#include "Max.h"
#include "iparamb2.h"
#include "../../PubUtilLib/plInterp/plAnimEaseTypes.h"
class plNoteTrackWatcher;
class plMtlChangeCallback;
class plAnimStealthNode;
class NoteTrack;
class plPassAnimDlgProc;
class plStealthNodeAccessor;
class plMaxNode;
class plErrorMsg;
class plPassMtlBase : public Mtl
{
protected:
friend class plPassAnimDlgProc;
friend class plStealthNodeAccessor;
friend class plNoteTrackWatcher;
plNoteTrackWatcher *fNTWatcher;
IParamBlock2 *fBasicPB;
IParamBlock2 *fAdvPB;
IParamBlock2 *fLayersPB;
IParamBlock2 *fAnimPB;
Interval fIValid;
hsBool fLoading;
hsTArray<NoteTrack *> fNotetracks;
hsBool fStealthsChanged;
hsTArray<plMtlChangeCallback *> fChangeCallbacks;
void IUpdateAnimNodes( void );
plAnimStealthNode *IFindStealth( const char *animName );
plAnimStealthNode *IVerifyStealthPresent( const char *animName );
int IGetNumStealths( hsBool update = true );
plAnimStealthNode *IGetStealth( int index, hsBool update = true );
void ICloneBase( plPassMtlBase *target, RemapDir &remap );
virtual void ICloneRefs( plPassMtlBase *target, RemapDir &remap ) = 0;
public:
// mcn note: as far as I can tell, this is always the same pointer passed around to everyone.
// So since we have trouble getting it all the time, just store the first version we get and
// use that forever and ever
static IMtlParams *fIMtlParams;
plPassMtlBase( BOOL loading );
virtual ~plPassMtlBase();
virtual bool HasAlpha() = 0;
enum Refs
{
//kRefBasic, // Can't do this, long ago they were different in the "derived" classes,
//kRefAdv, // and even tho MAX says it doesn't write refs out by their index, it does
//kRefLayers,
//kRefAnim,
kRefNotetracks = 4 // MUST BE THE LAST REF ID SPECIFIED
};
void SetLoadingFlag( hsBool f ) { fLoading = f; }
void PostLoadAnimPBFixup( void );
void RegisterChangeCallback( plMtlChangeCallback *callback );
void UnregisterChangeCallback( plMtlChangeCallback *callback );
// Change notifys from our ntWatcher
virtual void NoteTrackAdded( void );
virtual void NoteTrackRemoved( void );
virtual void NameChanged( void );
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
virtual void Reset( void );
int NumRefs();
virtual RefTargetHandle GetReference( int i );
virtual void SetReference( int i, RefTargetHandle rtarg );
RefResult NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget, PartID &partID, RefMessage message );
// Convert time, called on the setupProps pass for each material applied to a node in the scene
virtual hsBool SetupProperties( plMaxNode *node, plErrorMsg *pErrMsg );
virtual hsBool ConvertDeInit( plMaxNode *node, plErrorMsg *pErrMsg );
int GetNumStealths( void );
plAnimStealthNode *GetStealth( int index );
// Static convert to our plPassMtlBase type, if possible
static plPassMtlBase *ConvertToPassMtl( Mtl *mtl );
// Blend types
enum
{
kBlendNone,
kBlendAlpha,
kBlendAdd,
kBlendMult
};
// Alpha blend types
enum
{
kAlphaDiscard,
kAlphaMultiply,
kAlphaAdd
};
// Advanced Block
virtual int GetBasicWire() = 0;
virtual int GetMeshOutlines() = 0;
virtual int GetTwoSided() = 0;
virtual int GetSoftShadow() = 0;
virtual int GetNoProj() = 0;
virtual int GetVertexShade() = 0;
virtual int GetNoShade() = 0;
virtual int GetNoFog() = 0;
virtual int GetWhite() = 0;
virtual int GetZOnly() = 0;
virtual int GetZClear() = 0;
virtual int GetZNoRead() = 0;
virtual int GetZNoWrite() = 0;
virtual int GetZInc() = 0;
virtual int GetAlphaTestHigh() = 0;
// Animation block
virtual char * GetAnimName() = 0;
virtual int GetAutoStart() = 0;
virtual int GetLoop() = 0;
virtual char * GetAnimLoopName() = 0;
virtual int GetEaseInType() { return plAnimEaseTypes::kNoEase; }
virtual float GetEaseInMinLength() { return 1; }
virtual float GetEaseInMaxLength() { return 1; }
virtual float GetEaseInNormLength() { return 1; }
virtual int GetEaseOutType() { return plAnimEaseTypes::kNoEase; }
virtual float GetEaseOutMinLength() { return 1; }
virtual float GetEaseOutMaxLength() { return 1; }
virtual float GetEaseOutNormLength() { return 1; }
virtual char * GetGlobalVarName() { return NULL; }
virtual int GetUseGlobal() { return 0; }
// Basic block
virtual int GetColorLock() = 0;
virtual Color GetAmbColor() = 0;
virtual Color GetColor() = 0;
virtual int GetOpacity() = 0;
virtual int GetEmissive() = 0;
virtual int GetUseSpec() = 0;
virtual int GetShine() = 0;
virtual Color GetSpecularColor() = 0;
virtual int GetDiffuseColorLock() = 0;
virtual Color GetRuntimeColor() = 0;
virtual Control *GetPreshadeColorController() = 0;
virtual Control *GetAmbColorController() = 0;
virtual Control *GetOpacityController() = 0;
virtual Control *GetSpecularColorController() = 0;
virtual Control *GetRuntimeColorController() = 0;
// Layer block
virtual Texmap *GetBaseLayer() = 0;
virtual int GetTopLayerOn() = 0;
virtual Texmap *GetTopLayer() = 0;
virtual int GetLayerBlend() = 0;
virtual int GetOutputAlpha() = 0;
virtual int GetOutputBlend() = 0;
};
// Make sure min is less than normal, which is less than max
class plEaseAccessor : public PBAccessor
{
protected:
bool fDoingUpdate;
int fBlockID;
int fEaseInMinID, fEaseInMaxID, fEaseInNormID, fEaseOutMinID, fEaseOutMaxID, fEaseOutNormID;
void AdjustMin(IParamBlock2 *pb, ParamID minID, ParamID normalID, ParamID maxID, float value)
{
if (value > pb->GetFloat(normalID))
{
pb->SetValue(normalID, 0, value);
if (value > pb->GetFloat(maxID))
pb->SetValue(maxID, 0, value);
}
}
void AdjustNormal(IParamBlock2 *pb, ParamID minID, ParamID normalID, ParamID maxID, float value)
{
if (value < pb->GetFloat(minID))
pb->SetValue(minID, 0, value);
if (value > pb->GetFloat(maxID))
pb->SetValue(maxID, 0, value);
}
void AdjustMax(IParamBlock2 *pb, ParamID minID, ParamID normalID, ParamID maxID, float value)
{
if (value < pb->GetFloat(normalID))
{
pb->SetValue(normalID, 0, value);
if (value < pb->GetFloat(minID))
pb->SetValue(minID, 0, value);
}
}
public:
plEaseAccessor(int blockID, int easeInMinID, int easeInMaxID, int easeInNormID,
int easeOutMinID, int easeOutMaxID, int easeOutNormID)
{
fDoingUpdate = false;
fBlockID = blockID;
fEaseInMinID = easeInMinID; fEaseInMaxID = easeInMaxID; fEaseInNormID = easeInNormID;
fEaseOutMinID = easeOutMinID; fEaseOutMaxID = easeOutMaxID; fEaseOutNormID = easeOutNormID;
}
void Set(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
if (fDoingUpdate)
return;
fDoingUpdate = true;
IParamBlock2 *pb = owner->GetParamBlockByID(fBlockID);
if (id == fEaseInMinID)
AdjustMin(pb, fEaseInMinID, fEaseInNormID, fEaseInMaxID, v.f);
else if (id == fEaseInNormID)
AdjustNormal(pb, fEaseInMinID, fEaseInNormID, fEaseInMaxID, v.f);
else if (id == fEaseInMaxID)
AdjustMax(pb, fEaseInMinID, fEaseInNormID, fEaseInMaxID, v.f);
else if (id == fEaseOutMinID)
AdjustMin(pb, fEaseOutMinID, fEaseOutNormID, fEaseOutMaxID, v.f);
else if (id == fEaseOutNormID)
AdjustNormal(pb, fEaseOutMinID, fEaseOutNormID, fEaseOutMaxID, v.f);
else if (id == fEaseOutMaxID)
AdjustMax(pb, fEaseOutMinID, fEaseOutNormID, fEaseOutMaxID, v.f);
fDoingUpdate = false;
}
};
//// plMtlChangeCallback /////////////////////////////////////////////////////
// Interface class for receiving info about when things change on a material.
class plMtlChangeCallback
{
public:
virtual void NoteTrackListChanged( void ) { ; }
virtual void SegmentListChanged( void ) { ; }
};
#endif // PL_PASSMTLBASE_H

View File

@ -0,0 +1,68 @@
/*==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==*/
#ifndef PL_PASSMTLBASICPB_H
#define PL_PASSMTLBASICPB_H
// Param ID's
enum
{
kPassBasColorLock,
kPassBasColorAmb,
kPassBasColor,
kPassBasOpacity,
kPassBasEmissive,
// Specular
kPassBasUseSpec,
kPassBasShine,
kPassBasShineStr,
// New color stuff
kPassBasDiffuseLock,
kPassBasRunColor,
kPassBasSpecColor
};
#endif //PL_PASSMTLBASICPB_H

View File

@ -0,0 +1,256 @@
/*==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 "plPassMtl.h"
#include "plPassMtlBasicPB.h"
#include "resource.h"
#include "iparamm2.h"
class PassBasicPBAccessor;
extern PassBasicPBAccessor basicAccessor;
class PassBasicDlgProc;
extern PassBasicDlgProc gPassBasicDlgProc;
static ParamBlockDesc2 gPassBasicPB
(
plPassMtl::kBlkBasic, _T("basic"), IDS_PASS_BASIC, GetPassMtlDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI, plPassMtl::kRefBasic,
// UI
IDD_PASS_BASIC, IDS_PASS_BASIC, 0, 0, &gPassBasicDlgProc,
// Color
kPassBasColorLock, _T("colorLock"), TYPE_BOOL, 0, 0,
p_ui, TYPE_CHECKBUTTON, IDC_LOCK_AD,
p_accessor, &basicAccessor,
end,
kPassBasColorAmb, _T("ambColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_AMB,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_COLOR_AMB,
p_accessor, &basicAccessor,
end,
kPassBasColor, _T("color"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_COLOR,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_COLOR,
p_default, Color(1,1,1),
p_accessor, &basicAccessor,
end,
kPassBasRunColor, _T("runtimeColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_RUNCOLOR,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_RUNCOLOR,
p_default, Color(-1,-1,-1),
p_accessor, &basicAccessor,
end,
kPassBasDiffuseLock, _T("diffuseLock"), TYPE_BOOL, 0, 0,
p_ui, TYPE_CHECKBUTTON, IDC_LOCK_COLORS,
p_accessor, &basicAccessor,
p_default, TRUE,
end,
// Opacity
kPassBasOpacity, _T("opacity"), TYPE_INT, P_ANIMATABLE, IDS_BASIC_OPAC,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_TR_EDIT, IDC_TR_SPIN, 0.4,
p_range, 0, 100,
p_default, 100,
end,
kPassBasEmissive, _T("emissive"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_LAYER_EMISSIVE_CB,
end,
// Specularity
kPassBasUseSpec, _T("useSpec"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_SPECULAR,
p_enable_ctrls, 2, kPassBasShine, kPassBasSpecColor,
end,
kPassBasShine, _T("shine"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_SH_EDIT, IDC_SH_SPIN, 0.4,
p_range, 0, 100,
end,
kPassBasSpecColor, _T("specularColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_SPECCOLOR,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_SPECCOLOR,
p_default, Color(0,0,0),
end,
// OBSOLETE--here so we can upgrade it to color if necessary
kPassBasShineStr, _T("shineStr"), TYPE_INT, 0, 0,
p_range, -1, 100,
p_default, -1,
end,
end
);
ParamBlockDesc2 *GetPassBasicPB() { return &gPassBasicPB; }
class PassBasicPBAccessor : public PBAccessor
{
bool fColorLocked;
public:
PassBasicPBAccessor() : fColorLocked( false ) {}
void Set(PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
plPassMtl* mtl = (plPassMtl*)owner;
IParamBlock2 *pb = mtl->GetParamBlockByID(plPassMtl::kBlkBasic);
switch (id)
{
case kPassBasColorLock:
if (val.i)
pb->SetValue(kPassBasColor, t, pb->GetColor(kPassBasColorAmb, t));
break;
case kPassBasDiffuseLock:
if (val.i)
pb->SetValue(kPassBasRunColor, t, pb->GetColor(kPassBasColor, t));
break;
case kPassBasColor:
case kPassBasColorAmb:
case kPassBasRunColor:
ISyncLockedColors( id, pb, val, t );
break;
}
}
void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid)
{
}
void ISyncLockedColors( ParamID settingID, IParamBlock2 *pb, PB2Value &val, TimeValue t )
{
int i, numToSet = 0;
ParamID toSet[ 2 ];
if( fColorLocked )
return;
fColorLocked = true;
if( settingID == kPassBasColorAmb && pb->GetInt( kPassBasColorLock, t ) )
{
toSet[ numToSet++ ] = kPassBasColor;
if( pb->GetInt( kPassBasDiffuseLock, t ) )
toSet[ numToSet++ ] = kPassBasRunColor;
}
else if( settingID == kPassBasRunColor && pb->GetInt( kPassBasDiffuseLock, t ) )
{
toSet[ numToSet++ ] = kPassBasColor;
if( pb->GetInt( kPassBasColorLock, t ) )
toSet[ numToSet++ ] = kPassBasColorAmb;
}
else if( settingID == kPassBasColor )
{
if( pb->GetInt( kPassBasColorLock, t ) )
toSet[ numToSet++ ] = kPassBasColorAmb;
if( pb->GetInt( kPassBasDiffuseLock, t ) )
toSet[ numToSet++ ] = kPassBasRunColor;
}
for( i = 0; i < numToSet; i++ )
{
pb->SetValue( toSet[ i ], t, *val.p );
if( pb->GetMap() )
pb->GetMap()->Invalidate( toSet[ i ] );
}
fColorLocked = false;
}
};
static PassBasicPBAccessor basicAccessor;
class PassBasicDlgProc : public ParamMap2UserDlgProc
{
#if 1
protected:
HIMAGELIST hLockButtons;
void LoadLockButtons()
{
static bool loaded = false;
if (loaded)
return;
loaded = true;
HINSTANCE hInst = hInstance;
hLockButtons = ImageList_Create(16, 15, TRUE, 2, 0);
HBITMAP hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BUTTONS));
HBITMAP hMask = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_MASKBUTTONS));
ImageList_Add(hLockButtons, hBitmap, hMask);
DeleteObject(hBitmap);
DeleteObject(hMask);
}
void ISetLock(HWND hButton)
{
LoadLockButtons();
ICustButton *iBut = GetICustButton(hButton);
iBut->SetImage(hLockButtons,0,1,0,1,16,15);
iBut->SetType(CBT_CHECK);
ReleaseICustButton(iBut);
}
public:
PassBasicDlgProc() : hLockButtons(NULL) {}
~PassBasicDlgProc() { if (hLockButtons) ImageList_Destroy(hLockButtons); }
#endif
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
IParamBlock2 *pb = map->GetParamBlock();
switch (msg)
{
case WM_INITDIALOG:
{
ISetLock(GetDlgItem(hWnd, IDC_LOCK_AD));
ISetLock(GetDlgItem(hWnd, IDC_LOCK_COLORS));
}
return TRUE;
}
return FALSE;
}
void DeleteThis() {}
};
static PassBasicDlgProc gPassBasicDlgProc;

View File

@ -0,0 +1,57 @@
/*==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==*/
#ifndef PL_PASSMTLLAYERSPB_H
#define PL_PASSMTLLAYERSPB_H
enum
{
// Layers
kPassLayBase,
kPassLayTopOn,
kPassLayTop,
kPassLayBlend,
kPassLayOutputBlend,
kPassLayOutputAlpha,
};
#endif //PL_PASSMTLLAYERSPB_H

View File

@ -0,0 +1,102 @@
/*==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 "plPassMtl.h"
#include "plPassMtlLayersPB.h"
#include "resource.h"
#include "iparamm2.h"
#include "Layers/plLayerTex.h"
class PassMtlLayersAccessor;
extern PassMtlLayersAccessor gLayersAccessor;
class LayersDlgProc;
extern LayersDlgProc gLayersDlgProc;
static ParamBlockDesc2 gPassMtlLayersPB
(
plPassMtl::kBlkLayers, _T("layers"), IDS_PASS_LAYERS, GetPassMtlDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI, plPassMtl::kRefLayers,
// UI
IDD_PASS_LAYERS, IDS_PASS_LAYERS, 0, 0, NULL,
kPassLayBase, _T("baseLayer"), TYPE_TEXMAP, 0, IDS_BASIC_AMB,
p_ui, TYPE_TEXMAPBUTTON, IDC_LAYER1,
p_subtexno, 0,
end,
kPassLayTopOn, _T("topLayerOn"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_TOP_ON,
p_default, FALSE,
p_enable_ctrls, 3, kPassLayTop, kPassLayBlend, kPassLayOutputAlpha,
end,
kPassLayTop, _T("topLayer"), TYPE_TEXMAP, 0, 0,
p_ui, TYPE_TEXMAPBUTTON, IDC_LAYER2,
p_subtexno, 1,
end,
kPassLayBlend, _T("layerBlend"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_LAYER_ALPHA, IDC_LAYER_ADD, IDC_LAYER_MULTIPLY,
p_vals, plPassMtlBase::kBlendAlpha, plPassMtlBase::kBlendAdd, plPassMtlBase::kBlendMult,
p_default, plPassMtlBase::kBlendAdd,
end,
kPassLayOutputAlpha, _T("ouputAlpha"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_OUTPUTA_DISCARD, IDC_OUTPUTA_ADD, IDC_OUTPUTA_MULT,
p_vals, plPassMtlBase::kAlphaDiscard, plPassMtlBase::kAlphaAdd, plPassMtlBase::kAlphaMultiply,
p_default, plPassMtlBase::kAlphaDiscard,
end,
kPassLayOutputBlend, _T("outputBlend"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_OUTPUTB_NONE, IDC_OUTPUTB_ALPHA, IDC_OUTPUTB_ADD,
p_vals, plPassMtlBase::kBlendNone, plPassMtlBase::kBlendAlpha, plPassMtlBase::kBlendAdd,
p_default, plPassMtlBase::kBlendNone,
end,
end
);
ParamBlockDesc2 *GetPassLayersPB() { return &gPassMtlLayersPB; }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,301 @@
/*==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 "hsTypes.h"
#include "max.h"
//#include "mtlhdr.h"
#include "Shaders.h"
//===========================================================================
// Useful variables...
//===========================================================================
static PhongShader phongShader;
static BlinnShader blinnShader;
static MetalShader metalShader;
static hsMaxShader plasmaShader;
static Shader *shaders[3] = {
&phongShader,
&metalShader,
&blinnShader,
};
AColor black(0.0f,0.0f,0.0f,0.0f);
//===========================================================================
// Useful functions...
//===========================================================================
Shader *GetShader(int s) { return shaders[s]; };
#if 1
// Quadratic
static inline float Soften(float r) {
return r*(2.0f-r);
}
#else
// Cubic
static inline float Soften(float r) {
return r*r*(3.0f-2.0f*r);
}
#endif
float CompK(float f0) {
return float(2.0*sqrt(f0)/sqrt(1.0-f0));
}
float fres_metal(float c, float k) {
float b,rpl, rpp,c2;
b = k*k + 1.0f;
c2 = c*c;
rpl = (b*c2-2*c+1)/(b*c2+2*c+1);
rpp = (b-2*c+c2)/(b+2*c+c2);
return (.5f*(rpl+rpp));
}
//===========================================================================
// Phong shader... don't know if this is ever going to be used
//===========================================================================
void PhongShader::Illum(ShadeContext &sc, SIllumParams &ip) {
LightDesc *l;
Color lightCol;
BOOL is_shiny;
Point3 R;
if (is_shiny=(ip.sh_str>0.0f))
R = sc.ReflectVector();
for (int i=0; i<sc.nLights; i++) {
l = sc.Light(i);
register float NL, diffCoef;
Point3 L;
if (l->Illuminate(sc,ip.N,lightCol,L,NL,diffCoef)) {
// diffuse
if (NL<=0.0f)
continue;
if (l->affectDiffuse)
ip.diffIllum += diffCoef*lightCol;
if (is_shiny&&l->affectSpecular) {
// specular (Phong)
float c = DotProd(L,R);
if (c>0.0f) {
if (ip.softThresh!=0.0&&diffCoef<ip.softThresh) {
float r = diffCoef/ip.softThresh;
c *= Soften(r);
}
c = (float)pow((double)c, (double)ip.ph_exp); // could use table lookup for speed
ip.specIllum += c*ip.sh_str*lightCol;
}
}
}
}
ip.specIllum *= ip.spec;
}
//===========================================================================
// hsMax shader... write this?
//===========================================================================
void hsMaxShader::Illum(ShadeContext &sc, SIllumParams &ip) {
LightDesc *l;
Color lightCol;
BOOL is_shiny;
Point3 R;
if (is_shiny=(ip.sh_str>0.0f))
R = sc.ReflectVector();
for (int i=0; i<sc.nLights; i++) {
l = sc.Light(i);
register float NL, diffCoef;
Point3 L;
if (l->Illuminate(sc,ip.N,lightCol,L,NL,diffCoef)) {
// diffuse
if (NL<=0.0f)
continue;
if (l->affectDiffuse)
ip.diffIllum += diffCoef*lightCol;
if (is_shiny&&l->affectSpecular) {
// specular
float c = DotProd(L,R);
if (c>0.0f) {
c = (float)pow((double)c, (double)ip.ph_exp); // could use table lookup for speed
ip.specIllum += c*ip.sh_str*lightCol;
}
}
}
}
ip.specIllum *= ip.spec;
}
//===========================================================================
// Blinn shader... don't know if this is ever going to be used
//===========================================================================
void BlinnShader::Illum(ShadeContext &sc, SIllumParams &ip) {
LightDesc *l;
Color lightCol;
// Blinn style phong
BOOL is_shiny=(ip.sh_str>0.0f)?1:0;
double ph_exp = double(ip.ph_exp)*4.0; // This is to make the hilite compatible with normal phong
for (int i=0; i<sc.nLights; i++) {
l = sc.Light(i);
register float NL, diffCoef;
Point3 L;
if (l->Illuminate(sc,ip.N,lightCol,L,NL,diffCoef)) {
// diffuse
if (NL<=0.0f)
continue;
if (l->affectDiffuse)
ip.diffIllum += diffCoef*lightCol;
// specular (Phong)
if (is_shiny&&l->affectSpecular) {
Point3 H = FNormalize(L-ip.V);
float c = DotProd(ip.N,H);
if (c>0.0f) {
if (ip.softThresh!=0.0&&diffCoef<ip.softThresh) {
c *= Soften(diffCoef/ip.softThresh);
}
c = (float)pow((double)c, ph_exp); // could use table lookup for speed
ip.specIllum += c*ip.sh_str*lightCol;
}
}
}
}
ip.specIllum *= ip.spec;
}
//===========================================================================
// Metal shader... don't know if this is ever going to be used
//===========================================================================
void MetalShader::Illum(ShadeContext &sc, SIllumParams &ip) {
LightDesc *l;
Color lightCol;
BOOL gotKav = FALSE;
float kav, fav0, m2inv,NV;
//IPoint2 sp = sc.ScreenCoord();
BOOL is_shiny;
if (ip.sh_str>0.0f) {
NV = -DotProd(ip.N,ip.V); // N dot V: view vector is TOWARDS us.
is_shiny = 1;
float r = 1.0f-ip.shine;
if (r==0.0f) r = .00001f;
m2inv = 1.0f/(r*r);
}
else
is_shiny = 0;
for (int i=0; i<sc.nLights; i++) {
l = sc.Light(i);
register float NL, diffCoef;
Point3 L;
if (!l->Illuminate(sc,ip.N,lightCol,L,NL,diffCoef))
continue;
// diffuse
if (NL>0.0f&&l->affectDiffuse) // TBD is the NL test necessary?
ip.diffIllum += diffCoef*lightCol;
if (is_shiny&&l->affectSpecular) { // SPECULAR
Color fcol;
float LH,NH,VH;
float sec2; // Was double?? TBD
Point3 H;
if (NV<0.0f) continue;
H = FNormalize(L-ip.V);
LH = DotProd(L,H); // cos(phi)
NH = DotProd(ip.N,H); // cos(alpha)
if (NH==0.0f) continue;
VH = -DotProd(ip.V,H);
// compute geometrical attenuation factor
float G = (NV<NL)? (2.0f*NV*NH/VH): (2.0f*NL*NH/VH);
if (G>0.0f) {
// Compute (approximate) indices of refraction
// this can be factored out for non-texture-mapped mtls
if (!gotKav) {
fav0 = Intens(ip.diff);
if (fav0>=1.0f) fav0 = .9999f;
kav = CompK(fav0);
gotKav = TRUE;
}
float fav = fres_metal(LH,kav);
float t = (fav-fav0)/(1.0f-fav0);
fcol = (1.0f-t)*ip.diff + Color(t,t,t);
// Beckman distribution (from Cook-Torrance paper)
sec2 = 1.0f/(NH*NH); // 1/sqr(cos)
float D = (.5f/PI)*sec2*sec2*m2inv*(float)exp((1.0f-sec2)*m2inv);
if (G>1.0f) G = 1.0f;
float Rs = ip.sh_str*D*G/(NV+.05f);
ip.specIllum += fcol*Rs*lightCol;
}
}
}
ip.diffIllum *= 1.0f - ip.sh_str;
}
void MetalShader::SetShininess(float shininess, float shineStr) {
float r = 1.0f-shininess;
if (r==0.0f) r = .00001f;
fm2inv = 1.0f/(r*r);
fshin_str = shineStr;
}
float MetalShader::EvalHilite(float x) {
float c = (float)cos(x*PI);
float sec2 = 1.0f/(c*c); /* 1/sqr(cos) */
return fshin_str*(.5f/PI)*sec2*sec2*fm2inv*(float)exp((1.0f-sec2)*fm2inv);
}

View File

@ -0,0 +1,156 @@
/*==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==*/
#ifndef __SHADERS_H
#define __SHADERS_H
class Shader;
//===========================================================================
// Interface tools...
//===========================================================================
struct SIllumParams {
unsigned long flags;
float sh_str, ph_exp, shine, softThresh;
Color amb, diff, spec;
Point3 N, V;
Color diffIllum, specIllum;
};
const int SHADER_PHONG = 0;
const int SHADER_METAL = 1;
const int SHADER_BLINN = 2;
const int SHADER_PLASMA = 3;
// Return shader of given type, using indices above...
Shader *GetShader(int s);
extern AColor black;
//===========================================================================
// Abstract shader...
//===========================================================================
class Shader {
public:
virtual void Illum(ShadeContext &sc, SIllumParams &ip)=0;
virtual void AffectReflMap(ShadeContext &sc, SIllumParams &ip, Color &rcol)=0;
virtual void SetShininess(float shininess, float shineStr)=0;
virtual float EvalHilite(float x)=0;
};
//===========================================================================
// Phong shader...
//===========================================================================
class PhongShader : public Shader {
float fs;
float shin_str;
public:
void Illum(ShadeContext &sc, SIllumParams &ip);
void AffectReflMap(ShadeContext &sc, SIllumParams &ip, Color &rcol) { rcol *= ip.spec; };
void SetShininess(float shininess, float shineStr) {
fs = (float)pow(2.0,shininess*10.0);
shin_str = shineStr;
}
float EvalHilite(float x) {
return shin_str*(float)pow((double)cos(x*PI),(double)fs);
}
};
//===========================================================================
// Blinn shader...
//===========================================================================
class BlinnShader : public Shader {
float fs;
float shin_str;
public:
void Illum(ShadeContext &sc, SIllumParams &ip);
void AffectReflMap(ShadeContext &sc, SIllumParams &ip, Color &rcol) { rcol *= ip.spec; };
void SetShininess(float shininess, float shineStr) {
fs = (float)pow(2.0,shininess*10.0);
shin_str = shineStr;
}
float EvalHilite(float x) {
return shin_str*(float)pow((double)cos(x*PI),(double)fs);
}
};
//===========================================================================
// Metal shader...
//===========================================================================
class MetalShader : public Shader {
float fm2inv, fshin_str;
public:
void Illum(ShadeContext &sc, SIllumParams &ip);
void AffectReflMap(ShadeContext &sc, SIllumParams &ip, Color &rcol) { rcol *= ip.diff; };
void SetShininess(float shininess, float shineStr);
float EvalHilite(float x);
};
//===========================================================================
// hsMax layer shader...
//===========================================================================
class hsMaxShader : public Shader {
float fs;
float shin_str;
public:
void Illum(ShadeContext &sc, SIllumParams &ip);
void AffectReflMap(ShadeContext &sc, SIllumParams &ip, Color &rcol) { rcol *= ip.spec; };
void SetShininess(float shininess, float shineStr) {
fs = (float)pow(2.0,shininess*10.0);
shin_str = shineStr;
}
float EvalHilite(float x) {
return shin_str*(float)pow((double)cos(x*PI),(double)fs);
}
};
#endif

View File

@ -0,0 +1,222 @@
/*==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 "hsTypes.h"
#include "max.h"
#include "texutil.h"
#include "iparamb2.h"
#include <commdlg.h>
#include "bmmlib.h"
#include "bitmap.h"
#include "Layers\plPlasmaMAXLayer.h"
#include "plBMSampler.h"
plBMSampler::plBMSampler(plPlasmaMAXLayer *layer, Bitmap *bm) : fBM(bm), fInitialized(false)
{
// Get our parameters
if( fBM && layer && layer->GetSamplerInfo( &fData ) )
{
u1 = fData.fClipU + fData.fClipW;
v1 = fData.fClipV + fData.fClipH;
bmw = fBM->Width();
bmh = fBM->Height();
fbmw = float(bmw-1);
fbmh = float(bmh-1);
clipx = int(fData.fClipU*fbmw);
clipy = int(fData.fClipV*fbmh);
fclipw = fData.fClipW*fbmw;
fcliph = fData.fClipH*fbmh;
cliph = fcliph;
fInitialized = true;
}
}
int plBMSampler::PlaceUV(ShadeContext &sc, float &u, float &v, int iu, int iv)
{
if (!fInitialized)
return 1;
if (u<fData.fClipU||v<fData.fClipV||u>u1||v>v1)
return 0;
u = (u-fData.fClipU)/fData.fClipW;
v = (v-fData.fClipV)/fData.fClipH;
return 1;
}
void plBMSampler::PlaceUVFilter(ShadeContext &sc, float &u, float &v, int iu, int iv)
{
if (!fInitialized)
return;
u = (u-fData.fClipU)/fData.fClipW;
v = (v-fData.fClipV)/fData.fClipH;
}
AColor plBMSampler::Sample(ShadeContext& sc, float u,float v)
{
AColor none(0.0f, 0.0f, 0.0f, 0.0f);
if (!fInitialized)
return none;
BMM_Color_64 c;
int x,y;
float fu,fv;
fu = frac(u);
fv = 1.0f-frac(v);
if (fData.fEnableCrop)
{
if (fData.fCropPlacement)
{
if (!PlaceUV(sc,fu, fv, int(u), int(v)))
return AColor(0,0,0,0);
x = (int)(fu*fbmw+0.5f);
y = (int)(fv*fbmh+0.5f);
}
else
{
x = mod(clipx + (int)(fu*fclipw+0.5f),bmw);
y = mod(clipy + (int)(fv*fcliph+0.5f),bmh);
}
}
else
{
x = (int)(fu*fbmw+0.5f);
y = (int)(fv*fbmh+0.5f);
}
fBM->GetLinearPixels(x,y,1,&c);
switch(fData.fAlphaSource)
{
case plBMSamplerData::kDiscard:
c.a = 0xffff;
break;
case plBMSamplerData::kFromRGB:
c.a = (c.r+c.g+c.b)/3;
break;
// TBD
// XPCOL needs to be handled in bitmap for filtering.
// Need to open a bitmap with this property.
// case ALPHA_XPCOL: break;
}
return c;
}
AColor plBMSampler::SampleFilter(ShadeContext& sc, float u,float v, float du, float dv)
{
AColor none(0.0f, 0.0f, 0.0f, 0.0f);
if (!fInitialized)
return none;
fBM->SetFilter(BMM_FILTER_PYRAMID);
BMM_Color_64 c;
float fu,fv;
fu = frac(u);
fv = 1.0f-frac(v);
if (fData.fEnableCrop)
{
if (fData.fCropPlacement)
{
PlaceUVFilter(sc,fu, fv, int(u), int(v));
du /= fData.fClipW;
dv /= fData.fClipH;
float du2 = 0.5f*du;
float ua = fu-du2;
float ub = fu+du2;
if (ub<=0.0f||ua>=1.0f) return none;
float dv2 = 0.5f*dv;
float va = fv-dv2;
float vb = fv+du2;
if (vb<=0.0f||va>=1.0f) return none;
BOOL clip = 0;
if (ua<0.0f) { ua=0.0f; clip = 1; }
if (ub>1.0f) { ub=1.0f; clip = 1; }
if (va<0.0f) { va=0.0f; clip = 1; }
if (vb>1.0f) { vb=1.0f; clip = 1; }
fBM->GetFiltered(fu,fv,du,dv,&c);
switch(fData.fAlphaSource)
{
case plBMSamplerData::kDiscard:
c.a = 0xffff;
break;
case plBMSamplerData::kFromRGB:
c.a = (c.r + c.g + c.b)/3;
break;
}
AColor ac(c);
if (clip)
{
float f = ((ub-ua)/du) * ((vb-va)/dv);
ac *= f;
}
return ac;
}
else
{
fu = (fData.fClipU + fData.fClipW*fu);
fv = (fData.fClipV + fData.fClipH*fv);
du *= fData.fClipW;
dv *= fData.fClipH;
fBM->GetFiltered(fu,fv,du,dv,&c);
}
}
else
fBM->GetFiltered(fu,fv,du,dv,&c);
switch (fData.fAlphaSource)
{
case plBMSamplerData::kDiscard:
c.a = 0xffff;
break;
case plBMSamplerData::kFromRGB:
c.a = (c.r + c.g + c.b)/3;
break;
}
return c;
}

View File

@ -0,0 +1,101 @@
/*==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==*/
#ifndef _plBMSampler_h
#define _plBMSampler_h
#include "max.h"
#include "imtl.h"
class plPlasmaMAXLayer;
class plBMSamplerData
{
public:
bool fEnableCrop;
int fCropPlacement;
float fClipU, fClipV;
float fClipW, fClipH;
enum ASource
{
kFromTexture,
kFromRGB,
kDiscard
};
ASource fAlphaSource;
plBMSamplerData()
{
fEnableCrop = false;
fCropPlacement = 0;
fClipU = fClipV = 0.f;
fClipW = fClipH = 1.f;
fAlphaSource = kFromTexture;
}
};
class plBMSampler : public MapSampler
{
protected:
Bitmap *fBM;
plBMSamplerData fData;
float u1,v1;
int bmw,bmh,clipx, clipy, cliph;
float fclipw,fcliph, fbmh, fbmw;
bool fInitialized;
plBMSampler() {}
public:
plBMSampler(plPlasmaMAXLayer *layer, Bitmap *bm);
int PlaceUV(ShadeContext& sc, float &u, float &v, int iu, int iv);
void PlaceUVFilter(ShadeContext& sc, float &u, float &v, int iu, int iv);
AColor Sample(ShadeContext& sc, float u,float v);
AColor SampleFilter(ShadeContext& sc, float u,float v, float du, float dv);
// float SampleMono(ShadeContext& sc, float u,float v);
// float SampleMonoFilter(ShadeContext& sc, float u,float v, float du, float dv);
};
#endif //_plBMSampler_h

View File

@ -0,0 +1,696 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDetailCurveCtrl Class Functions //
// Custom Win32 Control class for drawing the detail map opacity curve so //
// the artists can figure out what the hell is going on. //
// Cyan, Inc. //
// //
// To use: //
// 1. Create a new plDetailCurveCtrl, giving it a parent window and a //
// client rect. //
// 2. Set the start and end percentages, along with the start and end //
// opacities. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 10.1.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plDetailCurveCtrl.h"
#include "resource.h"
//// Static Stuff /////////////////////////////////////////////////////////////
int plDetailCurveCtrl::fClassRefCnt = 0;
HINSTANCE plDetailCurveCtrl::fInstance = NULL;
HBITMAP plDetailCurveCtrl::fBgndImage = NULL;
HFONT plDetailCurveCtrl::fFont = NULL;
#ifdef MCN_TWO_GRAPH_MODE
HBITMAP plDetailCurveCtrl::fBgndImage2 = NULL;
bool plDetailCurveCtrl::fXAsMipmapLevel = false;
#endif
const char gCtrlClassName[] = "DetailCurveClass";
#define kHiResStep 0.01f
void plDetailCurveCtrl::IRegisterCtrl( HINSTANCE instance )
{
if( fClassRefCnt == 0 )
{
fInstance = instance;
WNDCLASSEX clInfo;
memset( &clInfo, 0, sizeof( clInfo ) );
clInfo.cbSize = sizeof( clInfo );
clInfo.style = CS_OWNDC | CS_NOCLOSE;
clInfo.lpfnWndProc = (WNDPROC)IWndProc;
clInfo.cbClsExtra = 0;
clInfo.cbWndExtra = 0;
clInfo.hInstance = fInstance;
clInfo.hIcon = NULL;
clInfo.hCursor = LoadCursor( NULL, IDC_CROSS );
clInfo.hbrBackground = NULL;
clInfo.lpszMenuName = NULL;
clInfo.lpszClassName = gCtrlClassName;
clInfo.hIconSm = NULL;
RegisterClassEx( &clInfo );
fBgndImage = (HBITMAP)LoadImage( fInstance, MAKEINTRESOURCE( IDB_DETAILBGND ), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR );
#ifdef MCN_TWO_GRAPH_MODE
fBgndImage2 = (HBITMAP)LoadImage( fInstance, MAKEINTRESOURCE( IDB_DETAILBGND2 ), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR );
#endif
HDC hDC = GetDC( NULL );
fFont = CreateFont( -MulDiv( 8, GetDeviceCaps( hDC, LOGPIXELSY ), 72 ), 0, 0, 0, 0, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial" );
ReleaseDC( NULL, hDC );
}
fClassRefCnt++;
}
void plDetailCurveCtrl::IUnregisterCtrl( void )
{
fClassRefCnt--;
if( fClassRefCnt == 0 )
{
UnregisterClass( gCtrlClassName, fInstance );
if( fFont != NULL )
DeleteObject( fFont );
}
}
//// Constructor & Destructor /////////////////////////////////////////////////
plDetailCurveCtrl::plDetailCurveCtrl( HWND parentWnd, WPARAM id, RECT *clientRect, HINSTANCE instance )
{
// Class init
if( instance == NULL )
instance = (HINSTANCE)GetWindowLong( parentWnd, GWL_HINSTANCE );
IRegisterCtrl( instance );
// Per-object init
fDblDC = NULL;
fDblBitmap = NULL;
fStartPercent = 0;
fStartOpac = 0;
fEndPercent = 1.f;
fEndOpac = 1.f;
fNumLevels = 8;
fDraggingStart = fDraggingEnd = false;
fCanDragStart = fCanDragEnd = false;
// Note: we create originally as disabled since the default detail setting is disabled.
// The MAX Update stuff should change this if necessary after we're created
fHWnd = ::CreateWindowEx( WS_EX_CLIENTEDGE, gCtrlClassName, "Detail Curve", WS_CHILD | WS_VISIBLE | WS_BORDER | WS_DISABLED,
clientRect->left, clientRect->top, clientRect->right - clientRect->left,
clientRect->bottom - clientRect->top,
parentWnd, (HMENU)id, instance, 0 );
if( fHWnd == NULL )
return;
SetWindowLong( fHWnd, GWL_USERDATA, (LONG)this );
}
plDetailCurveCtrl::~plDetailCurveCtrl()
{
if( fDblDC != NULL )
{
SelectObject( fDblDC, (HBITMAP)NULL );
DeleteObject( fDblBitmap );
DeleteDC( fDblDC );
}
if( fWhiteBrush != NULL )
DeleteObject( fWhiteBrush );
if( fBluePen != NULL )
DeleteObject( fBluePen );
if( fLiteBluePen != NULL )
DeleteObject( fLiteBluePen );
if( fBlueBrush != NULL )
DeleteObject( fBlueBrush );
// DestroyWindow( fHWnd );
IUnregisterCtrl();
}
//// IInitDblBuffer ///////////////////////////////////////////////////////////
// Note: For some strange reason, grabbing the HDC of the window doesn't do
// any good, 'cause it's black-and-white (right, THAT makes sense). Grabbing
// the desktop DC works, however.
void plDetailCurveCtrl::IInitDblBuffer( void )
{
if( fDblDC == NULL )
{
int width, height;
RECT r;
HDC desk = GetDC( NULL );
GetClientRect( fHWnd, &r );
width = r.right - r.left;
height = r.bottom - r.top;
fDblDC = CreateCompatibleDC( desk );
fDblBitmap = CreateCompatibleBitmap( desk/*fDblDC*/, width, height );
SelectObject( fDblDC, fDblBitmap );
ReleaseDC( NULL, desk );
fWhiteBrush = CreateSolidBrush( RGB( 255, 255, 255 ) );
fBluePen = CreatePen( PS_SOLID, 1, RGB( 0, 0, 255 ) );
fLiteBluePen = CreatePen( PS_SOLID, 1, RGB( 127, 127, 255 ) );
fBlueBrush = CreateSolidBrush( RGB( 0, 0, 255 ) );
IRefreshDblBuffer();
}
}
//// IRefreshDblBuffer ////////////////////////////////////////////////////////
void plDetailCurveCtrl::IRefreshDblBuffer( void )
{
HDC hBgndDC;
RECT clientRect, r;
SIZE bgndSize;
int width, height, x, y;
HPEN oldPen;
BITMAPINFO bmpInfo;
POINT pt1, pt2;
IInitDblBuffer();
GetClientRect( fHWnd, &clientRect );
width = clientRect.right - clientRect.left;
height = clientRect.bottom - clientRect.top;
if( fDblBitmap != NULL )
{
FillRect( fDblDC, &clientRect, fWhiteBrush );
if( fBgndImage != NULL )
{
// Draw bgnd
hBgndDC = CreateCompatibleDC( fDblDC );
#ifdef MCN_TWO_GRAPH_MODE
SelectObject( hBgndDC, fXAsMipmapLevel ? fBgndImage2 : fBgndImage );
#else
SelectObject( hBgndDC, fBgndImage );
#endif
bmpInfo.bmiHeader.biSize = sizeof( bmpInfo.bmiHeader );
bmpInfo.bmiHeader.biBitCount = 0;
GetDIBits( hBgndDC, fBgndImage, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS );
bgndSize.cx = bmpInfo.bmiHeader.biWidth;
bgndSize.cy = bmpInfo.bmiHeader.biHeight;
x = ( width - bgndSize.cx ) >> 1;
y = ( height - bgndSize.cy ) >> 1;
BitBlt( fDblDC, x, y, bgndSize.cx, bgndSize.cy, hBgndDC, 0, 0, SRCCOPY );
SelectObject( hBgndDC, (HBITMAP)NULL );
DeleteDC( hBgndDC );
/// Draw graph
if( IsWindowEnabled( fHWnd ) )
{
bgndSize.cx -= 8;
oldPen = (HPEN)SelectObject( fDblDC, fLiteBluePen );
/// This line draws the light blue "actual" curve, which shows what happens
/// when you actually interpolate the curve across the mipmap levels. It's
/// more accurate in that it shows the actual values computed for each level,
/// but less accurate because it doesn't take into account mipmap sampling
/// and such. Given the latter, we leave it out (for now) to avoid confusing
/// the artists.
// IDrawCurve( fDblDC, true, x, y, &bgndSize );
SelectObject( fDblDC, fBluePen );
IDrawCurve( fDblDC, false, x, y, &bgndSize );
SelectObject( fDblDC, oldPen );
if( fStartPercent == 0.07f && fStartOpac == 0.23f && fEndPercent == 0.19f && fEndOpac == 0.79f )
{
const char str[] = "\x48\x61\x70\x70\x79\x20\x62\x64\x61\x79\x20\x74\x6f\x20\x6d\x63\x6e\x21";
SetBkMode( fDblDC, TRANSPARENT );
SetTextColor( fDblDC, RGB( 0, 0, 255 ) );
SelectObject( fDblDC, fFont );
TextOut( fDblDC, x, y + bgndSize.cy - 10, str, strlen( str ) );
}
// Draw our two markers
IXlateValuesToClientPt( fStartPercent, fStartOpac, &pt1, x, y, &bgndSize );
SetRect( &fStartDragPt, pt1.x - 4, pt1.y - 4, pt1.x + 4, pt1.y + 4 );
r = fStartDragPt;
if( !fCanDragStart )
InflateRect( &r, -2, -2 );
FillRect( fDblDC, &r, fBlueBrush );
IXlateValuesToClientPt( fEndPercent, fEndOpac, &pt2, x, y, &bgndSize );
SetRect( &fEndDragPt, pt2.x - 4, pt2.y - 4, pt2.x + 4, pt2.y + 4 );
r = fEndDragPt;
if( !fCanDragEnd )
InflateRect( &r, -2, -2 );
FillRect( fDblDC, &r, fBlueBrush );
}
}
}
}
//// IDrawCurve ///////////////////////////////////////////////////////////////
// Draw the damned curve.
void plDetailCurveCtrl::IDrawCurve( HDC hDC, bool clampToInts, int cornerX, int cornerY, SIZE *bgndSize )
{
float dist, penX, penBaseY, penXStep, penYScale;
POINT pt1;
// Calc stuff
penX = (float)cornerX;
penBaseY = (float)( cornerY + bgndSize->cy );
penXStep = (float)bgndSize->cx * kHiResStep;
penYScale = (float)bgndSize->cy;
// Draw curve
pt1.x = (int)penX;
pt1.y = (int)( penBaseY - penYScale * fStartOpac );
float artificialBias = 1.f / (float)fNumLevels; // So we never get a howFar less than 0
float artificialMaxDist = 1.f - artificialBias;
for( dist = 0.f; dist <= 1.f; dist += kHiResStep )
{
float opac = IXlateDistToValue( dist, clampToInts );
if( dist == 0.f )
MoveToEx( hDC, (int)penX, (int)( penBaseY - penYScale * opac ), NULL );
else
LineTo( hDC, (int)penX, (int)( penBaseY - penYScale * opac ) );
penX += penXStep;
}
}
//// IXlateDistToValue ////////////////////////////////////////////////////////
// I.E. from distance across graph to distance up on graph (percentage-wise)
float plDetailCurveCtrl::IXlateDistToValue( float dist, bool clampToInts )
{
const float artificialBias = 1.f / (float)fNumLevels; // So we never get a howFar less than 0
const float artificialMaxDist = 1.f - artificialBias;
float howFar, opac;
howFar = IXlateDistToX( dist, clampToInts );
if( howFar < fStartPercent )
opac = fStartOpac;
else if( howFar > fEndPercent )
opac = fEndOpac;
else
opac = ( howFar - fStartPercent ) * ( fEndOpac - fStartOpac ) / ( fEndPercent - fStartPercent ) + fStartOpac;
return opac;
}
//// IXlateDistToX ////////////////////////////////////////////////////////////
// I.E. from the distance in percentage across the graph to the actual x
// value on the graph
float plDetailCurveCtrl::IXlateDistToX( float dist, bool clampToInts )
{
const float artificialBias = 1.f / (float)fNumLevels; // So we never get a howFar less than 0
const float artificialMaxDist = 1.f - artificialBias;
float howFar;
#ifdef MCN_TWO_GRAPH_MODE
if( fXAsMipmapLevel )
{
howFar = dist * (float)fNumLevels;
if( clampToInts )
howFar = (float)( (int)howFar );
howFar /= (float)fNumLevels;
return howFar;
}
#endif
if( dist == 0.f )
howFar = 0.f;
else
{
howFar = 1.f - ( ( 1.f - dist ) * artificialMaxDist );
howFar = ( (float)fNumLevels - 1.f / howFar );
if( howFar < 0.f )
howFar = 0.f;
else if( howFar > (float)fNumLevels - 1.f )
howFar = (float)fNumLevels - 1.f;
if( clampToInts )
howFar = (float)( (int)howFar );
howFar /= (float)fNumLevels - 1.f;
}
return howFar;
}
//// IXlateXToDist ////////////////////////////////////////////////////////////
// I.E. from the actual x value of the graph to the actual distance in
// percentage across the graph.
float plDetailCurveCtrl::IXlateXToDist( float howFar )
{
const float artificialBias = 1.f / (float)fNumLevels; // So we never get a howFar less than 0
const float artificialMaxDist = 1.f - artificialBias;
float dist;
#ifdef MCN_TWO_GRAPH_MODE
if( fXAsMipmapLevel )
{
return howFar;
}
#endif
if( howFar == 0.f )
dist = 0.f;
else
{
howFar *= (float)fNumLevels - 1.f;
howFar = 1.f / ( (float)fNumLevels - howFar );
howFar = ( ( howFar - 1.f ) / artificialMaxDist ) + 1.f;
}
return howFar;
}
//// IXlateValuesToClientPt ///////////////////////////////////////////////////
// I.E. from graph x,y values to client coordinates
void plDetailCurveCtrl::IXlateValuesToClientPt( float x, float y, POINT *pt, int cornerX, int cornerY, SIZE *bgndSize )
{
pt->x = cornerX + (int)( IXlateXToDist( x ) * (float)bgndSize->cx );
pt->y = cornerY + bgndSize->cy;
pt->y -= (int)( (float)bgndSize->cy * y );
}
//// IMapMouseToValues ////////////////////////////////////////////////////////
// Map mouse x,y coordinates in clientspace to graph values. If the last param
// is true, maps to the start point, else maps to the end point
void plDetailCurveCtrl::IMapMouseToValues( int x, int y, bool mapToStart )
{
BITMAPINFO bmpInfo;
int cX, cY, width, height;
RECT clientRect;
float vX, vY;
SIZE bgndSize;
if( fBgndImage == NULL || fDblDC == NULL || !IsWindowEnabled( fHWnd ) )
return;
GetClientRect( fHWnd, &clientRect );
width = clientRect.right - clientRect.left;
height = clientRect.bottom - clientRect.top;
bmpInfo.bmiHeader.biSize = sizeof( bmpInfo.bmiHeader );
bmpInfo.bmiHeader.biBitCount = 0;
GetDIBits( fDblDC, fBgndImage, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS );
bgndSize.cx = bmpInfo.bmiHeader.biWidth;
bgndSize.cy = bmpInfo.bmiHeader.biHeight;
cX = ( width - bgndSize.cx ) >> 1;
cY = ( height - bgndSize.cy ) >> 1;
bgndSize.cx -= 8;
// Xlate to graph space and clamp
x -= cX;
y = bgndSize.cy - ( y - cY );
if( x < 0 )
x = 0;
else if( x > bgndSize.cx )
x = bgndSize.cx;
if( y < 0 )
y = 0;
else if( y > bgndSize.cy )
y = bgndSize.cy;
vX = IXlateDistToX( (float)x / (float)bgndSize.cx, false );
vY = (float)y / (float)bgndSize.cy;
if( mapToStart )
{
fStartPercent = vX;
fStartOpac = vY;
if( fEndPercent < fStartPercent )
{
fEndPercent = fStartPercent;
ISendDraggedMessage( false );
}
}
else
{
fEndPercent = vX;
fEndOpac = vY;
if( fEndPercent < fStartPercent )
{
fStartPercent = fEndPercent;
ISendDraggedMessage( true );
}
}
IRefreshDblBuffer();
InvalidateRect( fHWnd, NULL, false );
RedrawWindow( fHWnd, NULL, NULL, RDW_UPDATENOW );
ISendDraggedMessage( mapToStart );
}
//// ISendDraggedMessage //////////////////////////////////////////////////////
void plDetailCurveCtrl::ISendDraggedMessage( bool itWasTheStartPoint )
{
HWND parent = GetParent( fHWnd );
if( parent == NULL )
return;
SendMessage( parent, PL_DC_POINT_DRAGGED, itWasTheStartPoint ? PL_DC_START_POINT : PL_DC_END_POINT,
(LPARAM)this );
}
//// SetStart/EndPoint ////////////////////////////////////////////////////////
void plDetailCurveCtrl::SetStartPoint( float percentLevel, float opacity )
{
fStartPercent = percentLevel;
fStartOpac = opacity;
IRefreshDblBuffer();
InvalidateRect( fHWnd, NULL, false );
}
void plDetailCurveCtrl::SetEndPoint( float percentLevel, float opacity )
{
fEndPercent = percentLevel;
fEndOpac = opacity;
IRefreshDblBuffer();
InvalidateRect( fHWnd, NULL, false );
}
void plDetailCurveCtrl::SetNumLevels( int numLevels )
{
fNumLevels = numLevels;
IRefreshDblBuffer();
InvalidateRect( fHWnd, NULL, false );
}
//// IWndProc /////////////////////////////////////////////////////////////////
LRESULT CALLBACK plDetailCurveCtrl::IWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
HDC hDC;
RECT clientRect;
int width, height;
PAINTSTRUCT pInfo;
POINT pt;
plDetailCurveCtrl *ctrl = (plDetailCurveCtrl *)GetWindowLong( hWnd, GWL_USERDATA );
GetClientRect( hWnd, &clientRect );
width = clientRect.right - clientRect.left;
height = clientRect.bottom - clientRect.top;
switch( msg )
{
case WM_CREATE:
return 0;
case WM_ENABLE:
if( ctrl != NULL )
ctrl->IRefreshDblBuffer();
return 0;
case WM_PAINT:
BeginPaint( hWnd, &pInfo );
hDC = (HDC)pInfo.hdc;
if( ctrl != NULL )
{
if( ctrl->fDblDC == NULL )
ctrl->IInitDblBuffer();
BitBlt( hDC, 0, 0, width, height, ctrl->fDblDC, 0, 0, SRCCOPY );
}
EndPaint( hWnd, &pInfo );
return 0;
case WM_ERASEBKGND:
return TRUE;
case WM_LBUTTONDOWN:
if( ctrl != NULL && !ctrl->fDraggingStart && !ctrl->fDraggingEnd )
{
pt.x = LOWORD( lParam );
pt.y = HIWORD( lParam );
if( PtInRect( &ctrl->fStartDragPt, pt ) )
{
if( !ctrl->fCanDragStart && !ctrl->fCanDragEnd )
SetCapture( hWnd );
ctrl->fDraggingStart = true;
}
else if( PtInRect( &ctrl->fEndDragPt, pt ) )
{
if( !ctrl->fCanDragStart && !ctrl->fCanDragEnd )
SetCapture( hWnd );
ctrl->fDraggingEnd = true;
}
}
return 0;
case WM_MOUSEMOVE:
if( ctrl != NULL )
{
pt.x = LOWORD( lParam );
pt.y = HIWORD( lParam );
if( ctrl->fDraggingStart || ctrl->fDraggingEnd )
{
ctrl->IMapMouseToValues( (short)LOWORD( lParam ), (short)HIWORD( lParam ), ctrl->fDraggingStart );
}
else if( PtInRect( &ctrl->fStartDragPt, pt ) )
{
if( !ctrl->fCanDragStart )
{
ctrl->fCanDragStart = true;
ctrl->fCanDragEnd = false;
SetCapture( hWnd );
ctrl->IRefreshDblBuffer();
InvalidateRect( hWnd, NULL, false );
}
}
else if( PtInRect( &ctrl->fEndDragPt, pt ) )
{
if( !ctrl->fCanDragEnd )
{
ctrl->fCanDragEnd = true;
ctrl->fCanDragStart = false;
SetCapture( hWnd );
ctrl->IRefreshDblBuffer();
InvalidateRect( hWnd, NULL, false );
}
}
else if( ctrl->fCanDragStart || ctrl->fCanDragEnd )
{
ctrl->fCanDragStart = false;
ctrl->fCanDragEnd = false;
ReleaseCapture();
ctrl->IRefreshDblBuffer();
InvalidateRect( hWnd, NULL, false );
}
}
return 0;
case WM_LBUTTONUP:
if( ctrl != NULL && ( ctrl->fDraggingStart || ctrl->fDraggingEnd ) )
{
if( !ctrl->fCanDragStart && !ctrl->fCanDragEnd )
ReleaseCapture();
ctrl->fDraggingStart = false;
ctrl->fDraggingEnd = false;
}
return 0;
#ifdef MCN_TWO_GRAPH_MODE
case WM_RBUTTONDOWN:
fXAsMipmapLevel = !fXAsMipmapLevel;
ctrl->IRefreshDblBuffer();
InvalidateRect( hWnd, NULL, false );
return 0;
#endif
case WM_DESTROY:
delete ctrl;
SetWindowLong( hWnd, GWL_USERDATA, 0 );
return 0;
default:
return DefWindowProc( hWnd, msg, wParam, lParam );
}
}

View File

@ -0,0 +1,144 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDetailCurveCtrl Class Header //
// Custom Win32 Control class for drawing the detail map opacity curve so //
// the artists can figure out what the hell is going on. //
// Cyan, Inc. //
// //
// To use: //
// 1. Create a new plDetailCurveCtrl, giving it a parent window and a //
// client rect. //
// 2. Set the start and end percentages, along with the start and end //
// opacities. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 10.1.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plDetailCurveCtrl_h
#define _plDetailCurveCtrl_h
#include "Max.h"
#include "resource.h"
#define GET_DETAIL_CURVE_CTRL( dlg, id ) (GetDlgItem( dlg, id ) ? (plDetailCurveCtrl *)GetWindowLong( GetDlgItem( dlg, id ), GWL_USERDATA ) : NULL )
// Message to parent to let it know a point got dragged. lParam = pointer to control, wParam = 1 if start point, 0 if end point
#define PL_DC_POINT_DRAGGED WM_USER + 50
#define PL_DC_START_POINT 1
#define PL_DC_END_POINT 0
/// The following #define was for back when I had two graphs, one was with mipmap level
/// as the X axis, the other was as it is now (distance). Uncomment this define to
/// re-enable the two-graph mode (right-click switches)
//#define MCN_TWO_GRAPH_MODE
//// Class Definition /////////////////////////////////////////////////////////
class plDetailCurveCtrl
{
protected:
HWND fHWnd;
HDC fDblDC;
HBITMAP fDblBitmap;
HBRUSH fWhiteBrush, fBlueBrush;
HPEN fBluePen, fLiteBluePen;
RECT fStartDragPt, fEndDragPt;
bool fDraggingStart, fDraggingEnd;
bool fCanDragStart, fCanDragEnd;
int fNumLevels;
float fStartPercent, fEndPercent;
float fStartOpac, fEndOpac;
void IInitDblBuffer( void );
void IRefreshDblBuffer( void );
void IDrawCurve( HDC hDC, bool clampToInts, int cornerX, int cornerY, SIZE *bgndSize );
float IXlateDistToValue( float dist, bool clampToInts );
float IXlateDistToX( float dist, bool clampToInts );
float IXlateXToDist( float howFar );
void IXlateValuesToClientPt( float x, float y, POINT *pt, int cornerX, int cornerY, SIZE *bgndSize );
void IMapMouseToValues( int x, int y, bool mapToStart );
void ISendDraggedMessage( bool itWasTheStartPoint );
static HINSTANCE fInstance;
static int fClassRefCnt;
static HBITMAP fBgndImage;
static HFONT fFont;
#ifdef MCN_TWO_GRAPH_MODE
static HBITMAP fBgndImage2;
static bool fXAsMipmapLevel;
#endif
static void IRegisterCtrl( HINSTANCE instance );
static void IUnregisterCtrl( void );
static LRESULT CALLBACK IWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
public:
plDetailCurveCtrl( HWND parentWnd, WPARAM id, RECT *clientRect, HINSTANCE instance = NULL );
~plDetailCurveCtrl();
void SetStartPoint( float percentLevel, float opacity );
void SetEndPoint( float percentLevel, float opacity );
void SetNumLevels( int numLevels );
void GetStartPoint( float &percent, float &opacity ) { percent = fStartPercent; opacity = fStartOpac; }
void GetEndPoint( float &percent, float &opacity ) { percent = fEndPercent; opacity = fEndOpac; }
};
#endif // _plDetailCurveCtrl_h

View File

@ -0,0 +1,99 @@
/*==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==*/
#if 0
int ybot, ytop, ylast, i, iy;
HPEN linePen = (HPEN)GetStockObject(WHITE_PEN);
HPEN fgPen = CreatePen(PS_SOLID,0,GetSysColor(COLOR_BTNFACE));
HPEN bgPen = CreatePen(PS_SOLID,0,GetSysColor(COLOR_BTNSHADOW));
int width = rect.w() - 4;
int height = rect.h() - 4;
int miplevel = 0;
const float depth = 9;
float detailDropoffStart = theHsMaxLayer->GetDetailDropoffStart(curTime) * depth;
float detailDropoffStop = theHsMaxLayer->GetDetailDropoffStop(curTime) * depth;
float detailMax = theHsMaxLayer->GetDetailMax(curTime);
float detailMin = theHsMaxLayer->GetDetailMin(curTime);
int nextmip = 1;
ytop = rect.top + 2;
ybot = ytop + height;
ylast = -1;
for (i=0; i < width; i++) {
if (i==nextmip) {
miplevel++;
nextmip *= 2;
}
int ix = i + rect.left + 2;
float alpha = (miplevel - detailDropoffStart) * (detailMin - detailMax) / (detailDropoffStop - detailDropoffStart)
+ detailMax;
if (alpha > detailMax)
alpha = detailMax;
if (alpha < detailMin)
alpha = detailMin;
iy = (int)(ybot - alpha * height);
SelectPen(hdc, fgPen);
VertLine(hdc, ix, ybot, iy);
if (iy-1 > ytop) {
// Fill in above curve
SelectPen(hdc,bgPen);
VertLine(hdc, ix, ytop, iy-1);
}
if (ylast>=0) {
SelectPen(hdc,linePen);
VertLine(hdc, ix-1, iy-1, ylast);
}
ylast = iy;
}
SelectObject( hdc, linePen );
DeleteObject(fgPen);
DeleteObject(bgPen);
WhiteRect3D(hdc, rect, 1);
#endif

View File

@ -0,0 +1,48 @@
/*==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==*/
//
// This message is used to notify the SceneWatcher of changes in the materials.
// There is a refmsg sent out when material parameters change, but for some
// reason it is not propogated to the node that the material is applied to.
// User refmsgs always make it through though.
//
#define REFMSG_USER_MAT REFMSG_USER+1

View File

@ -0,0 +1,86 @@
/*==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 "plMtlImport.h"
extern ClassDesc2* GetPassMtlDesc();
extern ClassDesc2* GetLayerTexDesc();
extern ClassDesc2* GetStaticEnvLayerDesc();
extern ClassDesc2* GetMultiMtlDesc();
extern ClassDesc2* GetDecalMtlDesc();
extern ClassDesc2* GetCompMtlDesc();
extern ClassDesc2* GetParticleMtlDesc();
extern ClassDesc2* GetDynamicEnvLayerDesc();
extern ClassDesc2* GetBumpMtlDesc();
extern ClassDesc2* GetDynamicTextLayerDesc();
extern ClassDesc2* GetClothingMtlDesc();
extern ClassDesc2* GetAngleAttenLayerDesc();
extern ClassDesc2* GetStealthClassDesc();
extern ClassDesc2* GetBinkClassDesc();
extern ClassDesc2* GetMAXCameraLayerDesc();
int plPlasmaMtlImport::GetNumMtlDescs( void )
{
return 15;
}
ClassDesc2 *plPlasmaMtlImport::GetMtlDesc( int i )
{
switch (i)
{
case 0: return GetPassMtlDesc();
case 1: return GetLayerTexDesc();
case 2: return GetMultiMtlDesc();
case 3: return GetDecalMtlDesc();
case 4: return GetCompMtlDesc();
case 5: return GetStaticEnvLayerDesc();
case 6: return GetParticleMtlDesc();
case 7: return GetDynamicEnvLayerDesc();
case 8: return GetBumpMtlDesc();
case 9: return GetDynamicTextLayerDesc();
case 10: return GetClothingMtlDesc();
case 11: return GetAngleAttenLayerDesc();
case 12: return GetStealthClassDesc();
case 13: return GetBinkClassDesc();
case 14: return GetMAXCameraLayerDesc();
default: return 0;
}
}

View File

@ -0,0 +1,54 @@
/*==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==*/
#ifndef _plMtlImport_h
#define _plMtlImport_h
#include "Max.h"
#include "iparamb2.h"
namespace plPlasmaMtlImport
{
int GetNumMtlDescs( void );
ClassDesc2 *GetMtlDesc( int i );
};
#endif //_plMtlImport_h

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

View File

@ -0,0 +1,338 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by MaxPlasmaMtls.rc
//
#define IDS_LAYER 400
#define IDS_MAX_CAMERA_LAYER 401
#define IDS_PASS_MTL 402
#define IDS_PASS_BASIC 403
#define IDS_PASS_ADV 404
#define IDS_PASS_LAYERS 405
#define IDS_PASS_OUTPUT 406
#define IDS_LAYER_TEX 407
#define IDS_LAYER_BASIC 408
#define IDS_MULTI_MTL 409
#define IDS_DECAL_MTL 410
#define IDS_COMP_MTL 411
#define IDS_PASS_ANIM 412
#define IDS_STATIC_ENVMAP_LAYER 413
#define IDS_PARTICLE_HEIGHT 414
#define IDS_DYNAMIC_ENVMAP_LAYER 415
#define IDS_BASIC_AMB 416
#define IDS_BASIC_COLOR 417
#define IDS_BASIC_OPAC 418
#define IDS_PASS_ANIM_EASE 419
#define IDS_MAX_CAMERA_LAYER_PROPS 420
#define IDS_CAM_LAYER_CAMERA 421
#define IDS_CAM_LAYER_ROOT_NODE 422
#define IDS_BASIC_RUNCOLOR 428
#define IDS_BASIC_SPECCOLOR 429
#define IDS_BUMP_MTL 430
#define IDS_BITMAP_CLIPU 432
#define IDS_BITMAP_CLIPV 433
#define IDS_BITMAP_CLIPW 434
#define IDS_BITMAP_CLIPH 435
#define IDS_STATIC_ENVMAP_LAYER_TEX 436
#define IDS_CUBIC_RENDER_TITLE 437
#define IDS_BITMAP_TEXSIZE 438
#define IDS_BITMAP_BASENAME 439
#define IDS_SELECT_NODE 440
#define IDS_PARTICLE_MTL 441
#define IDS_PARTICLE_OPACITY 442
#define IDS_PARTICLE_COLOR 443
#define IDS_PARTICLE_WIDTH 444
#define IDS_PARTICLE_AMB_COLOR 445
#define IDS_SELECT_ANCHOR 446
#define IDS_DYNAMIC_ENVMAP_LAYER_TEX 447
#define IDS_DYN_TEXT_LAYER 449
#define IDS_DYN_TEXT_LAYER_PROPS 450
#define IDS_CLOTHING_MTL 451
#define IDS_ANGLE_ATTEN_LAYER 452
#define IDS_ANGLE_ATTEN_LAYER_PROPS 453
#define IDS_ANIMSTEALTH 454
#define IDS_STEALTH_NAME 455
#define IDS_NTWATCHER_NAME 456
#define IDB_BUTTONS 457
#define IDB_MASKBUTTONS 458
#define IDB_DETAILBGND 459
#define IDD_PASS_BASIC 700
#define IDD_LAYER_BASIC 701
#define IDD_LAYER_TEX 702
#define IDD_PASS_LAYERS 703
#define IDD_MULTIPASS 704
#define IDD_PASS_ADV 705
#define IDD_DECAL_LAYERS 706
#define IDD_DECAL_BASIC 707
#define IDD_COMPOSITE 708
#define IDD_PASS_ANIM 709
#define IDD_STATIC_ENVMAP_LAYER 710
#define IDD_PARTICLE 711
#define IDD_DYNAMIC_ENVMAP_LAYER 712
#define IDD_BUMP_BASIC 713
#define IDD_BUMP_ANIM 714
#define IDD_DYN_TEXT_LAYER 715
#define IDD_CLOTHING 716
#define IDD_PASS_ANIM_EASE 717
#define IDD_ANGLE_ATTEN_LAYER 718
#define IDD_STEALTH_ANIM 719
#define IDD_MAX_CAMERA_LAYER 720
#define IDC_PLACEHOLDER 1209
#define IDC_CLOTHING_FORCED_ACC 1285
#define IDC_LAYER_EDIT 3004
#define IDC_LAYER_SPIN 3005
#define IDC_ALPHA_TEXT 3006
#define IDC_DISCARD_ALPHA 3007
#define IDC_BLEND_TEXT 3008
#define IDC_NO_FILTERING 3009
#define IDC_USE_BITMAP 3010
#define IDC_SCALE_NONE 3011
#define IDC_MIPBLUR_SPIN 3012
#define IDC_SCALE_ALL 3013
#define IDC_NO_DISCARD 3014
#define IDC_SCALE_HALF 3015
#define IDC_LAYER_NAME 3016
#define IDC_LAYER1 3018
#define IDC_LAYER2 3020
#define IDC_MIPBIAS_SPIN 3021
#define IDC_LEFT_NAME 3022
#define IDC_TOP_ON 3023
#define IDC_TOP_NAME 3024
#define IDC_BLEND_TEXT3 3025
#define IDC_BACK_NAME 3025
#define IDC_LAYER_ALPHA 3026
#define IDC_RIGHT_NAME 3026
#define IDC_BOTTOM_NAME 3027
#define IDC_LAYER_ADD 3028
#define IDC_GENERATE_FACES 3028
#define IDC_LAYER_MULTIPLY 3029
#define IDC_OUTPUTA_DISCARD 3032
#define IDC_OUTPUTA_ADD 3034
#define IDC_OUTPUTA_MULT 3035
#define IDC_OUTPUTB_NONE 3036
#define IDC_OUTPUTB_ALPHA 3037
#define IDC_OUTPUTB_ADD 3038
#define IDC_LOCK_AD 3040
#define IDC_LOCK_COLORS 3041
#define IDC_Z_ZNOWRITE 3042
#define IDC_SHADE_NO_FOG 3043
#define IDC_SHADE_SOFTSHADOW 3044
#define IDC_SHADE_NO_PROJ 3045
#define IDC_SHADE_VERTEXSHADE 3046
#define IDC_SHADE_NOSHADE 3047
#define IDC_SHADE_SPECULAR 3048
#define IDC_ALPHA_TEST_HIGH 3048
#define IDC_SHADE_WHITE 3049
#define IDC_USAGE_TYPE 3050
#define IDC_LAYER_RELOAD 3051
#define IDC_LAYER_COLOR_AMB 3052
#define IDC_LAYER_LOAD_GEN 3052
#define IDC_LAYER_COLOR 3053
#define IDC_CLOTHING_TINT2 3053
#define IDC_LAYER_RUNCOLOR 3054
#define IDC_HSMAX_LAYER_RGBOUT 3054
#define IDC_LAYER_SPECCOLOR 3055
#define IDC_HSMAX_LAYER_ALPHAOUT 3055
#define IDC_HSMAX_LAYER_RGBOUT2 3056
#define IDC_HSMAX_LAYER_ALPHAOUT2 3057
#define IDC_CLIP_X 3058
#define IDC_BASE_FILENAME 3058
#define IDC_CLIP_XSPIN 3059
#define IDC_CLIP_Y 3060
#define IDC_CLIP_YSPIN 3061
#define IDC_CLIP_W 3062
#define IDC_CLIP_WSPIN 3063
#define IDC_CLIP_H 3064
#define IDC_CLIP_HSPIN 3065
#define IDC_BM_CLIP 3066
#define IDC_BM_CROP_IMAGE 3067
#define IDC_BM_CROP 3068
#define IDC_BM_PLACE 3069
#define IDC_TEX1 3070
#define IDC_EXPORTWIDTH 3070
#define IDC_EXPORTWIDTH_SPINNER 3071
#define IDC_TEXON1 3071
#define IDC_TEX2 3072
#define IDC_EXPORTHEIGHT 3072
#define IDC_TEXON2 3073
#define IDC_EXPORTHEIGHT_SPINNER 3073
#define IDC_TEX3 3074
#define IDC_DT_LMARGIN 3074
#define IDC_TEXON3 3075
#define IDC_DT_LMARGIN_SPIN 3075
#define IDC_TEX4 3076
#define IDC_TEXON4 3077
#define IDC_DT_TMARGIN 3078
#define IDC_TEX5 3078
#define IDC_DT_TMARGIN_SPIN 3079
#define IDC_TEXON5 3079
#define IDC_DT_RMARGIN 3080
#define IDC_TEX6 3080
#define IDC_DT_RMARGIN_SPIN 3081
#define IDC_TEXON6 3081
#define IDC_DT_BMARGIN 3082
#define IDC_TEX7 3082
#define IDC_DT_BMARGIN_SPIN 3083
#define IDC_TEXON7 3083
#define IDC_DT_FONTSIZE 3084
#define IDC_TEX8 3084
#define IDC_DT_FONTSIZE_SPIN 3085
#define IDC_TEXON8 3085
#define IDC_TEX9 3086
#define IDC_TEXON9 3087
#define IDC_TEX10 3088
#define IDC_TEXON10 3089
#define IDC_Z_ZNOREAD 3090
#define IDC_Z_INC 3092
#define IDC_MISC_WIRE 3093
#define IDC_MISC_TWOSIDED 3094
#define IDC_MISC_MESHOUTLINES 3095
#define IDC_USE_MIPBIAS 3096
#define IDC_BLEND_INV_COLOR 3097
#define IDC_BLEND_INV_ALPHA 3098
#define IDC_BLEND_NO_COLOR 3099
#define IDC_USAGE_SETUP 3100
#define IDC_Z_ZCLEAR 3101
#define IDC_FORCE_NONCOMPRESSED 3102
#define IDC_SH_EDIT 3103
#define IDC_REFRACT 3103
#define IDC_TR_EDIT 3105
#define IDC_MIPBLUR_EDIT 3106
#define IDC_MIPBIAS_EDIT 3107
#define IDC_MTL_USE_GLOBAL 3110
#define IDC_SH_SPIN 3112
#define IDC_TR_SPIN 3114
#define IDC_USE_DETAIL 3129
#define IDC_DETAIL_SAMPLE 3130
#define IDC_DETAIL_START_SIZE_EDIT 3131
#define IDC_DETAIL_START_SIZE_SPIN 3132
#define IDC_DETAIL_START_OPAC_EDIT 3133
#define IDC_DETAIL_START_OPAC_SPIN 3134
#define IDC_DETAIL_STOP_SIZE_EDIT 3135
#define IDC_DETAIL_STOP_SIZE_SPIN 3136
#define IDC_DETAIL_STOP_OPAC_EDIT 3137
#define IDC_DETAIL_STOP_OPAC_SPIN 3138
#define IDC_COMBO2 3139
#define IDC_COMBO3 3140
#define IDC_NAMES 3142
#define IDC_LOOP 3143
#define IDC_AUTO_START 3144
#define IDC_LOOPS 3145
#define IDC_REFRESH_ANIMS 3146
#define IDC_LAYER_EMISSIVE_CB 3147
#define IDC_FRONT_NAME 3148
#define IDC_TEXSIZE_EDIT 3149
#define IDC_TEXSIZE_SPIN 3150
#define IDC_PARTICLE_HEIGHT 3151
#define IDC_FARDIST_EDIT 3151
#define IDC_PARTICLE_HEIGHT_SPIN 3152
#define IDC_FARDIST_SPIN 3152
#define IDC_PARTICLE_WIDTH 3153
#define IDC_PARTICLE_WIDTH_SPIN 3154
#define IDC_PARTICLE_XTILE 3155
#define IDC_PARTICLE_XTILE_SPIN 3156
#define IDC_PARTICLE_YTILE 3157
#define IDC_PARTICLE_YTILE_SPIN 3158
#define IDC_PARTICLE_OPACITY 3159
#define IDC_PARTICLE_OPACITY_SPIN 3160
#define IDC_PARTICLE_COLOR 3161
#define IDC_PARTICLE_NORMAL 3162
#define IDC_PARTICLE_TEXTURE 3163
#define IDC_CLOTHING_TEXTURE2 3164
#define IDC_PARTICLE_ORIENT_VELOCITY 3164
#define IDC_CLOTHING_TEXTURE3 3165
#define IDC_PARTICLE_ORIENT_UP 3165
#define IDC_CLOTHING_TEXTURE4 3166
#define IDC_PARTICLE_BLEND_ALPHA 3166
#define IDC_PARTICLE_BLEND_ADD 3167
#define IDC_PARTICLE_AMB_COLOR 3168
#define IDC_ANCHOR_NODE 3169
#define IDC_PARTICLE_ORIENT_VELSTRETCH 3169
#define IDC_USEMAXFOG 3170
#define IDC_PARTICLE_ORIENT_VELFLOW 3170
#define IDC_SCOL_LABEL 3172
#define IDC_RCOL_LABEL 3173
#define IDC_INTEN_EDIT 3174
#define IDC_INTEN_SPIN 3175
#define IDC_CLOTHING_TILE1_NAME 3176
#define IDC_CLOTHING_TILE2_NAME 3177
#define IDC_DUMMY_EDIT1 3178
#define IDC_CLOTHING_TILE3_NAME 3178
#define IDC_DUMMY_SPIN1 3179
#define IDC_CLOTHING_TILE4_NAME 3179
#define IDC_DUMMY_EDIT2 3180
#define IDC_CLOTHING_TEXTURE1 3180
#define IDC_DUMMY_SPIN2 3181
#define IDC_CLOTHING_TILESET 3181
#define IDC_CLOTHING_TILE1_SIZE 3182
#define IDC_CLOTHING_TILE2_SIZE 3183
#define IDC_CLOTHING_TILE3_SIZE 3184
#define IDC_CLOTHING_TILE4_SIZE 3185
#define IDC_CLOTHING_LAYER 3186
#define IDC_DYNTEXT_MAKESTATIC 3186
#define IDC_DT_TEXT 3187
#define IDC_DT_FONTFACE 3188
#define IDC_DOUBLE_FADE 3189
#define IDC_TRANSP_ANGLE_0 3190
#define IDC_TRANSP_ANGLE_0_SPIN 3191
#define IDC_OPAQUE_ANGLE_0 3192
#define IDC_PARTICLE_NOFILTER 3192
#define IDC_OPAQUE_ANGLE_0_SPIN 3193
#define IDC_TRANSP_ANGLE_1 3194
#define IDC_TRANSP_ANGLE_1_SPIN 3195
#define IDC_OPAQUE_ANGLE_1 3196
#define IDC_OPAQUE_ANGLE_1_SPIN 3197
#define IDC_REFLECT 3198
#define IDC_LO_CLAMP 3199
#define IDC_CLOTHING_DESCRIPTION 3199
#define IDC_LO_CLAMP_SPIN 3200
#define IDC_CLOTHING_THUMBNAIL 3200
#define IDC_HI_CLAMP 3201
#define IDC_USEINITIMAGE 3201
#define IDC_HI_CLAMP_SPIN 3202
#define IDC_INITIMAGE 3202
#define IDC_INITIMAGE_RELOAD 3203
#define IDC_DYNTEXT_ALPHA 3204
#define IDC_CLOTHING_DEFAULT 3205
#define IDC_MTL_GLOBAL_NAME 3207
#define IDC_CLOTHING_CUSTOM_TEXT_SPECS 3208
#define IDC_Z_ZONLY 3391
#define IDC_PASS_ANIM_EASE_IN_NONE 3463
#define IDC_PASS_ANIM_EASE_IN_CONST_ACCEL 3464
#define IDC_PASS_ANIM_EASE_IN_SPLINE 3465
#define IDC_PASS_ANIM_EASE_IN_TIME 3466
#define IDC_PASS_ANIM_EASE_IN_TIME_SPIN 3467
#define IDC_PASS_ANIM_EASE_OUT_NONE 3468
#define IDC_PASS_ANIM_EASE_OUT_CONST_ACCEL 3469
#define IDC_PASS_ANIM_EASE_OUT_SPLINE 3470
#define IDC_PASS_ANIM_EASE_OUT_TIME 3471
#define IDC_PASS_ANIM_EASE_OUT_TIME_SPIN 3472
#define IDC_PASS_ANIM_EASE_IN_MIN 3473
#define IDC_PASS_ANIM_EASE_IN_MIN_SPIN 3474
#define IDC_PASS_ANIM_EASE_IN_MAX 3475
#define IDC_PASS_ANIM_EASE_IN_MAX_SPIN 3476
#define IDC_PASS_ANIM_EASE_OUT_MIN 3477
#define IDC_PASS_ANIM_EASE_OUT_MIN_SPIN 3478
#define IDC_PASS_ANIM_EASE_OUT_MAX 3479
#define IDC_PASS_ANIM_EASE_OUT_MAX_SPIN 3480
#define IDC_DETAIL_CURVE_CTRL 3481
#define IDC_RELOAD_ANIMS 3482
#define IDC_CLOTHING_TINT1 3483
#define IDC_CAM_LAYER_REFLECT 3484
#define IDC_CAM_LAYER_EXPLICIT_CAM 3485
#define IDC_CAM_LAYER_UV_SRC 3486
#define IDC_CAM_LAYER_CAMERA 3487
#define IDC_CAM_LAYER_ROOT_NODE 3488
#define IDC_CAM_LAYER_EXPLICIT_CAM2 3489
#define IDC_CAM_LAYER_FORCE 3490
#define IDC_CAM_LAYER_DISABLE_COLOR 3491
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 200
#define _APS_NEXT_COMMAND_VALUE 50000
#define _APS_NEXT_CONTROL_VALUE 3492
#define _APS_NEXT_SYMED_VALUE 200
#endif
#endif