mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 02:27:40 -04:00
Initial Commit of CyanWorlds.com Engine Open Source Client/Plugin
This commit is contained in:
@ -0,0 +1,266 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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;
|
||||
}
|
@ -0,0 +1,970 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// 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, ¢erFrame );
|
||||
::MapWindowPoints( nil, parentMap->GetHWnd(), (POINT *)¢erFrame, 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 );
|
||||
}
|
||||
|
@ -0,0 +1,247 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// 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
|
@ -0,0 +1,660 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "hsTypes.h"
|
||||
#include "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; }
|
@ -0,0 +1,178 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_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
|
@ -0,0 +1,37 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_BUMPMTLANIMPB_H
|
||||
#define PL_BUMPMTLANIMPB_H
|
||||
|
||||
enum
|
||||
{
|
||||
kBumpAnimName,
|
||||
kBumpAnimAutoStart,
|
||||
kBumpAnimLoop,
|
||||
kBumpAnimLoopName,
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,93 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "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; }
|
@ -0,0 +1,38 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_BUMPMTLBASICPB_H
|
||||
#define PL_BUMPMTLBASICPB_H
|
||||
|
||||
// Param ID's
|
||||
enum
|
||||
{
|
||||
kBumpBasSpecular,
|
||||
kBumpBasRunColor,
|
||||
kBumpBasLayer
|
||||
|
||||
};
|
||||
|
||||
#endif //PL_BUMPMTLBASICPB_H
|
@ -0,0 +1,92 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "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;
|
||||
|
||||
|
@ -0,0 +1,699 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -0,0 +1,201 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_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
|
@ -0,0 +1,426 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//#include "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;
|
@ -0,0 +1,568 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "hsTypes.h"
|
||||
#include "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;
|
||||
}
|
||||
*/
|
@ -0,0 +1,154 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef __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
|
@ -0,0 +1,277 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "hsTypes.h"
|
||||
#include "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();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,86 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
@ -0,0 +1,65 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_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
|
@ -0,0 +1,51 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "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
|
||||
);
|
@ -0,0 +1,784 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "hsTypes.h"
|
||||
#include "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); }
|
||||
|
@ -0,0 +1,193 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_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
|
@ -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/>.
|
||||
|
||||
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
|
@ -0,0 +1,95 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "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; }
|
@ -0,0 +1,47 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_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
|
@ -0,0 +1,93 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "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; }
|
@ -0,0 +1,52 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_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
|
@ -0,0 +1,236 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "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;
|
@ -0,0 +1,40 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_DECALMTLLAYERSPB_H
|
||||
#define PL_DECALMTLLAYERSPB_H
|
||||
|
||||
enum
|
||||
{
|
||||
// Layers
|
||||
kDecalLayBase,
|
||||
kDecalLayOutputBlend,
|
||||
kDecalLayTopOn,
|
||||
kDecalLayTop,
|
||||
kDecalLayBlend,
|
||||
kDecalLayOutputAlpha,
|
||||
};
|
||||
|
||||
#endif //PL_DECALMTLLAYERSPB_H
|
@ -0,0 +1,87 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#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; }
|
@ -0,0 +1,370 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "hsTypes.h"
|
||||
#include "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));
|
||||
}
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef __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
|
@ -0,0 +1,326 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "hsTypes.h"
|
||||
#include "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);
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_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
|
@ -0,0 +1,50 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "hsTypes.h"
|
||||
#include "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
|
||||
);
|
@ -0,0 +1,37 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_MULTIPASS_MTL_PB_H
|
||||
#define PL_MULTIPASS_MTL_PB_H
|
||||
|
||||
enum
|
||||
{
|
||||
kMultCount,
|
||||
kMultPasses,
|
||||
kMultOn,
|
||||
kMultLayerCounts
|
||||
};
|
||||
|
||||
#endif //PL_MULTIPASS_MTL_PB_H
|
@ -0,0 +1,127 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// 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;
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
@ -0,0 +1,620 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "hsTypes.h"
|
||||
#include "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)); }
|
@ -0,0 +1,182 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_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
|
@ -0,0 +1,234 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "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;
|
@ -0,0 +1,305 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// 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 );
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,84 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// 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
|
@ -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/>.
|
||||
|
||||
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
|
@ -0,0 +1,846 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "hsTypes.h"
|
||||
#include "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); }
|
@ -0,0 +1,197 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_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
|
@ -0,0 +1,59 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_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
|
@ -0,0 +1,94 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "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; }
|
@ -0,0 +1,85 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_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
|
@ -0,0 +1,95 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "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; }
|
||||
|
@ -0,0 +1,660 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// 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;
|
||||
}
|
@ -0,0 +1,285 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_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
|
@ -0,0 +1,52 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_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
|
@ -0,0 +1,240 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "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;
|
||||
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef PL_PASSMTLLAYERSPB_H
|
||||
#define PL_PASSMTLLAYERSPB_H
|
||||
|
||||
enum
|
||||
{
|
||||
// Layers
|
||||
kPassLayBase,
|
||||
kPassLayTopOn,
|
||||
kPassLayTop,
|
||||
|
||||
kPassLayBlend,
|
||||
kPassLayOutputBlend,
|
||||
kPassLayOutputAlpha,
|
||||
};
|
||||
|
||||
#endif //PL_PASSMTLLAYERSPB_H
|
@ -0,0 +1,86 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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; }
|
Reference in New Issue
Block a user