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

Initial Commit of CyanWorlds.com Engine Open Source Client/Plugin

This commit is contained in:
JWPlatt
2011-03-12 12:34:52 -05:00
commit a20a222fc2
3976 changed files with 1301356 additions and 0 deletions

View File

@ -0,0 +1,492 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "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,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/>.
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,402 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
///////////////////////////////////////////////////////////////////////////////
// //
// 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,168 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
///////////////////////////////////////////////////////////////////////////////
// //
// 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,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/>.
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,559 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "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,212 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
///////////////////////////////////////////////////////////////////////////////
// //
// 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,304 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "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,683 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "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,163 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#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,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/>.
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,52 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#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,751 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "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,87 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#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,399 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "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,145 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#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,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/>.
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,149 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
///////////////////////////////////////////////////////////////////////////////
// //
// 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,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/>.
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,237 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
///////////////////////////////////////////////////////////////////////////////
// //
// 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,499 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "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,72 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
///////////////////////////////////////////////////////////////////////////////
// //
// 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