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

CWE Directory Reorganization

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

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

View File

@ -0,0 +1,282 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// Export/convert-specific functionality of plAnimStealthNode //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plAnimStealthNode.h"
#include "plPassMtlBase.h"
#include "resource.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxComponent/plMaxAnimUtils.h"
#include "../MaxConvert/plConvert.h"
#include "../MaxConvert/hsMaterialConverter.h"
#include "../plSurface/hsGMaterial.h"
#include "../plSurface/plLayerAnimation.h"
#include "iparamm2.h"
//// Helpers /////////////////////////////////////////////////////////////////
static void ISearchLayerRecur( plLayerInterface *layer, const char *segName, hsTArray<plKey>& keys )
{
if( !layer )
return;
plLayerAnimation *animLayer = plLayerAnimation::ConvertNoRef(layer);
if (animLayer)
{
char *ID = animLayer->GetSegmentID();
if (ID == nil)
ID = "";
if (!strcmp(ID, segName))
{
if( keys.kMissingIndex == keys.Find(animLayer->GetKey()) )
keys.Append(animLayer->GetKey());
}
}
ISearchLayerRecur(layer->GetAttached(), segName, keys);
}
static int ISearchLayerRecur(hsGMaterial* mat, const char *segName, hsTArray<plKey>& keys)
{
if (segName == nil || strcmp( segName, ENTIRE_ANIMATION_NAME ) == 0 )
segName = "";
int i;
for( i = 0; i < mat->GetNumLayers(); i++ )
ISearchLayerRecur(mat->GetLayer(i), segName, keys);
return keys.GetCount();
}
static int GetMatAnimModKey(Mtl* mtl, plMaxNodeBase* node, const char* segName, hsTArray<plKey>& keys)
{
int retVal = 0;
int i;
//if( begin < 0 )
// begin = 0;
if( mtl->ClassID() == Class_ID(MULTI_CLASS_ID,0) )
{
for( i = 0; i < mtl->NumSubMtls(); i++ )
retVal += GetMatAnimModKey(mtl->GetSubMtl(i), node, segName, keys);
}
else
{
hsTArray<hsGMaterial*> matList;
if (node)
hsMaterialConverter::Instance().GetMaterialArray(mtl, (plMaxNode*)node, matList);
else
hsMaterialConverter::Instance().CollectConvertedMaterials(mtl, matList);
for( i = 0; i < matList.GetCount(); i++ )
{
retVal += ISearchLayerRecur(matList[i], segName, keys);
}
}
return retVal;
}
SegmentSpec *plAnimStealthNode::IGetSegmentSpec( void ) const
{
if( fCachedSegMap != nil )
{
const char *name = GetSegmentName();
if( name != nil )
{
SegmentMap::iterator i = fCachedSegMap->find( name );
if( i != fCachedSegMap->end() )
{
SegmentSpec *spec = i->second;
return spec;
}
}
}
return nil;
}
hsScalar plAnimStealthNode::GetSegStart( void ) const
{
SegmentSpec *spec = IGetSegmentSpec();
if( spec != nil )
return spec->fStart;
return 0.f;
}
hsScalar plAnimStealthNode::GetSegEnd( void ) const
{
SegmentSpec *spec = IGetSegmentSpec();
if( spec != nil )
return spec->fEnd;
return 0.f;
}
void plAnimStealthNode::GetLoopPoints( hsScalar &start, hsScalar &end ) const
{
start = GetSegStart();
end = GetSegEnd();
const char *loopName = GetLoopName();
if( loopName != nil && loopName[ 0 ] != 0 && fCachedSegMap != nil )
GetSegMapAnimTime( loopName, fCachedSegMap, SegmentSpec::kLoop, start, end );
}
void plAnimStealthNode::GetAllStopPoints( hsTArray<hsScalar> &out )
{
if( fCachedSegMap == nil )
return;
for (SegmentMap::iterator it = fCachedSegMap->begin(); it != fCachedSegMap->end(); it++)
{
SegmentSpec *spec = it->second;
if( spec->fType == SegmentSpec::kStopPoint )
{
out.Append( spec->fStart );
}
}
}
//// StuffToTimeConvert //////////////////////////////////////////////////////
// Handles converting all the settings we have that are applicable for an
// animTimeConvert and stuffing it into said ATC.
void plAnimStealthNode::StuffToTimeConvert( plAnimTimeConvert &convert, hsScalar maxLength )
{
const char *segName = GetSegmentName();
bool isEntire = ( segName == nil || strcmp( segName, ENTIRE_ANIMATION_NAME ) == 0 ) ? true : false;
if( isEntire )
{
convert.SetBegin( 0 );
convert.SetEnd( maxLength );
}
else
{
SegmentSpec *spec = IGetSegmentSpec();
convert.SetBegin( ( spec != nil ) ? spec->fStart : 0.f );
convert.SetEnd( ( spec != nil ) ? spec->fEnd : 0.f );
}
// Even if we're not looping, set the loop points. (A responder
// could tell us later to start looping.)
if( isEntire )
convert.SetLoopPoints( 0, maxLength );
else
{
hsScalar loopStart, loopEnd;
GetLoopPoints( loopStart, loopEnd );
convert.SetLoopPoints( loopStart, loopEnd );
}
convert.Loop( GetLoop() );
// Auto-start
if( GetAutoStart() )
convert.Start( 0 );
else
convert.Stop( true );
// Stuff stop points
GetAllStopPoints( convert.GetStopPoints() );
// Ease curve stuff
if( GetEaseInType() != plAnimEaseTypes::kNoEase )
{
convert.SetEase( true, GetEaseInType(), GetEaseInMin(), GetEaseInMax(), GetEaseInLength() );
}
if( GetEaseOutType() != plAnimEaseTypes::kNoEase )
{
convert.SetEase( false, GetEaseOutType(), GetEaseOutMin(), GetEaseOutMax(), GetEaseOutLength() );
}
}
//// plAnimObjInterface Functions ////////////////////////////////////////////
hsBool plAnimStealthNode::GetKeyList( INode *restrictedNode, hsTArray<plKey> &outKeys )
{
if( !fPreppedForConvert )
{
hsMessageBox( "This messages is to warn you that mcn screwed up in his attempt to create "
"a SetupProperties() pass for materials in this scene. You should probably let him know as soon as "
"possible, and also make a copy of this exact scene so that he can test with it and figure out what "
"is going wrong. Thank you.", "Mathew is Stupid Error", hsMessageBoxNormal );
}
GetMatAnimModKey( GetParentMtl(), (plMaxNode *)restrictedNode, GetSegmentName(), outKeys );
return true;
}
//// SetupProperties /////////////////////////////////////////////////////////
hsBool plAnimStealthNode::SetupProperties( plMaxNode *node, plErrorMsg *pErrMsg )
{
fPreppedForConvert = true;
plPassMtlBase *parent = GetParentMtl();
if( parent != nil && fCachedSegMap == nil )
{
fCachedSegMap = GetAnimSegmentMap( parent, nil );
}
return true;
}
//// ConvertDeInit ///////////////////////////////////////////////////////////
hsBool plAnimStealthNode::ConvertDeInit( plMaxNode *node, plErrorMsg *pErrMsg )
{
fPreppedForConvert = false;
if( fCachedSegMap != nil )
DeleteSegmentMap( fCachedSegMap );
fCachedSegMap = nil;
return true;
}

View File

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

View File

@ -0,0 +1,263 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plAnimStealthNode - Stealthy hidden INode that represents a single //
// segment's worth of animation info for a material. //
// Stored as an INode so they can be "selected" //
// by components as targets of animation messages. //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plAnimStealthNode_h
#define _plAnimStealthNode_h
#include "Max.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "hsTypes.h"
#include "../pnKeyedObject/plKey.h"
#include "../MaxComponent/plAnimObjInterface.h"
#include "../MaxComponent/plMaxAnimUtils.h"
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
#define ANIMSTEALTH_CLASSID Class_ID(0xd0272f8, 0x750349c9)
#define REFMSG_NOTETRACK_ADDED REFMSG_USER + 1
class plPassMtlBase;
class NoteTrack;
class plMaxNode;
class plErrorMsg;
class plAnimTimeConvert;
//// Class Def ///////////////////////////////////////////////////////////////
class plAnimStealthNode : public HelperObject, public plAnimObjInterface
{
protected:
ClassDesc2 *fClassDesc;
IParamBlock2 *fParamBlock;
plPassMtlBase *fParentMtl;
static ParamBlockDesc2 sAnimStealthPB;
hsBool fPreppedForConvert;
SegmentMap *fCachedSegMap;
SegmentSpec *IGetSegmentSpec( void ) const;
public:
// Some IDs
enum
{
kBlockPB = 0
};
enum Refs
{
kRefParamBlock,
kRefParentMtl
};
// ParamBlock IDs
enum ParamBlockIDs
{
kPBAutoStart, // Start the Animation on load (V2)
kPBLoop, // Start Looping at Begin Location
kPBName, // Name of the notetrack animation to play
kPBLoopName, // Name of the notetrack specified loop
kPBEaseInType,
kPBEaseOutType,
kPBEaseInLength,
kPBEaseOutLength,
kPBEaseInMin,
kPBEaseInMax,
kPBEaseOutMin,
kPBEaseOutMax
};
plAnimStealthNode( BOOL loading );
virtual ~plAnimStealthNode();
void DeleteThis() { delete this; }
INode *GetINode( void );
plPassMtlBase *GetParentMtl( void );
void SetParentMtl( plPassMtlBase *parent );
void SetNodeName( const char *parentName );
// Create the dialog for this object and place it inside the given dialog, centering it in the given control if any
bool CreateAndEmbedDlg( IParamMap2 *parentMap, IMtlParams *parentParams, HWND frameCtrl = nil );
// Release said dialog
void ReleaseDlg( void );
// Switch underlying objects in the dialog (to avoid unnecessary deletion/recreations)
void SwitchDlg( plAnimStealthNode *toSwitchTo );
// Get the actual window handle of the currently active dialog displaying us
HWND GetWinDlg( void ) const;
// Interesting functions
const char *GetSegmentName( void ) const;
void SetSegment( const char *name ); // nil for "entire animation"
// Conversion from stealth's INode to the actual object
static bool CanConvertToStealth( INode *objNode );
static plAnimStealthNode *ConvertToStealth( INode *objNode );
///////////////////////////////////////////////////////////////////////////////////////
// Required Max functions
//
TCHAR* GetObjectName() { return (TCHAR*)fClassDesc->ClassName(); }
void InitNodeName(TSTR& s) { s = fClassDesc->InternalName(); }
void GetClassName(TSTR& s) { s = fClassDesc->ClassName(); }
Class_ID ClassID() { return ANIMSTEALTH_CLASSID; }
RefTargetHandle Clone(RemapDir &remap);
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
RefResult NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget, PartID& partID, RefMessage message);
// allow retreival of our paramblock from other plug-ins
// and the max core
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
// We override because we don't want to be able to animate this sucker
int NumSubs() { return 0; }
Animatable *SubAnim( int i ) { return nil; }
TSTR SubAnimName( int i ) { return fClassDesc->ClassName(); }
// plug-in mouse creation callback
CreateMouseCallBack* GetCreateMouseCallBack();
void BeginEditParams(IObjParam *ip, ULONG flags, Animatable *prev);
void EndEditParams(IObjParam *ip, ULONG flags, Animatable *next);
// void SelectionSetChanged(Interface *ip, IUtil *iu);
void BuildMesh(TimeValue t);
void FreeCaches();
void GetLocalBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box);
void GetWorldBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box);
int Display(TimeValue t, INode *node, ViewExp *vpt, int flags);
int HitTest(TimeValue t, INode *node, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt);
ObjectState Eval(TimeValue t) { return ObjectState(this); }
IOResult Save(ISave* isave);
IOResult Load(ILoad* iload);
int CanConvertToType( Class_ID obtype ) { return ( obtype == ANIMSTEALTH_CLASSID ) ? 1 : 0; }
const char *GetCategory() { return fClassDesc->Category(); }
/// Parameter access
bool GetAutoStart( void ) const;
void SetAutoStart( bool b );
bool GetLoop( void ) const;
const char *GetLoopName( void ) const;
void SetLoop( bool b, const char *name );
UInt8 GetEaseInType( void ) const;
hsScalar GetEaseInLength( void ) const;
hsScalar GetEaseInMin( void ) const;
hsScalar GetEaseInMax( void ) const;
void SetEaseIn( UInt8 type, hsScalar length, hsScalar min, hsScalar max );
UInt8 GetEaseOutType( void ) const;
hsScalar GetEaseOutLength( void ) const;
hsScalar GetEaseOutMin( void ) const;
hsScalar GetEaseOutMax( void ) const;
void SetEaseOut( UInt8 type, hsScalar length, hsScalar min, hsScalar max );
// Conversion stuff
void GetAllStopPoints( hsTArray<hsScalar> &out );
hsScalar GetSegStart( void ) const;
hsScalar GetSegEnd( void ) const;
void GetLoopPoints( hsScalar &start, hsScalar &end ) const;
void StuffToTimeConvert( plAnimTimeConvert &convert, hsScalar maxLength );
// plAnimObjInterface functions
virtual void PickTargetNode( IParamBlock2 *destPB, ParamID destParamID, ParamID typeID );
virtual hsBool IsNodeRestricted( void ) { return true; }
virtual const char *GetIfaceSegmentName( hsBool allowNil );
virtual hsBool GetKeyList( INode *restrictedNode, hsTArray<plKey> &outKeys );
virtual hsBool MightRequireSeparateMaterial( void ) { return true; }
// Convert time, called on the setupProps pass for each material applied to a node in the scene
virtual hsBool SetupProperties( plMaxNode *node, plErrorMsg *pErrMsg );
virtual hsBool ConvertDeInit( plMaxNode *node, plErrorMsg *pErrMsg );
// Returns true if the parent material is applied to any node in the scene, false otherwise
hsBool IsParentUsedInScene( void );
};
//// Accessor for Parent's ParamBlock ////////////////////////////////////////
class plStealthNodeAccessor : public PBAccessor
{
protected:
void ISetParent( ReferenceTarget *target, plPassMtlBase *parent );
void IHandleSet( PB2Value &v, ReferenceMaker *owner, ParamID id, int tabIndex, TimeValue t );
public:
plStealthNodeAccessor() { }
static plStealthNodeAccessor &GetInstance( void );
virtual void Set( PB2Value &v, ReferenceMaker *owner, ParamID id, int tabIndex, TimeValue t );
virtual void TabChanged( tab_changes changeCode, Tab<PB2Value> *tab, ReferenceMaker *owner,
ParamID id, int tabIndex, int count );
};
#endif //_plAnimStealthNode_h

View File

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

View File

@ -0,0 +1,194 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_BUMPMTL_H
#define PL_BUMPMTL_H
#include "Max.h"
#include "iparamb2.h"
#include "../resource.h"
#include "plPassMtlBase.h"
#define BUMP_MTL_CLASS_ID Class_ID(0x4dbf7b0a, 0x92226de)
extern TCHAR *GetString(int id);
class plBumpMtl : public plPassMtlBase
{
protected:
virtual void ICloneRefs( plPassMtlBase *target, RemapDir &remap );
public:
enum RefIDs
{
kRefBasic,
kRefAnim,
};
enum BlockIDs
{
kBlkBasic,
kBlkAnim,
};
plBumpMtl(BOOL loading);
void DeleteThis() { delete this; }
//From Animatable
Class_ID ClassID() { return BUMP_MTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_BUMP_MTL); }
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void NotifyChanged();
BOOL SupportsMultiMapsInViewport() { return FALSE; }
void SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb);
// Shade and displacement calculation
static void GetInterpVtxValue(int channel, ShadeContext &sc, Point3 &interpVal);
void Shade(ShadeContext& sc);
void ShadeWithBackground(ShadeContext &sc, Color background, bool useVtxAlpha = true);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
virtual RefTargetHandle GetReference( int i );
virtual void SetReference( int i, RefTargetHandle rtarg );
// SubTexmap access methods
int NumSubTexmaps();
Texmap* GetSubTexmap(int i);
void SetSubTexmap(int i, Texmap *m);
TSTR GetSubTexmapSlotName(int i);
TSTR GetSubTexmapTVName(int i);
BOOL SetDlgThing(ParamDlg* dlg);
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
// void SetParamDlg(ParamDlg *dlg);
// void SetNumSubTexmaps(int num);
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
ULONG Requirements( int subMtlNum );
virtual bool HasAlpha();
// Massive list of inherited accessor functions for ParamBlock data
// Advanced Block
virtual int GetBasicWire();
virtual int GetMeshOutlines();
virtual int GetTwoSided();
virtual int GetSoftShadow();
virtual int GetNoProj();
virtual int GetVertexShade();
virtual int GetNoShade();
virtual int GetNoFog();
virtual int GetWhite();
virtual int GetZOnly();
virtual int GetZClear();
virtual int GetZNoRead();
virtual int GetZNoWrite();
virtual int GetZInc();
virtual int GetAlphaTestHigh();
// Animation block
virtual char * GetAnimName();
virtual int GetAutoStart();
virtual int GetLoop();
virtual char * GetAnimLoopName();
// Basic block
virtual int GetColorLock();
virtual Color GetAmbColor();
virtual Color GetColor();
virtual int GetOpacity();
virtual int GetEmissive();
virtual int GetUseSpec();
virtual int GetShine();
virtual Color GetSpecularColor();
virtual Control *GetPreshadeColorController();
virtual Control *GetAmbColorController();
virtual Control *GetOpacityController();
virtual Control *GetSpecularColorController();
virtual int GetDiffuseColorLock();
virtual Color GetRuntimeColor();
virtual Control *GetRuntimeColorController();
// Layer block
virtual Texmap *GetBaseLayer();
virtual int GetTopLayerOn();
virtual Texmap *GetTopLayer();
virtual int GetLayerBlend();
virtual int GetOutputAlpha();
virtual int GetOutputBlend();
};
#endif //PL_BUMPMTL_H

View File

@ -0,0 +1,53 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_BUMPMTLANIMPB_H
#define PL_BUMPMTLANIMPB_H
enum
{
kBumpAnimName,
kBumpAnimAutoStart,
kBumpAnimLoop,
kBumpAnimLoopName,
};
#endif

View File

@ -0,0 +1,109 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plBumpMtl.h"
#include "plPassBaseParamIDs.h"
#include "resource.h"
#include "iparamm2.h"
#include "plPassAnimDlgProc.h"
#include "plAnimStealthNode.h"
using namespace plPassBaseParamIDs;
static ParamBlockDesc2 gBumpAnimPB
(
plBumpMtl::kBlkAnim, _T("anim"), IDS_PASS_ANIM, GetBumpMtlDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI + P_CALLSETS_ON_LOAD, plBumpMtl::kRefAnim,
// UI
IDD_PASS_ANIM, IDS_PASS_ANIM, 0, 0, &plPassAnimDlgProc::Get(),
#ifdef MCN_UPGRADE_OLD_ANIM_BLOCKS
// THE FOLLOWING ARE ALL OLD PARAMETERS AND SHOULD NO LONGER BE USED. The only reason
// they're here is so we can convert old paramBlocks into the new plAnimStealthNode format
kPBAnimName, _T("animName"), TYPE_STRING, 0, 0,
end,
kPBAnimAutoStart, _T("autoStart"), TYPE_BOOL, 0, 0,
end,
kPBAnimLoop, _T("loop"), TYPE_BOOL, 0, 0,
end,
kPBAnimLoopName, _T("loopName"), TYPE_STRING, 0, 0,
end,
// Anim Ease
kPBAnimEaseInType, _T("easeInType"), TYPE_INT, 0, 0,
end,
kPBAnimEaseInLength, _T("easeInLength"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseInMin, _T("easeInMin"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseInMax, _T("easeInMax"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutType, _T("easeOutType"), TYPE_INT, 0, 0,
end,
kPBAnimEaseOutLength, _T("easeOutLength"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutMin, _T("easeOutMin"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutMax, _T("easeOutMax"), TYPE_FLOAT, 0, 0,
end,
#endif // MCN_UPGRADE_OLD_ANIM_BLOCKS
kPBAnimUseGlobal, _T("UseGlobal"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_MTL_USE_GLOBAL,
end,
kPBAnimGlobalName, _T("GlobalName"), TYPE_STRING, 0, 0,
p_default, _T(""),
end,
kPBAnimStealthNodes, _T( "testing" ), TYPE_REFTARG_TAB, 0, 0, 0,
p_accessor, &plStealthNodeAccessor::GetInstance(),
end,
end
);
ParamBlockDesc2 *GetBumpAnimPB() { return &gBumpAnimPB; }

View File

@ -0,0 +1,54 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_BUMPMTLBASICPB_H
#define PL_BUMPMTLBASICPB_H
// Param ID's
enum
{
kBumpBasSpecular,
kBumpBasRunColor,
kBumpBasLayer
};
#endif //PL_BUMPMTLBASICPB_H

View File

@ -0,0 +1,108 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plBumpMtl.h"
#include "plBumpMtlBasicPB.h"
#include "resource.h"
#include "iparamm2.h"
class BumpBasicDlgProc;
extern BumpBasicDlgProc gBumpBasicDlgProc;
static ParamBlockDesc2 gBumpBasicPB
(
plBumpMtl::kBlkBasic, _T("basic"), IDS_PASS_BASIC, GetBumpMtlDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI, plBumpMtl::kRefBasic,
// UI
IDD_BUMP_BASIC, IDS_PASS_BASIC, 0, 0, &gBumpBasicDlgProc,
kBumpBasLayer, _T("bumpLayer"), TYPE_TEXMAP, 0, IDS_BASIC_AMB,
p_ui, TYPE_TEXMAPBUTTON, IDC_LAYER1,
p_subtexno, 0,
end,
kBumpBasRunColor, _T("runtimeColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_RUNCOLOR,
// p_ui, TYPE_COLORSWATCH, IDC_LAYER_RUNCOLOR,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_INTEN_EDIT, IDC_INTEN_SPIN,
IDC_DUMMY_EDIT1, IDC_DUMMY_SPIN1, IDC_DUMMY_EDIT2, IDC_DUMMY_SPIN2,
SPIN_AUTOSCALE,
p_default, Color(1,0,0),
end,
// Specularity
kBumpBasSpecular, _T("useSpec"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_SPECULAR,
end,
end
);
ParamBlockDesc2 *GetBumpBasicPB() { return &gBumpBasicPB; }
class BumpBasicDlgProc : public ParamMap2UserDlgProc
{
#if 1
protected:
public:
BumpBasicDlgProc() {}
~BumpBasicDlgProc() { }
#endif
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
IParamBlock2 *pb = map->GetParamBlock();
switch (msg)
{
case WM_INITDIALOG:
{
}
return TRUE;
}
return FALSE;
}
void DeleteThis() {}
};
static BumpBasicDlgProc gBumpBasicDlgProc;

View File

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

View File

@ -0,0 +1,217 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_CLOTHINGMTL_H
#define PL_CLOTHINGMTL_H
#include "Max.h"
#include "iparamb2.h"
#include "../resource.h"
#include "hsTemplates.h"
class Bitmap;
class plClothingItem;
class plMaxNode;
class plClothingElement;
#define CLOTHING_MTL_CLASS_ID Class_ID(0x792c6de4, 0x1f952b65)
extern TCHAR *GetString(int id);
class plClothingTileset
{
public:
char *fName;
hsTArray<plClothingElement *> fElements;
plClothingTileset();
~plClothingTileset();
void SetName(char *name);
void AddElement(plClothingElement *element);
};
class plClothingMtl : public Mtl
{
protected:
IParamBlock2 *fBasicPB;
Interval fIValid;
public:
IMtlParams *fIMtlParams;
static const char *LayerStrings[];
static const UInt8 LayerToPBIdx[];
enum
{
kRefBasic,
};
enum
{
kBlkBasic,
};
enum // Param block indicies
{
kTileset,
kTexmap,
kDescription,
kThumbnail,
kLayer,
kTexmapSkin,
kTexmap2,
kDefault,
kCustomTextSpecs,
kTexmapBase,
kTexmapSkinBlend1,
kTexmapSkinBlend2,
kTexmapSkinBlend3,
kTexmapSkinBlend4,
kTexmapSkinBlend5,
kTexmapSkinBlend6,
kDefaultTint1,
kDefaultTint2,
kForcedAcc,
};
enum
{
kMaxTiles = 4,
};
enum
{
kBlendNone,
kBlendAlpha,
//kBlendAdd,
};
static const UINT32 ButtonConstants[kMaxTiles];
static const UINT32 TextConstants[kMaxTiles * 2];
hsTArray<plClothingTileset *> fTilesets;
hsTArray<plClothingElement *> fElements;
virtual void InitTilesets();
virtual void ReleaseTilesets();
plClothingElement *FindElementByName(char *name);
int GetTilesetIndex() { return fBasicPB->GetInt(ParamID(kTileset)); }
DllExport Texmap *GetTexmap(int index, int layer);
Texmap *GetThumbnail() { return fBasicPB->GetTexmap(ParamID(kThumbnail)); }
char *GetDescription() { return fBasicPB->GetStr(ParamID(kDescription)); }
char *GetCustomText() { return fBasicPB->GetStr(ParamID(kCustomTextSpecs)); }
hsBool GetDefault() { return fBasicPB->GetInt(ParamID(kDefault)) != 0; }
Color GetDefaultTint1() { return fBasicPB->GetColor(plClothingMtl::kDefaultTint1); }
Color GetDefaultTint2() { return fBasicPB->GetColor(plClothingMtl::kDefaultTint2); }
char *GetForcedAccessoryName() { return fBasicPB->GetStr(ParamID(kForcedAcc)); }
plClothingMtl(BOOL loading);
void DeleteThis() { delete this; }
//From Animatable
Class_ID ClassID() { return CLOTHING_MTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_CLOTHING_MTL); }
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void Reset();
void NotifyChanged();
BOOL SupportsMultiMapsInViewport() { return FALSE; }
void SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb);
// Shade and displacement calculation
void Shade(ShadeContext& sc);
void ShadeWithBackground(ShadeContext &sc, Color background);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
// SubTexmap access methods
int NumSubTexmaps();
Texmap* GetSubTexmap(int i);
void SetSubTexmap(int i, Texmap *m);
TSTR GetSubTexmapSlotName(int i);
TSTR GetSubTexmapTVName(int i);
BOOL SetDlgThing(ParamDlg* dlg);
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs() { return 0; }
Animatable* SubAnim(int i) { return nil; }
TSTR SubAnimName(int i) { return ""; }
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
ULONG Requirements( int subMtlNum );
};
#endif //PL_ClothingMTL_H

View File

@ -0,0 +1,442 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//#include "plClothingMtl.h"
#include "../../AssetMan/PublicInterface/AssManBaseTypes.h"
#include "max.h"
class plClothingEditBox
{
protected:
int fCtrlID;
int fPBEditID;
plClothingEditBox() {};
void IGetText(IParamBlock2 *pb, HWND hCtrl)
{
// Get the previous value
const char *oldVal = pb->GetStr(fPBEditID);
if (!oldVal)
oldVal = "";
// Get the text from the edit and store it in the paramblock
int len = GetWindowTextLength(hCtrl)+1;
if (len > 1)
{
char *buf = TRACKED_NEW char[len];
GetWindowText(hCtrl, buf, len);
// If the old value is different from the current one, update
if (strcmp(oldVal, buf))
pb->SetValue(fPBEditID, 0, buf);
delete [] buf;
}
else
{
// If the old value wasn't empty, update
if (*oldVal != '\0')
pb->SetValue(fPBEditID, 0, "");
}
}
public:
plClothingEditBox(int ctrlID, int pbEditID) : fCtrlID(ctrlID), fPBEditID(pbEditID) {}
void UpdateText(IParamBlock2 *pb, HWND hWnd)
{
const char *str = pb->GetStr(fPBEditID);
SetDlgItemText(hWnd, fCtrlID, (str != nil ? str : ""));
}
BOOL ProcessMsg(IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// If this isn't a message we process, return
if (!(msg == WM_INITDIALOG || msg == WM_DESTROY ||
(msg == WM_COMMAND && LOWORD(wParam) == fCtrlID)))
return FALSE;
IParamBlock2 *pb = map->GetParamBlock();
// Initializing the dialog, set the text box
if (msg == WM_INITDIALOG)
{
UpdateText(pb, hWnd);
return FALSE;
}
// Being destroyed, but we may not have gotten the text from the edit box
// (EN_KILLFOCUS seems to be sent after the window isn't recieving any more messages)
if (msg == WM_DESTROY)
{
IGetText(pb, GetDlgItem(hWnd, fCtrlID));
return FALSE;
}
int notification = HIWORD(wParam);
HWND hCtrl = (HWND)lParam;
// Disable Max accelerators when the edit box gets focus
if (notification == EN_SETFOCUS)
{
//plMaxAccelerators::Disable();
DisableAccelerators();
return TRUE;
}
// The edit control is losing focus, get it's contents
else if (notification == EN_KILLFOCUS)
{
IGetText(pb, hCtrl);
//plMaxAccelerators::Enable();
EnableAccelerators();
return TRUE;
}
return FALSE;
}
};
class ClothingBasicDlgProc;
extern ClothingBasicDlgProc gClothingBasicDlgProc;
static ParamBlockDesc2 gClothingMtlPB
(
plClothingMtl::kBlkBasic, _T("Clothing"), IDS_PASS_BASIC, GetClothingMtlDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI + P_CALLSETS_ON_LOAD, plClothingMtl::kRefBasic,
// UI
IDD_CLOTHING, IDS_PASS_BASIC, 0, 0, &gClothingBasicDlgProc,
plClothingMtl::kTileset, _T("tileset"), TYPE_INT, 0, 0,
p_default, 0,
end,
plClothingMtl::kTexmap, _T("texmap"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kDescription, _T("ItemDescription"), TYPE_STRING, 0, 0,
p_ui, TYPE_EDITBOX, IDC_CLOTHING_DESCRIPTION,
end,
plClothingMtl::kThumbnail, _T("Thumbnail"), TYPE_TEXMAP, 0, 0,
end,
plClothingMtl::kLayer, _T("Layer"), TYPE_INT, 0, 0,
p_default, plClothingElement::kLayerTint1,
end,
plClothingMtl::kTexmapSkin, _T("SkinLayer"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmap2, _T("TintLayer2"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kDefault, _T("Default"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_CLOTHING_DEFAULT,
p_default, 0,
end,
plClothingMtl::kCustomTextSpecs, _T("TextSpecs"), TYPE_STRING, 0, 0,
end,
plClothingMtl::kTexmapBase, _T("BaseLayer"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmapSkinBlend1, _T("SkinBlend(1)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmapSkinBlend2, _T("SkinBlend(2)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmapSkinBlend3, _T("SkinBlend(3)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmapSkinBlend4, _T("SkinBlend(4)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmapSkinBlend5, _T("SkinBlend(5)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kTexmapSkinBlend6, _T("SkinBlend(6)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
end,
plClothingMtl::kDefaultTint1, _T("DefaultTint1"), TYPE_RGBA, 0, 0,
p_ui, TYPE_COLORSWATCH, IDC_CLOTHING_TINT1,
p_default, Color(1,1,1),
end,
plClothingMtl::kDefaultTint2, _T("DefaultTint2"), TYPE_RGBA, 0, 0,
p_ui, TYPE_COLORSWATCH, IDC_CLOTHING_TINT2,
p_default, Color(1,1,1),
end,
plClothingMtl::kForcedAcc, _T("ForcedAcc"), TYPE_STRING, 0, 0,
p_ui, TYPE_EDITBOX, IDC_CLOTHING_FORCED_ACC,
end,
end
);
class ClothingBasicDlgProc : public ParamMap2UserDlgProc
{
protected:
plClothingEditBox fCustomText;
public:
ClothingBasicDlgProc() : fCustomText(IDC_CLOTHING_CUSTOM_TEXT_SPECS, plClothingMtl::kCustomTextSpecs) {}
~ClothingBasicDlgProc() {}
void UpdateDisplay(IParamMap2 *pmap)
{
HWND hWnd = pmap->GetHWnd();
IParamBlock2 *pb = pmap->GetParamBlock();
plClothingMtl *mtl = (plClothingMtl *)pb->GetOwner();
HWND cbox = NULL;
plPlasmaMAXLayer *layer;
PBBitmap *pbbm;
ICustButton *bmSelectBtn;
char buff[256];
// Setup the tiles
int i, j;
int layerSet = pb->GetInt(ParamID(plClothingMtl::kLayer));
int layerIdx = plClothingMtl::LayerToPBIdx[layerSet];
for (j = 0; j < plClothingMtl::kMaxTiles; j++)
{
layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(layerIdx), 0, j);
pbbm = (layer == nil ? nil : layer->GetPBBitmap());
bmSelectBtn = GetICustButton(GetDlgItem(hWnd, plClothingMtl::ButtonConstants[j]));
bmSelectBtn->SetText(pbbm ? (TCHAR*)pbbm->bi.Filename() : "(none)");
ReleaseICustButton(bmSelectBtn);
}
// And the thumbnail...
layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(plClothingMtl::kThumbnail));
if (layer == nil)
{
layer = TRACKED_NEW plLayerTex;
pb->SetValue(ParamID(plClothingMtl::kThumbnail), 0, layer);
}
pbbm = layer->GetPBBitmap();
if (pbbm)
{
bmSelectBtn = GetICustButton(GetDlgItem(hWnd, IDC_CLOTHING_THUMBNAIL));
bmSelectBtn->SetText((TCHAR*)pbbm->bi.Filename());
ReleaseICustButton(bmSelectBtn);
}
int setIdx = pb->GetInt(ParamID(plClothingMtl::kTileset));
ComboBox_SetCurSel(GetDlgItem(hWnd, IDC_CLOTHING_TILESET), setIdx);
ComboBox_SetCurSel(GetDlgItem(hWnd, IDC_CLOTHING_LAYER), pb->GetInt(ParamID(plClothingMtl::kLayer)));
mtl->InitTilesets();
plClothingTileset *tileset = mtl->fTilesets.Get(setIdx);
for (i = 0; i < tileset->fElements.GetCount(); i++)
{
plClothingElement *element = tileset->fElements.Get(i);
SendMessage(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i]),
WM_SETTEXT, NULL, (LPARAM)element->fName);
sprintf(buff, "(%d, %d)", element->fWidth, element->fHeight);
SendMessage(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i + 1]),
WM_SETTEXT, NULL, (LPARAM)buff);
ShowWindow(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i]), SW_SHOW);
ShowWindow(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i + 1]), SW_SHOW);
ShowWindow(GetDlgItem(hWnd, plClothingMtl::ButtonConstants[i]), SW_SHOW);
}
for (i = tileset->fElements.GetCount(); i < plClothingMtl::kMaxTiles; i++)
{
ShowWindow(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i]), SW_HIDE);
ShowWindow(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i + 1]), SW_HIDE);
ShowWindow(GetDlgItem(hWnd, plClothingMtl::ButtonConstants[i]), SW_HIDE);
}
mtl->ReleaseTilesets();
fCustomText.UpdateText(pb, hWnd);
}
virtual void Update(TimeValue t, Interval& valid, IParamMap2* pmap) { UpdateDisplay(pmap); }
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// Check if it is for our edit box
if (fCustomText.ProcessMsg(map, hWnd, msg, wParam, lParam))
return TRUE;
int id = LOWORD(wParam);
int code = HIWORD(wParam);
IParamBlock2 *pb = map->GetParamBlock();
plClothingMtl *mtl = (plClothingMtl *)pb->GetOwner();
HWND cbox = NULL;
plPlasmaMAXLayer *layer;
PBBitmap *pbbm;
ICustButton *bmSelectBtn;
int layerIdx = plClothingMtl::LayerToPBIdx[pb->GetInt(ParamID(plClothingMtl::kLayer))];
switch (msg)
{
case WM_INITDIALOG:
int j;
mtl->InitTilesets();
cbox = GetDlgItem(hWnd, IDC_CLOTHING_TILESET);
for (j = 0; j < mtl->fTilesets.GetCount(); j++)
SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)mtl->fTilesets.Get(j)->fName);
mtl->ReleaseTilesets();
cbox = GetDlgItem(hWnd, IDC_CLOTHING_LAYER);
for (j = 0; j < plClothingElement::kLayerMax; j++)
ComboBox_AddString(cbox, plClothingMtl::LayerStrings[j]);
return TRUE;
case WM_COMMAND:
if (id == IDC_CLOTHING_TILESET)
{
int setIdx = SendMessage(GetDlgItem(hWnd, id), CB_GETCURSEL, 0, 0);
pb->SetValue(plClothingMtl::kTileset, t, setIdx);
return TRUE;
}
if (id == IDC_CLOTHING_LAYER)
{
pb->SetValue(plClothingMtl::kLayer, t, ComboBox_GetCurSel(GetDlgItem(hWnd, id)));
return TRUE;
}
if (id == IDC_CLOTHING_THUMBNAIL)
{
layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(plClothingMtl::kThumbnail));
if (layer == nil)
return FALSE;
BitmapInfo bi;
bi.SetName(layer->GetPBBitmap() == nil ? "" : layer->GetPBBitmap()->bi.Name());
BOOL selectedNewBitmap = layer->HandleBitmapSelection();
if (selectedNewBitmap)
{
pbbm = layer->GetPBBitmap();
bmSelectBtn = GetICustButton(GetDlgItem(hWnd, IDC_CLOTHING_THUMBNAIL));
bmSelectBtn->SetText(pbbm != nil ? (TCHAR*)pbbm->bi.Filename() : "(none)");
ReleaseICustButton(bmSelectBtn);
}
return TRUE;
}
int buttonIdx = -1;
if (id == IDC_CLOTHING_TEXTURE1) buttonIdx = 0;
else if (id == IDC_CLOTHING_TEXTURE2) buttonIdx = 1;
else if (id == IDC_CLOTHING_TEXTURE3) buttonIdx = 2;
else if (id == IDC_CLOTHING_TEXTURE4) buttonIdx = 3;
if (buttonIdx != -1)
{
layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(layerIdx), 0, buttonIdx);
if (layer == nil)
{ // First time we've set a layer on this spot
layer = TRACKED_NEW plLayerTex;
pb->SetValue(ParamID(layerIdx), 0, layer, buttonIdx);
}
jvUniqueId oldId;
layer->GetBitmapAssetId(oldId);
BitmapInfo bi;
bi.SetName(layer->GetPBBitmap() == nil ? "" : layer->GetPBBitmap()->bi.Name());
BOOL selectedNewBitmap = layer->HandleBitmapSelection();
if (selectedNewBitmap)
{
// Check if it's ok, and undo if not.
hsBool choiceOk = true;
pbbm = layer->GetPBBitmap();
if (pbbm != nil)
{
mtl->InitTilesets();
plClothingTileset *tileset = mtl->fTilesets.Get(pb->GetInt(plClothingMtl::kTileset));
plClothingElement *element = tileset->fElements.Get(buttonIdx);
float targRatio = (float)element->fWidth / (float)element->fHeight;
float ratio = (float)pbbm->bi.Width() / (float)pbbm->bi.Height();
if (targRatio != ratio)
{
choiceOk = false;
hsMessageBox("That image's width/height ratio does not match the one for this tile. "
"Restoring the old selection.", "Invalid image", hsMessageBoxNormal);
}
else if (pbbm->bi.Width() < element->fWidth)
{
choiceOk = false;
hsMessageBox("The chosen image is too small for that tile slot. "
"Restoring the old selection.", "Invalid image", hsMessageBoxNormal);
}
mtl->ReleaseTilesets();
}
if (!choiceOk)
{
layer->SetBitmapAssetId(oldId);
layer->SetBitmap(&bi);
}
else
{
bmSelectBtn = GetICustButton(GetDlgItem(hWnd, plClothingMtl::ButtonConstants[buttonIdx]));
bmSelectBtn->SetText(pbbm != nil ? (TCHAR*)pbbm->bi.Filename() : "(none)");
ReleaseICustButton(bmSelectBtn);
}
}
}
return TRUE;
}
return FALSE;
}
void DeleteThis() {}
};
static ClothingBasicDlgProc gClothingBasicDlgProc;

View File

@ -0,0 +1,584 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plCompositeMtl.h"
#include "plPassMtl.h"
//#include "plCompositeMtlPB.h"
#include "plCompositeMtlDlg.h"
class plCompositeClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading) { return TRACKED_NEW plCompositeMtl(loading); }
const TCHAR* ClassName() { return GetString(IDS_COMP_MTL); }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
Class_ID ClassID() { return COMP_MTL_CLASS_ID; }
const TCHAR* Category() { return NULL; }
const TCHAR* InternalName() { return _T("PlasmaComposite"); }
HINSTANCE HInstance() { return hInstance; }
};
static plCompositeClassDesc plCompositeMtlDesc;
ClassDesc2* GetCompMtlDesc() { return &plCompositeMtlDesc; }
#include "plCompositeMtlPBDec.h"
const char *plCompositeMtl::BlendStrings[] = // Make sure these match up in order with the Blend enum (in the header)
{
"Vertex Alpha",
"Inverse Vtx Alpha",
"Vertex Illum Red",
"Inv. Vtx Illum Red",
"Vertex Illum Green",
"Inv. Vtx Illum Green",
"Vertex Illum Blue",
"Inv. Vtx Illum Blue"
};
plCompositeMtl::plCompositeMtl(BOOL loading) : fPassesPB(NULL)
{
plCompositeMtlDesc.MakeAutoParamBlocks(this);
if (!loading)
Reset();
int i;
for (i = 0; i < NSUBMTLS; i++)
{
plPassMtl *newMtl = TRACKED_NEW plPassMtl(false);
fPassesPB->SetValue(kCompPasses, 0, newMtl, i);
GetCOREInterface()->AssignNewName(fPassesPB->GetMtl(kCompPasses, 0, i));
}
}
void plCompositeMtl::Reset()
{
fIValid.SetEmpty();
}
ParamDlg* plCompositeMtl::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
fMtlDlg = TRACKED_NEW plCompositeMtlDlg(hwMtlEdit, imp, this);
return fMtlDlg;
}
void plCompositeMtl::SetParamDlg(ParamDlg *dlg)
{
fMtlDlg = (plCompositeMtlDlg*)dlg;
}
BOOL plCompositeMtl::SetDlgThing(ParamDlg* dlg)
{
if (dlg == fMtlDlg)
{
fMtlDlg->SetThing(this);
return TRUE;
}
return FALSE;
}
Interval plCompositeMtl::Validity(TimeValue t)
{
Interval valid = FOREVER;
/* for (int i = 0; i < fSubTexmap.Count(); i++)
{
if (fSubTexmap[i])
valid &= fSubTexmap[i]->Validity(t);
}
*/
// float u;
// fPBlock->GetValue(pb_spin,t,u,valid);
return valid;
}
// The index for a face on a composite material is really just a bitmask for all the submaterials. This function only
// computes it... The mesh creator will ask it to be created if it's needed.
int plCompositeMtl::ComputeMaterialIndex(float opac[][2], int vertCount)
{
int index = 0;
int i;//, j;
int bitmask = 1;
for (i = NumSubMtls() - 1, bitmask <<= i; i >= 0; i--, bitmask >>= 1)
{
index |= bitmask;
/*
if (i == 0)
index |= bitmask; // it's not opaqued out, so include the base layer
else if (fPassesPB->GetInt(kCompOn, 0, i - 1)) // is the checkbox ticked? (ie, are we using it?)
{
bool transparent = true;
for (j = 0; j < vertCount; j++)
{
if (opac[j][i - 1] != 0.0)
transparent = false;
}
if (transparent)
continue; // totally transparent for this face, skip it
index |= bitmask; // include this material
bool opaque = true;
for (j = 0; j < vertCount; j++)
{
if (opac[j][i - 1] < 1.0)
opaque = false;
}
if (opaque && !((plPassMtlBase *)fPassesPB->GetMtl(kCompPasses, 0, i))->HasAlpha())
break; // This material is totally opaque, no sense including anything underneath it
}
*/
}
return index;
}
int plCompositeMtl::GetBlendStyle(int index)
{
return fPassesPB->GetInt(kCompBlend, 0, index - 1);
}
// Determines whether all materials are only blending on one channel (and possibly its inverse) and therefore
// it's ok to overwrite the vertex alpha exported for the span using this material.
// Returns: -1 if we use multiple sources, otherwise the source we all agree on
int plCompositeMtl::CanWriteAlpha()
{
int blend[3];
blend[0] = ((((plPassMtlBase *)GetSubMtl(0))->GetOutputBlend() == plPassMtlBase::kBlendNone) ? -1 : kCompBlendVertexAlpha);
blend[1] = (fPassesPB->GetInt(kCompOn, 0, 0) ? RemoveInverse(GetBlendStyle(1)) : -1);
blend[2] = (fPassesPB->GetInt(kCompOn, 0, 1) ? RemoveInverse(GetBlendStyle(2)) : -1);
int source = blend[0];
int i;
for (i = 1; i < 3; i++)
{
if (source < 0)
{
source = blend[i];
continue;
}
if (source >= 0 && blend[i] >= 0 && blend[i] != source)
return -1;
}
return source;
}
/*===========================================================================*\
| Subanim & References support
\*===========================================================================*/
int plCompositeMtl::NumSubs()
{
return NumSubMtls();
}
TSTR plCompositeMtl::SubAnimName(int i)
{
return GetSubMtlSlotName(i);
}
Animatable* plCompositeMtl::SubAnim(int i)
{
return GetSubMtl(i);
}
int plCompositeMtl::NumRefs()
{
return 1;
}
RefTargetHandle plCompositeMtl::GetReference(int i)
{
if (i == kRefPasses)
return fPassesPB;
return NULL;
}
void plCompositeMtl::SetReference(int i, RefTargetHandle rtarg)
{
if (i == kRefPasses)
fPassesPB = (IParamBlock2 *)rtarg;
}
int plCompositeMtl::NumParamBlocks()
{
return 1;
}
IParamBlock2 *plCompositeMtl::GetParamBlock(int i)
{
if (i == kRefPasses)
return fPassesPB;
return NULL;
}
IParamBlock2 *plCompositeMtl::GetParamBlockByID(BlockID id)
{
if (fPassesPB->ID() == id)
return fPassesPB;
return NULL;
}
RefResult plCompositeMtl::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message )
{
switch (message)
{
case REFMSG_CHANGE:
fIValid.SetEmpty();
if (hTarget == fPassesPB)
{
ParamID changingParam = fPassesPB->LastNotifyParamID();
fPassesPB->GetDesc()->InvalidateUI(changingParam);
}
break;
}
return REF_SUCCEED;
}
////////////////////////////////////////////////////////////////////////////////
// Subtexmap access
int plCompositeMtl::NumSubMtls()
{
// return fPassesPB->GetInt(kMultCount);
return NSUBMTLS;
}
Mtl *plCompositeMtl::GetSubMtl(int i)
{
if (i < NumSubMtls())
return fPassesPB->GetMtl(kCompPasses, 0, i);
return NULL;
}
void plCompositeMtl::SetSubMtl(int i, Mtl *m)
{
if (i < NumSubMtls())
fPassesPB->SetValue(kCompPasses, 0, m, i);
}
TSTR plCompositeMtl::GetSubMtlSlotName(int i)
{
TSTR str;
str.printf("Pass %d", i+1);
return str;
}
TSTR plCompositeMtl::GetSubMtlTVName(int i)
{
return GetSubMtlSlotName(i);
}
/*===========================================================================*\
| Standard IO
\*===========================================================================*/
#define MTL_HDR_CHUNK 0x4000
IOResult plCompositeMtl::Save(ISave *isave)
{
IOResult res;
isave->BeginChunk(MTL_HDR_CHUNK);
res = MtlBase::Save(isave);
if (res!=IO_OK) return res;
isave->EndChunk();
return IO_OK;
}
IOResult plCompositeMtl::Load(ILoad *iload)
{
IOResult res;
int id;
while (IO_OK==(res=iload->OpenChunk()))
{
switch(id = iload->CurChunkID())
{
case MTL_HDR_CHUNK:
res = MtlBase::Load(iload);
break;
}
iload->CloseChunk();
if (res!=IO_OK)
return res;
}
return IO_OK;
}
/*===========================================================================*\
| Updating and cloning
\*===========================================================================*/
RefTargetHandle plCompositeMtl::Clone(RemapDir &remap)
{
plCompositeMtl *mnew = TRACKED_NEW plCompositeMtl(FALSE);
*((MtlBase*)mnew) = *((MtlBase*)this);
mnew->ReplaceReference(kRefPasses, remap.CloneRef(fPassesPB));
mnew->fIValid.SetEmpty();
BaseClone(this, mnew, remap);
return (RefTargetHandle)mnew;
}
void plCompositeMtl::NotifyChanged()
{
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
}
void plCompositeMtl::Update(TimeValue t, Interval& valid)
{
if (!fIValid.InInterval(t))
{
fIValid.SetInfinite();
// fPassesPB->GetValue(kMtlLayLayer1On, t, fMapOn[0], fIValid);
for (int i = 0; i < NumSubMtls(); i++)
{
if (GetSubMtl(i))
GetSubMtl(i)->Update(t, fIValid);
}
}
valid &= fIValid;
}
/*===========================================================================*\
| Determine the characteristics of the material
\*===========================================================================*/
void plCompositeMtl::SetAmbient(Color c, TimeValue t) {}
void plCompositeMtl::SetDiffuse(Color c, TimeValue t) {}
void plCompositeMtl::SetSpecular(Color c, TimeValue t) {}
void plCompositeMtl::SetShininess(float v, TimeValue t) {}
Color plCompositeMtl::GetAmbient(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plCompositeMtl::GetDiffuse(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plCompositeMtl::GetSpecular(int mtlNum, BOOL backFace) { return Color(0,0,0); }
float plCompositeMtl::GetXParency(int mtlNum, BOOL backFace) { return 0.0f; }
float plCompositeMtl::GetShininess(int mtlNum, BOOL backFace) { return 0.0f; }
float plCompositeMtl::GetShinStr(int mtlNum, BOOL backFace) { return 0.0f; }
float plCompositeMtl::WireSize(int mtlNum, BOOL backFace) { return 0.0f; }
/*===========================================================================*\
| Actual shading takes place
\*===========================================================================*/
void plCompositeMtl::Shade(ShadeContext& sc)
{
// Get the background color
Color backColor, backTrans;
//sc.GetBGColor(backColor, backTrans);
backColor.Black();
backTrans.White();
Point3 vtxIllum, vtxAlpha;
plPassMtl::GetInterpVtxValue(MAP_ALPHA, sc, vtxAlpha);
plPassMtl::GetInterpVtxValue(MAP_SHADING, sc, vtxIllum);
int count = NumSubMtls();
for (int i = 0; i < count; i++)
{
if (i > 0 && fPassesPB->GetInt(kCompOn, 0, i - 1) == 0) // Material is unchecked, skip it.
continue;
Mtl *mtl = GetSubMtl(i);
if (mtl == NULL || mtl->ClassID() != PASS_MTL_CLASS_ID)
continue;
float opacity;
if (i == 0)
{
opacity = 1.0f;
}
else
{
int blendMethod = fPassesPB->GetInt(kCompBlend, 0, i - 1);
switch(blendMethod)
{
case kCompBlendVertexAlpha:
case kCompBlendInverseVtxAlpha:
opacity = vtxAlpha.x;
break;
case kCompBlendVertexIllumRed:
case kCompBlendInverseVtxIllumRed:
opacity = vtxIllum.x;
break;
case kCompBlendVertexIllumGreen:
case kCompBlendInverseVtxIllumGreen:
opacity = vtxIllum.y;
break;
case kCompBlendVertexIllumBlue:
case kCompBlendInverseVtxIllumBlue:
opacity = vtxIllum.z;
break;
default:
opacity = 1.0f;
break;
}
if (IsInverseBlend(blendMethod))
opacity = 1 - opacity;
}
plPassMtl *passMtl = (plPassMtl*)mtl;
passMtl->ShadeWithBackground(sc, backColor, false); // Don't include the vtx alpha, that's OUR job
float currTrans = (1 - (1 - sc.out.t.r) * opacity);
backTrans *= currTrans;
backColor = backColor * currTrans + sc.out.c * opacity;
}
sc.out.t = backTrans;
sc.out.c = backColor;
}
float plCompositeMtl::EvalDisplacement(ShadeContext& sc)
{
return 0.0f;
}
Interval plCompositeMtl::DisplacementValidity(TimeValue t)
{
Interval iv;
iv.SetInfinite();
return iv;
}
/*
void plCompositeMtl::SetNumSubMtls(int num)
{
TimeValue t = GetCOREInterface()->GetTime();
int curNum = fPassesPB->GetInt(kMultCount);
fPassesPB->SetValue(kMultCount, 0, num);
fPassesPB->SetCount(kMultPasses, num);
fPassesPB->SetCount(kMultOn, num);
for (int i = curNum; i < num; i++)
{
plPassMtl *newMtl = TRACKED_NEW plPassMtl(false);
fPassesPB->SetValue(kMultPasses, t, newMtl, i);
fPassesPB->SetValue(kMultOn, t, TRUE, i);
GetCOREInterface()->AssignNewName(fPassesPB->GetMtl(kMultPasses, t, i));
}
}
*/
void plCompositeMtl::SetOpacityVal(float *target, UVVert *alpha, UVVert *illum, int method)
{
if (method == kCompBlendVertexAlpha || method == kCompBlendInverseVtxAlpha)
{
if (alpha == NULL)
*target = 1.0f;
else
*target = alpha->x;
}
else if (method == kCompBlendVertexIllumRed || method == kCompBlendInverseVtxIllumRed)
{
if (illum == NULL)
*target = 1.0f;
else
*target = illum->x;
}
else if (method == kCompBlendVertexIllumGreen || method == kCompBlendInverseVtxIllumGreen)
{
if (illum == NULL)
*target = 1.0f;
else
*target = illum->y;
}
else if (method == kCompBlendVertexIllumBlue || method == kCompBlendInverseVtxIllumBlue)
{
if (illum == NULL)
*target = 1.0f;
else
*target = illum->z;
}
else
{
*target = 1.0f;
}
if (method == kCompBlendInverseVtxAlpha ||
method == kCompBlendInverseVtxIllumRed ||
method == kCompBlendInverseVtxIllumGreen ||
method == kCompBlendInverseVtxIllumBlue)
{
*target = 1.0f - *target;
}
}
/*
int plCompositeMtl::UVChannelsNeeded(bool makeAlphaLayer)
{
if (makeAlphaLayer)
return 1;
// Otherwise, we do have vertex alpha... can we get by without taking up a UV channel?
int channels = 0;
int i;
for (i = 0; i < NumSubMtls() - 1; i++)
{
if (!fPassesPB->GetInt(kCompOn, 0, i))
continue; // The material is unchecked, no need to see if it needs a channel
int method = fPassesPB->GetInt(kCompBlend, 0, i);
if (!(method == kCompBlendVertexAlpha || method1 == kCompBlendInverseVtxAlpha))
{
channels = 1;
break;
}
}
return channels;
}
*/

View File

@ -0,0 +1,170 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef __PLCOMPMTL__H
#define __PLCOMPMTL__H
#include "Max.h"
#include "../resource.h"
#include "istdplug.h"
#include "iparamb2.h"
#include "iparamm2.h"
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
#define COMP_MTL_CLASS_ID Class_ID(0x237c422d, 0x64ab6371)
class plCompositeMtlDlg;
class plCompositeMtl : public Mtl
{
protected:
IParamBlock2 *fPassesPB;
Interval fIValid;
plCompositeMtlDlg *fMtlDlg;
public:
enum
{
kCompPasses,
kCompOn,
kCompBlend,
kCompUVChannels,
kCompLayerCounts
};
// Make sure to pair up each blend mode with an inverse after it
// (This way we check for an inverse blend by doing an odd/even check.)
enum BlendMethod // These should match up in order with the blend strings
{
kCompBlendVertexAlpha,
kCompBlendInverseVtxAlpha,
kCompBlendVertexIllumRed,
kCompBlendInverseVtxIllumRed,
kCompBlendVertexIllumGreen,
kCompBlendInverseVtxIllumGreen,
kCompBlendVertexIllumBlue,
kCompBlendInverseVtxIllumBlue,
kCompNumBlendMethods
};
static const char *BlendStrings[];
enum { kRefPasses };
enum { kBlkPasses };
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void Reset();
void NotifyChanged();
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
// Shade and displacement calculation
void Shade(ShadeContext& sc);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
// SubTexmap access methods
int NumSubMtls();
Mtl* GetSubMtl(int i);
void SetSubMtl(int i, Mtl *m);
TSTR GetSubMtlSlotName(int i);
TSTR GetSubMtlTVName(int i);
BOOL SetDlgThing(ParamDlg* dlg);
plCompositeMtl(BOOL loading);
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
//From Animatable
Class_ID ClassID() { return COMP_MTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_COMP_MTL); }
RefTargetHandle Clone(RemapDir &remap);
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
void DeleteThis() { delete this; }
void SetParamDlg(ParamDlg *dlg);
int ComputeMaterialIndex(float opac[][2], int vertCount);
int GetBlendStyle(int index);
int CanWriteAlpha();
bool IsInverseBlend(int blend) const { return blend & 1; }
int RemoveInverse(int blend) { return blend - (blend & 1); }
//void SetNumSubMtls(int num);
void SetOpacityVal(float *pt, UVVert *alphas, UVVert *illums, int method);
//DllExport int UVChannelsNeeded(bool makeAlphaLayer);
};
#endif // __PLCOMPMTL__H

View File

@ -0,0 +1,293 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "max.h"
#include "MaxIcon.h"
#include "resource.h"
#include "plCompositeMtl.h"
//#include "plCompositeMtlPB.h"
//#include "plMaxLayer.h"
#include "plCompositeMtlDlg.h"
struct LayerID
{
int layerID;
int activeID;
int blendID;
};
static LayerID kLayerID[] =
{
{ IDC_TEX1, 0, 0 },
{ IDC_TEX2, IDC_TEXON2, IDC_COMBO2 },
{ IDC_TEX3, IDC_TEXON3, IDC_COMBO3 }
};
//-----------------------------------------------------------------------------
// Constructor and destructor
//-----------------------------------------------------------------------------
plCompositeMtlDlg::plCompositeMtlDlg(HWND hwMtlEdit, IMtlParams *imp, plCompositeMtl *m)
{
fDADMgr.Init(this);
fhMtlEdit = hwMtlEdit;
fhRollup = NULL;
fMtl = m;
fPBlock = fMtl->GetParamBlockByID(plCompositeMtl::kBlkPasses);
ip = imp;
valid = FALSE;
for (int i = 0; i < NSUBMTLS; i++)
fLayerBtns[i] = NULL;
curTime = imp->GetTime();
fhRollup = ip->AddRollupPage(
hInstance,
MAKEINTRESOURCE(IDD_COMPOSITE),
ForwardProc,
"Composite Parameters",
(LPARAM)this);
}
plCompositeMtlDlg::~plCompositeMtlDlg()
{
fMtl->SetParamDlg(NULL);
for (int i = 0; i < NSUBMTLS; i++)
{
ReleaseICustButton(fLayerBtns[i]);
fLayerBtns[i] = NULL;
}
SetWindowLong(fhRollup, GWL_USERDATA, NULL);
ip->DeleteRollupPage(fhRollup);
fhRollup = NULL;
}
//-----------------------------------------------------------------------------
// Functions inheirited from ParamDlg
//-----------------------------------------------------------------------------
void plCompositeMtlDlg::SetThing(ReferenceTarget *m)
{
assert(m->SuperClassID() == MATERIAL_CLASS_ID);
assert(m->ClassID() == COMP_MTL_CLASS_ID);
// Bad?
if (fMtl)
fMtl->SetParamDlg(NULL);
fMtl = (plCompositeMtl *)m;
if (fMtl)
fMtl->SetParamDlg(this);
LoadDialog();
IUpdateMtlDisplay();
}
void plCompositeMtlDlg::SetTime(TimeValue t)
{
if (t != curTime)
{
curTime = t;
Interval v;
fMtl->Update(ip->GetTime(),v);
LoadDialog();
IUpdateMtlDisplay();
}
}
void plCompositeMtlDlg::ReloadDialog()
{
Interval v;
fMtl->Update(ip->GetTime(), v);
LoadDialog();
}
void plCompositeMtlDlg::ActivateDlg(BOOL onOff)
{
}
int plCompositeMtlDlg::FindSubMtlFromHWND(HWND hwnd)
{
for (int i = 0; i < NSUBMTLS; i++)
{
if (hwnd == fLayerBtns[i]->GetHwnd())
return i;
}
return -1;
}
BOOL plCompositeMtlDlg::ForwardProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
plCompositeMtlDlg *theDlg;
if (msg == WM_INITDIALOG)
{
theDlg = (plCompositeMtlDlg*)lParam;
theDlg->fhRollup = hDlg;
SetWindowLong(hDlg, GWL_USERDATA, lParam);
}
else
{
if ((theDlg = (plCompositeMtlDlg *)GetWindowLong(hDlg, GWL_USERDATA)) == NULL)
return FALSE;
}
return theDlg->LayerPanelProc(hDlg,msg,wParam,lParam);
}
//----------------------------------------------------------------------------
// Layer panel processor
//----------------------------------------------------------------------------
BOOL plCompositeMtlDlg::LayerPanelProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
int id = LOWORD(wParam);
int code = HIWORD(wParam);
int i;
switch (msg)
{
case WM_INITDIALOG:
{
for (i = 0; i < NSUBMTLS; i++)
{
fLayerBtns[i] = GetICustButton(GetDlgItem(hDlg, kLayerID[i].layerID));
fLayerBtns[i]->SetDADMgr(&fDADMgr);
if (i > 0) // the first material doesn't get one, nyah nyah!
{
HWND cbox = NULL;
int j;
for (j = 0; j < plCompositeMtl::kCompNumBlendMethods; j++)
{
cbox = GetDlgItem(hDlg, kLayerID[i].blendID);
SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)plCompositeMtl::BlendStrings[j]);
}
SendMessage(cbox, CB_SETCURSEL, 0, 0);
}
}
// TEMP testing
UpdateLayerDisplay();
IUpdateMtlDisplay();
}
return TRUE;
case WM_DESTROY:
for (i = 0; i < NSUBMTLS; i++)
{
ReleaseICustButton(fLayerBtns[i]);
fLayerBtns[i] = NULL;
}
break;
case WM_COMMAND:
{
for (i = 0; i < NSUBMTLS; i++)
{
if (id == kLayerID[i].activeID)
{
bool checked = SendMessage(GetDlgItem(hDlg, id), BM_GETCHECK, 0, 0) == BST_CHECKED;
fPBlock->SetValue(plCompositeMtl::kCompOn, curTime, checked, i - 1);
return TRUE;
}
if (id == kLayerID[i].layerID)
{
PostMessage(fhMtlEdit, WM_SUB_MTL_BUTTON, i, (LPARAM)fMtl);
return TRUE;
}
if (id == kLayerID[i].blendID)
{
fPBlock->SetValue(plCompositeMtl::kCompBlend, curTime, SendMessage(GetDlgItem(hDlg, id), CB_GETCURSEL, 0, 0), i - 1);
return TRUE;
}
}
}
// IUpdateMtlDisplay();
break;
}
return FALSE;
}
void plCompositeMtlDlg::UpdateLayerDisplay()
{
int i;
for (i = 0; i < NSUBMTLS; i++)
{
Mtl *m = fPBlock->GetMtl(plCompositeMtl::kCompPasses, curTime, i);
TSTR nm;
if (m)
nm = m->GetName();
else
nm = "None";
fLayerBtns[i]->SetText(nm.data());
ShowWindow(GetDlgItem(fhRollup, kLayerID[i].layerID), SW_SHOW);
ShowWindow(GetDlgItem(fhRollup, kLayerID[i].activeID), SW_SHOW);
if (i > 0)
{
int check = (fPBlock->GetInt(plCompositeMtl::kCompOn, curTime, i - 1) == 0 ? BST_UNCHECKED : BST_CHECKED);
SendMessage(GetDlgItem(fhRollup, kLayerID[i].activeID), BM_SETCHECK, (WPARAM)check, 0);
int selection = fPBlock->GetInt(plCompositeMtl::kCompBlend, curTime, i - 1);
SendMessage(GetDlgItem(fhRollup, kLayerID[i].blendID), CB_SETCURSEL, (WPARAM)selection, 0);
}
}
}
void plCompositeMtlDlg::LoadDialog()
{
if (fMtl)
{
fPBlock = fMtl->GetParamBlockByID(plCompositeMtl::kBlkPasses);
if (fhRollup)
UpdateLayerDisplay();
}
}

View File

@ -0,0 +1,102 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_COMPMTLDLG_H
#define PL_COMPMTLDLG_H
#define NSUBMTLS 3
class plCompositeMtlDlg : public ParamDlg
{
protected:
IParamBlock2 *fPBlock;
HWND fhMtlEdit; // Window handle of the materials editor dialog
HWND fhRollup; // Our rollup panel
IMtlParams *ip;
plCompositeMtl *fMtl; // current mtl being edited.
TimeValue curTime;
int isActive;
BOOL valid;
// int offset;
ICustButton *fLayerBtns[NSUBMTLS];
MtlDADMgr fDADMgr; // For drag-drop sub-materials
public:
// Constructor and destructor
plCompositeMtlDlg(HWND hwMtlEdit, IMtlParams *imp, plCompositeMtl *m);
~plCompositeMtlDlg();
// Functions inherited from ParamDLg:
Class_ID ClassID() { return COMP_MTL_CLASS_ID; }
void SetThing(ReferenceTarget *m);
ReferenceTarget* GetThing() { return (ReferenceTarget*)fMtl; }
void SetTime(TimeValue t);
void ReloadDialog();
void ActivateDlg(BOOL onOff);
void DeleteThis() { delete this; }
int FindSubMtlFromHWND(HWND hw);
static BOOL CALLBACK ForwardProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL LayerPanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
void UpdateLayerDisplay();
void LoadDialog();
/*
// Lower-level crap
void Invalidate(); // Called by ParamMtl
BOOL IsActive() { return isActive; }
private:
void ClampOffset();
void SetNumMats();
void UpdateLayers();
void UpdateControlFor(int np);
void VScroll(int code, short int cpos );
*/
protected:
void IUpdateMtlDisplay() { if (ip) ip->MtlChanged(); }
};
#endif

View File

@ -0,0 +1,81 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_COMPOSITE_MTL_PB_H
#define PL_COMPOSITE_MTL_PB_H
enum
{
kCompPasses,
kCompOn,
kCompBlend,
kCompUVChannels,
kCompLayerCounts
};
// Make sure to pair up each blend mode with an inverse after it
// (This way we check for an inverse blend by doing an odd/even check.)
enum BlendMethod // These should match up in order with the blend strings
{
kCompBlendVertexAlpha,
kCompBlendInverseVtxAlpha,
kCompBlendVertexIllumRed,
kCompBlendInverseVtxIllumRed,
kCompBlendVertexIllumGreen,
kCompBlendInverseVtxIllumGreen,
kCompBlendVertexIllumBlue,
kCompBlendInverseVtxIllumBlue,
kCompNumBlendMethods
};
static char *BlendStrings[] = // Make sure these match up in order with the Blend enum
{
"Vertex Alpha",
"Inverse Vtx Alpha",
"Vertex Illum Red",
"Inv. Vtx Illum Red",
"Vertex Illum Green",
"Inv. Vtx Illum Green",
"Vertex Illum Blue",
"Inv. Vtx Illum Blue"
};
#endif //PL_COMPOSITE_MTL_PB_H

View File

@ -0,0 +1,67 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plCompositeMtl.h"
//#include "plCompositeMtlPB.h"
ClassDesc2* GetCompMtlDesc();
static ParamBlockDesc2 gCompositeMtlPB
(
plCompositeMtl::kBlkPasses, _T("composite"), 0, GetCompMtlDesc(),
P_AUTO_CONSTRUCT, plCompositeMtl::kRefPasses,
plCompositeMtl::kCompPasses, _T("passes"), TYPE_MTL_TAB, 3, 0, 0,
end,
plCompositeMtl::kCompOn, _T("passOn"), TYPE_BOOL_TAB, 2, 0, 0,
p_default, TRUE,
end,
plCompositeMtl::kCompBlend, _T("BlendMethod"), TYPE_INT_TAB, 2, 0, 0,
p_default, 0,
end,
plCompositeMtl::kCompUVChannels, _T("UVChannels"), TYPE_INT_TAB, 2, 0, 0,
p_default, 0,
end,
plCompositeMtl::kCompLayerCounts, _T("LayerCounts"), TYPE_INT_TAB, 3, 0, 0,
p_default, 0,
end,
end
);

View File

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

View File

@ -0,0 +1,209 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_DECALMTL_H
#define PL_DECALMTL_H
#include "Max.h"
#include "iparamb2.h"
#include "../resource.h"
#include "plPassMtlBase.h"
#define DECAL_MTL_CLASS_ID Class_ID(0x691d2257, 0x419d629e)
extern TCHAR *GetString(int id);
class plDecalMtl : public plPassMtlBase
{
protected:
virtual void ICloneRefs( plPassMtlBase *target, RemapDir &remap );
public:
enum
{
kRefBasic,
kRefLayers,
kRefAdv,
kRefAnim,
};
enum Blocks
{
kBlkBasic,
kBlkLayers,
kBlkAdv,
kBlkAnim,
};
plDecalMtl(BOOL loading);
void DeleteThis() { delete this; }
//From Animatable
Class_ID ClassID() { return DECAL_MTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_DECAL_MTL); }
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void NotifyChanged();
BOOL SupportsMultiMapsInViewport() { return FALSE; }
void SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb);
// Shade and displacement calculation
void Shade(ShadeContext& sc);
void ShadeWithBackground(ShadeContext &sc, Color background);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
virtual RefTargetHandle GetReference( int i );
virtual void SetReference( int i, RefTargetHandle rtarg );
// SubTexmap access methods
int NumSubTexmaps();
Texmap* GetSubTexmap(int i);
void SetSubTexmap(int i, Texmap *m);
TSTR GetSubTexmapSlotName(int i);
TSTR GetSubTexmapTVName(int i);
int SubTexmapOn(int i);
BOOL SetDlgThing(ParamDlg* dlg);
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
// void SetParamDlg(ParamDlg *dlg);
// void SetNumSubTexmaps(int num);
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
ULONG Requirements( int subMtlNum );
virtual bool HasAlpha();
// Massive list of inherited accessor functions for ParamBlock data
// Advanced Block
virtual int GetBasicWire();
virtual int GetMeshOutlines();
virtual int GetTwoSided();
virtual int GetSoftShadow();
virtual int GetNoProj();
virtual int GetVertexShade();
virtual int GetNoShade();
virtual int GetNoFog();
virtual int GetWhite();
virtual int GetZOnly();
virtual int GetZClear();
virtual int GetZNoRead();
virtual int GetZNoWrite();
virtual int GetZInc();
virtual int GetAlphaTestHigh();
// Animation block
virtual char * GetAnimName();
virtual int GetAutoStart();
virtual int GetLoop();
virtual char * GetAnimLoopName();
virtual int GetEaseInType();
virtual float GetEaseInMinLength();
virtual float GetEaseInMaxLength();
virtual float GetEaseInNormLength();
virtual int GetEaseOutType();
virtual float GetEaseOutMinLength();
virtual float GetEaseOutMaxLength();
virtual float GetEaseOutNormLength();
virtual int GetUseGlobal();
virtual char * GetGlobalVarName();
// Basic block
virtual int GetColorLock();
virtual Color GetAmbColor();
virtual Color GetColor();
virtual int GetOpacity();
virtual int GetEmissive();
virtual int GetUseSpec();
virtual int GetShine();
virtual Color GetSpecularColor();
virtual Control *GetPreshadeColorController();
virtual Control *GetAmbColorController();
virtual Control *GetOpacityController();
virtual Control *GetSpecularColorController();
virtual int GetDiffuseColorLock();
virtual Color GetRuntimeColor();
virtual Control *GetRuntimeColorController();
// Layer block
virtual Texmap *GetBaseLayer();
virtual int GetTopLayerOn();
virtual Texmap *GetTopLayer();
virtual int GetLayerBlend();
virtual int GetOutputAlpha();
virtual int GetOutputBlend();
};
#endif //PL_DECALMTL_H

View File

@ -0,0 +1,83 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_DECALMTLADVPB_H
#define PL_DECALMTLADVPB_H
// Param ID's
enum
{
// Specular
kDecalAdvUseSpec, // Not used anymore, feel free to replace with new fields as necessary
kDecalAdvSpecType, // ditto
kDecalAdvShine, // ...
kDecalAdvShineStr, // ...
// Misc
kDecalAdvWire,
kDecalAdvMeshOutlines,
kDecalAdvTwoSided,
// Shading
kDecalAdvSoftShadow,
kDecalAdvNoProj,
kDecalAdvVertexShade,
kDecalAdvNoShade,
kDecalAdvNoFog,
kDecalAdvWhite,
// Z
kDecalAdvZOnly,
kDecalAdvZClear,
kDecalAdvZNoRead,
kDecalAdvZNoWrite,
kDecalAdvZInc,
};
// Specular types
enum
{
kSpecTypeAlpha,
kSpecTypeColor,
kSpecTypeHighlight
};
#endif //PL_DECALMTLADVPB_H

View File

@ -0,0 +1,111 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plDecalMtl.h"
#include "plPassBaseParamIDs.h"
using namespace plPassBaseParamIDs;
static ParamBlockDesc2 gDecalAdvPB
(
plDecalMtl::kBlkAdv, _T("advanced"), IDS_PASS_ADV, GetDecalMtlDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI, plDecalMtl::kRefAdv,
// UI
IDD_PASS_ADV, IDS_PASS_ADV, 0, APPENDROLL_CLOSED, NULL,
// Misc Properties
kPBAdvWire, _T("basicWire"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_MISC_WIRE,
end,
kPBAdvMeshOutlines, _T("meshOutlines"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_MISC_MESHOUTLINES,
end,
kPBAdvTwoSided, _T("twoSided"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_MISC_TWOSIDED,
end,
// Shade properties
kPBAdvSoftShadow, _T("softShadow"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_SOFTSHADOW,
end,
kPBAdvNoProj, _T("noProj"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_NO_PROJ,
end,
kPBAdvVertexShade, _T("vertexShade"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_VERTEXSHADE,
end,
kPBAdvNoShade, _T("noShade"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_NOSHADE,
end,
kPBAdvNoFog, _T("noFog"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_NO_FOG,
end,
kPBAdvWhite, _T("white"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_WHITE,
end,
// Z Properties
kPBAdvZOnly, _T("zOnly"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZONLY,
end,
kPBAdvZClear, _T("zClear"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZCLEAR,
end,
kPBAdvZNoRead, _T("zNoRead"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZNOREAD,
end,
kPBAdvZNoWrite, _T("zNoWrite"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZNOWRITE,
p_default, TRUE,
end,
kPBAdvZInc, _T("zInc"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_INC,
p_default, TRUE,
end,
kPBAdvAlphaTestHigh, _T("aTestHigh"), TYPE_BOOL, 0, 0,
p_default, FALSE,
end,
end
);
ParamBlockDesc2 *GetDecalAdvPB() { return &gDecalAdvPB; }

View File

@ -0,0 +1,63 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_DECALMTLANIMPB_H
#define PL_DECALMTLANIMPB_H
enum
{
kDecalAnimName,
kDecalAnimAutoStart,
kDecalAnimLoop,
kDecalAnimLoopName,
kDecalEaseInType, // Not used, but reserved
kDecalEaseOutType, //
kDecalEaseInLength, //
kDecalEaseOutLength, //
kDecalEaseInMin, //
kDecalEaseInMax, //
kDecalEaseOutMin, //
kDecalEaseOutMax, //
kDecalAnimUseGlobal, //
kDecalAnimGlobalName, //
};
#endif

View File

@ -0,0 +1,109 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plDecalMtl.h"
#include "plPassBaseParamIDs.h"
#include "resource.h"
#include "iparamm2.h"
#include "plPassAnimDlgProc.h"
#include "plAnimStealthNode.h"
using namespace plPassBaseParamIDs;
static ParamBlockDesc2 gDecalAnimPB
(
plDecalMtl::kBlkAnim, _T("anim"), IDS_PASS_ANIM, GetDecalMtlDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI + P_CALLSETS_ON_LOAD, plDecalMtl::kRefAnim,
// UI
IDD_PASS_ANIM, IDS_PASS_ANIM, 0, 0, &plPassAnimDlgProc::Get(),
#ifdef MCN_UPGRADE_OLD_ANIM_BLOCKS
// THE FOLLOWING ARE ALL OLD PARAMETERS AND SHOULD NO LONGER BE USED. The only reason
// they're here is so we can convert old paramBlocks into the new plAnimStealthNode format
kPBAnimName, _T("animName"), TYPE_STRING, 0, 0,
end,
kPBAnimAutoStart, _T("autoStart"), TYPE_BOOL, 0, 0,
end,
kPBAnimLoop, _T("loop"), TYPE_BOOL, 0, 0,
end,
kPBAnimLoopName, _T("loopName"), TYPE_STRING, 0, 0,
end,
// Anim Ease
kPBAnimEaseInType, _T("easeInType"), TYPE_INT, 0, 0,
end,
kPBAnimEaseInLength, _T("easeInLength"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseInMin, _T("easeInMin"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseInMax, _T("easeInMax"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutType, _T("easeOutType"), TYPE_INT, 0, 0,
end,
kPBAnimEaseOutLength, _T("easeOutLength"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutMin, _T("easeOutMin"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutMax, _T("easeOutMax"), TYPE_FLOAT, 0, 0,
end,
#endif // MCN_UPGRADE_OLD_ANIM_BLOCKS
kPBAnimUseGlobal, _T("UseGlobal"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_MTL_USE_GLOBAL,
end,
kPBAnimGlobalName, _T("GlobalName"), TYPE_STRING, 0, 0,
p_default, _T(""),
end,
kPBAnimStealthNodes, _T( "testing" ), TYPE_REFTARG_TAB, 0, 0, 0,
p_accessor, &plStealthNodeAccessor::GetInstance(),
end,
end
);
ParamBlockDesc2 *GetDecalAnimPB() { return &gDecalAnimPB; }

View File

@ -0,0 +1,68 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_DECALMTLBASICPB_H
#define PL_DECALMTLBASICPB_H
// Param ID's
enum
{
kDecalBasColorLock,
kDecalBasColorAmb,
kDecalBasColor,
kDecalBasOpacity,
kDecalBasEmissive,
// Specular
kDecalBasUseSpec,
kDecalBasShine,
kDecalBasShineStr,
// New color stuff
kDecalBasDiffuseLock,
kDecalBasRunColor,
kDecalBasSpecColor
};
#endif //PL_DECALMTLBASICPB_H

View File

@ -0,0 +1,252 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plDecalMtl.h"
#include "plDecalMtlBasicPB.h"
#include "resource.h"
#include "iparamm2.h"
class DecalBasicPBAccessor;
extern DecalBasicPBAccessor basicAccessor;
class DecalBasicDlgProc;
extern DecalBasicDlgProc gDecalBasicDlgProc;
static ParamBlockDesc2 gDecalBasicPB
(
plDecalMtl::kBlkBasic, _T("basic"), IDS_PASS_BASIC, GetDecalMtlDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI, plDecalMtl::kRefBasic,
// UI
IDD_PASS_BASIC, IDS_PASS_BASIC, 0, 0, &gDecalBasicDlgProc,
// Color
kDecalBasColorLock, _T("colorLock"), TYPE_BOOL, 0, 0,
p_ui, TYPE_CHECKBUTTON, IDC_LOCK_AD,
p_accessor, &basicAccessor,
end,
kDecalBasColorAmb, _T("ambColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_AMB,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_COLOR_AMB,
p_accessor, &basicAccessor,
end,
kDecalBasColor, _T("color"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_COLOR,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_COLOR,
p_default, Color(1,1,1),
p_accessor, &basicAccessor,
end,
kDecalBasRunColor, _T("runtimeColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_RUNCOLOR,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_RUNCOLOR,
p_default, Color(1,1,1),
p_accessor, &basicAccessor,
end,
kDecalBasDiffuseLock, _T("diffuseLock"), TYPE_BOOL, 0, 0,
p_ui, TYPE_CHECKBUTTON, IDC_LOCK_COLORS,
p_accessor, &basicAccessor,
p_default, TRUE,
end,
// Opacity
kDecalBasOpacity, _T("opacity"), TYPE_INT, P_ANIMATABLE, IDS_BASIC_OPAC,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_TR_EDIT, IDC_TR_SPIN, 0.4,
p_range, 0, 100,
p_default, 100,
end,
kDecalBasEmissive, _T("emissive"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_LAYER_EMISSIVE_CB,
end,
// Specularity
kDecalBasUseSpec, _T("useSpec"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_SPECULAR,
p_enable_ctrls, 2, kDecalBasShine, kDecalBasShineStr,
end,
kDecalBasShine, _T("shine"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_SH_EDIT, IDC_SH_SPIN, 0.4,
p_range, 0, 100,
end,
kDecalBasSpecColor, _T("specularColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_SPECCOLOR,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_SPECCOLOR,
p_default, Color(0,0,0),
end,
// OBSOLETE--here so we can upgrade it to color if necessary
kDecalBasShineStr, _T("shineStr"), TYPE_INT, 0, 0,
p_range, -1, 100,
p_default, -1,
end,
end
);
ParamBlockDesc2 *GetDecalBasicPB() { return &gDecalBasicPB; }
class DecalBasicPBAccessor : public PBAccessor
{
bool fColorLocked;
public:
DecalBasicPBAccessor() : fColorLocked( false ) {}
void Set(PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
plDecalMtl* mtl = (plDecalMtl*)owner;
IParamBlock2 *pb = mtl->GetParamBlockByID(plDecalMtl::kBlkBasic);
switch (id)
{
case kDecalBasColorLock:
if (val.i)
pb->SetValue(kDecalBasColor, t, pb->GetColor(kDecalBasColorAmb, t));
break;
case kDecalBasDiffuseLock:
if (val.i)
pb->SetValue(kDecalBasRunColor, t, pb->GetColor(kDecalBasColor, t));
break;
case kDecalBasColor:
case kDecalBasColorAmb:
case kDecalBasRunColor:
ISyncLockedColors( id, pb, val, t );
break;
}
}
void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid)
{
}
void ISyncLockedColors( ParamID settingID, IParamBlock2 *pb, PB2Value &val, TimeValue t )
{
int i, numToSet = 0;
ParamID toSet[ 2 ];
if( fColorLocked )
return;
fColorLocked = true;
if( settingID == kDecalBasColorAmb && pb->GetInt( kDecalBasColorLock, t ) )
{
toSet[ numToSet++ ] = kDecalBasColor;
if( pb->GetInt( kDecalBasDiffuseLock, t ) )
toSet[ numToSet++ ] = kDecalBasRunColor;
}
else if( settingID == kDecalBasRunColor && pb->GetInt( kDecalBasDiffuseLock, t ) )
{
toSet[ numToSet++ ] = kDecalBasColor;
if( pb->GetInt( kDecalBasColorLock, t ) )
toSet[ numToSet++ ] = kDecalBasColorAmb;
}
else if( settingID == kDecalBasColor )
{
if( pb->GetInt( kDecalBasColorLock, t ) )
toSet[ numToSet++ ] = kDecalBasColorAmb;
if( pb->GetInt( kDecalBasDiffuseLock, t ) )
toSet[ numToSet++ ] = kDecalBasRunColor;
}
for( i = 0; i < numToSet; i++ )
{
pb->SetValue( toSet[ i ], t, *val.p );
pb->GetMap()->Invalidate( toSet[ i ] );
}
fColorLocked = false;
}
};
static DecalBasicPBAccessor basicAccessor;
class DecalBasicDlgProc : public ParamMap2UserDlgProc
{
#if 1
protected:
HIMAGELIST hLockButtons;
void LoadLockButtons()
{
static bool loaded = false;
if (loaded)
return;
loaded = true;
HINSTANCE hInst = hInstance;
hLockButtons = ImageList_Create(16, 15, TRUE, 2, 0);
HBITMAP hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BUTTONS));
HBITMAP hMask = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_MASKBUTTONS));
ImageList_Add(hLockButtons, hBitmap, hMask);
DeleteObject(hBitmap);
DeleteObject(hMask);
}
void ISetLock(HWND hButton)
{
LoadLockButtons();
ICustButton *iBut = GetICustButton(hButton);
iBut->SetImage(hLockButtons,0,1,0,1,16,15);
iBut->SetType(CBT_CHECK);
ReleaseICustButton(iBut);
}
public:
DecalBasicDlgProc() : hLockButtons(NULL) {}
~DecalBasicDlgProc() { if (hLockButtons) ImageList_Destroy(hLockButtons); }
#endif
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
IParamBlock2 *pb = map->GetParamBlock();
switch (msg)
{
case WM_INITDIALOG:
{
ISetLock(GetDlgItem(hWnd, IDC_LOCK_AD));
ISetLock(GetDlgItem(hWnd, IDC_LOCK_COLORS));
}
return TRUE;
}
return FALSE;
}
void DeleteThis() {}
};
static DecalBasicDlgProc gDecalBasicDlgProc;

View File

@ -0,0 +1,56 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_DECALMTLLAYERSPB_H
#define PL_DECALMTLLAYERSPB_H
enum
{
// Layers
kDecalLayBase,
kDecalLayOutputBlend,
kDecalLayTopOn,
kDecalLayTop,
kDecalLayBlend,
kDecalLayOutputAlpha,
};
#endif //PL_DECALMTLLAYERSPB_H

View File

@ -0,0 +1,103 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plDecalMtl.h"
#include "plDecalMtlLayersPB.h"
#include "resource.h"
#include "iparamm2.h"
#include "Layers/plLayerTex.h"
class DecalMtlLayersAccessor;
extern DecalMtlLayersAccessor gLayersAccessor;
class LayersDlgProc;
extern LayersDlgProc gLayersDlgProc;
static ParamBlockDesc2 gDecalMtlLayersPB
(
plDecalMtl::kBlkLayers, _T("layers"), IDS_PASS_LAYERS, GetDecalMtlDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI, plDecalMtl::kRefLayers,
// UI
IDD_PASS_LAYERS, IDS_PASS_LAYERS, 0, 0, NULL,
kDecalLayBase, _T("baseLayer"), TYPE_TEXMAP, 0, IDS_BASIC_AMB,
p_ui, TYPE_TEXMAPBUTTON, IDC_LAYER1,
p_subtexno, 0,
end,
kDecalLayOutputBlend, _T("outputBlend"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_OUTPUTB_NONE, IDC_OUTPUTB_ALPHA, IDC_OUTPUTB_ADD,
p_vals, plPassMtlBase::kBlendNone, plPassMtlBase::kBlendAlpha, plPassMtlBase::kBlendAdd,
p_default, plPassMtlBase::kBlendNone,
end,
kDecalLayTopOn, _T("topLayerOn"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_TOP_ON,
p_default, FALSE,
p_enable_ctrls, 3, kDecalLayTop, kDecalLayBlend, kDecalLayOutputAlpha,
end,
kDecalLayTop, _T("topLayer"), TYPE_TEXMAP, 0, 0,
p_ui, TYPE_TEXMAPBUTTON, IDC_LAYER2,
p_subtexno, 1,
end,
kDecalLayBlend, _T("layerBlend"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_LAYER_ALPHA, IDC_LAYER_ADD, IDC_LAYER_MULTIPLY,
p_vals, plPassMtlBase::kBlendAlpha, plPassMtlBase::kBlendAdd, plPassMtlBase::kBlendMult,
p_default, plPassMtlBase::kBlendAdd,
end,
kDecalLayOutputAlpha, _T("ouputAlpha"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_OUTPUTA_DISCARD, IDC_OUTPUTA_ADD, IDC_OUTPUTA_MULT,
p_vals, plPassMtlBase::kAlphaDiscard, plPassMtlBase::kAlphaAdd, plPassMtlBase::kAlphaMultiply,
p_default, plPassMtlBase::kAlphaDiscard,
end,
end
);
ParamBlockDesc2 *GetDecalLayersPB() { return &gDecalMtlLayersPB; }

View File

@ -0,0 +1,386 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plMultipassMtl.h"
#include "plPassMtl.h"
#include "plMultipassMtlPB.h"
#include "plMultipassMtlDlg.h"
class plMultipassClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading) { return TRACKED_NEW plMultipassMtl(loading); }
const TCHAR* ClassName() { return GetString(IDS_MULTI_MTL); }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
Class_ID ClassID() { return MULTIMTL_CLASS_ID; }
const TCHAR* Category() { return NULL; }
const TCHAR* InternalName() { return _T("PlasmaMultipass"); }
HINSTANCE HInstance() { return hInstance; }
};
static plMultipassClassDesc plMultipassMtlDesc;
ClassDesc2* GetMultiMtlDesc() { return &plMultipassMtlDesc; }
#include "plMultipassMtlPB.cpp"
plMultipassMtl::plMultipassMtl(BOOL loading) : fPassesPB(NULL)
{
plMultipassMtlDesc.MakeAutoParamBlocks(this);
if (!loading)
Reset();
SetNumSubMtls(1);
}
void plMultipassMtl::Reset()
{
fIValid.SetEmpty();
}
ParamDlg* plMultipassMtl::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
{
fMtlDlg = TRACKED_NEW plMultipassMtlDlg(hwMtlEdit, imp, this);
return fMtlDlg;
}
void plMultipassMtl::SetParamDlg(ParamDlg *dlg)
{
fMtlDlg = (plMultipassMtlDlg*)dlg;
}
BOOL plMultipassMtl::SetDlgThing(ParamDlg* dlg)
{
if (dlg == fMtlDlg)
{
fMtlDlg->SetThing(this);
return TRUE;
}
return FALSE;
}
Interval plMultipassMtl::Validity(TimeValue t)
{
Interval valid = FOREVER;
/* for (int i = 0; i < fSubTexmap.Count(); i++)
{
if (fSubTexmap[i])
valid &= fSubTexmap[i]->Validity(t);
}
*/
// float u;
// fPBlock->GetValue(pb_spin,t,u,valid);
return valid;
}
/*===========================================================================*\
| Subanim & References support
\*===========================================================================*/
int plMultipassMtl::NumSubs()
{
return NumSubMtls();
}
TSTR plMultipassMtl::SubAnimName(int i)
{
return GetSubMtlSlotName(i);
}
Animatable* plMultipassMtl::SubAnim(int i)
{
return GetSubMtl(i);
}
int plMultipassMtl::NumRefs()
{
return 1;
}
RefTargetHandle plMultipassMtl::GetReference(int i)
{
if (i == kRefPasses)
return fPassesPB;
return NULL;
}
void plMultipassMtl::SetReference(int i, RefTargetHandle rtarg)
{
if (i == kRefPasses)
fPassesPB = (IParamBlock2 *)rtarg;
}
int plMultipassMtl::NumParamBlocks()
{
return 1;
}
IParamBlock2 *plMultipassMtl::GetParamBlock(int i)
{
if (i == kRefPasses)
return fPassesPB;
return NULL;
}
IParamBlock2 *plMultipassMtl::GetParamBlockByID(BlockID id)
{
if (fPassesPB->ID() == id)
return fPassesPB;
return NULL;
}
RefResult plMultipassMtl::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message )
{
switch (message)
{
case REFMSG_CHANGE:
fIValid.SetEmpty();
if (hTarget == fPassesPB)
{
ParamID changingParam = fPassesPB->LastNotifyParamID();
fPassesPB->GetDesc()->InvalidateUI(changingParam);
}
break;
}
return REF_SUCCEED;
}
////////////////////////////////////////////////////////////////////////////////
// Subtexmap access
int plMultipassMtl::NumSubMtls()
{
return fPassesPB->GetInt(kMultCount);
}
Mtl *plMultipassMtl::GetSubMtl(int i)
{
if (i < NumSubMtls())
return fPassesPB->GetMtl(kMultPasses, 0, i);
return NULL;
}
void plMultipassMtl::SetSubMtl(int i, Mtl *m)
{
if (i < NumSubMtls())
fPassesPB->SetValue(kMultPasses, 0, m, i);
}
TSTR plMultipassMtl::GetSubMtlSlotName(int i)
{
TSTR str;
str.printf("Pass %d", i+1);
return str;
}
TSTR plMultipassMtl::GetSubMtlTVName(int i)
{
return GetSubMtlSlotName(i);
}
/*===========================================================================*\
| Standard IO
\*===========================================================================*/
#define MTL_HDR_CHUNK 0x4000
IOResult plMultipassMtl::Save(ISave *isave)
{
IOResult res;
isave->BeginChunk(MTL_HDR_CHUNK);
res = MtlBase::Save(isave);
if (res!=IO_OK) return res;
isave->EndChunk();
return IO_OK;
}
IOResult plMultipassMtl::Load(ILoad *iload)
{
IOResult res;
int id;
while (IO_OK==(res=iload->OpenChunk()))
{
switch(id = iload->CurChunkID())
{
case MTL_HDR_CHUNK:
res = MtlBase::Load(iload);
break;
}
iload->CloseChunk();
if (res!=IO_OK)
return res;
}
return IO_OK;
}
/*===========================================================================*\
| Updating and cloning
\*===========================================================================*/
RefTargetHandle plMultipassMtl::Clone(RemapDir &remap)
{
plMultipassMtl *mnew = TRACKED_NEW plMultipassMtl(FALSE);
*((MtlBase*)mnew) = *((MtlBase*)this);
mnew->ReplaceReference(kRefPasses, remap.CloneRef(fPassesPB));
mnew->fIValid.SetEmpty();
BaseClone(this, mnew, remap);
return (RefTargetHandle)mnew;
}
void plMultipassMtl::NotifyChanged()
{
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
}
void plMultipassMtl::Update(TimeValue t, Interval& valid)
{
if (!fIValid.InInterval(t))
{
fIValid.SetInfinite();
// fPassesPB->GetValue(kMtlLayLayer1On, t, fMapOn[0], fIValid);
for (int i = 0; i < NumSubMtls(); i++)
{
if (GetSubMtl(i))
GetSubMtl(i)->Update(t, fIValid);
}
}
valid &= fIValid;
}
/*===========================================================================*\
| Determine the characteristics of the material
\*===========================================================================*/
void plMultipassMtl::SetAmbient(Color c, TimeValue t) {}
void plMultipassMtl::SetDiffuse(Color c, TimeValue t) {}
void plMultipassMtl::SetSpecular(Color c, TimeValue t) {}
void plMultipassMtl::SetShininess(float v, TimeValue t) {}
Color plMultipassMtl::GetAmbient(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plMultipassMtl::GetDiffuse(int mtlNum, BOOL backFace) { return Color(0,0,0); }
Color plMultipassMtl::GetSpecular(int mtlNum, BOOL backFace) { return Color(0,0,0); }
float plMultipassMtl::GetXParency(int mtlNum, BOOL backFace) { return 0.0f; }
float plMultipassMtl::GetShininess(int mtlNum, BOOL backFace) { return 0.0f; }
float plMultipassMtl::GetShinStr(int mtlNum, BOOL backFace) { return 0.0f; }
float plMultipassMtl::WireSize(int mtlNum, BOOL backFace) { return 0.0f; }
/*===========================================================================*\
| Actual shading takes place
\*===========================================================================*/
void plMultipassMtl::Shade(ShadeContext& sc)
{
// Get the background color
Color backColor, backTrans;
backColor.Black();
backTrans.White();
int count = NumSubMtls();
for (int i = 0; i < count; i++)
{
if (fPassesPB->GetInt(kMultOn, 0, i) == 0)
continue;
// Call each pass' shade function with the previous color
Mtl *mtl = GetSubMtl(i);
//backTrans = Color(0,0,0);
if (mtl->ClassID() == PASS_MTL_CLASS_ID)
{
plPassMtl *passMtl = (plPassMtl*)mtl;
passMtl->ShadeWithBackground(sc, backColor);
backTrans *= sc.out.t;
backColor = backColor * sc.out.t + sc.out.c;
}
}
sc.out.t = backTrans;
sc.out.c = backColor;
}
float plMultipassMtl::EvalDisplacement(ShadeContext& sc)
{
return 0.0f;
}
Interval plMultipassMtl::DisplacementValidity(TimeValue t)
{
Interval iv;
iv.SetInfinite();
return iv;
}
void plMultipassMtl::SetNumSubMtls(int num)
{
TimeValue t = GetCOREInterface()->GetTime();
int curNum = fPassesPB->GetInt(kMultCount);
fPassesPB->SetValue(kMultCount, 0, num);
fPassesPB->SetCount(kMultPasses, num);
fPassesPB->SetCount(kMultOn, num);
fPassesPB->SetCount(kMultLayerCounts, num);
for (int i = curNum; i < num; i++)
{
plPassMtl *newMtl = TRACKED_NEW plPassMtl(false);
fPassesPB->SetValue(kMultPasses, t, newMtl, i);
fPassesPB->SetValue(kMultOn, t, TRUE, i);
GetCOREInterface()->AssignNewName(fPassesPB->GetMtl(kMultPasses, t, i));
}
}

View File

@ -0,0 +1,136 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef __PLMAXMTL__H
#define __PLMAXMTL__H
#include "Max.h"
#include "../resource.h"
#include "istdplug.h"
#include "iparamb2.h"
#include "iparamm2.h"
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
#define MULTIMTL_CLASS_ID Class_ID(0x3f687a, 0x28c62bd7)
class plMultipassMtlDlg;
class plMultipassMtl : public Mtl
{
protected:
IParamBlock2 *fPassesPB;
Interval fIValid;
plMultipassMtlDlg *fMtlDlg;
public:
enum { kRefPasses };
enum { kBlkPasses };
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void Reset();
void NotifyChanged();
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
// Shade and displacement calculation
void Shade(ShadeContext& sc);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
// SubTexmap access methods
int NumSubMtls();
Mtl* GetSubMtl(int i);
void SetSubMtl(int i, Mtl *m);
TSTR GetSubMtlSlotName(int i);
TSTR GetSubMtlTVName(int i);
BOOL SetDlgThing(ParamDlg* dlg);
plMultipassMtl(BOOL loading);
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
//From Animatable
Class_ID ClassID() { return MULTIMTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_MULTI_MTL); }
RefTargetHandle Clone(RemapDir &remap);
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
void DeleteThis() { delete this; }
void SetParamDlg(ParamDlg *dlg);
void SetNumSubMtls(int num);
};
#endif // __PLMAXMTL__H

View File

@ -0,0 +1,342 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "max.h"
#include "MaxIcon.h"
#include "resource.h"
#include "plMultipassMtl.h"
#include "plMultipassMtlPB.h"
//#include "plMaxLayer.h"
#include "plMultipassMtlDlg.h"
struct LayerID
{
int layerID;
int activeID;
};
static LayerID kLayerID[] =
{
{ IDC_TEX1, IDC_TEXON1 },
{ IDC_TEX2, IDC_TEXON2 },
{ IDC_TEX3, IDC_TEXON3 },
{ IDC_TEX4, IDC_TEXON4 },
{ IDC_TEX5, IDC_TEXON5 },
{ IDC_TEX6, IDC_TEXON6 },
{ IDC_TEX7, IDC_TEXON7 },
{ IDC_TEX8, IDC_TEXON8 },
{ IDC_TEX9, IDC_TEXON9 },
{ IDC_TEX10, IDC_TEXON10 },
};
//-----------------------------------------------------------------------------
// Constructor and destructor
//-----------------------------------------------------------------------------
plMultipassMtlDlg::plMultipassMtlDlg(HWND hwMtlEdit, IMtlParams *imp, plMultipassMtl *m)
{
fDADMgr.Init(this);
fhMtlEdit = hwMtlEdit;
fhRollup = NULL;
fMtl = m;
fPBlock = fMtl->GetParamBlockByID(plMultipassMtl::kBlkPasses);
ip = imp;
valid = FALSE;
for (int i = 0; i < NSUBMTLS; i++)
fLayerBtns[i] = NULL;
curTime = imp->GetTime();
fhRollup = ip->AddRollupPage(
hInstance,
MAKEINTRESOURCE(IDD_MULTIPASS),
ForwardProc,
"Multipass Parameters",
(LPARAM)this);
}
plMultipassMtlDlg::~plMultipassMtlDlg()
{
fMtl->SetParamDlg(NULL);
for (int i = 0; i < NSUBMTLS; i++)
{
ReleaseICustButton(fLayerBtns[i]);
fLayerBtns[i] = NULL;
}
SetWindowLong(fhRollup, GWL_USERDATA, NULL);
ip->DeleteRollupPage(fhRollup);
fhRollup = NULL;
}
//-----------------------------------------------------------------------------
// Functions inheirited from ParamDlg
//-----------------------------------------------------------------------------
void plMultipassMtlDlg::SetThing(ReferenceTarget *m)
{
assert(m->SuperClassID() == MATERIAL_CLASS_ID);
assert(m->ClassID() == MULTIMTL_CLASS_ID);
// Bad?
if (fMtl)
fMtl->SetParamDlg(NULL);
fMtl = (plMultipassMtl *)m;
if (fMtl)
fMtl->SetParamDlg(this);
LoadDialog();
IUpdateMtlDisplay();
}
void plMultipassMtlDlg::SetTime(TimeValue t)
{
if (t != curTime)
{
curTime = t;
Interval v;
fMtl->Update(ip->GetTime(),v);
LoadDialog();
IUpdateMtlDisplay();
}
}
void plMultipassMtlDlg::ReloadDialog()
{
Interval v;
fMtl->Update(ip->GetTime(), v);
LoadDialog();
}
void plMultipassMtlDlg::ActivateDlg(BOOL onOff)
{
}
int plMultipassMtlDlg::FindSubMtlFromHWND(HWND hwnd)
{
for (int i = 0; i < NSUBMTLS; i++)
{
if (hwnd == fLayerBtns[i]->GetHwnd())
return i;
}
return -1;
}
BOOL plMultipassMtlDlg::ForwardProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
plMultipassMtlDlg *theDlg;
if (msg == WM_INITDIALOG)
{
theDlg = (plMultipassMtlDlg*)lParam;
theDlg->fhRollup = hDlg;
SetWindowLong(hDlg, GWL_USERDATA, lParam);
}
else
{
if ((theDlg = (plMultipassMtlDlg *)GetWindowLong(hDlg, GWL_USERDATA)) == NULL)
return FALSE;
}
return theDlg->LayerPanelProc(hDlg,msg,wParam,lParam);
}
//----------------------------------------------------------------------------
// Layer panel processor
//----------------------------------------------------------------------------
BOOL plMultipassMtlDlg::LayerPanelProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
int id = LOWORD(wParam);
int code = HIWORD(wParam);
int i;
switch (msg)
{
case WM_INITDIALOG:
{
int nLayers = fPBlock->GetInt(kMultCount);
for (i = 0; i < NSUBMTLS; i++)
{
fLayerBtns[i] = GetICustButton(GetDlgItem(hDlg, kLayerID[i].layerID));
fLayerBtns[i]->SetDADMgr(&fDADMgr);
/* if (i < nLayers)
{
SetCheckBox(hDlg, kLayerID[i].activeID, fPBlock->GetInt(kMtlLayerOn, curTime, i));
}
*/
fNumTexSpin = SetupIntSpinner(hDlg, IDC_LAYER_SPIN, IDC_LAYER_EDIT, 1, 10, nLayers);
}
// TEMP testing
UpdateLayerDisplay();
IUpdateMtlDisplay();
}
return TRUE;
case WM_DESTROY:
for (i = 0; i < NSUBMTLS; i++)
{
ReleaseICustButton(fLayerBtns[i]);
fLayerBtns[i] = NULL;
}
ReleaseISpinner(fNumTexSpin);
fNumTexSpin = NULL;
break;
case CC_SPINNER_CHANGE:
if (id == IDC_LAYER_SPIN && !code)
{
IGetSpinnerVal();
return TRUE;
}
break;
case CC_SPINNER_BUTTONUP:
if (id == IDC_LAYER_SPIN && code)
{
IGetSpinnerVal();
return TRUE;
}
break;
case WM_COMMAND:
{
for (i = 0; i < NSUBMTLS; i++)
{
if (id == kLayerID[i].activeID)
{
// fMtl->EnableMap(i,GetCheckBox(hwndDlg, id));
bool checked = SendMessage(GetDlgItem(hDlg, id), BM_GETCHECK, 0, 0) == BST_CHECKED;
fPBlock->SetValue(kMultOn, curTime, checked, i);
return TRUE;
}
if (id == kLayerID[i].layerID)
{
PostMessage(fhMtlEdit, WM_SUB_MTL_BUTTON, i, (LPARAM)fMtl);
return TRUE;
}
}
}
// IUpdateMtlDisplay();
break;
}
return FALSE;
}
void plMultipassMtlDlg::UpdateLayerDisplay()
{
int numlayers = fPBlock->GetInt(kMultCount);
fNumTexSpin->SetValue(numlayers, FALSE);
int i;
for (i = 0; i < numlayers && i < NSUBMTLS; i++)
{
Mtl *m = fPBlock->GetMtl(kMultPasses, curTime, i);
TSTR nm;
if (m)
nm = m->GetName();
else
nm = "None";
fLayerBtns[i]->SetText(nm.data());
ShowWindow(GetDlgItem(fhRollup, kLayerID[i].layerID), SW_SHOW);
ShowWindow(GetDlgItem(fhRollup, kLayerID[i].activeID), SW_SHOW);
SetCheckBox(fhRollup, kLayerID[i].activeID, fPBlock->GetInt(kMultOn, curTime, i));
}
for (i = numlayers; i < NSUBMTLS; i++)
{
ShowWindow(GetDlgItem(fhRollup, kLayerID[i].layerID), SW_HIDE);
ShowWindow(GetDlgItem(fhRollup, kLayerID[i].activeID), SW_HIDE);
}
}
void plMultipassMtlDlg::LoadDialog()
{
if (fMtl)
{
fPBlock = fMtl->GetParamBlockByID(plMultipassMtl::kBlkPasses);
if (fhRollup)
UpdateLayerDisplay();
}
}
bool plMultipassMtlDlg::ISetNumLayers(int num)
{
if (num >= 1 && num <= NSUBMTLS)
{
fMtl->SetNumSubMtls(num);
UpdateLayerDisplay();
// IUpdateMtlDisplay();
return true;
}
return false;
}
void plMultipassMtlDlg::IGetSpinnerVal()
{
ISpinnerControl *spin = GetISpinner(GetDlgItem(fhRollup, IDC_LAYER_SPIN));
if (!spin)
return;
// If new number of layers is invalid, set to current num
if (!ISetNumLayers(spin->GetIVal()))
{
int nLayers = fPBlock->GetInt(kMultCount);
spin->SetValue(nLayers, FALSE);
}
ReleaseISpinner(spin);
}

View File

@ -0,0 +1,105 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_MAXMTLDLG_H
#define PL_MAXMTLDLG_H
#define NSUBMTLS 10
class plMultipassMtlDlg : public ParamDlg
{
protected:
IParamBlock2 *fPBlock;
HWND fhMtlEdit; // Window handle of the materials editor dialog
HWND fhRollup; // Our rollup panel
IMtlParams *ip;
plMultipassMtl *fMtl; // current mtl being edited.
TimeValue curTime;
int isActive;
BOOL valid;
// int offset;
ISpinnerControl *fNumTexSpin;
ICustButton *fLayerBtns[NSUBMTLS];
MtlDADMgr fDADMgr; // For drag-drop sub-materials
public:
// Constructor and destructor
plMultipassMtlDlg(HWND hwMtlEdit, IMtlParams *imp, plMultipassMtl *m);
~plMultipassMtlDlg();
// Functions inherited from ParamDLg:
Class_ID ClassID() { return MULTIMTL_CLASS_ID; }
void SetThing(ReferenceTarget *m);
ReferenceTarget* GetThing() { return (ReferenceTarget*)fMtl; }
void SetTime(TimeValue t);
void ReloadDialog();
void ActivateDlg(BOOL onOff);
void DeleteThis() { delete this; }
int FindSubMtlFromHWND(HWND hw);
static BOOL CALLBACK ForwardProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL LayerPanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
void UpdateLayerDisplay();
void LoadDialog();
/*
// Lower-level crap
void Invalidate(); // Called by ParamMtl
BOOL IsActive() { return isActive; }
private:
void ClampOffset();
void SetNumMats();
void UpdateLayers();
void UpdateControlFor(int np);
void VScroll(int code, short int cpos );
*/
protected:
void IUpdateMtlDisplay() { if (ip) ip->MtlChanged(); }
bool ISetNumLayers(int num);
void IGetSpinnerVal();
};
#endif

View File

@ -0,0 +1,66 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plMultipassMtl.h"
#include "plMultipassMtlPB.h"
ClassDesc2* GetMultiMtlDesc();
static ParamBlockDesc2 gMultipassMtlPB
(
plMultipassMtl::kBlkPasses, _T("multipass"), 0, GetMultiMtlDesc(),
P_AUTO_CONSTRUCT, plMultipassMtl::kRefPasses,
kMultCount, _T("numPasses"), TYPE_INT, 0, 0,
p_default, 0,
end,
kMultPasses, _T("passes"), TYPE_MTL_TAB, 0, 0, 0,
end,
kMultOn, _T("passOn"), TYPE_BOOL_TAB, 0, 0, 0,
p_default, TRUE,
end,
kMultLayerCounts, _T("LayerCounts"), TYPE_INT_TAB, 0, 0, 0,
p_default, 0,
end,
end
);

View File

@ -0,0 +1,53 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_MULTIPASS_MTL_PB_H
#define PL_MULTIPASS_MTL_PB_H
enum
{
kMultCount,
kMultPasses,
kMultOn,
kMultLayerCounts
};
#endif //PL_MULTIPASS_MTL_PB_H

View File

@ -0,0 +1,143 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plNoteTrackWatcher - Dummy object to watch for notetrack additions or //
// removals from the main material that owns it. //
// All of this is required because MAX will notify //
// an object's dependents about notetrack actions but //
// NOT the object itself, and the Add/DeleteNoteTrack //
// functions are non-virtual. ARRRGH! //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plNoteTrackWatcher.h"
#include "plPassMtlBase.h"
#include "iparamm2.h"
#include "resource.h"
//// Watcher Class Desc //////////////////////////////////////////////////////
plNoteTrackWatcher::plNoteTrackWatcher( plPassMtlBase *parentMtl ) : fParentMtl(nil)
{
fNoteTrackCount = parentMtl->NumNoteTracks();
MakeRefByID( FOREVER, kRefParentMtl, parentMtl );
}
plNoteTrackWatcher::~plNoteTrackWatcher()
{
if( fParentMtl != nil )
{
fParentMtl->fNTWatcher = nil;
DeleteReference( kRefParentMtl );
}
DeleteAllRefsFromMe();
}
BOOL plNoteTrackWatcher::IsRealDependency( ReferenceTarget *rtarg )
{
if( rtarg == fParentMtl )
return false;
return true;
}
int plNoteTrackWatcher::NumRefs()
{
return 1;
}
RefTargetHandle plNoteTrackWatcher::GetReference( int i )
{
if( i == kRefParentMtl )
return fParentMtl;
return nil;
}
void plNoteTrackWatcher::SetReference( int i, RefTargetHandle rtarg )
{
if( i == kRefParentMtl )
fParentMtl = (plPassMtlBase *)rtarg;
}
RefResult plNoteTrackWatcher::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message)
{
switch( message )
{
case REFMSG_SUBANIM_STRUCTURE_CHANGED:
if( hTarget == fParentMtl && fParentMtl != nil )
{
// Structure of parent material changed--did it gain or lose a notetrack?
int oldCount = fNoteTrackCount;
fNoteTrackCount = fParentMtl->NumNoteTracks();
if( oldCount != fNoteTrackCount )
{
// Is it an addition?
if( fNoteTrackCount > oldCount )
// Yes, notify parent.
fParentMtl->NoteTrackAdded();
else
// Deletion, also notify parent
fParentMtl->NoteTrackRemoved();
}
}
break;
case REFMSG_NODE_NAMECHANGE:
if( hTarget == fParentMtl )
{
fParentMtl->NameChanged();
}
break;
case REFMSG_TARGET_DELETED:
fParentMtl = nil;
break;
}
return REF_SUCCEED;
}

View File

@ -0,0 +1,104 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plNoteTrackWatcher - Dummy object to watch for notetrack additions or //
// removals from the main material that owns it. //
// All of this is required because MAX will notify //
// an object's dependents about notetrack actions but //
// NOT the object itself, and the Add/DeleteNoteTrack //
// functions are non-virtual. ARRRGH! //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plNoteTrackWatcher_h
#define _plNoteTrackWatcher_h
#include "Max.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "hsTypes.h"
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
#define NTWATCHER_CLASSID Class_ID(0x313f531e, 0xa5f132f)
#define REFMSG_NOTETRACK_ADDED REFMSG_USER + 1
class plPassMtlBase;
class NoteTrack;
//// Class Def ///////////////////////////////////////////////////////////////
class plNoteTrackWatcher : public ReferenceMaker
{
protected:
plPassMtlBase *fParentMtl;
// For tracking notetrack additions to the parent
int fNoteTrackCount;
public:
enum Refs
{
kRefParentMtl = 0
};
plNoteTrackWatcher( plPassMtlBase *parentMtl );
virtual ~plNoteTrackWatcher();
void DeleteThis() { delete this; }
Class_ID ClassID() { return NTWATCHER_CLASSID; }
SClass_ID SuperClassID() { return REF_MAKER_CLASS_ID; }
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
RefResult NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget, PartID& partID, RefMessage message);
virtual BOOL IsRealDependency( ReferenceTarget *rtarg );
};
#endif //_plNoteTrackWatcher_h

View File

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

View File

@ -0,0 +1,198 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_PARTICLEMTL_H
#define PL_PARTICLEMTL_H
#include "Max.h"
//#include "istdplug.h"
#include "iparamb2.h"
//#include "iparamm2.h"
#include "../resource.h"
class Bitmap;
#define PARTICLE_MTL_CLASS_ID Class_ID(0x26df05ff, 0x60660749)
extern TCHAR *GetString(int id);
class plParticleMtl : public Mtl
{
protected:
IParamBlock2 *fBasicPB;
Interval fIValid;
public:
IMtlParams *fIMtlParams;
enum
{
kRefBasic,
};
enum
{
kBlkBasic,
};
enum // Param block indicies
{
kOpacity,
kColor,
kWidth,
kHeight,
kXTiles,
kYTiles,
kNormal,
kBlend,
kOrientation,
kBitmap,
kTexmap,
kColorAmb,
kNoFilter
};
enum
{
kBlendNone,
kBlendAlpha,
kBlendAdd
};
enum
{
kOrientVelocity,
kOrientUp,
kOrientVelStretch,
kOrientVelFlow
};
enum
{
kNormalViewFacing,
kNormalUp,
kNormalNearestLight,
kNormalFromCenter,
kNormalVelUpVel,
kEmissive,
kNumNormalOptions
};
static const char *NormalStrings[];
plParticleMtl(BOOL loading);
void DeleteThis() { delete this; }
//From Animatable
Class_ID ClassID() { return PARTICLE_MTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_PARTICLE_MTL); }
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void Reset();
void NotifyChanged();
BOOL SupportsMultiMapsInViewport() { return FALSE; }
void SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb);
// Shade and displacement calculation
void Shade(ShadeContext& sc);
void ShadeWithBackground(ShadeContext &sc, Color background);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
// SubTexmap access methods
int NumSubTexmaps();
Texmap* GetSubTexmap(int i);
void SetSubTexmap(int i, Texmap *m);
TSTR GetSubTexmapSlotName(int i);
TSTR GetSubTexmapTVName(int i);
BOOL SetDlgThing(ParamDlg* dlg);
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
// void SetParamDlg(ParamDlg *dlg);
// void SetNumSubTexmaps(int num);
DllExport Control *GetAmbColorController();
DllExport Control *GetColorController();
DllExport Control *GetOpacityController();
DllExport Control *GetWidthController();
DllExport Control *GetHeightController();
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
ULONG Requirements( int subMtlNum );
};
#endif //PL_PARTICLEMTL_H

View File

@ -0,0 +1,250 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plParticleMtl.h"
class PartMtlPBAccessor;
extern PartMtlPBAccessor partMtl_accessor;
class ParticleBasicDlgProc;
extern ParticleBasicDlgProc gParticleBasicDlgProc;
#define PL_PARTICLE_MTL_MIN_TILES 1
#define PL_PARTICLE_MTL_MAX_TILES 16
static ParamBlockDesc2 gParticleMtlPB
(
plParticleMtl::kBlkBasic, _T("particle"), IDS_PASS_BASIC, GetParticleMtlDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI + P_CALLSETS_ON_LOAD, plParticleMtl::kRefBasic,
// UI
IDD_PARTICLE, IDS_PASS_BASIC, 0, 0, &gParticleBasicDlgProc,
plParticleMtl::kOpacity, _T("opacity"), TYPE_INT, P_ANIMATABLE, IDS_PARTICLE_OPACITY,
p_default, 100,
p_range, 0, 100,
p_ui, TYPE_SPINNER, EDITTYPE_INT,
IDC_PARTICLE_OPACITY, IDC_PARTICLE_OPACITY_SPIN, 1.0,
end,
plParticleMtl::kColorAmb, _T("ambColor"), TYPE_RGBA, P_ANIMATABLE, IDS_PARTICLE_AMB_COLOR,
p_ui, TYPE_COLORSWATCH, IDC_PARTICLE_AMB_COLOR,
p_default, Color(0,0,0),
end,
plParticleMtl::kColor, _T("color"), TYPE_RGBA, P_ANIMATABLE, IDS_PARTICLE_COLOR,
p_ui, TYPE_COLORSWATCH, IDC_PARTICLE_COLOR,
p_default, Color(1,1,1),
end,
plParticleMtl::kWidth, _T("width"), TYPE_FLOAT, P_ANIMATABLE, IDS_PARTICLE_WIDTH,
p_default, 1.0,
p_range, 0.01, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_PARTICLE_WIDTH, IDC_PARTICLE_WIDTH_SPIN, 1.0,
end,
plParticleMtl::kHeight, _T("height"), TYPE_FLOAT, P_ANIMATABLE, IDS_PARTICLE_HEIGHT,
p_default, 1.0,
p_range, 0.01, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_PARTICLE_HEIGHT, IDC_PARTICLE_HEIGHT_SPIN, 1.0,
end,
plParticleMtl::kXTiles, _T("xTiling"), TYPE_INT, 0, 0,
p_default, 1,
p_range, PL_PARTICLE_MTL_MIN_TILES, PL_PARTICLE_MTL_MAX_TILES,
p_ui, TYPE_SPINNER, EDITTYPE_POS_INT,
IDC_PARTICLE_XTILE, IDC_PARTICLE_XTILE_SPIN, 1.0,
p_accessor, &partMtl_accessor,
end,
plParticleMtl::kYTiles, _T("yTiling"), TYPE_INT, 0, 0,
p_default, 1,
p_range, PL_PARTICLE_MTL_MIN_TILES, PL_PARTICLE_MTL_MAX_TILES,
p_ui, TYPE_SPINNER, EDITTYPE_POS_INT,
IDC_PARTICLE_YTILE, IDC_PARTICLE_YTILE_SPIN, 1.0,
p_accessor, &partMtl_accessor,
end,
plParticleMtl::kNormal, _T("normal"), TYPE_INT, 0, 0,
p_default, 0,
end,
plParticleMtl::kBlend, _T("texBlend"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 2, IDC_PARTICLE_BLEND_ALPHA, IDC_PARTICLE_BLEND_ADD,
p_vals, plParticleMtl::kBlendAlpha, plParticleMtl::kBlendAdd,
p_default, plParticleMtl::kBlendAlpha,
end,
plParticleMtl::kOrientation, _T("layerBlend"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 4, IDC_PARTICLE_ORIENT_VELOCITY, IDC_PARTICLE_ORIENT_UP, IDC_PARTICLE_ORIENT_VELSTRETCH, IDC_PARTICLE_ORIENT_VELFLOW,
p_vals, plParticleMtl::kOrientVelocity, plParticleMtl::kOrientUp, plParticleMtl::kOrientVelStretch, plParticleMtl::kOrientVelFlow,
p_default, plParticleMtl::kOrientVelocity,
end,
plParticleMtl::kBitmap, _T("bitmap"), TYPE_BITMAP, P_SHORT_LABELS, 0,
///p_ui, TYPE_BITMAPBUTTON, IDC_PARTICLE_TEXTURE,
//p_accessor, &partMtl_accessor,
end,
plParticleMtl::kTexmap, _T("texmap"), TYPE_TEXMAP, 0, 0,
// p_ui, TYPE_TEXMAPBUTTON, IDC_LAYER2,
end,
plParticleMtl::kNoFilter, _T("noFilter"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_PARTICLE_NOFILTER,
p_default, FALSE,
end,
end
);
class PartMtlPBAccessor : public PBAccessor
{
public:
void Set(PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
plParticleMtl* mtl = (plParticleMtl *)owner;
//plLayerTex *layer;
switch (id)
{
case plParticleMtl::kBitmap:
break;
case plParticleMtl::kXTiles:
case plParticleMtl::kYTiles:
if (val.i < PL_PARTICLE_MTL_MIN_TILES)
val.i = PL_PARTICLE_MTL_MIN_TILES;
if (val.i > PL_PARTICLE_MTL_MAX_TILES)
val.i = PL_PARTICLE_MTL_MAX_TILES;
break;
}
}
void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid)
{
}
};
static PartMtlPBAccessor partMtl_accessor;
class ParticleBasicDlgProc : public ParamMap2UserDlgProc
{
public:
ParticleBasicDlgProc() {}
~ParticleBasicDlgProc() {}
void UpdateDisplay(IParamMap2 *pmap)
{
HWND hWnd = pmap->GetHWnd();
IParamBlock2 *pb = pmap->GetParamBlock();
HWND cbox = GetDlgItem(hWnd, IDC_PARTICLE_NORMAL);
plPlasmaMAXLayer *layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(plParticleMtl::kTexmap));
PBBitmap *pbbm;
ICustButton *bmSelectBtn;
SendMessage(cbox, CB_SETCURSEL, pb->GetInt(plParticleMtl::kNormal), 0);
pbbm = (layer == nil ? nil : layer->GetPBBitmap());
bmSelectBtn = GetICustButton(GetDlgItem(hWnd,IDC_PARTICLE_TEXTURE));
bmSelectBtn->SetText(pbbm ? (TCHAR*)pbbm->bi.Filename() : "(none)");
ReleaseICustButton(bmSelectBtn);
}
virtual void Update(TimeValue t, Interval& valid, IParamMap2* pmap) { UpdateDisplay(pmap); }
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
int id = LOWORD(wParam);
int code = HIWORD(wParam);
IParamBlock2 *pb = map->GetParamBlock();
HWND cbox = NULL;
plPlasmaMAXLayer *layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(plParticleMtl::kTexmap));
switch (msg)
{
case WM_INITDIALOG:
int j;
for (j = 0; j < plParticleMtl::kNumNormalOptions; j++)
{
cbox = GetDlgItem(hWnd, IDC_PARTICLE_NORMAL);
SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)plParticleMtl::NormalStrings[j]);
}
UpdateDisplay(map);
return TRUE;
case WM_COMMAND:
if (id == IDC_PARTICLE_NORMAL)
{
pb->SetValue(plParticleMtl::kNormal, t, SendMessage(GetDlgItem(hWnd, id), CB_GETCURSEL, 0, 0));
return TRUE;
}
else if (id == IDC_PARTICLE_TEXTURE)
{
if (layer == nil)
return FALSE;
layer->HandleBitmapSelection();
UpdateDisplay(map);
return TRUE;
}
else if (id == IDC_PARTICLE_NOFILTER)
{
if (!layer)
return FALSE;
if( pb->GetInt(plParticleMtl::kNoFilter) )
{
layer->GetParamBlockByID( plLayerTex::kBlkBitmap )->SetValue(kBmpNoFilter, t, 1);
}
else
{
layer->GetParamBlockByID( plLayerTex::kBlkBitmap )->SetValue(kBmpNoFilter, t, 0);
}
return TRUE;
}
break;
}
return FALSE;
}
void DeleteThis() {}
};
static ParticleBasicDlgProc gParticleBasicDlgProc;

View File

@ -0,0 +1,321 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plPassAnimDlgProc - Base Animation Dlg Proc for plPassMtlBase //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plPassAnimDlgProc.h"
#include "plPassBaseParamIDs.h"
#include "../MaxComponent/plNotetrackAnim.h"
#include "resource.h"
#include "iparamm2.h"
#include "plAnimStealthNode.h"
#include "../MaxComponent/plMaxAnimUtils.h"
#include "../MaxComponent/plAnimComponent.h"
#include "../MaxExport/plErrorMsg.h"
const char *kPassNameNone = ENTIRE_ANIMATION_NAME;
#include "plAnimStealthNode.h"
using namespace plPassBaseParamIDs;
plPassAnimDlgProc::plPassAnimDlgProc()
{
fCurrParamMap = nil;
fInitingNames = false;
}
plPassAnimDlgProc::~plPassAnimDlgProc()
{
if( fCurrParamMap != nil )
{
plPassMtlBase *mtl = (plPassMtlBase *)( fCurrParamMap->GetParamBlock()->GetOwner() );
mtl->RegisterChangeCallback( this );
}
}
plPassAnimDlgProc &plPassAnimDlgProc::Get( void )
{
static plPassAnimDlgProc instance;
return instance;
}
void plPassAnimDlgProc::Update(TimeValue t, Interval& valid, IParamMap2* pmap)
{
/* plAnimStealthNode *testStealth = (plAnimStealthNode *)pmap->GetParamBlock()->GetINode( (ParamID)kPBAnimTESTING );
if( testStealth != nil )
{
IParamBlock2 *pb = testStealth->GetParamBlockByID( plAnimStealthNode::kBlockPB );
if( pb && pb->GetMap() && pb->GetMap()->GetUserDlgProc() )
pb->GetMap()->GetUserDlgProc()->Update( t, valid, pmap );
}
*/
HWND hWnd = pmap->GetHWnd();
IParamBlock2 *pb = pmap->GetParamBlock();
plAnimComponentProc::SetBoxToAgeGlobal(GetDlgItem(hWnd, IDC_MTL_GLOBAL_NAME), pb->GetStr(ParamID(kPBAnimGlobalName)));
}
BOOL plPassAnimDlgProc::DlgProc(TimeValue t, IParamMap2 *pMap, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if( fCurrParamMap != pMap )
{
if( fCurrParamMap != nil )
{
plPassMtlBase *mtl = (plPassMtlBase *)( fCurrParamMap->GetParamBlock()->GetOwner() );
mtl->UnregisterChangeCallback( this );
}
fCurrParamMap = pMap;
if( fCurrParamMap != nil )
{
plPassMtlBase *mtl = (plPassMtlBase *)( fCurrParamMap->GetParamBlock()->GetOwner() );
mtl->RegisterChangeCallback( this );
}
}
IParamBlock2 *pb = pMap->GetParamBlock();
plPassMtlBase *mtl = (plPassMtlBase*)pb->GetOwner();
HWND gWnd = GetDlgItem(hWnd, IDC_MTL_GLOBAL_NAME);
char buff[512];
switch (msg)
{
case WM_DESTROY:
if( fCurrParamMap != nil )
{
plPassMtlBase *mtl = (plPassMtlBase *)( fCurrParamMap->GetParamBlock()->GetOwner() );
mtl->RegisterChangeCallback( this );
fCurrParamMap = nil;
}
break;
case WM_INITDIALOG:
{
fhWnd = hWnd;
fCurrStealth = nil;
IInitControls(mtl, pb);
plAnimComponentProc::FillAgeGlobalComboBox(gWnd, pb->GetStr(ParamID(kPBAnimGlobalName)));
plAnimComponentProc::SetBoxToAgeGlobal(gWnd, pb->GetStr(ParamID(kPBAnimGlobalName)));
IEnableGlobal(hWnd, pb->GetInt( (ParamID)kPBAnimUseGlobal ) );
bool stopPoints = false;
if( DoesHaveStopPoints( pb->GetOwner() ) )
{
stopPoints = true;
break;
}
IEnableEaseStopPoints( pMap, stopPoints );
}
return TRUE;
case WM_COMMAND:
// Anim name selection changed
if (LOWORD(wParam) == IDC_NAMES && HIWORD(wParam) == CBN_SELCHANGE)
{
IUpdateSegmentSel( pMap );
return TRUE;
}
// Refresh clicked
else if (LOWORD(wParam) == IDC_REFRESH_ANIMS && HIWORD(wParam) == BN_CLICKED)
{
IInitControls(mtl, pb);
return TRUE;
}
else if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_MTL_GLOBAL_NAME)
{
ComboBox_GetLBText(gWnd, ComboBox_GetCurSel(gWnd), buff);
pb->SetValue(ParamID(kPBAnimGlobalName), 0, _T(buff));
}
else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_MTL_USE_GLOBAL)
{
IEnableGlobal(hWnd, pb->GetInt( (ParamID)kPBAnimUseGlobal ) );
}
break;
}
return FALSE;
}
void plPassAnimDlgProc::SegmentListChanged( void )
{
if( fCurrParamMap != nil )
ILoadNames( fCurrParamMap->GetParamBlock() );
}
void plPassAnimDlgProc::IUpdateSegmentSel( IParamMap2 *thisMap, hsBool clear )
{
plAnimStealthNode *newStealth;
HWND hAnims = GetDlgItem( fhWnd, IDC_NAMES );
// Get current selection
if( clear )
newStealth = nil;
else
{
int sel = SendDlgItemMessage( fhWnd, IDC_NAMES, CB_GETCURSEL, 0, 0 );
if( sel == CB_ERR )
{
// Somehow we don't have a selection...fine, just destroy
newStealth = nil;
}
else
{
newStealth = (plAnimStealthNode *)SendDlgItemMessage( fhWnd, IDC_NAMES, CB_GETITEMDATA, sel, 0 );
}
}
// Did we really not change?
if( newStealth == fCurrStealth )
return;
if( fCurrStealth != nil && newStealth != nil )
{
fCurrStealth->SwitchDlg( newStealth );
}
else
{
// Destroy the old
if( fCurrStealth != nil )
fCurrStealth->ReleaseDlg();
// Show the new
if( newStealth != nil )
IExposeStealthNode( newStealth, thisMap );
}
// And update!
fCurrStealth = newStealth;
}
void plPassAnimDlgProc::IExposeStealthNode( HelperObject *node, IParamMap2 *thisMap )
{
if( node->ClassID() != ANIMSTEALTH_CLASSID )
return;
// Get our stealth pointer
plAnimStealthNode *stealth = (plAnimStealthNode *)node;
// Create the paramMap-based dialog for us
IParamBlock2 *pb = thisMap->GetParamBlock();
plPassMtlBase *mtl = (plPassMtlBase *)pb->GetOwner();
if( !stealth->CreateAndEmbedDlg( thisMap, mtl->fIMtlParams, GetDlgItem( fhWnd, IDC_PLACEHOLDER ) ) )
{
}
}
void plPassAnimDlgProc::SetThing(ReferenceTarget *m)
{
plPassMtlBase *mtl = (plPassMtlBase*)m;
IInitControls(mtl, mtl->fAnimPB );
}
void plPassAnimDlgProc::IInitControls(Animatable *anim, IParamBlock2 *pb)
{
ILoadNames( pb );
IEnableGlobal( fhWnd, pb->GetInt( ParamID( kPBAnimUseGlobal ) ) );
}
void plPassAnimDlgProc::ILoadNames(IParamBlock2 *pb )
{
// The following is to prevent IGetNumStealths() from re-calling us
if( fInitingNames )
return;
fInitingNames = true;
HWND hAnims = GetDlgItem(fhWnd, IDC_NAMES);
SendMessage(hAnims, CB_RESETCONTENT, 0, 0);
plPassMtlBase *mtl = (plPassMtlBase *)pb->GetOwner();
// Loop through our stealth nodes and add them all to the combo,
// since that's what we're selecting...erm, yeah
int i, count = mtl->IGetNumStealths( true );
for( i = 0; i < count; i++ )
{
plAnimStealthNode *stealth = mtl->IGetStealth( i, false );
if( stealth != nil )
{
int idx = SendMessage( hAnims, CB_ADDSTRING, 0, (LPARAM)stealth->GetSegmentName() );
SendMessage( hAnims, CB_SETITEMDATA, idx, (LPARAM)stealth );
}
}
SendMessage( hAnims, CB_SETCURSEL, 0, 0 );
IUpdateSegmentSel( pb->GetMap() );
fInitingNames = false;
}
void plPassAnimDlgProc::IEnableGlobal(HWND hWnd, hsBool enable)
{
Edit_Enable(GetDlgItem(hWnd, IDC_MTL_GLOBAL_NAME), enable);
ComboBox_Enable(GetDlgItem(hWnd, IDC_NAMES), !enable);
HWND stealthWnd = ( fCurrStealth != nil ) ? fCurrStealth->GetWinDlg() : nil;
if( stealthWnd != nil )
EnableWindow( stealthWnd, !enable );
}
void plPassAnimDlgProc::IEnableEaseStopPoints( IParamMap2 *pm, bool enable )
{
pm->Enable( (ParamID)kPBAnimEaseInMin, enable );
pm->Enable( (ParamID)kPBAnimEaseInMax, enable );
pm->Enable( (ParamID)kPBAnimEaseOutMin, enable );
pm->Enable( (ParamID)kPBAnimEaseOutMax, enable );
}

View File

@ -0,0 +1,100 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plPassAnimDlgProc - Base Animation Dlg Proc for plPassMtlBase //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plPassAnimDlgProc_h
#define _plPassAnimDlgProc_h
#include "plPassMtlBase.h"
#include "iparamm2.h"
class plAnimStealthNode;
class IParamMap2;
class plPassAnimDlgProc : public ParamMap2UserDlgProc, public plMtlChangeCallback
{
protected:
// Combo itemdata values
enum
{
kName, // Name of an animation/loop
kDefault, // Default combo value
kInvalid, // Invalid entry (couldn't find)
};
plAnimStealthNode *fCurrStealth;
IParamMap2 *fCurrParamMap;
bool fInitingNames;
HWND fhWnd;
public:
plPassAnimDlgProc();
virtual ~plPassAnimDlgProc();
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void DeleteThis() {}
void SetThing(ReferenceTarget *m);
virtual void Update(TimeValue t, Interval& valid, IParamMap2* pmap);
void SegmentListChanged( void );
static plPassAnimDlgProc &Get( void );
protected:
// Set all the controls to their stored value
void IInitControls(Animatable *anim, IParamBlock2 *pb);
void IEnableGlobal(HWND hWnd, hsBool enable);
void ILoadNames( IParamBlock2 *pb );
void IExposeStealthNode( HelperObject *stealth, IParamMap2 *thisMap );
void IUpdateSegmentSel( IParamMap2 *thisMap, hsBool clear = false );
void IEnableEaseStopPoints( IParamMap2 *pm, bool enable );
};
#endif //_plPassAnimDlgProc_h

View File

@ -0,0 +1,116 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plPassBaseParamIDs - Common ParamIDs for all plPassMtlBase-derived mtls //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plPassBaseParamIDs_h
#define _plPassBaseParamIDs_h
#define MCN_UPGRADE_OLD_ANIM_BLOCKS
namespace plPassBaseParamIDs
{
enum AdvancedIDs
{
// Specular
kPBAdvUseSpec, // Not used anymore, feel free to replace with new fields as necessary
kPBAdvSpecType, // ditto
kPBAdvShine, // ...
kPBAdvShineStr, // ...
// Misc
kPBAdvWire,
kPBAdvMeshOutlines,
kPBAdvTwoSided,
// Shading
kPBAdvSoftShadow,
kPBAdvNoProj,
kPBAdvVertexShade,
kPBAdvNoShade,
kPBAdvNoFog,
kPBAdvWhite,
// Z
kPBAdvZOnly,
kPBAdvZClear,
kPBAdvZNoRead,
kPBAdvZNoWrite,
kPBAdvZInc,
// Alpha test
kPBAdvAlphaTestHigh
};
enum SpecularTypes
{
kSpecTypeAlpha,
kSpecTypeColor,
kSpecTypeHighlight
};
enum AnimationIDs
{
kPBAnimName,
kPBAnimAutoStart,
kPBAnimLoop,
kPBAnimLoopName,
kPBAnimEaseInType,
kPBAnimEaseOutType,
kPBAnimEaseInLength,
kPBAnimEaseOutLength,
kPBAnimEaseInMin,
kPBAnimEaseInMax,
kPBAnimEaseOutMin,
kPBAnimEaseOutMax,
kPBAnimUseGlobal,
kPBAnimGlobalName,
kPBAnimStealthNodes
};
}
#endif //_plPassBaseParamIDs_h

View File

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

View File

@ -0,0 +1,213 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_PASSMTL_H
#define PL_PASSMTL_H
#include "Max.h"
//#include "istdplug.h"
#include "iparamb2.h"
//#include "iparamm2.h"
#include "../resource.h"
#include "plPassMtlBase.h"
#include "hsTemplates.h"
#define PASS_MTL_CLASS_ID Class_ID(0x42b6718f, 0x2d579b35)
extern TCHAR *GetString(int id);
class plPassMtl : public plPassMtlBase
{
protected:
virtual void ICloneRefs( plPassMtlBase *target, RemapDir &remap );
public:
enum RefIDs
{
kRefBasic,
kRefAdv,
kRefLayers,
kRefAnim,
};
enum Blocks
{
kBlkBasic,
kBlkAdv,
kBlkLayers,
kBlkAnim,
};
plPassMtl(BOOL loading);
virtual ~plPassMtl();
void DeleteThis() { delete this; }
//From Animatable
Class_ID ClassID() { return PASS_MTL_CLASS_ID; }
SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
void GetClassName(TSTR& s) { s = GetString(IDS_PASS_MTL); }
ParamDlg *CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
void Update(TimeValue t, Interval& valid);
Interval Validity(TimeValue t);
void NotifyChanged();
BOOL SupportsMultiMapsInViewport() { return FALSE; }
void SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb);
// Shade and displacement calculation
static void GetInterpVtxValue(int channel, ShadeContext &sc, Point3 &interpVal);
void Shade(ShadeContext& sc);
void ShadeWithBackground(ShadeContext &sc, Color background, bool useVtxAlpha = true);
float EvalDisplacement(ShadeContext& sc);
Interval DisplacementValidity(TimeValue t);
virtual RefTargetHandle GetReference( int i );
virtual void SetReference( int i, RefTargetHandle rtarg );
// SubTexmap access methods
int NumSubTexmaps();
Texmap* GetSubTexmap(int i);
void SetSubTexmap(int i, Texmap *m);
TSTR GetSubTexmapSlotName(int i);
TSTR GetSubTexmapTVName(int i);
int SubTexmapOn(int i);
BOOL SetDlgThing(ParamDlg* dlg);
RefTargetHandle Clone( RemapDir &remap );
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int NumParamBlocks();
IParamBlock2* GetParamBlock(int i);
IParamBlock2* GetParamBlockByID(BlockID id);
// void SetParamDlg(ParamDlg *dlg);
// void SetNumSubTexmaps(int num);
// From MtlBase and Mtl
void SetAmbient(Color c, TimeValue t);
void SetDiffuse(Color c, TimeValue t);
void SetSpecular(Color c, TimeValue t);
void SetShininess(float v, TimeValue t);
Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE);
Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE);
Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE);
float GetXParency(int mtlNum=0, BOOL backFace=FALSE);
float GetShininess(int mtlNum=0, BOOL backFace=FALSE);
float GetShinStr(int mtlNum=0, BOOL backFace=FALSE);
float WireSize(int mtlNum=0, BOOL backFace=FALSE);
ULONG Requirements( int subMtlNum );
virtual bool HasAlpha();
// Massive list of inherited accessor functions for ParamBlock data
// Advanced Block
virtual int GetBasicWire();
virtual int GetMeshOutlines();
virtual int GetTwoSided();
virtual int GetSoftShadow();
virtual int GetNoProj();
virtual int GetVertexShade();
virtual int GetNoShade();
virtual int GetNoFog();
virtual int GetWhite();
virtual int GetZOnly();
virtual int GetZClear();
virtual int GetZNoRead();
virtual int GetZNoWrite();
virtual int GetZInc();
virtual int GetAlphaTestHigh();
// Animation block
virtual char * GetAnimName();
virtual int GetAutoStart();
virtual int GetLoop();
virtual char * GetAnimLoopName();
virtual int GetEaseInType();
virtual float GetEaseInMinLength();
virtual float GetEaseInMaxLength();
virtual float GetEaseInNormLength();
virtual int GetEaseOutType();
virtual float GetEaseOutMinLength();
virtual float GetEaseOutMaxLength();
virtual float GetEaseOutNormLength();
virtual int GetUseGlobal();
virtual char * GetGlobalVarName();
// Basic block
virtual int GetColorLock();
virtual Color GetAmbColor();
virtual Color GetColor();
virtual int GetOpacity();
virtual int GetEmissive();
virtual int GetUseSpec();
virtual int GetShine();
virtual Color GetSpecularColor();
virtual Control *GetPreshadeColorController();
virtual Control *GetAmbColorController();
virtual Control *GetOpacityController();
virtual Control *GetSpecularColorController();
virtual int GetDiffuseColorLock();
virtual Color GetRuntimeColor();
virtual Control *GetRuntimeColorController();
// Layer block
virtual Texmap *GetBaseLayer();
virtual int GetTopLayerOn();
virtual Texmap *GetTopLayer();
virtual int GetLayerBlend();
virtual int GetOutputAlpha();
virtual int GetOutputBlend();
};
#endif //PL_PASSMTL_H

View File

@ -0,0 +1,75 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_PASSMTLADVPB_H
#define PL_PASSMTLADVPB_H
// Param ID's
enum
{
// Specular
kPassAdvUseSpec, // Not used anymore, feel free to replace with new fields as necessary
kPassAdvSpecType, // ditto
kPassAdvShine, // ...
kPassAdvShineStr, // ...
// Misc
kPassAdvWire,
kPassAdvMeshOutlines,
kPassAdvTwoSided,
// Shading
kPassAdvSoftShadow,
kPassAdvNoProj,
kPassAdvVertexShade,
kPassAdvNoShade,
kPassAdvNoFog,
kPassAdvWhite,
// Z
kPassAdvZOnly,
kPassAdvZClear,
kPassAdvZNoRead,
kPassAdvZNoWrite,
kPassAdvZInc,
};
#endif //PL_PASSMTLADVPB_H

View File

@ -0,0 +1,110 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plPassMtl.h"
#include "plPassBaseParamIDs.h"
using namespace plPassBaseParamIDs;
static ParamBlockDesc2 gPassAdvPB
(
plPassMtl::kBlkAdv, _T("advanced"), IDS_PASS_ADV, GetPassMtlDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI, plPassMtl::kRefAdv,
// UI
IDD_PASS_ADV, IDS_PASS_ADV, 0, APPENDROLL_CLOSED, NULL,
// Misc Properties
kPBAdvWire, _T("basicWire"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_MISC_WIRE,
end,
kPBAdvMeshOutlines, _T("meshOutlines"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_MISC_MESHOUTLINES,
end,
kPBAdvTwoSided, _T("twoSided"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_MISC_TWOSIDED,
end,
// Shade properties
kPBAdvSoftShadow, _T("softShadow"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_SOFTSHADOW,
end,
kPBAdvNoProj, _T("noProj"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_NO_PROJ,
end,
kPBAdvVertexShade, _T("vertexShade"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_VERTEXSHADE,
end,
kPBAdvNoShade, _T("noShade"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_NOSHADE,
end,
kPBAdvNoFog, _T("noFog"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_NO_FOG,
end,
kPBAdvWhite, _T("white"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_WHITE,
end,
// Z Properties
kPBAdvZOnly, _T("zOnly"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZONLY,
end,
kPBAdvZClear, _T("zClear"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZCLEAR,
end,
kPBAdvZNoRead, _T("zNoRead"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZNOREAD,
end,
kPBAdvZNoWrite, _T("zNoWrite"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_ZNOWRITE,
end,
kPBAdvZInc, _T("zInc"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_INC,
end,
kPBAdvAlphaTestHigh, _T("aTestHigh"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_ALPHA_TEST_HIGH,
p_default, FALSE,
end,
end
);
ParamBlockDesc2 *GetPassAdvPB() { return &gPassAdvPB; }

View File

@ -0,0 +1,101 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_PASSMTLANIMPB_H
#define PL_PASSMTLANIMPB_H
enum { kPassAnimMain, kPassAnimEase };
#define WM_ROLLOUT_OPEN WM_USER+1
class plAnimEaseDlgProc : public ParamMap2UserDlgProc
{
protected:
void EnableStopPoints(IParamMap2 *pm, bool enable)
{
pm->Enable(kPassEaseInMin, enable);
pm->Enable(kPassEaseInMax, enable);
pm->Enable(kPassEaseOutMin, enable);
pm->Enable(kPassEaseOutMax, enable);
}
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
IParamBlock2 *pb = map->GetParamBlock();
bool stopPoints = false;
if (DoesHaveStopPoints(pb->GetOwner()))
{
stopPoints = true;
break;
}
EnableStopPoints(map, stopPoints);
// If we're doing an ease, set the ease rollup to open
// if (pb->GetInt(kPassEaseInType) != plAnimEaseTypes::kNoEase ||
// pb->GetInt(kPassEaseOutType) != plAnimEaseTypes::kNoEase)
// PostMessage(hWnd, WM_ROLLOUT_OPEN, 0, 0);
}
return TRUE;
// Max doesn't know about the rollup until after WM_CREATE, so we get
// around it by posting a message
//case WM_ROLLOUT_OPEN:
// {
// IRollupWindow *rollup = GetCOREInterface(MTLEDIT_INTERFACE)->GetCommandPanelRollup();
// int idx = rollup->GetPanelIndex(hWnd);
// rollup->SetPanelOpen(idx, TRUE);
// }
// return TRUE;
}
return FALSE;
}
void DeleteThis() {}
};
#endif

View File

@ -0,0 +1,111 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plPassMtl.h"
#include "plPassBaseParamIDs.h"
#include "resource.h"
#include "iparamm2.h"
#include "plPassAnimDlgProc.h"
#include "plAnimStealthNode.h"
using namespace plPassBaseParamIDs;
static ParamBlockDesc2 gPassAnimPB
(
plPassMtl::kBlkAnim, _T("anim"), IDS_PASS_ANIM, GetPassMtlDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI + P_CALLSETS_ON_LOAD, plPassMtl::kRefAnim,
// UI
IDD_PASS_ANIM, IDS_PASS_ANIM, 0, 0, &plPassAnimDlgProc::Get(),
#ifdef MCN_UPGRADE_OLD_ANIM_BLOCKS
// THE FOLLOWING ARE ALL OLD PARAMETERS AND SHOULD NO LONGER BE USED. The only reason
// they're here is so we can convert old paramBlocks into the new plAnimStealthNode format
kPBAnimName, _T("animName"), TYPE_STRING, 0, 0,
end,
kPBAnimAutoStart, _T("autoStart"), TYPE_BOOL, 0, 0,
end,
kPBAnimLoop, _T("loop"), TYPE_BOOL, 0, 0,
end,
kPBAnimLoopName, _T("loopName"), TYPE_STRING, 0, 0,
end,
// Anim Ease
kPBAnimEaseInType, _T("easeInType"), TYPE_INT, 0, 0,
end,
kPBAnimEaseInLength, _T("easeInLength"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseInMin, _T("easeInMin"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseInMax, _T("easeInMax"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutType, _T("easeOutType"), TYPE_INT, 0, 0,
end,
kPBAnimEaseOutLength, _T("easeOutLength"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutMin, _T("easeOutMin"), TYPE_FLOAT, 0, 0,
end,
kPBAnimEaseOutMax, _T("easeOutMax"), TYPE_FLOAT, 0, 0,
end,
#endif // MCN_UPGRADE_OLD_ANIM_BLOCKS
kPBAnimUseGlobal, _T("UseGlobal"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_MTL_USE_GLOBAL,
end,
kPBAnimGlobalName, _T("GlobalName"), TYPE_STRING, 0, 0,
p_default, _T(""),
end,
kPBAnimStealthNodes, _T( "testing" ), TYPE_REFTARG_TAB, 0, 0, 0,
p_accessor, &plStealthNodeAccessor::GetInstance(),
end,
end
);
ParamBlockDesc2 *GetPassAnimPB() { return &gPassAnimPB; }

View File

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

View File

@ -0,0 +1,301 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_PASSMTLBASE_H
#define PL_PASSMTLBASE_H
#include "hsTemplates.h"
#include "Max.h"
#include "iparamb2.h"
#include "../../PubUtilLib/plInterp/plAnimEaseTypes.h"
class plNoteTrackWatcher;
class plMtlChangeCallback;
class plAnimStealthNode;
class NoteTrack;
class plPassAnimDlgProc;
class plStealthNodeAccessor;
class plMaxNode;
class plErrorMsg;
class plPassMtlBase : public Mtl
{
protected:
friend class plPassAnimDlgProc;
friend class plStealthNodeAccessor;
friend class plNoteTrackWatcher;
plNoteTrackWatcher *fNTWatcher;
IParamBlock2 *fBasicPB;
IParamBlock2 *fAdvPB;
IParamBlock2 *fLayersPB;
IParamBlock2 *fAnimPB;
Interval fIValid;
hsBool fLoading;
hsTArray<NoteTrack *> fNotetracks;
hsBool fStealthsChanged;
hsTArray<plMtlChangeCallback *> fChangeCallbacks;
void IUpdateAnimNodes( void );
plAnimStealthNode *IFindStealth( const char *animName );
plAnimStealthNode *IVerifyStealthPresent( const char *animName );
int IGetNumStealths( hsBool update = true );
plAnimStealthNode *IGetStealth( int index, hsBool update = true );
void ICloneBase( plPassMtlBase *target, RemapDir &remap );
virtual void ICloneRefs( plPassMtlBase *target, RemapDir &remap ) = 0;
public:
// mcn note: as far as I can tell, this is always the same pointer passed around to everyone.
// So since we have trouble getting it all the time, just store the first version we get and
// use that forever and ever
static IMtlParams *fIMtlParams;
plPassMtlBase( BOOL loading );
virtual ~plPassMtlBase();
virtual bool HasAlpha() = 0;
enum Refs
{
//kRefBasic, // Can't do this, long ago they were different in the "derived" classes,
//kRefAdv, // and even tho MAX says it doesn't write refs out by their index, it does
//kRefLayers,
//kRefAnim,
kRefNotetracks = 4 // MUST BE THE LAST REF ID SPECIFIED
};
void SetLoadingFlag( hsBool f ) { fLoading = f; }
void PostLoadAnimPBFixup( void );
void RegisterChangeCallback( plMtlChangeCallback *callback );
void UnregisterChangeCallback( plMtlChangeCallback *callback );
// Change notifys from our ntWatcher
virtual void NoteTrackAdded( void );
virtual void NoteTrackRemoved( void );
virtual void NameChanged( void );
// Loading/Saving
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
virtual void Reset( void );
int NumRefs();
virtual RefTargetHandle GetReference( int i );
virtual void SetReference( int i, RefTargetHandle rtarg );
RefResult NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget, PartID &partID, RefMessage message );
// Convert time, called on the setupProps pass for each material applied to a node in the scene
virtual hsBool SetupProperties( plMaxNode *node, plErrorMsg *pErrMsg );
virtual hsBool ConvertDeInit( plMaxNode *node, plErrorMsg *pErrMsg );
int GetNumStealths( void );
plAnimStealthNode *GetStealth( int index );
// Static convert to our plPassMtlBase type, if possible
static plPassMtlBase *ConvertToPassMtl( Mtl *mtl );
// Blend types
enum
{
kBlendNone,
kBlendAlpha,
kBlendAdd,
kBlendMult
};
// Alpha blend types
enum
{
kAlphaDiscard,
kAlphaMultiply,
kAlphaAdd
};
// Advanced Block
virtual int GetBasicWire() = 0;
virtual int GetMeshOutlines() = 0;
virtual int GetTwoSided() = 0;
virtual int GetSoftShadow() = 0;
virtual int GetNoProj() = 0;
virtual int GetVertexShade() = 0;
virtual int GetNoShade() = 0;
virtual int GetNoFog() = 0;
virtual int GetWhite() = 0;
virtual int GetZOnly() = 0;
virtual int GetZClear() = 0;
virtual int GetZNoRead() = 0;
virtual int GetZNoWrite() = 0;
virtual int GetZInc() = 0;
virtual int GetAlphaTestHigh() = 0;
// Animation block
virtual char * GetAnimName() = 0;
virtual int GetAutoStart() = 0;
virtual int GetLoop() = 0;
virtual char * GetAnimLoopName() = 0;
virtual int GetEaseInType() { return plAnimEaseTypes::kNoEase; }
virtual float GetEaseInMinLength() { return 1; }
virtual float GetEaseInMaxLength() { return 1; }
virtual float GetEaseInNormLength() { return 1; }
virtual int GetEaseOutType() { return plAnimEaseTypes::kNoEase; }
virtual float GetEaseOutMinLength() { return 1; }
virtual float GetEaseOutMaxLength() { return 1; }
virtual float GetEaseOutNormLength() { return 1; }
virtual char * GetGlobalVarName() { return NULL; }
virtual int GetUseGlobal() { return 0; }
// Basic block
virtual int GetColorLock() = 0;
virtual Color GetAmbColor() = 0;
virtual Color GetColor() = 0;
virtual int GetOpacity() = 0;
virtual int GetEmissive() = 0;
virtual int GetUseSpec() = 0;
virtual int GetShine() = 0;
virtual Color GetSpecularColor() = 0;
virtual int GetDiffuseColorLock() = 0;
virtual Color GetRuntimeColor() = 0;
virtual Control *GetPreshadeColorController() = 0;
virtual Control *GetAmbColorController() = 0;
virtual Control *GetOpacityController() = 0;
virtual Control *GetSpecularColorController() = 0;
virtual Control *GetRuntimeColorController() = 0;
// Layer block
virtual Texmap *GetBaseLayer() = 0;
virtual int GetTopLayerOn() = 0;
virtual Texmap *GetTopLayer() = 0;
virtual int GetLayerBlend() = 0;
virtual int GetOutputAlpha() = 0;
virtual int GetOutputBlend() = 0;
};
// Make sure min is less than normal, which is less than max
class plEaseAccessor : public PBAccessor
{
protected:
bool fDoingUpdate;
int fBlockID;
int fEaseInMinID, fEaseInMaxID, fEaseInNormID, fEaseOutMinID, fEaseOutMaxID, fEaseOutNormID;
void AdjustMin(IParamBlock2 *pb, ParamID minID, ParamID normalID, ParamID maxID, float value)
{
if (value > pb->GetFloat(normalID))
{
pb->SetValue(normalID, 0, value);
if (value > pb->GetFloat(maxID))
pb->SetValue(maxID, 0, value);
}
}
void AdjustNormal(IParamBlock2 *pb, ParamID minID, ParamID normalID, ParamID maxID, float value)
{
if (value < pb->GetFloat(minID))
pb->SetValue(minID, 0, value);
if (value > pb->GetFloat(maxID))
pb->SetValue(maxID, 0, value);
}
void AdjustMax(IParamBlock2 *pb, ParamID minID, ParamID normalID, ParamID maxID, float value)
{
if (value < pb->GetFloat(normalID))
{
pb->SetValue(normalID, 0, value);
if (value < pb->GetFloat(minID))
pb->SetValue(minID, 0, value);
}
}
public:
plEaseAccessor(int blockID, int easeInMinID, int easeInMaxID, int easeInNormID,
int easeOutMinID, int easeOutMaxID, int easeOutNormID)
{
fDoingUpdate = false;
fBlockID = blockID;
fEaseInMinID = easeInMinID; fEaseInMaxID = easeInMaxID; fEaseInNormID = easeInNormID;
fEaseOutMinID = easeOutMinID; fEaseOutMaxID = easeOutMaxID; fEaseOutNormID = easeOutNormID;
}
void Set(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
if (fDoingUpdate)
return;
fDoingUpdate = true;
IParamBlock2 *pb = owner->GetParamBlockByID(fBlockID);
if (id == fEaseInMinID)
AdjustMin(pb, fEaseInMinID, fEaseInNormID, fEaseInMaxID, v.f);
else if (id == fEaseInNormID)
AdjustNormal(pb, fEaseInMinID, fEaseInNormID, fEaseInMaxID, v.f);
else if (id == fEaseInMaxID)
AdjustMax(pb, fEaseInMinID, fEaseInNormID, fEaseInMaxID, v.f);
else if (id == fEaseOutMinID)
AdjustMin(pb, fEaseOutMinID, fEaseOutNormID, fEaseOutMaxID, v.f);
else if (id == fEaseOutNormID)
AdjustNormal(pb, fEaseOutMinID, fEaseOutNormID, fEaseOutMaxID, v.f);
else if (id == fEaseOutMaxID)
AdjustMax(pb, fEaseOutMinID, fEaseOutNormID, fEaseOutMaxID, v.f);
fDoingUpdate = false;
}
};
//// plMtlChangeCallback /////////////////////////////////////////////////////
// Interface class for receiving info about when things change on a material.
class plMtlChangeCallback
{
public:
virtual void NoteTrackListChanged( void ) { ; }
virtual void SegmentListChanged( void ) { ; }
};
#endif // PL_PASSMTLBASE_H

View File

@ -0,0 +1,68 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_PASSMTLBASICPB_H
#define PL_PASSMTLBASICPB_H
// Param ID's
enum
{
kPassBasColorLock,
kPassBasColorAmb,
kPassBasColor,
kPassBasOpacity,
kPassBasEmissive,
// Specular
kPassBasUseSpec,
kPassBasShine,
kPassBasShineStr,
// New color stuff
kPassBasDiffuseLock,
kPassBasRunColor,
kPassBasSpecColor
};
#endif //PL_PASSMTLBASICPB_H

View File

@ -0,0 +1,256 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plPassMtl.h"
#include "plPassMtlBasicPB.h"
#include "resource.h"
#include "iparamm2.h"
class PassBasicPBAccessor;
extern PassBasicPBAccessor basicAccessor;
class PassBasicDlgProc;
extern PassBasicDlgProc gPassBasicDlgProc;
static ParamBlockDesc2 gPassBasicPB
(
plPassMtl::kBlkBasic, _T("basic"), IDS_PASS_BASIC, GetPassMtlDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI, plPassMtl::kRefBasic,
// UI
IDD_PASS_BASIC, IDS_PASS_BASIC, 0, 0, &gPassBasicDlgProc,
// Color
kPassBasColorLock, _T("colorLock"), TYPE_BOOL, 0, 0,
p_ui, TYPE_CHECKBUTTON, IDC_LOCK_AD,
p_accessor, &basicAccessor,
end,
kPassBasColorAmb, _T("ambColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_AMB,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_COLOR_AMB,
p_accessor, &basicAccessor,
end,
kPassBasColor, _T("color"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_COLOR,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_COLOR,
p_default, Color(1,1,1),
p_accessor, &basicAccessor,
end,
kPassBasRunColor, _T("runtimeColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_RUNCOLOR,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_RUNCOLOR,
p_default, Color(-1,-1,-1),
p_accessor, &basicAccessor,
end,
kPassBasDiffuseLock, _T("diffuseLock"), TYPE_BOOL, 0, 0,
p_ui, TYPE_CHECKBUTTON, IDC_LOCK_COLORS,
p_accessor, &basicAccessor,
p_default, TRUE,
end,
// Opacity
kPassBasOpacity, _T("opacity"), TYPE_INT, P_ANIMATABLE, IDS_BASIC_OPAC,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_TR_EDIT, IDC_TR_SPIN, 0.4,
p_range, 0, 100,
p_default, 100,
end,
kPassBasEmissive, _T("emissive"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_LAYER_EMISSIVE_CB,
end,
// Specularity
kPassBasUseSpec, _T("useSpec"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SHADE_SPECULAR,
p_enable_ctrls, 2, kPassBasShine, kPassBasSpecColor,
end,
kPassBasShine, _T("shine"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_SH_EDIT, IDC_SH_SPIN, 0.4,
p_range, 0, 100,
end,
kPassBasSpecColor, _T("specularColor"), TYPE_RGBA, P_ANIMATABLE, IDS_BASIC_SPECCOLOR,
p_ui, TYPE_COLORSWATCH, IDC_LAYER_SPECCOLOR,
p_default, Color(0,0,0),
end,
// OBSOLETE--here so we can upgrade it to color if necessary
kPassBasShineStr, _T("shineStr"), TYPE_INT, 0, 0,
p_range, -1, 100,
p_default, -1,
end,
end
);
ParamBlockDesc2 *GetPassBasicPB() { return &gPassBasicPB; }
class PassBasicPBAccessor : public PBAccessor
{
bool fColorLocked;
public:
PassBasicPBAccessor() : fColorLocked( false ) {}
void Set(PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
plPassMtl* mtl = (plPassMtl*)owner;
IParamBlock2 *pb = mtl->GetParamBlockByID(plPassMtl::kBlkBasic);
switch (id)
{
case kPassBasColorLock:
if (val.i)
pb->SetValue(kPassBasColor, t, pb->GetColor(kPassBasColorAmb, t));
break;
case kPassBasDiffuseLock:
if (val.i)
pb->SetValue(kPassBasRunColor, t, pb->GetColor(kPassBasColor, t));
break;
case kPassBasColor:
case kPassBasColorAmb:
case kPassBasRunColor:
ISyncLockedColors( id, pb, val, t );
break;
}
}
void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid)
{
}
void ISyncLockedColors( ParamID settingID, IParamBlock2 *pb, PB2Value &val, TimeValue t )
{
int i, numToSet = 0;
ParamID toSet[ 2 ];
if( fColorLocked )
return;
fColorLocked = true;
if( settingID == kPassBasColorAmb && pb->GetInt( kPassBasColorLock, t ) )
{
toSet[ numToSet++ ] = kPassBasColor;
if( pb->GetInt( kPassBasDiffuseLock, t ) )
toSet[ numToSet++ ] = kPassBasRunColor;
}
else if( settingID == kPassBasRunColor && pb->GetInt( kPassBasDiffuseLock, t ) )
{
toSet[ numToSet++ ] = kPassBasColor;
if( pb->GetInt( kPassBasColorLock, t ) )
toSet[ numToSet++ ] = kPassBasColorAmb;
}
else if( settingID == kPassBasColor )
{
if( pb->GetInt( kPassBasColorLock, t ) )
toSet[ numToSet++ ] = kPassBasColorAmb;
if( pb->GetInt( kPassBasDiffuseLock, t ) )
toSet[ numToSet++ ] = kPassBasRunColor;
}
for( i = 0; i < numToSet; i++ )
{
pb->SetValue( toSet[ i ], t, *val.p );
if( pb->GetMap() )
pb->GetMap()->Invalidate( toSet[ i ] );
}
fColorLocked = false;
}
};
static PassBasicPBAccessor basicAccessor;
class PassBasicDlgProc : public ParamMap2UserDlgProc
{
#if 1
protected:
HIMAGELIST hLockButtons;
void LoadLockButtons()
{
static bool loaded = false;
if (loaded)
return;
loaded = true;
HINSTANCE hInst = hInstance;
hLockButtons = ImageList_Create(16, 15, TRUE, 2, 0);
HBITMAP hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BUTTONS));
HBITMAP hMask = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_MASKBUTTONS));
ImageList_Add(hLockButtons, hBitmap, hMask);
DeleteObject(hBitmap);
DeleteObject(hMask);
}
void ISetLock(HWND hButton)
{
LoadLockButtons();
ICustButton *iBut = GetICustButton(hButton);
iBut->SetImage(hLockButtons,0,1,0,1,16,15);
iBut->SetType(CBT_CHECK);
ReleaseICustButton(iBut);
}
public:
PassBasicDlgProc() : hLockButtons(NULL) {}
~PassBasicDlgProc() { if (hLockButtons) ImageList_Destroy(hLockButtons); }
#endif
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
IParamBlock2 *pb = map->GetParamBlock();
switch (msg)
{
case WM_INITDIALOG:
{
ISetLock(GetDlgItem(hWnd, IDC_LOCK_AD));
ISetLock(GetDlgItem(hWnd, IDC_LOCK_COLORS));
}
return TRUE;
}
return FALSE;
}
void DeleteThis() {}
};
static PassBasicDlgProc gPassBasicDlgProc;

View File

@ -0,0 +1,57 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_PASSMTLLAYERSPB_H
#define PL_PASSMTLLAYERSPB_H
enum
{
// Layers
kPassLayBase,
kPassLayTopOn,
kPassLayTop,
kPassLayBlend,
kPassLayOutputBlend,
kPassLayOutputAlpha,
};
#endif //PL_PASSMTLLAYERSPB_H

View File

@ -0,0 +1,102 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plPassMtl.h"
#include "plPassMtlLayersPB.h"
#include "resource.h"
#include "iparamm2.h"
#include "Layers/plLayerTex.h"
class PassMtlLayersAccessor;
extern PassMtlLayersAccessor gLayersAccessor;
class LayersDlgProc;
extern LayersDlgProc gLayersDlgProc;
static ParamBlockDesc2 gPassMtlLayersPB
(
plPassMtl::kBlkLayers, _T("layers"), IDS_PASS_LAYERS, GetPassMtlDesc(),
P_AUTO_CONSTRUCT + P_AUTO_UI, plPassMtl::kRefLayers,
// UI
IDD_PASS_LAYERS, IDS_PASS_LAYERS, 0, 0, NULL,
kPassLayBase, _T("baseLayer"), TYPE_TEXMAP, 0, IDS_BASIC_AMB,
p_ui, TYPE_TEXMAPBUTTON, IDC_LAYER1,
p_subtexno, 0,
end,
kPassLayTopOn, _T("topLayerOn"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_TOP_ON,
p_default, FALSE,
p_enable_ctrls, 3, kPassLayTop, kPassLayBlend, kPassLayOutputAlpha,
end,
kPassLayTop, _T("topLayer"), TYPE_TEXMAP, 0, 0,
p_ui, TYPE_TEXMAPBUTTON, IDC_LAYER2,
p_subtexno, 1,
end,
kPassLayBlend, _T("layerBlend"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_LAYER_ALPHA, IDC_LAYER_ADD, IDC_LAYER_MULTIPLY,
p_vals, plPassMtlBase::kBlendAlpha, plPassMtlBase::kBlendAdd, plPassMtlBase::kBlendMult,
p_default, plPassMtlBase::kBlendAdd,
end,
kPassLayOutputAlpha, _T("ouputAlpha"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_OUTPUTA_DISCARD, IDC_OUTPUTA_ADD, IDC_OUTPUTA_MULT,
p_vals, plPassMtlBase::kAlphaDiscard, plPassMtlBase::kAlphaAdd, plPassMtlBase::kAlphaMultiply,
p_default, plPassMtlBase::kAlphaDiscard,
end,
kPassLayOutputBlend, _T("outputBlend"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_OUTPUTB_NONE, IDC_OUTPUTB_ALPHA, IDC_OUTPUTB_ADD,
p_vals, plPassMtlBase::kBlendNone, plPassMtlBase::kBlendAlpha, plPassMtlBase::kBlendAdd,
p_default, plPassMtlBase::kBlendNone,
end,
end
);
ParamBlockDesc2 *GetPassLayersPB() { return &gPassMtlLayersPB; }