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

CWE Directory Reorganization

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

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

View File

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

View File

@ -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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
void DummyCodeIncludeFunc(); //Anim Comp
void DummyCodeIncludeFuncActive(); //Activator Comp
void DummyCodeIncludeFuncResponder(); //Responder Comp
void DummyCodeIncludeFuncAudio(); //Audio Comps
void DummyCodeIncludeFuncA(); //Player Comp
void DummyCodeIncludeFuncCollection(); // ??? Isn't used! ??? Why is it here? ???
void DummyCodeIncludeFuncTypes(); //Type Comps (Portal, StartingPoint, etc...)
void DummyCodeIncludeFuncMisc(); //Misc Comps (Interesting, PageInfo, Room, etc..)
void DummyCodeIncludeFuncPhys(); //Physical Comps
void DummyCodeIncludeFuncParticles(); //Particle Comps
void DummyCodeIncludeAvatarFunc(); //Avatar Comps
void DummyCodeIncludeFuncSmooth(); //Smoot Comp
void DummyCodeIncludeFuncClickable(); //Clickable Comp
void DummyCodeIncludeFuncSeekPoint(); //Avatar Seekpoint Comp
void DummyCodeIncludeFuncSingleSht(); //OneShot Comp
void DummyCodeIncludeFuncAGComp(); //Avatar Anim Comp
void DummyCodeIncludeFuncClickDrag(); //click-draggable gadget
void DummyCodeIncludeFuncInventStuff(); //InventoryObj Comp
void DummyCodeIncludeFuncVolumeGadget();// phys volume activator
//void DummyCodeIncludeFuncActivatorGadget();// activator activator
void DummyCodeIncludeFuncImpactGadget(); // collision activator
void DummyCodeIncludeFuncSoftVolume(); // Soft Volume
void DummyCodeIncludeFuncPhysConst(); // Phys Constraints
void DummyCodeIncludeFuncCameras(); // new cameras
void DummyCodeIncludePythonFileFunc();
void DummyCodeIncludeFuncDistrib(); // Geometry distribution functions
void DummyCodeIncludeFuncCluster(); // Geometry clustering functions
void DummyCodeIncludeFuncExcludeRegion();
void DummyCodeIncludeFuncGUI(); // User Interface components
void DummyCodeIncludeFuncIgnore(); // User Interface components
void DummyCodeIncludeFuncBlow(); // Procedural wind modifier
void DummyCodeIncludeFuncWater(); // All things wet.
void DummyCodeIncludeFuncLightMap(); // LightMap
void DummyCodeIncludeFuncXImposter(); // Like a billboard, but exier.
void DummyCodeIncludeFuncRepComp(); // Different representations
void DummyCodeIncludeFuncLineFollow(); // Things that follow a line
void DummyCodeIncludeFuncMorph(); // Like putty in my hands
void DummyCodeIncludeFuncLODFade(); // Alpha blending lod transition
void DummyCodeIncludeFuncBehaviors(); // Av Behaviors, like Sitting
void DummyCodeIncludeFuncNavigablesRegion(); //Ladder Climbing...
void DummyCodeIncludeFuncTemplate();
void DummyCodeIncludeFuncClothing();
void DummyCodeIncludeFuncMultistageBeh();
void DummyCodeIncludeFuncAnimDetector();
void DummyCodeIncludeFuncShadow(); // Components controlling shadow generation.
void DummyCodeIncludeFuncFootstepSound();
void DummyCodeIncludeFuncFootPrint(); // dynamic decals
void DummyCodeIncludFuncNPCSpawn(); // npc spawners
void DummyCodeIncludeFuncClimbTrigger();
void DummyCodeIncludeFuncObjectFlocker();
void DummyCodeIncludeFuncGrassShader();

View File

@ -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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

View File

@ -0,0 +1,786 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "max.h"
#include "resource.h"
#include "hsTemplates.h"
#include "pfGUISkinComp.h"
#include "plGUICompClassIDs.h"
#include "../MaxMain/plMaxNodeBase.h"
pfGUISkinEditProc *pfGUISkinEditProc::fInstance = nil;
int pfGUISkinEditProc::fZoom = 3; // So re-opening the dialog will keep the same zoom level
extern HINSTANCE hInstance;
pfGUISkinEditProc::pfGUISkinEditProc( plGUISkinComp *comp )
{
fInstance = this;
fComp = comp;
fDblDC = nil;
fDblBitmap = nil;
fXOffset = fYOffset = 0;
fCurrPBRefSet = plGUISkinComp::kRefUpLeftCorner;
fDefPen = CreatePen( PS_SOLID, 3, RGB( 200, 0, 0 ) );
fOtherPen = CreatePen( PS_DOT, 1, RGB( 200, 0, 0 ) );
fDragging = false;
fDragTimer = 0;
// Back up the old settings
IParamBlock2 *pb = fComp->GetParamBlockByID( plComponent::kBlkComp );
for( int i = 0; i < pfGUISkin::kNumElements; i++ )
{
int id = i * 4 + plGUISkinComp::kRefUpLeftCorner;
fBackups[ i ].fX = pb->GetInt( id + 0 );
fBackups[ i ].fY = pb->GetInt( id + 1 );
fBackups[ i ].fWidth = pb->GetInt( id + 2 );
fBackups[ i ].fHeight = pb->GetInt( id + 3 );
}
}
pfGUISkinEditProc::~pfGUISkinEditProc()
{
fInstance = nil;
DeleteObject( fDefPen );
IKillDblBuffer();
}
void pfGUISkinEditProc::IJustDrawOneRect( int whichElement, IParamBlock2 *pb, HDC hDC, HPEN whichPen, int refToIgnore )
{
whichElement = ( whichElement * 4 ) + plGUISkinComp::kRefUpLeftCorner;
if( whichElement == refToIgnore )
return;
RECT r;
SetRect( &r, pb->GetInt( whichElement + 0 ),
pb->GetInt( whichElement + 1 ),
pb->GetInt( whichElement + 0 ) + pb->GetInt( whichElement + 2 ),
pb->GetInt( whichElement + 1 ) + pb->GetInt( whichElement + 3 ) );
r.left *= fZoom; r.right *= fZoom; r.top *= fZoom; r.bottom *= fZoom;
SelectObject( hDC, whichPen );
int rop2 = SetROP2( hDC, R2_NOTXORPEN );
MoveToEx( hDC, r.left, r.top, nil );
LineTo( hDC, r.right, r.top );
LineTo( hDC, r.right, r.bottom );
LineTo( hDC, r.left, r.bottom );
LineTo( hDC, r.left, r.top );
SetROP2( hDC, rop2 );
}
void pfGUISkinEditProc::IRefreshDblBuffer( void )
{
// Image buffer is where we keep our resized image. Dbl buffer is where we draw our bounds
if( fDblDC == nil )
IInitDblBuffer();
else
{
// Copy the zoomed image as our backdrop
BitBlt( fDblDC, 0, 0, fDblWidth, fDblHeight, fImageDC, 0, 0, SRCCOPY );
RECT r;
IParamBlock2 *pb = fComp->GetParamBlockByID( plComponent::kBlkComp );
if( pb != nil )
{
// Draw all the other elements other than our current one
for( int i = 0; i < pfGUISkin::kNumElements; i++ )
IJustDrawOneRect( i, pb, fDblDC, fOtherPen, fCurrPBRefSet );
// Now draw the bounds of our current element
SetRect( &r, pb->GetInt( fCurrPBRefSet + 0 ),
pb->GetInt( fCurrPBRefSet + 1 ),
pb->GetInt( fCurrPBRefSet + 0 ) + pb->GetInt( fCurrPBRefSet + 2 ),
pb->GetInt( fCurrPBRefSet + 1 ) + pb->GetInt( fCurrPBRefSet + 3 ) );
// While we have it here, go ahead and update our status text for this element
char str[ 256 ];
sprintf( str, "Left: %d\nTop: %d\nWidth: %d\nHeight: %d\n", r.left, r.top, r.right - r.left, r.bottom - r.top );
SetDlgItemText( fHWnd, IDC_GUI_INFO, str );
r.left *= fZoom; r.right *= fZoom; r.top *= fZoom; r.bottom *= fZoom;
SelectObject( fDblDC, fDefPen );
int rop2 = SetROP2( fDblDC, R2_NOTXORPEN );
MoveToEx( fDblDC, r.left, r.top, nil );
LineTo( fDblDC, r.right, r.top );
LineTo( fDblDC, r.right, r.bottom );
LineTo( fDblDC, r.left, r.bottom );
LineTo( fDblDC, r.left, r.top );
SetROP2( fDblDC, rop2 );
fCurrElemRect = r;
MapWindowPoints( GetDlgItem( fHWnd, IDC_GUI_PREVIEW ), fHWnd, (POINT *)&fCurrElemRect, 2 );
OffsetRect( &fCurrElemRect, -fXOffset, -fYOffset );
}
}
}
void pfGUISkinEditProc::IRefreshImageBuffer( void )
{
IInitDblBuffer();
plLayerTex *layer = fComp->GetSkinBitmap();
PBBitmap *pbBMap = layer->GetPBBitmap();
if( pbBMap->bm == nil )
pbBMap->Load();
if( pbBMap->bm != nil )
{
// Copy into a new temp bitmap that is the right format for us to read
Bitmap *newBM;
BitmapInfo bi;
bi.SetName( _T("y879873b") );
bi.SetType( BMM_TRUE_32 );
bi.SetFlags( MAP_HAS_ALPHA );
bi.SetWidth( fDblWidth );
bi.SetHeight( fDblHeight );
newBM = TheManager->Create( &bi );
BMM_Color_64 foo = { 0, 0, 0, 0 };
newBM->CopyImage( pbBMap->bm, COPY_IMAGE_RESIZE_LO_QUALITY, foo, nil );
// Now copy from our newly created bitmap into our DC....way slow :(
BITMAPINFO *bitInfo = newBM->ToDib( 24, nil, false );
if( bitInfo != nil )
{
SetDIBitsToDevice( fImageDC, 0, 0, fDblWidth, fDblHeight,
0, 0, 0, fDblHeight,
( (UInt8 *)bitInfo ) + bitInfo->bmiHeader.biSize,
bitInfo,
DIB_RGB_COLORS );
}
newBM->DeleteThis();
}
IRefreshDblBuffer();
}
void pfGUISkinEditProc::IInitDblBuffer( void )
{
if( fDblDC == NULL )
{
int width, height;
HDC desk = GetDC( NULL );
plLayerTex *layer = fComp->GetSkinBitmap();
PBBitmap *pbBMap = layer->GetPBBitmap();
if( pbBMap == nil )
return;
width = pbBMap->bi.Width() * fZoom;
height = pbBMap->bi.Height() * fZoom;
// GetClientRect( fHWnd, &r );
// width = r.right - r.left;
// height = r.bottom - r.top;
// Note: For some strange reason, grabbing the HDC of the window doesn't do
// any good, 'cause it's black-and-white (right, THAT makes sense). Grabbing
// the desktop DC works, however.
fDblDC = CreateCompatibleDC( desk );
fDblBitmap = CreateCompatibleBitmap( desk/*fDblDC*/, width, height );
SelectObject( fDblDC, fDblBitmap );
fImageDC = CreateCompatibleDC( desk );
fImageBitmap = CreateCompatibleBitmap( desk/*fDblDC*/, width, height );
SelectObject( fImageDC, fImageBitmap );
ReleaseDC( NULL, desk );
fDblWidth = width;
fDblHeight = height;
ISetScrollRanges();
IRefreshImageBuffer();
}
}
void pfGUISkinEditProc::IKillDblBuffer( void )
{
if( fDblDC != NULL )
{
SelectObject( fDblDC, (HBITMAP)NULL );
DeleteObject( fDblBitmap );
DeleteDC( fDblDC );
}
if( fImageDC != NULL )
{
SelectObject( fImageDC, (HBITMAP)NULL );
DeleteObject( fImageBitmap );
DeleteDC( fImageDC );
}
fDblDC = fImageDC = nil;
fDblBitmap = fImageBitmap = nil;
}
void pfGUISkinEditProc::ISetScrollRanges( void )
{
SCROLLINFO info;
int visW = fPreviewRect.right - fPreviewRect.left;
int visH = fPreviewRect.bottom - fPreviewRect.top;
if( visW < fDblWidth )
{
if( fXOffset > fDblWidth - visW )
fXOffset = fDblWidth - visW;
else if( fXOffset < 0 )
fXOffset = 0;
info.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
info.nMin = 0;
info.nMax = fDblWidth;// - visW;
info.nPage = visW;
info.nPos = fXOffset;
info.cbSize = sizeof( info );
SetScrollInfo( GetDlgItem( fHWnd, IDC_GUI_HORZSCROLL ), SB_CTL, &info, true );
ShowWindow( GetDlgItem( fHWnd, IDC_GUI_HORZSCROLL ), true );
}
else
{
ShowWindow( GetDlgItem( fHWnd, IDC_GUI_HORZSCROLL ), false );
fXOffset = 0;
}
if( visH < fDblHeight )
{
if( fYOffset > fDblHeight - visH )
fYOffset = fDblHeight - visH;
else if( fYOffset < 0 )
fYOffset = 0;
info.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
info.nMin = 0;
info.nMax = fDblHeight;// - visH;
info.nPage = visH;
info.nPos = fYOffset;
info.cbSize = sizeof( info );
SetScrollInfo( GetDlgItem( fHWnd, IDC_GUI_VERTSCROLL ), SB_CTL, &info, true );
ShowWindow( GetDlgItem( fHWnd, IDC_GUI_VERTSCROLL ), true );
}
else
{
ShowWindow( GetDlgItem( fHWnd, IDC_GUI_VERTSCROLL ), false );
fYOffset = 0;
}
}
bool pfGUISkinEditProc::IPointWithinRange( int x, int y, int ptX, int ptY )
{
if( x > ptX - kRangeSlop && x < ptX + kRangeSlop &&
y > ptY - kRangeSlop && y < ptY + kRangeSlop )
return true;
return false;
}
bool pfGUISkinEditProc::IPointWithinVertRange( int x, int y, int ptX, int ptY1, int ptY2 )
{
if( x > ptX - kRangeSlop && x < ptX + kRangeSlop &&
y > ptY1 - kRangeSlop && y < ptY2 + kRangeSlop )
return true;
return false;
}
bool pfGUISkinEditProc::IPointWithinHorzRange( int x, int y, int ptX1, int ptX2, int ptY )
{
if( x > ptX1 - kRangeSlop && x < ptX2 + kRangeSlop &&
y > ptY - kRangeSlop && y < ptY + kRangeSlop )
return true;
return false;
}
UInt8 pfGUISkinEditProc::IGetDragTypeFlags( int x, int y )
{
// Corners
if( IPointWithinRange( x, y, fCurrElemRect.left, fCurrElemRect.top ) )
return kLeft | kTop;
if( IPointWithinRange( x, y, fCurrElemRect.right, fCurrElemRect.top ) )
return kRight | kTop;
if( IPointWithinRange( x, y, fCurrElemRect.right, fCurrElemRect.bottom ) )
return kRight | kBottom;
if( IPointWithinRange( x, y, fCurrElemRect.left, fCurrElemRect.bottom ) )
return kLeft | kBottom;
// Edges
if( IPointWithinVertRange( x, y, fCurrElemRect.left, fCurrElemRect.top, fCurrElemRect.bottom ) )
return kLeft;
if( IPointWithinVertRange( x, y, fCurrElemRect.right, fCurrElemRect.top, fCurrElemRect.bottom ) )
return kRight;
if( IPointWithinHorzRange( x, y, fCurrElemRect.left, fCurrElemRect.right, fCurrElemRect.top ) )
return kTop;
if( IPointWithinHorzRange( x, y, fCurrElemRect.left, fCurrElemRect.right, fCurrElemRect.bottom ) )
return kBottom;
// The middle
if( x >= fCurrElemRect.left && x <= fCurrElemRect.right && y >= fCurrElemRect.top && y <= fCurrElemRect.bottom )
return kDragAll;
return 0;
}
INT_PTR CALLBACK pfGUISkinEditProc::DlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
return fInstance->DialogProc( hDlg, msg, wParam, lParam );
}
INT_PTR CALLBACK pfGUISkinEditProc::DialogProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
PAINTSTRUCT pInfo;
RECT r;
HDC hDC;
int maxDim, i, j, x, y;
bool timerActive = false;
static struct plElemPair
{
pfGUISkin::Elements el;
const char *name;
} sElemPairs[] = { { pfGUISkin::kUpLeftCorner, "Upper-left Corner" },
{ pfGUISkin::kTopSpan, "Top Span" },
{ pfGUISkin::kUpRightCorner, "Upper-right Corner" },
{ pfGUISkin::kRightSpan, "Right Span" },
{ pfGUISkin::kLowerRightCorner, "Lower-right Corner" },
{ pfGUISkin::kBottomSpan, "Bottom Span" },
{ pfGUISkin::kLowerLeftCorner, "Lower-left Corner" },
{ pfGUISkin::kLeftSpan, "Left Span" },
{ pfGUISkin::kMiddleFill, "Middle Fill" },
{ pfGUISkin::kSelectedFill, "Selected Middle Fill" },
{ pfGUISkin::kSubMenuArrow, "Sub-Menu Arrow" },
{ pfGUISkin::kSelectedSubMenuArrow, "Selected Sub-Menu Arrow" },
{ pfGUISkin::kTreeButtonClosed, "Tree-view Button, Closed" },
{ pfGUISkin::kTreeButtonOpen, "Tree-view Button, Open" },
{ pfGUISkin::kNumElements, nil } };
fHWnd = hDlg;
switch( msg )
{
case WM_INITDIALOG:
// Get preview rect
GetClientRect( GetDlgItem( hDlg, IDC_GUI_PREVIEW ), &fPreviewRect );
MapWindowPoints( GetDlgItem( hDlg, IDC_GUI_PREVIEW ), hDlg, (POINT *)&fPreviewRect, 2 );
SendDlgItemMessage( hDlg, IDC_GUI_ZIN, BM_SETIMAGE, (WPARAM)IMAGE_ICON,
(LPARAM)LoadImage( hInstance, MAKEINTRESOURCE( IDI_ZOOMIN ), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR ) );
SendDlgItemMessage( hDlg, IDC_GUI_ZOUT, BM_SETIMAGE, (WPARAM)IMAGE_ICON,
(LPARAM)LoadImage( hInstance, MAKEINTRESOURCE( IDI_ZOOMOUT ), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR ) );
// Fill element list
SendDlgItemMessage( hDlg, IDC_GUI_ELEMENTS, LB_RESETCONTENT, 0, 0 );
for( i = 0; sElemPairs[ i ].el != pfGUISkin::kNumElements; i++ )
{
int idx = SendDlgItemMessage( hDlg, IDC_GUI_ELEMENTS, LB_ADDSTRING, 0, (LPARAM)sElemPairs[ i ].name );
SendDlgItemMessage( hDlg, IDC_GUI_ELEMENTS, LB_SETITEMDATA, (WPARAM)idx, (LPARAM)sElemPairs[ i ].el );
if( sElemPairs[ i ].el == pfGUISkin::kUpLeftCorner )
j = idx;
}
SendDlgItemMessage( hDlg, IDC_GUI_ELEMENTS, LB_SETCURSEL, j, 0 );
fOrigCursor = LoadCursor( nil, IDC_ARROW );//GetCursor();
break;
case WM_COMMAND:
if( LOWORD( wParam ) == IDCANCEL )
{
// Since we've been editing the PB directly, we have to now restore them
// to their original values
IParamBlock2 *pb = fComp->GetParamBlockByID( plComponent::kBlkComp );
for( int i = 0; i < pfGUISkin::kNumElements; i++ )
{
int id = i * 4 + plGUISkinComp::kRefUpLeftCorner;
pb->SetValue( id + 0, 0, (int)fBackups[ i ].fX );
pb->SetValue( id + 1, 0, (int)fBackups[ i ].fY );
pb->SetValue( id + 2, 0, (int)fBackups[ i ].fWidth );
pb->SetValue( id + 3, 0, (int)fBackups[ i ].fHeight );
}
EndDialog( hDlg, 1 );
}
else if( LOWORD( wParam ) == IDOK )
EndDialog( hDlg, 0 );
else if( LOWORD( wParam ) == IDC_GUI_ZIN )
{
fXOffset /= fZoom; fYOffset /= fZoom;
fZoom++;
fXOffset *= fZoom; fYOffset *= fZoom;
IKillDblBuffer();
IRefreshImageBuffer();
InvalidateRect( hDlg, &fPreviewRect, false );
}
else if( LOWORD( wParam ) == IDC_GUI_ZOUT )
{
if( fZoom > 1 )
{
fXOffset /= fZoom; fYOffset /= fZoom;
fZoom--;
fXOffset *= fZoom; fYOffset *= fZoom;
IKillDblBuffer();
IRefreshImageBuffer();
InvalidateRect( hDlg, &fPreviewRect, false );
}
}
else if( LOWORD( wParam ) == IDC_GUI_ELEMENTS )
{
int idx = SendDlgItemMessage( hDlg, IDC_GUI_ELEMENTS, LB_GETCURSEL, 0, 0 );
fCurrPBRefSet = SendDlgItemMessage( hDlg, IDC_GUI_ELEMENTS, LB_GETITEMDATA, (WPARAM)idx, 0 ) * 4 + plGUISkinComp::kRefUpLeftCorner;
IRefreshDblBuffer();
InvalidateRect( hDlg, &fPreviewRect, false );
}
return true;
case WM_CLOSE:
EndDialog( hDlg, 0 );
return true;
case WM_HSCROLL:
OffsetRect( &fCurrElemRect, fXOffset, fYOffset );
switch( LOWORD( wParam ) )
{
case SB_PAGEUP: fXOffset -= 300; break;
case SB_PAGEDOWN: fXOffset += 300; break;
case SB_LINEUP: fXOffset -= 16; break;
case SB_LINEDOWN: fXOffset += 16; break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
fXOffset = HIWORD( wParam );
break;
}
maxDim = fDblWidth - ( fPreviewRect.right - fPreviewRect.left );
if( fXOffset < 0 )
fXOffset = 0;
else if( fXOffset > maxDim )
fXOffset = maxDim;
SetScrollPos( GetDlgItem( hDlg, IDC_GUI_HORZSCROLL ), SB_CTL, fXOffset, true );
OffsetRect( &fCurrElemRect, -fXOffset, -fYOffset );
InvalidateRect( hDlg, &fPreviewRect, false );
break;
case WM_VSCROLL:
OffsetRect( &fCurrElemRect, fXOffset, fYOffset );
switch( LOWORD( wParam ) )
{
case SB_PAGEUP: fYOffset -= 300; break;
case SB_PAGEDOWN: fYOffset += 300; break;
case SB_LINEUP: fYOffset -= 16; break;
case SB_LINEDOWN: fYOffset += 16; break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
fYOffset = HIWORD( wParam );
break;
}
maxDim = fDblHeight - ( fPreviewRect.bottom - fPreviewRect.top );
if( fYOffset < 0 )
fYOffset = 0;
else if( fYOffset > maxDim )
fYOffset = maxDim;
SetScrollPos( GetDlgItem( hDlg, IDC_GUI_VERTSCROLL ), SB_CTL, fYOffset, true );
OffsetRect( &fCurrElemRect, -fXOffset, -fYOffset );
InvalidateRect( hDlg, &fPreviewRect, false );
break;
case WM_PAINT:
{
BeginPaint( hDlg, &pInfo );
hDC = (HDC)pInfo.hdc;
if( fDblDC == NULL )
IInitDblBuffer();
int width = fDblWidth;
int height = fDblHeight;
if( width > fPreviewRect.right - fPreviewRect.left )
width = fPreviewRect.right - fPreviewRect.left;
if( height > fPreviewRect.bottom - fPreviewRect.top )
height = fPreviewRect.bottom - fPreviewRect.top;
BitBlt( hDC, fPreviewRect.left, fPreviewRect.top, width, height, fDblDC, fXOffset, fYOffset, SRCCOPY );
r = fPreviewRect;
r.left += width;
FillRect( hDC, &r, ColorMan()->GetBrush( kBackground ) );
r = fPreviewRect;
r.top += height;
FillRect( hDC, &r, ColorMan()->GetBrush( kBackground ) );
EndPaint( hDlg, &pInfo );
}
break;
case WM_LBUTTONDOWN:
SetCapture( hDlg );
fDragging = true;
fDragType = IGetDragTypeFlags( GET_X_LPARAM( lParam ), GET_Y_LPARAM( lParam ) );
if( fDragType == kDragAll )
{
fDragOffsetX = fCurrElemRect.left - GET_X_LPARAM( lParam );
fDragOffsetY = fCurrElemRect.top - GET_Y_LPARAM( lParam );
}
else if( fDragType == 0 )
{
fDragOffsetX = GET_X_LPARAM( lParam ) + fXOffset;
fDragOffsetY = GET_Y_LPARAM( lParam ) + fYOffset;
}
else
fDragOffsetX = fDragOffsetY = 0;
break;
case WM_LBUTTONUP:
ReleaseCapture();
fDragging = false;
break;
case WM_TIMER:
// We do the same processing as MOUSEMOVE, but we need to make sure we have the right
// mouse position first
{
POINT pt;
GetCursorPos( &pt );
MapWindowPoints( nil, hDlg, &pt, 1 );
lParam = MAKELPARAM( pt.x, pt.y );
}
// Fall thru...
case WM_MOUSEMOVE:
x = GET_X_LPARAM( lParam );
y = GET_Y_LPARAM( lParam );
if( fDragging )
{
if( fDragType == 0 )
{
fXOffset = fDragOffsetX - x;
fYOffset = fDragOffsetY - y;
ISetScrollRanges(); // Will clamp offset \for us
}
else
{
// Translate x and y into bitmap space
POINT pt;
pt.x = x;
pt.y = y;
if( PtInRect( &fPreviewRect, pt ) )
{
MapWindowPoints( hDlg, GetDlgItem( hDlg, IDC_GUI_PREVIEW ), &pt, 1 );
pt.x += fDragOffsetX;
pt.y += fDragOffsetY;
// Note the + 1/2 zoom so it's the closest pixel by center, not by area
x = ( pt.x + fXOffset + ( fZoom >> 1 ) ) / fZoom;
y = ( pt.y + fYOffset + ( fZoom >> 1 ) ) / fZoom;
// Set depending on our current drag flags
// Note the logic here: if we drag left, we want width and left changing,
// if we drag both, just left, if we drag right, just width
IParamBlock2 *pb = fComp->GetParamBlockByID( plComponent::kBlkComp );
if( fDragType & kLeft )
{
if( fDragType & kRight )
pb->SetValue( fCurrPBRefSet + 0, 0, (int)x );
else
{
int old = pb->GetInt( fCurrPBRefSet + 0 ) + pb->GetInt( fCurrPBRefSet + 2 );
pb->SetValue( fCurrPBRefSet + 0, 0, (int)x );
pb->SetValue( fCurrPBRefSet + 2, 0, (int)old - x );
}
}
else if( fDragType & kRight )
pb->SetValue( fCurrPBRefSet + 2, 0, (int)x - pb->GetInt( fCurrPBRefSet + 0 ) );
if( fDragType & kTop )
{
if( fDragType & kBottom )
pb->SetValue( fCurrPBRefSet + 1, 0, (int)y );
else
{
int old = pb->GetInt( fCurrPBRefSet + 1 ) + pb->GetInt( fCurrPBRefSet + 3 );
pb->SetValue( fCurrPBRefSet + 1, 0, (int)y );
pb->SetValue( fCurrPBRefSet + 3, 0, (int)old - y );
}
}
else if( fDragType & kBottom )
pb->SetValue( fCurrPBRefSet + 3, 0, (int)y - pb->GetInt( fCurrPBRefSet + 1 ) );
// Clamp width and height
if( pb->GetInt( fCurrPBRefSet + 2 ) < 0 )
pb->SetValue( fCurrPBRefSet + 2, 0, (int)0 );
if( pb->GetInt( fCurrPBRefSet + 3 ) < 0 )
pb->SetValue( fCurrPBRefSet + 3, 0, (int)0 );
// Clamp X and Y
if( pb->GetInt( fCurrPBRefSet + 0 ) < 0 )
pb->SetValue( fCurrPBRefSet + 0, 0, (int)0 );
else if( pb->GetInt( fCurrPBRefSet + 0 ) + pb->GetInt( fCurrPBRefSet + 2 ) > fDblWidth / fZoom )
pb->SetValue( fCurrPBRefSet + 0, 0, (int)fDblWidth / fZoom - pb->GetInt( fCurrPBRefSet + 2 ) );
if( pb->GetInt( fCurrPBRefSet + 1 ) < 0 )
pb->SetValue( fCurrPBRefSet + 1, 0, (int)0 );
else if( pb->GetInt( fCurrPBRefSet + 1 ) + pb->GetInt( fCurrPBRefSet + 3 ) > fDblHeight / fZoom )
pb->SetValue( fCurrPBRefSet + 1, 0, (int)fDblHeight / fZoom - pb->GetInt( fCurrPBRefSet + 3 ) );
}
else
{
// Mouse is outside our preview, so scroll if possible
int dX = ( x < fPreviewRect.left ) ? x - fPreviewRect.left : ( x > fPreviewRect.right ) ? x - fPreviewRect.right : 0;
int dY = ( y < fPreviewRect.top ) ? y - fPreviewRect.top : ( y > fPreviewRect.bottom ) ? y - fPreviewRect.bottom : 0;
fXOffset += dX;
fYOffset += dY;
OffsetRect( &fCurrElemRect, -dX, -dY );
ISetScrollRanges(); // Will clamp origin for us
// Don't actually drag our bounds, 'cause we're scrolling
// Note: since we only get MOUSEMOVE when, gee, the mouse moves, if we've scrolled over, it'll only
// do it once and then wait for the mouse to nudge again. We'd rather it keep going until the user
// moves the mouse again, so we create a timer that calls us back in n somethingths so we can check again
if( fDragTimer == 0 )
fDragTimer = SetTimer( hDlg, 0, 200, nil );
timerActive = true; // So we don't kill it at the end here...
}
}
IRefreshDblBuffer();
InvalidateRect( hDlg, &fPreviewRect, false );
}
else
{
UInt8 dragType = IGetDragTypeFlags( x, y );
HCURSOR cursor;
switch( dragType )
{
case kLeft | kTop:
case kRight | kBottom:
cursor = LoadCursor( nil, IDC_SIZENWSE );
break;
case kLeft | kBottom:
case kRight | kTop:
cursor = LoadCursor( nil, IDC_SIZENESW );
break;
case kLeft:
case kRight:
cursor = LoadCursor( nil, IDC_SIZEWE );
break;
case kTop:
case kBottom:
cursor = LoadCursor( nil, IDC_SIZENS );
break;
case kLeft | kTop | kRight | kBottom:
cursor = LoadCursor( nil, IDC_SIZEALL );
break;
default:
{
POINT pt;
pt.x = x;
pt.y = y;
if( PtInRect( &fPreviewRect, pt ) )
cursor = LoadCursor( nil, IDC_HAND );
else
cursor = fOrigCursor;
}
break;
}
SetCursor( cursor );
if( !timerActive )
{
// No longer need our trick timer, so kill it
KillTimer( hDlg, fDragTimer );
fDragTimer = 0;
}
}
break;
}
return false;
}
plGUISkinComp *plGUISkinComp::GetGUIComp( INode *node )
{
if( node == nil )
return nil;
plComponentBase *base = ( ( plMaxNodeBase *)node )->ConvertToComponent();
if( base == nil )
return nil;
if( base->ClassID() == GUI_SKIN_CLASSID )
return (plGUISkinComp *)base;
return nil;
}

View File

@ -0,0 +1,170 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef _pfGUISkinComp_h
#define _pfGUISkinComp_h
#include "plComponent.h"
#include "../MaxPlasmaMtls/Layers/plLayerTex.h"
#include "../pfGameGUIMgr/pfGUIPopUpMenu.h"
/// skin component class
class plGUISkinComp : public plComponent
{
public:
plGUISkinComp();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg);
hsBool PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool DeInit(plMaxNode *node, plErrorMsg *pErrMsg);
plLayerTex *GetSkinBitmap( void );
virtual UInt32 GetNumMtls( void ) const;
virtual Texmap *GetMtl( UInt32 idx );
enum
{
kRefBitmap = 256, // So we can share it among other components
kRefUpLeftCorner = 257,
kRefTopSpan = 257 + 4,
kRefUpRightCorner = 257 + 8,
kRefRightSpan = 257 + 12,
kRefLowerRightCorner = 257 + 16,
kRefBottomSpan = 257 + 20,
kRefLowerLeftCorner = 257 + 24,
kRefLeftSpan = 257 + 28,
kRefMiddleFill = 257 + 32,
kRefSelectedFill = 257 + 36,
kRefSubMenuArrow = 257 + 40,
kRefSelectedSubMenuArrow = 257 + 44,
kRefTreeButtonClosed = 257 + 48,
kRefTreeButtonOpen = 257 + 52,
kRefItemMargin = 400,
kRefBorderMargin
};
pfGUISkin *GetConvertedSkin( void ) const { return fConvertedSkin; }
plKey GetConvertedSkinKey( void ) const;
// Given an INode, gives you a pointer to the GUI component if it actually is one, nil otherwise
static plGUISkinComp *GetGUIComp( INode *node );
protected:
pfGUISkin *fConvertedSkin;
};
/// skin editor proc class
class pfGUISkinEditProc
{
protected:
static pfGUISkinEditProc *fInstance;
static int fZoom;
plGUISkinComp *fComp;
RECT fPreviewRect, fCurrElemRect;
HDC fDblDC, fImageDC;
HBITMAP fDblBitmap, fImageBitmap;
int fDblWidth, fDblHeight;
int fXOffset, fYOffset;
int fCurrPBRefSet;
HWND fHWnd;
HPEN fDefPen, fOtherPen;
bool fDragging;
UInt8 fDragType;
int fDragTimer;
int fDragOffsetX, fDragOffsetY;
HCURSOR fOrigCursor;
pfGUISkin::pfSRect fBackups[ pfGUISkin::kNumElements ];
void IRefreshDblBuffer( void );
void IRefreshImageBuffer( void );
void IInitDblBuffer( void );
void IKillDblBuffer( void );
void ISetScrollRanges( void );
enum
{
kRangeSlop = 4
};
bool IPointWithinRange( int x, int y, int ptX, int ptY );
bool IPointWithinVertRange( int x, int y, int ptX, int ptY1, int ptY2 );
bool IPointWithinHorzRange( int x, int y, int ptX1, int ptX2, int ptY );
enum DragTypeFlags
{
kLeft = 0x01,
kTop = 0x02,
kRight = 0x04,
kBottom = 0x08,
kDragAll = kLeft | kTop | kRight | kBottom
};
UInt8 IGetDragTypeFlags( int x, int y );
void IJustDrawOneRect( int whichElement, IParamBlock2 *pb, HDC hDC, HPEN whichPen, int refToIgnore );
public:
pfGUISkinEditProc( plGUISkinComp *comp );
~pfGUISkinEditProc();
static INT_PTR CALLBACK DlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
INT_PTR CALLBACK DialogProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
};
#endif // _pfGUISkinComp_h

View File

@ -0,0 +1,461 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
//Resource related
#include "resource.h"
//Max related
#include "plComponent.h"
#include "plComponentReg.h"
//Messages related
#include "plgDispatch.h"
#include "../pnMessage/plObjRefMsg.h"
#include "../pnMessage/plIntRefMsg.h"
#include "../pnMessage/plNodeRefMsg.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
//Scene related
#include "../plScene/plSceneNode.h"
#include "../plInterp/plController.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxMain/plMaxNodeData.h"
#include "../pnKeyedObject/plKey.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "hsResMgr.h"
//Conversion related
#include "../MaxConvert/hsConverterUtils.h"
#include "../MaxConvert/hsControlConverter.h"
//Avatar related
#include "../plAvatar/plAGAnim.h"
#include "../plAvatar/plMatrixChannel.h"
#include "BipedKiller.h"
//Anim related
#include "plNotetrackAnim.h"
//
// DummyCodeIncludeFuncAGComp Function
// Necessary to keep the compiler from tossing this file.
// No functions herein are directly called, excepting this
// one.
//
//
void DummyCodeIncludeFuncAGComp()
{
}
enum {
kShareableBool, //Added in v1
kGlobalBool, //Added in v1
};
//////////////////////////////////////////////////////////////
//
// AnimAvatar Component
//
//
//
class plAnimAvatarComponent : public plComponent
{
//protected:
// static plAGAnimMgr *fManager;
public:
plAnimAvatarComponent();
virtual hsBool SetupProperties(plMaxNode* node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode* node, plErrorMsg *pErrMsg);
virtual plATCAnim * NewAnimation(const char *name, double begin, double end);
hsBool ConvertNode(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool ConvertNodeSegmentBranch(plMaxNode *node, plAGAnim *mod, plErrorMsg *pErrMsg);
hsBool MakePersistent(plMaxNode *node, plAGAnim *anim, const char *animName, plErrorMsg *pErrMsg);
virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); }
void DeleteThis() { delete this; }
};
//plAGAnimMgr * plAnimAvatarComponent::fManager = nil;
CLASS_DESC(plAnimAvatarComponent, gAnimAvatarDesc, "Compound Animation", "Compound Animation", COMP_TYPE_AVATAR, Class_ID(0x3192253d, 0x60c4178c))
//
// Anim Avatar ParamBlock2
//
//
ParamBlockDesc2 gAnimAvatarBk
(
plComponent::kBlkComp, _T("CompoundAnim"), 0, &gAnimAvatarDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
//Roll out
IDD_COMP_ANIM_AVATAR, IDS_COMP_ANIM_AVATARS, 0, 0, NULL,
// params
kShareableBool, _T("ShareableBool"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_ANIM_AVATAR_SHAREBOOL,
end,
kGlobalBool, _T("ShareableBool"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_ANIM_AVATAR_GLOBALBOOL,
end,
//kBoundCondRadio, _T("BoundingConditions"), TYPE_INT, 0, 0,
// p_ui, TYPE_RADIO, 2, IDC_COMP_PHYS_DETECTOR_RAD1, IDC_COMP_PHYS_DETECTOR_RAD2,
// end,
end
);
//
// Anim Avatar CONSTRUCTOR
//
//
plAnimAvatarComponent::plAnimAvatarComponent()
{
fClassDesc = &gAnimAvatarDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
//
// Anim Avatar PRECONVERT
//
//
hsBool plAnimAvatarComponent::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg)
{
if(node->GetMaxNodeData())
{
node->SetMovable(true);
node->SetForceLocal(true);
node->SetDrawable(false);
}
int childCount = node->NumberOfChildren();
for (int i = 0; i < childCount; i++)
{
SetupProperties((plMaxNode *)node->GetChildNode(i), pErrMsg);
}
return true;
}
//
//
// CONVERT
// top level conversion: recursive descent on the node and children
// for each node, search for segments to convert...
//
//
hsBool plAnimAvatarComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
Interface *theInterface = node->GetInterface();
RemoveBiped(node, theInterface);
ConvertNode(node, pErrMsg);
((plSceneNode *)node->GetRoomKey()->GetObjectPtr())->SetFilterGenericsOnly(true);
return true;
}
//
// CONVERTNODE
// look for all the segments on this node and convert them
// recurse on children
//
//
hsBool plAnimAvatarComponent::ConvertNode(plMaxNode *node, plErrorMsg *pErrMsg)
{
plNotetrackAnim noteAnim(node, pErrMsg);
// does this node have any segments specified?
if (noteAnim.HasNotetracks())
{
// for each segment we found:
while (const char *animName = noteAnim.GetNextAnimName())
{
plAnimInfo info = noteAnim.GetAnimInfo(animName);
plATCAnim *anim = NewAnimation(info.GetAnimName(), info.GetAnimStart(), info.GetAnimEnd());
const char *loopName = info.GetNextLoopName();
if (loopName)
{
anim->SetLoop(true);
hsScalar loopStart = info.GetLoopStart(loopName);
hsScalar loopEnd = info.GetLoopEnd(loopName);
anim->SetLoopStart(loopStart == -1 ? anim->GetStart() : loopStart);
anim->SetLoopEnd(loopEnd == -1 ? anim->GetEnd() : loopEnd);
}
while (const char *marker = info.GetNextMarkerName())
anim->AddMarker(marker, info.GetMarkerTime(marker));
ConvertNodeSegmentBranch(node, anim, pErrMsg);
MakePersistent(node, anim, info.GetAnimName(), pErrMsg);
}
}
// let's see if the children have any segments specified...
int childCount = node->NumberOfChildren();
for (int i = 0; i < childCount; i++)
ConvertNode((plMaxNode *)(node->GetChildNode(i)), pErrMsg);
return true;
}
// NewAnimation -------------------------------------------------------------------------
// -------------
plATCAnim * plAnimAvatarComponent::NewAnimation(const char *name, double begin, double end)
{
return TRACKED_NEW plATCAnim(name, begin, end);
}
//
// CONVERT NODE SEGMENT BRANCH
// we're now in the middle of converting a segment
// every node gets an animation channel for the time period in question
//
//
hsBool plAnimAvatarComponent::ConvertNodeSegmentBranch(plMaxNode *node, plAGAnim *mod, plErrorMsg *pErrMsg)
{
// Check for a suppression marker
plNotetrackAnim noteAnim(node, pErrMsg);
plAnimInfo info = noteAnim.GetAnimInfo(nil);
hsBool suppressed = info.IsSuppressed(mod->GetName());
// Get the affine parts and the TM Controller
plSceneObject *obj = node->GetSceneObject();
if(obj && !suppressed) {
hsAffineParts parts;
hsControlConverter::Instance().ReduceKeys(node->GetTMController(), node->GetKeyReduceThreshold());
plController* tmc = hsControlConverter::Instance().ConvertTMAnim(obj, node, &parts, mod->GetStart(), mod->GetEnd());
if (tmc)
{
plMatrixChannel *channel;
hsMatrix44 constSetting;
parts.ComposeMatrix(&constSetting);
// If all our keys match, there's no point in keeping an animation controller
// around. Just nuke it and replace it with a constant channel.
if (tmc->PurgeRedundantSubcontrollers())
{
channel = TRACKED_NEW plMatrixConstant(constSetting);
delete tmc;
tmc = nil;
}
else
{
channel = TRACKED_NEW plMatrixControllerChannel(tmc, &parts);
}
plMatrixChannelApplicator *app = TRACKED_NEW plMatrixChannelApplicator();
app->SetChannelName(node->GetKey()->GetName());
app->SetChannel(channel);
mod->AddApplicator(app);
}
// let's see if the children have any segments specified...
int childCount = node->NumberOfChildren();
for (int i = 0; i < childCount; i++)
ConvertNodeSegmentBranch((plMaxNode *)(node->GetChildNode(i)), mod, pErrMsg);
return true;
} else {
return false;
}
}
plKey FindSceneNode(plMaxNode *node)
{
plSceneObject *obj = node->GetSceneObject();
if(obj)
{
return obj->GetSceneNode();
} else {
plMaxNode *parent = (plMaxNode *)node->GetParentNode();
if(parent)
{
return FindSceneNode(parent);
} else {
return nil;
}
}
}
//
// MAKE PERSISTENT
// Perform wizardry necessary to make the object save itself.
//
//
hsBool plAnimAvatarComponent::MakePersistent(plMaxNode *node, plAGAnim *anim, const char *animName, plErrorMsg *pErrMsg)
{
// new approach: add to the generic pool on the scene node
plLocation nodeLoc = node->GetLocation();
plKey sceneNodeKey = FindSceneNode(node);
if(sceneNodeKey)
{
plKey animKey = hsgResMgr::ResMgr()->NewKey(animName, anim, nodeLoc);
plNodeRefMsg* refMsg = TRACKED_NEW plNodeRefMsg(sceneNodeKey, plNodeRefMsg::kOnRequest, -1, plNodeRefMsg::kGeneric);
hsgResMgr::ResMgr()->AddViaNotify(animKey, refMsg, plRefFlags::kActiveRef);
}
else
{
pErrMsg->Set(true, "Sorry", "Can't find node to save animation. Animation will not be saved.");
}
return true;
}
// plEmoteComponent ---------------------------------
// -----------------
class plEmoteComponent : public plAnimAvatarComponent
{
public:
enum {
kBodyUsage,
kFadeIn,
kFadeOut
};
enum {
kBodyUnknown,
kBodyUpper,
kBodyFull
};
plEmoteComponent();
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual plATCAnim * NewAnimation(const char *name, double begin, double end);
protected:
float fFadeIn;
float fFadeOut;
plEmoteAnim::BodyUsage fBodyUsage;
};
// gEmoteDesc ---------------------------------------------------------------------------------------------------------------------
// -----------
CLASS_DESC(plEmoteComponent, gEmoteDesc, "Emote Animation", "Emote Animation", COMP_TYPE_AVATAR, Class_ID(0x383c55ba, 0x6f1d454c))
// gEmoteDesc ----------
// -----------
ParamBlockDesc2 gEmoteBk
(
plComponent::kBlkComp, _T("EmoteAnim"), 0, &gEmoteDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
//Roll out
IDD_COMP_EMOTE, IDS_COMP_EMOTE, 0, 0, NULL,
plEmoteComponent::kBodyUsage, _T("Blend"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_BODY_UNKNOWN, IDC_BODY_UPPER, IDC_BODY_FULL,
p_vals, plEmoteComponent::kBodyUnknown, plEmoteComponent::kBodyUpper, plEmoteComponent::kBodyFull,
p_default, plEmoteComponent::kBodyUnknown,
end,
plEmoteComponent::kFadeIn, _T("Length"), TYPE_FLOAT, 0, 0,
p_default, 2.0,
p_range, 0.1, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_EMO_FADEIN, IDC_EMO_FADEIN_SPIN, 0.1,
end,
plEmoteComponent::kFadeOut, _T("Length"), TYPE_FLOAT, 0, 0,
p_default, 2.0,
p_range, 0.1, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_EMO_FADEOUT, IDC_EMO_FADEOUT_SPIN, 0.1,
end,
end
);
// plEmoteComponent ----------------
// -----------------
plEmoteComponent::plEmoteComponent()
{
fClassDesc = &gEmoteDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
// Convert ------------------------------------------------------------
// --------
plEmoteComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
Interface *theInterface = node->GetInterface();
RemoveBiped(node, theInterface);
fFadeIn = fCompPB->GetFloat(kFadeIn);
fFadeOut = fCompPB->GetFloat(kFadeOut);
fBodyUsage = static_cast<plEmoteAnim::BodyUsage>(fCompPB->GetInt(kBodyUsage));
ConvertNode(node, pErrMsg);
((plSceneNode *)node->GetRoomKey()->GetObjectPtr())->SetFilterGenericsOnly(true);
return true;
}
// NewAnimation ----------------------------------------------------------------------
// -------------
plATCAnim * plEmoteComponent::NewAnimation(const char *name, double begin, double end)
{
return TRACKED_NEW plEmoteAnim(name, begin, end, fFadeIn, fFadeOut, fBodyUsage);
}

View File

@ -0,0 +1,113 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plActivatorBaseComponent.h"
#include "../pnKeyedObject/plKey.h"
#include "../MaxMain/plMaxNode.h"
#include "../plModifier/plLogicModifier.h"
#include "../pnSceneObject/plSceneObject.h"
#include "hsResMgr.h"
#include "../pnMessage/plObjRefMsg.h"
void plActivatorBaseComponent::AddReceiverKey(plKey pKey, plMaxNode* node)
{
fReceivers.insert(ReceiverKey(node, pKey));
}
plKey plActivatorBaseComponent::GetLogicKey(plMaxNode* node)
{
LogicKeys::const_iterator it = fLogicModKeys.find(node);
if (it != fLogicModKeys.end())
return it->second;
return nil;
}
void plActivatorBaseComponent::IGetReceivers(plMaxNode* node, hsTArray<plKey>& receivers)
{
// Add the guys who want to be notified by all instances
ReceiverKeys::iterator lowIt = fReceivers.lower_bound(nil);
ReceiverKeys::iterator highIt = fReceivers.upper_bound(nil);
for (; lowIt != highIt; lowIt++)
receivers.Append(lowIt->second);
// Add the ones for just this instance
lowIt = fReceivers.lower_bound(node);
highIt = fReceivers.upper_bound(node);
for (; lowIt != highIt; lowIt++)
receivers.Append(lowIt->second);
}
// Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool plActivatorBaseComponent::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg)
{
fLogicModKeys.clear();
fReceivers.clear();
return true;
}
hsBool plActivatorBaseComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
node->SetForceLocal(true);
plLocation loc = node->GetLocation();
plSceneObject *obj = node->GetSceneObject();
// Create and register the VolumeGadget's logic component
plLogicModifier *logic = TRACKED_NEW plLogicModifier;
plKey logicKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), logic, node->GetLocation());
hsgResMgr::ResMgr()->AddViaNotify(logicKey, TRACKED_NEW plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
fLogicModKeys[node] = logicKey;
return true;
}
hsBool plActivatorBaseComponent::DeInit( plMaxNode *node, plErrorMsg *pErrMsg )
{
fReceivers.clear();
fLogicModKeys.clear();
return plPhysicCoreComponent::DeInit( node, pErrMsg );
}

View File

@ -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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plActivatorBaseComponent_inc
#define plActivatorBaseComponent_inc
#include "plComponent.h"
#include "plPhysicalComponents.h"
#include <map>
#include "hsTemplates.h"
#include "../pnKeyedObject/plKey.h"
class plMaxNode;
#define ACTIVATOR_BASE_CID Class_ID(0x23915577, 0x2d0f4cdd)
class plActivatorBaseComponent : public plPhysicCoreComponent
{
public:
typedef std::map<plMaxNode*, plKey> LogicKeys;
protected:
LogicKeys fLogicModKeys;
typedef std::multimap<plMaxNode*, plKey> ReceiverKeys;
typedef std::pair<plMaxNode*, plKey> ReceiverKey;
ReceiverKeys fReceivers;
// hsTArray<plKey> fReceivers;
void IGetReceivers(plMaxNode* node, hsTArray<plKey>& receivers);
public:
// Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg* pErrMsg);
virtual hsBool DeInit(plMaxNode *node, plErrorMsg *pErrMsg);
const LogicKeys& GetLogicKeys() { return fLogicModKeys; }
virtual plKey GetLogicKey(plMaxNode* node);
virtual void AddReceiverKey(plKey pKey, plMaxNode* node=nil);
virtual bool HasLogicOut() { return false; }
int CanConvertToType(Class_ID obtype)
{ return (obtype == ACTIVATOR_BASE_CID) ? 1 : plComponent::CanConvertToType(obtype); }
};
#endif // plActivatorBaseComponent_inc

View File

@ -0,0 +1,70 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plComponent.h"
#include "plComponentReg.h"
void DummyCodeIncludeFuncActive() {}
#define ACTIVATOR_CID Class_ID(0x205a7c50, 0x7a095602)
class plActiveComponent : public plComponent
{
public:
plActiveComponent();
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
};
OBSOLETE_CLASS_DESC(plActiveComponent, gActiveDesc, "Activator", "Activator", COMP_TYPE_LOGIC, ACTIVATOR_CID)
plActiveComponent::plActiveComponent()
{
fClassDesc = &gActiveDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
ParamBlockDesc2 gActiveBlock
(
plComponent::kBlkComp, _T("activeComp"), 0, &gActiveDesc, P_AUTO_CONSTRUCT, plComponent::kRefComp,
end
);

View File

@ -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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/

View File

@ -0,0 +1,441 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plAnimCompProc.h"
#include "../MaxMain/plMaxNode.h"
#include "plComponentBase.h"
#include "plPickNode.h"
#include "plAnimComponent.h"
#include "../../PubUtilLib/plInterp/plAnimEaseTypes.h"
plAnimCompProc::plAnimCompProc() :
fCompButtonID(0),
fCompParamID(0),
fNodeButtonID(0),
fNodeParamID(0)
{
}
BOOL plAnimCompProc::DlgProc(TimeValue t, IParamMap2* pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
IParamBlock2* pb = pm->GetParamBlock();
IUpdateNodeButton(hWnd, pb);
IUpdateCompButton(hWnd, pb);
ILoadUser(hWnd, pb);
}
return TRUE;
case WM_COMMAND:
{
int cmd = HIWORD(wParam);
int resID = LOWORD(wParam);
if (cmd == BN_CLICKED && resID == fCompButtonID)
{
ICompButtonPress(hWnd, pm->GetParamBlock());
return TRUE;
}
else if (cmd == BN_CLICKED && resID == fNodeButtonID)
{
INodeButtonPress(hWnd, pm->GetParamBlock());
return TRUE;
}
else if (IUserCommand(hWnd, pm->GetParamBlock(), cmd, resID))
return TRUE;
}
break;
}
return FALSE;
}
void plAnimCompProc::ICompButtonPress(HWND hWnd, IParamBlock2* pb)
{
IPickComponent(pb);
IUpdateCompButton(hWnd, pb);
IUpdateNodeButton(hWnd, pb);
ILoadUser(hWnd, pb);
}
void plAnimCompProc::IPickNode(IParamBlock2* pb, plComponentBase* comp)
{
plPick::CompTargets(pb, fNodeParamID, comp);
}
void plAnimCompProc::INodeButtonPress(HWND hWnd, IParamBlock2* pb)
{
plComponentBase* comp = IGetComp(pb);
if (comp)
IPickNode(pb, comp);
IUpdateNodeButton(hWnd, pb);
ILoadUser(hWnd, pb);
}
void plAnimCompProc::IUpdateNodeButton(HWND hWnd, IParamBlock2* pb)
{
HWND hButton = GetDlgItem(hWnd, fNodeButtonID);
plComponentBase* comp = IGetComp(pb);
if (!comp)
{
SetWindowText(hButton, "(none)");
EnableWindow(hButton, FALSE);
return;
}
// If this is an anim grouped component you can't pick a target
if (comp->ClassID() == ANIM_GROUP_COMP_CID)
{
IClearNode(pb);
SetWindowText(hButton, "(none)");
EnableWindow(hButton, FALSE);
return;
}
EnableWindow(hButton, TRUE);
// Make sure the node is actually in the components target list
plMaxNode* node = IGetNode(pb);
if (comp->IsTarget((plMaxNodeBase*)node))
SetWindowText(hButton, node->GetName());
else
SetWindowText(hButton, "(none)");
}
void plAnimCompProc::IUpdateCompButton(HWND hWnd, IParamBlock2* pb)
{
HWND hAnim = GetDlgItem(hWnd, fCompButtonID);
plComponentBase* comp = IGetComp(pb);
if (comp)
SetWindowText(hAnim, comp->GetINode()->GetName());
else
SetWindowText(hAnim, "(none)");
}
plComponentBase* plAnimCompProc::IGetComp(IParamBlock2* pb)
{
plMaxNode* node = nil;
if (pb->GetParameterType(fCompParamID) == TYPE_REFTARG)
node = (plMaxNode*)pb->GetReferenceTarget(fCompParamID);
else
node = (plMaxNode*)pb->GetINode(fCompParamID);
if (node)
return node->ConvertToComponent();
return nil;
}
plMaxNode* plAnimCompProc::IGetNode(IParamBlock2* pb)
{
if (pb->GetParameterType(fNodeParamID) == TYPE_REFTARG)
return (plMaxNode*)pb->GetReferenceTarget(fNodeParamID);
else
return (plMaxNode*)pb->GetINode(fNodeParamID);
}
void plAnimCompProc::IClearNode(IParamBlock2* pb)
{
if (pb->GetParameterType(fNodeParamID) == TYPE_REFTARG)
pb->SetValue(fNodeParamID, 0, (ReferenceTarget*)nil);
else
pb->SetValue(fNodeParamID, 0, (INode*)nil);
}
bool plAnimCompProc::GetCompAndNode(IParamBlock2* pb, plComponentBase*& comp, plMaxNode*& node)
{
comp = IGetComp(pb);
if (comp)
{
node = IGetNode(pb);
// If it's an anim group component (don't need a node), or we have a node
// and the component is attached to it, we're ok.
if (comp->ClassID() == ANIM_GROUP_COMP_CID ||
(node && comp->IsTarget((plMaxNodeBase*)node)))
return true;
}
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////
plMtlAnimProc::plMtlAnimProc() :
fMtlButtonID(0),
fMtlParamID(0),
fNodeButtonID(0),
fNodeParamID(0),
fAnimComboID(0),
fAnimParamID(0)
{
}
BOOL plMtlAnimProc::DlgProc(TimeValue t, IParamMap2* pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
IParamBlock2* pb = pm->GetParamBlock();
IOnInitDlg(hWnd, pb);
IUpdateMtlButton(hWnd, pb);
}
return TRUE;
case WM_COMMAND:
{
int cmd = HIWORD(wParam);
int resID = LOWORD(wParam);
IParamBlock2* pb = pm->GetParamBlock();
if (cmd == BN_CLICKED && resID == fMtlButtonID)
{
IMtlButtonPress(hWnd, pb);
return TRUE;
}
else if (cmd == BN_CLICKED && resID == fNodeButtonID)
{
INodeButtonPress(hWnd, pb);
return TRUE;
}
else if (cmd == CBN_SELCHANGE && resID == fAnimComboID)
{
IAnimComboChanged(hWnd, pb);
return TRUE;
}
else if (IUserCommand(hWnd, pb, cmd, resID))
return TRUE;
}
break;
}
return FALSE;
}
void plMtlAnimProc::IUpdateMtlButton(HWND hWnd, IParamBlock2* pb)
{
HWND hMtl = GetDlgItem(hWnd, fMtlButtonID);
// Get the saved material
Mtl *savedMtl = IGetMtl(pb);
if (savedMtl)
SetWindowText(hMtl, savedMtl->GetName());
else
SetWindowText(hMtl, "(none)");
// Enable the node button if a material is selected
EnableWindow(GetDlgItem(hWnd, fNodeButtonID), (savedMtl != nil));
// Update the dependencies of this
IUpdateNodeButton(hWnd, pb);
}
void plMtlAnimProc::IUpdateNodeButton(HWND hWnd, IParamBlock2* pb)
{
ISetNodeButtonText(hWnd, pb);
// Update the dependencies of this
ILoadAnimCombo(hWnd, pb);
}
#include "plNotetrackAnim.h"
void plMtlAnimProc::ILoadAnimCombo(HWND hWnd, IParamBlock2* pb)
{
HWND hAnim = GetDlgItem(hWnd, fAnimComboID);
ComboBox_ResetContent(hAnim);
int sel = ComboBox_AddString(hAnim, ENTIRE_ANIMATION_NAME);
ComboBox_SetCurSel(hAnim, sel);
const char* savedName = pb->GetStr(fAnimParamID);
if (!savedName)
savedName = "";
Mtl* mtl = IGetMtl(pb);
if (mtl)
{
plNotetrackAnim anim(mtl, nil);
while (const char* animName = anim.GetNextAnimName())
{
int idx = ComboBox_AddString(hAnim, animName);
ComboBox_SetItemData(hAnim, idx, 1);
if (!strcmp(animName, savedName))
ComboBox_SetCurSel(hAnim, idx);
}
EnableWindow(hAnim, TRUE);
}
else
EnableWindow(hAnim, FALSE);
// Update the dependencies of this
ILoadUser(hWnd, pb);
}
#include "plPickMaterialMap.h"
#include "../MaxMain/plMtlCollector.h"
void plMtlAnimProc::IMtlButtonPress(HWND hWnd, IParamBlock2* pb)
{
// Let the user pick a new material
Mtl* pickedMtl = plPickMaterialMap::PickMaterial(plMtlCollector::kUsedOnly |
plMtlCollector::kPlasmaOnly);
// Save the mtl in the pb and update the interface
if (pickedMtl != nil)
{
if (pb->GetParameterType(fMtlParamID) == TYPE_REFTARG)
pb->SetValue(fMtlParamID, 0, (ReferenceTarget*)pickedMtl);
else
pb->SetValue(fMtlParamID, 0, pickedMtl);
}
// Make sure the current node has the selected material on it (clear it otherwise)
INode* node = pb->GetINode(fNodeParamID);
if (!pickedMtl || !node || node->GetMtl() != pickedMtl)
pb->SetValue(fNodeParamID, 0, (INode*)nil);
IUpdateMtlButton(hWnd, pb);
}
void plMtlAnimProc::INodeButtonPress(HWND hWnd, IParamBlock2* pb)
{
IPickNode(pb);
IUpdateNodeButton(hWnd, pb);
}
void plMtlAnimProc::IAnimComboChanged(HWND hWnd, IParamBlock2* pb)
{
HWND hCombo = GetDlgItem(hWnd, fAnimComboID);
int idx = ComboBox_GetCurSel(hCombo);
if (idx != CB_ERR)
{
if (ComboBox_GetItemData(hCombo, idx) == 0)
pb->SetValue(fAnimParamID, 0, "");
else
{
// Get the name of the animation and save it
char buf[256];
ComboBox_GetText(hCombo, buf, sizeof(buf));
pb->SetValue(fAnimParamID, 0, buf);
}
}
// Update the dependencies of this
ILoadUser(hWnd, pb);
}
Mtl* plMtlAnimProc::IGetMtl(IParamBlock2* pb)
{
if (pb->GetParameterType(fMtlParamID) == TYPE_REFTARG)
return (Mtl*)pb->GetReferenceTarget(fMtlParamID);
else
return pb->GetMtl(fMtlParamID);
}
#include "plPickNodeBase.h"
static const char* kUserTypeAll = "(All)";
class plPickAllMtlNode : public plPickMtlNode
{
protected:
void IAddUserType(HWND hList)
{
int idx = ListBox_AddString(hList, kUserTypeAll);
if (!fPB->GetINode(fNodeParamID))
ListBox_SetCurSel(hList, idx);
}
void ISetUserType(plMaxNode* node, const char* userType)
{
if (hsStrEQ(userType, kUserTypeAll))
ISetNodeValue(nil);
}
public:
plPickAllMtlNode(IParamBlock2* pb, int nodeParamID, Mtl* mtl) :
plPickMtlNode(pb, nodeParamID, mtl)
{
}
};
void plMtlAnimProc::IPickNode(IParamBlock2* pb)
{
plPickAllMtlNode pick(pb, fNodeParamID, IGetMtl(pb));
pick.DoPick();
}
void plMtlAnimProc::ISetNodeButtonText(HWND hWnd, IParamBlock2* pb)
{
HWND hNode = GetDlgItem(hWnd, fNodeButtonID);
INode* node = pb->GetINode(fNodeParamID);
if (node)
SetWindowText(hNode, node->GetName());
else
SetWindowText(hNode, kUserTypeAll);
}

View File

@ -0,0 +1,124 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAnimCompProc_h_inc
#define plAnimCompProc_h_inc
#include "max.h"
#include "iparamm2.h"
class plComponentBase;
class plMaxNode;
class plAnimCompProc : public ParamMap2UserDlgProc
{
protected:
int fCompButtonID;
int fCompParamID;
int fNodeButtonID;
int fNodeParamID;
virtual void IPickComponent(IParamBlock2* pb)=0;
virtual void IPickNode(IParamBlock2* pb, plComponentBase* comp);
virtual void ILoadUser(HWND hWnd, IParamBlock2* pb)=0;
virtual bool IUserCommand(HWND hWnd, IParamBlock2* pb, int cmd, int resID)=0;
plMaxNode* IGetNode(IParamBlock2* pb);
void IClearNode(IParamBlock2* pb);
plComponentBase* IGetComp(IParamBlock2* pb);
void ICompButtonPress(HWND hWnd, IParamBlock2* pb);
void INodeButtonPress(HWND hWnd, IParamBlock2* pb);
void IUpdateCompButton(HWND hWnd, IParamBlock2* pb);
virtual void IUpdateNodeButton(HWND hWnd, IParamBlock2* pb);
public:
plAnimCompProc();
void DeleteThis() {}
BOOL DlgProc(TimeValue t, IParamMap2* pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
bool GetCompAndNode(IParamBlock2* pb, plComponentBase*& comp, plMaxNode*& node);
};
///////////////////////////////////////////////////////////////////////////////////////////
class plMtlAnimProc : public ParamMap2UserDlgProc
{
protected:
int fMtlButtonID;
int fMtlParamID;
int fNodeButtonID;
int fNodeParamID;
int fAnimComboID;
int fAnimParamID;
Mtl* IGetMtl(IParamBlock2* pb);
virtual void IOnInitDlg(HWND hWnd, IParamBlock2* pb) {}
virtual void ILoadUser(HWND hWnd, IParamBlock2* pb)=0;
virtual bool IUserCommand(HWND hWnd, IParamBlock2* pb, int cmd, int resID)=0;
virtual void IPickNode(IParamBlock2* pb);
virtual void ISetNodeButtonText(HWND hWnd, IParamBlock2* pb);
public:
plMtlAnimProc();
void DeleteThis() {}
BOOL DlgProc(TimeValue t, IParamMap2* pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
private:
void IMtlButtonPress(HWND hWnd, IParamBlock2* pb);
void INodeButtonPress(HWND hWnd, IParamBlock2* pb);
void IAnimComboChanged(HWND hWnd, IParamBlock2* pb);
void IUpdateMtlButton(HWND hWnd, IParamBlock2* pb);
void IUpdateNodeButton(HWND hWnd, IParamBlock2* pb);
void ILoadAnimCombo(HWND hWnd, IParamBlock2* pb);
};
#endif // plAnimCompProc_h_inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,214 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAnimComponent_inc
#define plAnimComponent_inc
#include <map>
#include "plComponent.h"
#include "plComponentReg.h"
#include "../pnKeyedObject/plKey.h"
#include "hsTemplates.h"
#include "plAnimObjInterface.h"
#include "plNoteTrackDlgComp.h"
#define ANIM_COMP_CID Class_ID(0x32e77ab, 0x28a80383)
#define ANIM_GROUP_COMP_CID Class_ID(0x341a57fc, 0x4cda6c64)
#define ANIM_COMPRESS_COMP_CID Class_ID(0x116d3175, 0x4e465807)
class plComponentBase;
class plMaxNode;
class plSimpleTMModifier;
class plLightModifier;
class plAGMasterMod;
class plAGAnim;
class plMsgForwarder;
class plController;
class plAGApplicator;
class plAnimComponentBase : public plComponent, public plAnimObjInterface
{
protected:
std::map<plMaxNode*, plAGMasterMod*> fMods;
std::map<plMaxNode*, plLightModifier*> fLightMods;
bool fNeedReset;
public:
plAnimComponentBase();
void DeleteThis() { delete this; }
hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool DeInit(plMaxNode *node, plErrorMsg *pErrMsg);
virtual plKey GetModKey(plMaxNode *node)=0;
const char *GetAnimName();
static IsAnimComponent(plComponentBase *comp);
std::map<plMaxNode*, plAGAnim*> fAnims;
// Static function for setting up scalar controllers
static void SetupCtl( plAGAnim *anim, plController *ctl, plAGApplicator *app, plMaxNode *node );
// Static function to grab the animation key given the INode pointing to either a) an anim component or b) a material stealth node
static bool GetAnimKey( plMaxNode *node, hsTArray<plKey> &outKeys );
// Static function to grab the animObjInterface for a given INode, regardless of type
static plAnimObjInterface *GetAnimInterface( INode *node );
// plAnimObjInterface functions
virtual void PickTargetNode( IParamBlock2 *destPB, ParamID destParamID, ParamID typeID );
virtual hsBool IsNodeRestricted( void ) { return true; }
virtual const char *GetIfaceSegmentName( hsBool allowNil );
protected:
hsBool IAddTMToAnim(plMaxNode *node, plAGAnim *anim, plErrorMsg *pErrMsg);
hsBool IAddLightToAnim(plMaxNode *node, plAGAnim *anim, plErrorMsg *pErrMsg);
hsBool IConvertNodeSegmentBranch(plMaxNode *node, plAGAnim *anim, plErrorMsg *pErrMsg);
hsBool IMakePersistent(plMaxNode *node, plAGAnim *anim, plErrorMsg *pErrMsg);
};
class plAnimComponent : public plAnimComponentBase
{
public:
plAnimComponent();
plKey GetModKey(plMaxNode *node);
virtual hsBool GetKeyList( INode *restrictedNode, hsTArray<plKey> &outKeys );
};
class plAnimGroupedComponent : public plAnimComponentBase
{
protected:
plMsgForwarder *fForward;
public:
plAnimGroupedComponent();
hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
plKey GetModKey(plMaxNode *node);
virtual hsBool IsNodeRestricted( void ) { return false; }
virtual hsBool GetKeyList( INode *restrictedNode, hsTArray<plKey> &outKeys );
};
//// Dialog Proc For Anim Selection /////////////////////////////////////////////////////////////
// Derive from this guy to handle selection of an animation. Also, you can pass a pointer in
// to another dialog proc to chain procs together (this proc will execute before the chained
// one).
class plPlasmaAnimSelectDlgProc : public ParamMap2UserDlgProc
{
protected:
ParamID fParamID;
int fDlgItem;
bool fUseNode;
ParamID fNodeParamID;
ParamID fTypeParamID;
int fNodeDlgItem;
TCHAR fTitle[ 128 ];
ParamMap2UserDlgProc *fChain;
void IUpdateNodeBtn( HWND hWnd, IParamBlock2 *pb );
public:
int GetHandledDlgItem( void ) const { return fDlgItem; }
// No node restriction version
plPlasmaAnimSelectDlgProc( ParamID paramID, int dlgItem, TCHAR *promptTitle, ParamMap2UserDlgProc *chainedDlgProc = nil );
// Node restricted version
plPlasmaAnimSelectDlgProc( ParamID paramID, int dlgItem, ParamID nodeParamID, ParamID typeParamID, int nodeDlgItem, TCHAR *promptTitle, ParamMap2UserDlgProc *chainedDlgProc = nil );
virtual void SetThing( ReferenceTarget *m );
virtual void Update( TimeValue t, Interval &valid, IParamMap2 *map );
virtual BOOL DlgProc( TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
void DeleteThis();
};
class plAnimComponentProc : public ParamMap2UserDlgProc
{
protected:
plComponentNoteTrackDlg fNoteTrackDlg;
IParamBlock2 *fPB;
void EnableGlobal(HWND hWnd, hsBool enable);
public:
static void FillAgeGlobalComboBox(HWND box, char *varName);
static void SetBoxToAgeGlobal(HWND box, char *varName);
virtual BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
virtual void Update(TimeValue t, Interval &valid, IParamMap2 *map);
void DeleteThis();
};
class plAnimCompressComp : public plComponent
{
public:
plAnimCompressComp();
void DeleteThis() { delete this; }
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
//virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
enum
{
kCompressionNone,
kCompressionLow,
kCompressionHigh,
};
enum
{
kAnimCompressLevel,
kAnimCompressThreshold,
};
};
#endif // plAnimComponent_inc

View File

@ -0,0 +1,631 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plAnimEventComponent.h"
#include "plComponentReg.h"
#include "resource.h"
#include "../MaxMain/plMaxNode.h"
#include "plAnimComponent.h"
#include "plNotetrackAnim.h"
#include "plAnimCompProc.h"
#include "plPickNode.h"
#include "../plModifier/plAnimEventModifier.h"
#include "../plMessage/plAnimCmdMsg.h"
#include "hsResMgr.h"
#include "../pnMessage/plRefMsg.h"
void DummyCodeIncludeFuncAnimDetector() {}
CLASS_DESC(plAnimEventComponent, gAnimEventDesc, "Anim Event", "AnimEvent", COMP_TYPE_DETECTOR, ANIMEVENT_CID)
class plAnimEventProc : public plAnimCompProc
{
protected:
virtual void IPickComponent(IParamBlock2* pb);
virtual void ILoadUser(HWND hWnd, IParamBlock2* pb);
virtual bool IUserCommand(HWND hWnd, IParamBlock2* pb, int cmd, int resID);
public:
plAnimEventProc();
};
static plAnimEventProc gAnimEventProc;
enum
{
kAnimComp,
kAnimNode,
kAnimEvent_DEAD,
kAnimName_DEAD,
kAnimBegin,
kAnimEnd,
kAnimMarkers,
};
enum
{
kAnimEventBegin,
kAnimEventEnd,
kAnimEventMarker,
};
ParamBlockDesc2 gAnimEventBlock
(
plComponent::kBlkComp, _T("animEvent"), 0, &gAnimEventDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_DETECTOR_ANIM, IDS_COMP_DETECTOR_ANIM, 0, 0, &gAnimEventProc,
kAnimComp, _T("animComp"), TYPE_INODE, 0, 0,
end,
kAnimNode, _T("animNode"), TYPE_INODE, 0, 0,
end,
kAnimBegin, _T("animBegin"), TYPE_BOOL, 0, 0,
end,
kAnimEnd, _T("animEnd"), TYPE_BOOL, 0, 0,
end,
kAnimMarkers, _T("animMarkers"), TYPE_STRING_TAB, 0, 0, 0,
end,
end
);
plAnimEventComponent::plAnimEventComponent() : fCanExport(false)
{
fClassDesc = &gAnimEventDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plAnimEventComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
plComponentBase* animComp;
plMaxNode* animNode;
if (!gAnimEventProc.GetCompAndNode(fCompPB, animComp, animNode))
{
pErrMsg->Set(true,
"Anim Event Component",
"Component %s does not have a valid anim component and node selected.\n"
"It will not be exported.",
GetINode()->GetName()).Show();
pErrMsg->Set(false);
fCanExport = false;
}
else
fCanExport = true;
return plActivatorBaseComponent::SetupProperties(node, pErrMsg);
}
hsBool plAnimEventComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
if (!fCanExport)
return false;
plAnimEventModifier* mod = TRACKED_NEW plAnimEventModifier;
plKey modKey = node->AddModifier(mod, IGetUniqueName(node));
fLogicModKeys[node] = modKey;
return true;
}
plEventCallbackMsg* CreateCallbackMsg(plAnimCmdMsg* animMsg, plKey modKey)
{
plEventCallbackMsg *eventMsg = TRACKED_NEW plEventCallbackMsg;
eventMsg->AddReceiver(modKey);
eventMsg->fRepeats = -1;
animMsg->AddCallback(eventMsg);
hsRefCnt_SafeUnRef(eventMsg); // AddCallback adds it's own ref, so remove ours (the default of 1)
return eventMsg;
}
hsBool plAnimEventComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
if (!fCanExport)
return false;
plKey modKey = fLogicModKeys[node];
plAnimEventModifier* mod = plAnimEventModifier::ConvertNoRef(modKey->GetObjectPtr());
plAnimComponentBase* animComp;
plMaxNode* animNode;
gAnimEventProc.GetCompAndNode(fCompPB, (plComponentBase*&)animComp, animNode);
//
// Create and setup the callback message
//
plKey animKey = animComp->GetModKey(animNode);
const char* animName = animComp->GetAnimName();
plAnimCmdMsg *animMsg = TRACKED_NEW plAnimCmdMsg;
animMsg->SetCmd(plAnimCmdMsg::kAddCallbacks);
animMsg->SetSender(modKey);
animMsg->SetAnimName(animName);
animMsg->AddReceiver(animKey);
if (fCompPB->GetInt(kAnimBegin))
{
plEventCallbackMsg *eventMsg = CreateCallbackMsg(animMsg, modKey);
eventMsg->fEvent = kBegin;
}
if (fCompPB->GetInt(kAnimEnd))
{
plEventCallbackMsg *eventMsg = CreateCallbackMsg(animMsg, modKey);
eventMsg->fEvent = kEnd;
}
if (fCompPB->Count(kAnimMarkers) > 0)
{
plNotetrackAnim anim(animComp, nil);
plAnimInfo info = anim.GetAnimInfo(animName);
int numMarkers = fCompPB->Count(kAnimMarkers);
for (int i = 0; i < numMarkers; i++)
{
const char* marker = fCompPB->GetStr(kAnimMarkers, 0, i);
float time = info.GetMarkerTime(marker);
plEventCallbackMsg *eventMsg = CreateCallbackMsg(animMsg, modKey);
eventMsg->fEvent = kTime;
eventMsg->fEventTime = time;
}
}
mod->SetCallback(animMsg);
hsTArray<plKey> receivers;
IGetReceivers(node, receivers);
mod->SetReceivers(receivers);
return true;
}
////////////////////////////////////////////////////////////////////////////////
plAnimEventProc::plAnimEventProc()
{
fCompButtonID = IDC_ANIM_BUTTON;
fCompParamID = kAnimComp;
fNodeButtonID = IDC_NODE_BUTTON;
fNodeParamID = kAnimNode;
}
void plAnimEventProc::IPickComponent(IParamBlock2* pb)
{
std::vector<Class_ID> cids;
cids.push_back(ANIM_COMP_CID);
cids.push_back(ANIM_GROUP_COMP_CID);
plPick::Node(pb, kAnimComp, &cids, true, false);
}
static int ListBox_AddStringData(HWND hList, const char* text, int data)
{
int idx = ListBox_AddString(hList, text);
ListBox_SetItemData(hList, idx, data);
return idx;
}
static bool IsMarkerSelected(IParamBlock2* pb, int paramID, const char* marker, bool remove=false)
{
int numMarkers = pb->Count(paramID);
for (int i = 0; i < numMarkers; i++)
{
if (hsStrEQ(marker, pb->GetStr(paramID, 0, i)))
{
if (remove)
pb->Delete(paramID, i, 1);
return true;
}
}
return false;
}
//
// Remove markers we had saved that aren't in the object's notetrack any more
//
static void RemoveDeadMarkers(IParamBlock2* pb, int paramID, plAnimInfo& info)
{
int numMarkers = pb->Count(paramID);
for (int i = numMarkers-1; i >= 0; i--)
{
float time = info.GetMarkerTime(pb->GetStr(paramID, 0, i));
if (time == -1)
{
pb->Delete(paramID, i, 1);
}
}
}
void plAnimEventProc::ILoadUser(HWND hWnd, IParamBlock2* pb)
{
HWND hList = GetDlgItem(hWnd, IDC_EVENT_LIST);
ListBox_ResetContent(hList);
plAnimComponentBase* comp;
plMaxNode* node;
//
// If we don't have a valid comp and node, we should be disabled
//
if (!GetCompAndNode(pb, (plComponentBase*&)comp, node))
{
EnableWindow(hList, FALSE);
return;
}
else
EnableWindow(hList, TRUE);
//
// Load the events
//
int idx;
idx = ListBox_AddStringData(hList, "(Begin)", kAnimEventBegin);
if (pb->GetInt(kAnimBegin))
ListBox_SetSel(hList, TRUE, idx);
idx = ListBox_AddStringData(hList, "(End)", kAnimEventEnd);
if (pb->GetInt(kAnimEnd))
ListBox_SetSel(hList, TRUE, idx);
if (comp)
{
// Get the shared animations for all the nodes this component is applied to
plNotetrackAnim anim(comp, nil);
plAnimInfo info = anim.GetAnimInfo(comp->GetAnimName());
RemoveDeadMarkers(pb, kAnimMarkers, info);
// Get all the markers in this animation
while (const char* marker = info.GetNextMarkerName())
{
idx = ListBox_AddStringData(hList, marker, kAnimEventMarker);
if (IsMarkerSelected(pb, kAnimMarkers, marker))
ListBox_SetSel(hList, TRUE, idx);
}
}
}
bool plAnimEventProc::IUserCommand(HWND hWnd, IParamBlock2* pb, int cmd, int resID)
{
if (cmd == LBN_SELCHANGE && resID == IDC_EVENT_LIST)
{
HWND hList = GetDlgItem(hWnd, IDC_EVENT_LIST);
int idx = ListBox_GetCurSel(hList);
BOOL selected = ListBox_GetSel(hList, idx);
int eventType = ListBox_GetItemData(hList, idx);
if (eventType == kAnimEventBegin)
pb->SetValue(kAnimBegin, 0, selected);
else if (eventType == kAnimEventEnd)
pb->SetValue(kAnimEnd, 0, selected);
else if (eventType == kAnimEventMarker)
{
char buf[256];
ListBox_GetText(hList, idx, buf);
if (selected)
{
if (!IsMarkerSelected(pb, kAnimMarkers, buf))
{
TCHAR* name = buf;
pb->Append(kAnimMarkers, 1, &name);
}
}
else
IsMarkerSelected(pb, kAnimMarkers, buf, true);
}
return true;
}
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
CLASS_DESC(plMtlEventComponent, gMtlEventDesc, "Mtl Event", "MtlEvent", COMP_TYPE_DETECTOR, MTLEVENT_CID)
class plMtlEventProc : public plMtlAnimProc
{
public:
plMtlEventProc();
protected:
virtual void ILoadUser(HWND hWnd, IParamBlock2* pb);
virtual bool IUserCommand(HWND hWnd, IParamBlock2* pb, int cmd, int resID);
};
static plMtlEventProc gMtlEventProc;
enum
{
kMtlMtl,
kMtlNode,
kMtlAnim,
kMtlBegin,
kMtlEnd,
kMtlMarkers,
};
ParamBlockDesc2 gMtlEventBlock
(
plComponent::kBlkComp, _T("mtlEvent"), 0, &gMtlEventDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_DETECTOR_MTL, IDS_COMP_DETECTOR_MTL, 0, 0, &gMtlEventProc,
kMtlMtl, _T("mtl"), TYPE_MTL, 0, 0,
end,
kMtlNode, _T("node"), TYPE_INODE, 0, 0,
end,
kMtlAnim, _T("anim"), TYPE_STRING, 0, 0,
end,
kMtlBegin, _T("animBegin"), TYPE_BOOL, 0, 0,
end,
kMtlEnd, _T("animEnd"), TYPE_BOOL, 0, 0,
end,
kMtlMarkers,_T("markers"), TYPE_STRING_TAB, 0, 0, 0,
end,
end
);
plMtlEventComponent::plMtlEventComponent() : fCanExport(false)
{
fClassDesc = &gMtlEventDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plMtlEventComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
Mtl* mtl = fCompPB->GetMtl(kMtlMtl);
if (!mtl)
{
pErrMsg->Set(true,
"Mtl Event Component",
"Component %s does not have a valid material selected.\n"
"It will not be exported.",
GetINode()->GetName()).Show();
pErrMsg->Set(false);
fCanExport = false;
}
else
fCanExport = true;
return plActivatorBaseComponent::SetupProperties(node, pErrMsg);
}
hsBool plMtlEventComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
if (!fCanExport)
return false;
plAnimEventModifier* mod = TRACKED_NEW plAnimEventModifier;
plKey modKey = node->AddModifier(mod, IGetUniqueName(node));
fLogicModKeys[node] = modKey;
return true;
}
// KLUDGE - The material animation key getter is here, so we have to include all this crap
#include "plResponderMtl.h"
hsBool plMtlEventComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
if (!fCanExport)
return false;
plKey modKey = fLogicModKeys[node];
plAnimEventModifier* mod = plAnimEventModifier::ConvertNoRef(modKey->GetObjectPtr());
Mtl* mtl = fCompPB->GetMtl(kMtlMtl);
plMaxNodeBase* mtlNode = (plMaxNodeBase*)fCompPB->GetINode(kMtlNode);
const char* mtlAnim = fCompPB->GetStr(kMtlAnim);
//
// Create and setup the callback message
//
hsTArray<plKey> animKeys;
GetMatAnimModKey(mtl, mtlNode, mtlAnim, animKeys);
plAnimCmdMsg *animMsg = TRACKED_NEW plAnimCmdMsg;
animMsg->SetCmd(plAnimCmdMsg::kAddCallbacks);
animMsg->SetSender(modKey);
animMsg->SetAnimName(mtlAnim);
animMsg->AddReceivers(animKeys);
if (fCompPB->GetInt(kMtlBegin))
{
plEventCallbackMsg *eventMsg = CreateCallbackMsg(animMsg, modKey);
eventMsg->fEvent = kBegin;
}
if (fCompPB->GetInt(kMtlEnd))
{
plEventCallbackMsg *eventMsg = CreateCallbackMsg(animMsg, modKey);
eventMsg->fEvent = kEnd;
}
if (fCompPB->Count(kMtlMarkers) > 0)
{
plNotetrackAnim anim(mtl, nil);
plAnimInfo info = anim.GetAnimInfo(mtlAnim);
int numMarkers = fCompPB->Count(kMtlMarkers);
for (int i = 0; i < numMarkers; i++)
{
const char* marker = fCompPB->GetStr(kMtlMarkers, 0, i);
float time = info.GetMarkerTime(marker);
plEventCallbackMsg *eventMsg = CreateCallbackMsg(animMsg, modKey);
eventMsg->fEvent = kTime;
eventMsg->fEventTime = time;
}
}
mod->SetCallback(animMsg);
hsTArray<plKey> receivers;
IGetReceivers(node, receivers);
mod->SetReceivers(receivers);
return true;
}
////////////////////////////////////////////////////////////////////////////////
plMtlEventProc::plMtlEventProc()
{
fMtlButtonID = IDC_MTL_BUTTON;
fMtlParamID = kMtlMtl;
fNodeButtonID = IDC_NODE_BUTTON;
fNodeParamID = kMtlNode;
fAnimComboID = IDC_ANIM_COMBO;
fAnimParamID = kMtlAnim;
}
void plMtlEventProc::ILoadUser(HWND hWnd, IParamBlock2* pb)
{
HWND hList = GetDlgItem(hWnd, IDC_EVENT_LIST);
ListBox_ResetContent(hList);
//
// If we don't have a valid material, we should be disabled
//
Mtl* mtl = pb->GetMtl(kMtlMtl);
if (!mtl)
{
EnableWindow(hList, FALSE);
return;
}
else
EnableWindow(hList, TRUE);
//
// Load the events
//
int idx;
idx = ListBox_AddStringData(hList, "(Begin)", kAnimEventBegin);
if (pb->GetInt(kMtlBegin))
ListBox_SetSel(hList, TRUE, idx);
idx = ListBox_AddStringData(hList, "(End)", kAnimEventEnd);
if (pb->GetInt(kMtlEnd))
ListBox_SetSel(hList, TRUE, idx);
if (mtl)
{
const char* mtlAnim = pb->GetStr(kMtlAnim);
// Get the shared animations for all the nodes this component is applied to
plNotetrackAnim anim(mtl, nil);
plAnimInfo info = anim.GetAnimInfo(mtlAnim);
RemoveDeadMarkers(pb, kMtlMarkers, info);
// Get all the markers in this animation
while (const char* marker = info.GetNextMarkerName())
{
idx = ListBox_AddStringData(hList, marker, kAnimEventMarker);
if (IsMarkerSelected(pb, kMtlMarkers, marker))
ListBox_SetSel(hList, TRUE, idx);
}
}
}
bool plMtlEventProc::IUserCommand(HWND hWnd, IParamBlock2* pb, int cmd, int resID)
{
if (cmd == LBN_SELCHANGE && resID == IDC_EVENT_LIST)
{
HWND hList = GetDlgItem(hWnd, IDC_EVENT_LIST);
int idx = ListBox_GetCurSel(hList);
BOOL selected = ListBox_GetSel(hList, idx);
int eventType = ListBox_GetItemData(hList, idx);
if (eventType == kAnimEventBegin)
pb->SetValue(kMtlBegin, 0, selected);
else if (eventType == kAnimEventEnd)
pb->SetValue(kMtlEnd, 0, selected);
else if (eventType == kAnimEventMarker)
{
char buf[256];
ListBox_GetText(hList, idx, buf);
if (selected)
{
if (!IsMarkerSelected(pb, kMtlMarkers, buf))
{
TCHAR* name = buf;
pb->Append(kMtlMarkers, 1, &name);
}
}
else
IsMarkerSelected(pb, kMtlMarkers, buf, true);
}
return true;
}
return false;
}

View File

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

View File

@ -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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plAnimObjInterface - Pure virtual interface class for providing a //
// common gateway for accessing and converting //
// animated objects (such as components and materials).//
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plAnimObjInterface_h
#define _plAnimObjInterface_h
#include "hsTemplates.h"
class plAnimObjInterface
{
public:
// If the following function returns true, then it makes sense to restrict
// the animation conversion to a specific node (i.e. PickTargetNode() makes
// sense)
virtual hsBool IsNodeRestricted( void ) = 0;
// Allows the user to pick an INode that this animation is applied to
// (ex. as a material or as a component) and stores it in the given ID
// of the given ParamBlock
virtual void PickTargetNode( IParamBlock2 *destPB, ParamID destParamID, ParamID typeID ) = 0;
// The following is the node type enum for paramBlocks that store the above node-restricted
// info (i.e. the values for the "typeID" param specified above)
enum NodeTypes
{
kUseParamBlockNode, // Use the node stored in the ParamBlock
kUseOwnerNode // Ignore the ParamBlock; use the node applied to (i.e. current node in convert process)
};
// Given the optional INode to restrict to, return the list of keys to send messages to for conversion
virtual hsBool GetKeyList( INode *restrictedNode, hsTArray<plKey> &outKeys ) = 0;
// Return the name of the segment/animation that this interface references. Pass "false" to get the
// ENTIRE_ANIMATION_NAME string for entire animations, "true" for nil.
virtual const char *GetIfaceSegmentName( hsBool allowNil ) = 0;
// This animation would require (depending on the node restriction) a separate material (i.e. material anim)
virtual hsBool MightRequireSeparateMaterial( void ) { return false; }
};
// Strings for above NodeTypes enums
#define kUseParamBlockNodeString "(All)"
#define kUseOwnerNodeString "(Applied Node)"
#endif // _plAnimObjInterface_h

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,208 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#define SOUND_3D_COMPONENT_ID Class_ID(0x1be5543f, 0x746f3a97)
#define BGND_MUSIC_COMPONENT_ID Class_ID(0x16b5b2a, 0x33c75095)
#define RANDOM_SOUND_COMPONENT_ID Class_ID(0x35033e37, 0x499568fb)
#define GUI_SOUND_COMPONENT_ID Class_ID(0x446f1ada, 0x6c594a8d)
#define EAX_LISTENER_COMPONENT_ID Class_ID(0x514f4b0a, 0x24672153)
#define SOUND_PHYS_COMP_ID Class_ID(0x29415900, 0x1ade37a5)
#include "../pnKeyedObject/plKey.h"
#include "../../AssetMan/PublicInterface/AssManBaseTypes.h"
#include "hsTemplates.h"
class plComponentBase;
class plMaxNode;
class plSoundBuffer;
class plSound;
class plAudioBaseComponentProc;
namespace plAudioComp
{
// Can't call these until after PreConvert
int GetSoundModIdx(plComponentBase *comp, plMaxNode *node);
plKey GetRandomSoundKey(plComponentBase *comp, plMaxNode *node);
bool IsSoundComponent(plComponentBase *comp);
bool IsLocalOnly( plComponentBase *comp );
}
class plBaseSoundEmitterComponent : public plComponent
{
public:
plBaseSoundEmitterComponent();
virtual ~plBaseSoundEmitterComponent();
RefTargetHandle Clone(RemapDir &remap);
IOResult Save(ISave* isave);
IOResult Load(ILoad* iload);
enum WhichSound
{
kBaseSound,
kCoverSound
};
virtual void SetSoundAssetId( WhichSound which, jvUniqueId assetId, const TCHAR *fileName );
virtual jvUniqueId GetSoundAssetID( WhichSound which );
virtual TCHAR *GetSoundFileName( WhichSound which );
// Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg, Class_ID classToConvert );
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg) = 0;
hsBool DeInit( plMaxNode *node, plErrorMsg *pErrMsg );
virtual hsBool ConvertGrouped( plMaxNode *baseNode, hsTArray<plBaseSoundEmitterComponent *> &groupArray, plErrorMsg *pErrMsg ) { return false; }
int GetSoundIdx(plMaxNode *node)
{
if (fIndices.find(node) != fIndices.end())
return fIndices[node];
return -1;
}
static plSoundBuffer *GetSourceBuffer( const char *fileName, plMaxNode *node, UInt32 srcBufferFlags );
static hsBool LookupLatestAsset( const char *waveName, char *retPath, plErrorMsg *errMsg );
virtual void UpdateSoundFileSelection( void );
// Loads the given combo box with category selections and sets the ParamID for the category parameter.
// Returns false if there are no categories to choose for this component
virtual hsBool UpdateCategories( HWND dialogBox, int &categoryID, ParamID &paramID );
virtual hsBool IsLocalOnly( void ) const { return true; }
// Virtuals for handling animated volumes
virtual hsBool AddToAnim( plAGAnim *anim, plMaxNode *node );
virtual bool AllowUnhide() { return fAllowUnhide; }
// Flags this component to create a grouped sound instead of a normal sound
void SetCreateGrouped( plMaxNode *baseNode, int commonSoundIdx );
// Grabs the current sound volume
virtual hsScalar GetSoundVolume( void ) const;
protected:
jvUniqueId fSoundAssetId; // used for the AssMan
jvUniqueId fCoverSoundAssetID;
hsBool fAssetsUpdated;
friend class plAudioBaseComponentProc;
static UInt32 fWarningFlags;
bool fAllowUnhide;
hsBool fCreateGrouped;
enum Warnings
{
kSrcBufferInvalid = 1,
kCoverBufferInvalid,
kCoverBufferWrongFormat,
kMergeSourceFormatMismatch
};
void IUpdateAssets( void );
static void IShowError( UInt32 type, const char *errMsg, const char *nodeName, plErrorMsg *pErrMsg );
std::map<plMaxNode*, int> fIndices;
std::map<plMaxNode*, bool> fValidNodes;
bool IValidate(plMaxNode *node, plErrorMsg *pErrMsg);
void IConvertOldVolume( void );
float IGetDigitalVolume( void ) const; // In scale 0. to 1., not in db
void IGrabFadeValues( plSound *sound );
void IGrabSoftRegion( plSound *sound, plErrorMsg *pErrMsg );
void IGrabEAXParams( plSound *sound, plErrorMsg *pErrMsg );
virtual UInt32 ICalcSourceBufferFlags() const;
static plSoundBuffer *IGetSourceBuffer( const char *fileName, plMaxNode *srcNode, UInt32 srcBufferFlags );
plSoundBuffer *IProcessSourceBuffer( plMaxNode *maxNode, plErrorMsg *errMsg );
virtual hsBool IAllowStereoFiles( void ) const { return true; }
virtual hsBool IAllowMonoFiles( void ) const { return true; }
virtual hsBool IHasWaveformProps( void ) const { return true; }
// Returns pointers to arrays defining the names and konstants for the supported categories
// for this component. Name array should have an extra "" entry at the end. Returns false if none supported
virtual hsBool IGetCategoryList( char **&catList, int *&catKonstantList ) { return false; }
void ISetBaseParameters( plSound *destSound, plErrorMsg *pErrMsg );
};
class plRandomSoundMod;
class plRandomSoundComponent : public plComponent
{
protected:
hsBool ICheckForSounds(plMaxNode* node);
public:
std::map<plMaxNode*, plRandomSoundMod*> fSoundMods;
plRandomSoundComponent();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg);
hsBool PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
void RemoveSound(int index);
void AddSelectedSound();
int GetCurGroupIdx();
int GetStartIndex(int group);
int GetEndIndex(int group);
};

View File

@ -0,0 +1,99 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
// Don't delete this, I use it for testing -Colin
#if 0
#include "max.h"
#include "resource.h"
#include "plComponent.h"
#include "plComponentReg.h"
#include "plAutoUIComp.h"
#include "plActivatorComponent.h"
class plAutoComponent : public plComponent
{
public:
plAutoComponent();
hsBool Convert(plMaxNode *node, plErrorMsg *msg);
};
AUTO_CLASS_DESC(plAutoComponent, gAutoDesc, "Auto", "Auto", "Test", Class_ID(0x21807fcf, 0x156e2218))
plAutoUIComp *gAutoUI;
void DummyCode()
{
gAutoUI = TRACKED_NEW plAutoUIComp(&gAutoDesc);
gAutoUI->AddCheckBox(0, "test", "Test", true);
gAutoUI->AddFloatSpinner(1, "t2", "T2", 0.5, 0.f, 100.f);
gAutoUI->AddEditBox(2, "blah", "Blah", "Test String", 5);
gAutoUI->AddPickNode(3, "pick", "Pick");
std::vector<Class_ID> cids;
cids.push_back(ACTIVATOR_CID);
cids.push_back(RESPONDER_CID);
gAutoUI->AddPickNode(4, "pick2", "Pick2", &cids);
}
plAutoComponent::plAutoComponent()
{
fClassDesc = &gAutoDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plAutoComponent::Convert(plMaxNode *node, plErrorMsg *msg)
{
hsBool c1 = gAutoUI->GetCheckBox(0, this);
TSTR str = gAutoUI->GetEditBox(2, this);
for (int i = 0; i < gAutoUI->Count(3, this); i++)
INode *node = gAutoUI->GetPickNode(3, this, i);
return true;
}
#endif

View File

@ -0,0 +1,576 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plAutoUIBase.h"
#include "max.h"
#include "iparamb2.h"
#include "plAutoUIParams.h"
#include "hsUtils.h"
#include "resource.h"
#include "plGUICompClassIDs.h"
plAutoUIBase::plAutoUIBase() :
fhDlg(nil), fDesc(nil), fPBlock(nil), fName(nil), fhRollup(nil)
{
}
plAutoUIBase::~plAutoUIBase()
{
if (fDesc)
{
// The internal names are just pointers Max keeps to OUR copy of the string.
// We'll free them here to prevent leaks
UInt16 count = fDesc->Count();
for (UInt16 i = 0; i < count; i++)
{
ParamID id = fDesc->IndextoID(i);
ParamDef& def = fDesc->GetParamDef(id);
char *name = def.int_name;
def.int_name = nil;
delete [] name;
if (def.type == TYPE_STRING)
{
char *defVal = def.def.s;
def.def.s = nil;
delete [] defVal;
}
}
delete fDesc;
fDesc = nil;
}
UInt32 count = fParams.size();
for (UInt32 i = 0; i < count; i++)
delete fParams[i];
fParams.clear();
delete [] fName;
fName = nil;
}
char *plAutoUIBase::IMakeScriptName(const char *fullName)
{
if (!fullName)
return nil;
char buf[256];
buf[0] = '\0';
char *bufptr = buf;
while (*fullName != '\0')
{
if (isalpha(*fullName) || isdigit(*fullName))
{
*bufptr = *fullName;
bufptr++;
}
fullName++;
}
*bufptr = '\0';
if (buf[0] == '\0')
return nil;
return hsStrcpy(buf);
}
////////////////////////////////////////////////////////////////////////////////
// Setup control
//
void plAutoUIBase::AddCheckBox(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates, hsBool def)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_BOOL, 0, 0,
p_default, def, end,
end);
plAutoUIParam* param = TRACKED_NEW plCheckBoxParam(id, name);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddFloatSpinner(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates, hsScalar def, hsScalar min, hsScalar max)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_FLOAT, 0, 0,
p_default, def,
p_range, min, max,
end,
end);
plAutoUIParam* param = TRACKED_NEW plSpinnerParam(id, name, true);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddIntSpinner(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates, int def, int min, int max)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INT, 0, 0,
p_default, def,
p_range, min, max,
end,
end);
plAutoUIParam* param = TRACKED_NEW plSpinnerParam(id, name, false);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddEditBox(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates, const char *def, int lines)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_STRING, 0, 0,
p_default, def ? hsStrcpy(def) : nil, end,
end);
plAutoUIParam* param = TRACKED_NEW plEditParam(id, name, lines);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickNodeList(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates, std::vector<Class_ID>* filter)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE_TAB, 0, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickListParam(id, name, filter);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickNodeButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates, std::vector<Class_ID>* filter, bool canConvertToType)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickButtonParam(id, name, filter, canConvertToType);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickComponentButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates, std::vector<Class_ID>* filter, bool canConvertToType)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickComponentButtonParam(id, name, filter, canConvertToType);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickComponentList(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates, std::vector<Class_ID>* filter)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE_TAB, 0, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickComponentListParam(id, name, filter);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickActivatorButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickActivatorButtonParam(id, name);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickActivatorList(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE_TAB, 0, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickActivatorListParam(id, name);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickDynamicTextButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_REFTARG, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickDynamicTextButtonParam(id, name);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickGUIDialogButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickSingleComponentButtonParam(id, name,plAutoUIParam::kTypeGUIDialog,GUI_DIALOG_COMP_CLASS_ID);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickExcludeRegionButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickExcludeRegionButtonParam(id, name);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickWaterComponentButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickWaterComponentButtonParam(id, name);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickSwimCurrentInterfaceButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickSwimCurrentInterfaceButtonParam(id, name);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickClusterComponentButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickClusterComponentButtonParam(id, name);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickAnimationButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickAnimationButtonParam(id, name);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickBehaviorButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickBehaviorButtonParam(id, name);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickMaterialButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_REFTARG, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickMaterialButtonParam(id, name);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickMaterialAnimationButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_REFTARG, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickMaterialAnimationButtonParam(id, name);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickGUIPopUpMenuButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickSingleComponentButtonParam(id, name,plAutoUIParam::kTypeGUIPopUpMenu,GUI_MENUANCHOR_CLASSID);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickGUISkinButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickSingleComponentButtonParam(id, name,plAutoUIParam::kTypeGUISkin,GUI_SKIN_CLASSID);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddDropDownList(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates, std::vector<std::string>* options)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_STRING, 0, 0,
p_default, nil, end,
end);
plAutoUIParam* param = TRACKED_NEW plDropDownListParam(id, name, options);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
void plAutoUIBase::AddPickGrassComponentButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates)
{
char *scriptNameNew = scriptName ? hsStrcpy(scriptName) : IMakeScriptName(name);
fDesc->AddParam(id, scriptNameNew, TYPE_INODE, 0, 0,
end,
end);
plAutoUIParam* param = TRACKED_NEW plPickGrassComponentButtonParam(id, name);
param->SetVisInfo(vid, vstates);
fParams.push_back(param);
}
BOOL CALLBACK plAutoUIBase::ForwardDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
plAutoUIBase *pthis = NULL;
if (msg == WM_INITDIALOG)
{
SetWindowLong(hDlg, GWL_USERDATA, lParam);
pthis = (plAutoUIBase*)lParam;
}
else
pthis = (plAutoUIBase*)GetWindowLong(hDlg, GWL_USERDATA);
return pthis->DlgProc(hDlg, msg, wParam, lParam);
}
#define WM_SIZE_PANEL WM_APP+1
BOOL plAutoUIBase::DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_INITDIALOG)
{
fhDlg = hDlg;
ICreateControls();
PostMessage(fhDlg, WM_SIZE_PANEL, 0, 0);
}
UInt32 count = fParams.size();
for (UInt32 i = 0; i < count; i++)
{
if (fParams[i]->IsMyMessage(msg, wParam, lParam, fPBlock))
{
if (fParams[i]->GetParamType() == plAutoUIParam::kTypeDropDownList && HIWORD(wParam) == CBN_SELENDOK)
{
plDropDownListParam* ddl = (plDropDownListParam*)fParams[i];
ParamID id = ddl->GetID();
std::string str = ddl->GetString(fPBlock);
int yOffset = 10;
// We now have the id and current state of the drop-down list that changed
// so now we need to update the visible state of the controls
for (UInt32 idx = 0; idx < fParams.size(); idx++)
{
plAutoUIParam* par = fParams[idx];
if (par->CheckVisibility(id, str))
{
par->Show(yOffset);
yOffset += par->GetHeight() + 5;
}
else
{
par->Hide();
}
}
IRollupWindow *rollup = GetCOREInterface()->GetCommandPanelRollup();
int index = rollup->GetPanelIndex(fhDlg);
if (index >= 0)
rollup->SetPageDlgHeight(index, yOffset);
InvalidateRect(fhDlg, NULL, TRUE);
}
return TRUE;
}
}
// During init but after everything else we want to update the visibility
if (msg == WM_SIZE_PANEL)
{
// Ok, this sucks but I don't know of a better way at this point
// We need to intialize the visible state of the controls, and the only way to do this
// is by looping through and finding all of the drop-down lists
for (UInt32 i = 0; i < fParams.size(); i++)
{
if (fParams[i]->GetParamType() == plAutoUIParam::kTypeDropDownList)
{
plDropDownListParam* ddl = (plDropDownListParam*)fParams[i];
ParamID id = ddl->GetID();
std::string str = "";
const char* cstr = ddl->GetString(fPBlock);
int yOffset = 10;
if (cstr)
str = cstr;
// We now have the id and current state of the drop-down list that changed
// so now we need to update the visible state of the controls
for (UInt32 idx = 0; idx < fParams.size(); idx++)
{
if (fParams[idx]->CheckVisibility(id, str))
{
fParams[idx]->Show(yOffset);
yOffset += fParams[idx]->GetHeight() + 5;
}
else
{
fParams[idx]->Hide();
}
}
IRollupWindow *rollup = GetCOREInterface()->GetCommandPanelRollup();
int index = rollup->GetPanelIndex(fhDlg);
if (index >= 0)
rollup->SetPageDlgHeight(index, yOffset);
InvalidateRect(fhDlg, NULL, TRUE);
}
}
return TRUE;
}
return FALSE;
}
void plAutoUIBase::ICreateControls()
{
int yOffset = 10;
UInt32 count = fParams.size();
for (UInt32 i = 0; i < count; i++)
yOffset = fParams[i]->Create(fhDlg, fPBlock, yOffset)+5;
//yOffset = fParams[i]->CreateControls(fhDlg, fPBlock, yOffset)+5;
RECT rect;
GetWindowRect(fhDlg, &rect);
MoveWindow(fhDlg, rect.left, rect.top, rect.right - rect.left, yOffset+5, FALSE);
}
void plAutoUIBase::CreateAutoRollup(IParamBlock2 *pb)
{
fPBlock = pb;
// Don't bother putting up a rollup if there are no params
if (pb->NumParams() == 0)
return;
fhRollup = GetCOREInterface()->AddRollupPage(hInstance,
MAKEINTRESOURCE(IDD_COMP_AUTO),
ForwardDlgProc,
(fName ? fName : (char*)fDesc->cd->ClassName()),
(LPARAM)this);
}
void plAutoUIBase::DestroyAutoRollup()
{
if (fhDlg)
{
GetCOREInterface()->DeleteRollupPage(fhDlg);
fhDlg = nil;
}
fPBlock = nil;
}

View File

@ -0,0 +1,139 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAutoUIBase_h_inc
#define plAutoUIBase_h_inc
//#include "max.h"
//#include "plComponentBase.h"
//#include "plComponentReg.h"
#include "hsTypes.h"
#include "hsWindows.h"
#include <vector>
class ParamBlockDesc2;
class IParamBlock2;
class Class_ID;
class plAutoUIParam;
class plAutoUIClassDesc;
class plAutoUIBase
{
protected:
HWND fhDlg;
std::vector<plAutoUIParam*> fParams;
ParamBlockDesc2 *fDesc;
IParamBlock2 *fPBlock;
char *fName;
HWND fhRollup;
plAutoUIBase();
public:
virtual ~plAutoUIBase();
/////////////////////////////////////////////////////////////////////////////////////
// Add control (and associated data). These should only be called at DLL load time.
// The id parameter must be unique, and while you can add and delete id's, you can
// never reuse an id.
//
// 'scriptName' is a MaxScript visible name. Here's what the help file says:
// "They should begin with an alpha character, have only alphanumerics, and have no
// spaces, punctuations, etc. The convention for multi-word names is to use
// studly-caps, eg, paintRadius."
// (Note: if this is nil, one will be generated from 'name'.)
//
// 'name' is the name that will show up in the user interface (a copy is made, so you
// can free the pointer after this function returns if it was allocated)
//
void AddCheckBox (Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates,
hsBool def=false);
void AddFloatSpinner(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates,
hsScalar def=0.f, hsScalar min=0.f, hsScalar max=1.f);
void AddIntSpinner (Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates,
int def=1, int min=0, int max=1);
void AddEditBox (Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates,
const char *def=nil, int lines=1);
void AddPickNodeList(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates,
std::vector<Class_ID>* filter=nil);
void AddPickNodeButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates,
std::vector<Class_ID>* filter=nil, bool canConvertToType=false);
void AddPickComponentButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates,
std::vector<Class_ID>* filter=nil, bool canConvertToType=false);
void AddPickComponentList(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates,
std::vector<Class_ID>* filter=nil);
void AddPickActivatorList(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddPickActivatorButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddPickDynamicTextButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddPickGUIDialogButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddPickExcludeRegionButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddPickAnimationButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddPickBehaviorButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddPickMaterialButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddPickMaterialAnimationButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddPickWaterComponentButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddPickSwimCurrentInterfaceButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddPickClusterComponentButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddPickGUIPopUpMenuButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddPickGUISkinButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void AddDropDownList(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates, std::vector<std::string>* options = nil);
void AddPickGrassComponentButton(Int16 id, const char *scriptName, const char *name, int vid, std::vector<std::string>* vstates);
void CreateAutoRollup(IParamBlock2 *pb);
void DestroyAutoRollup();
const char *GetName() { return fName; }
protected:
char *IMakeScriptName(const char *fullName);
void ICreateControls();
static BOOL CALLBACK ForwardDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
};
#endif // plAutoUIBase_h_inc

View File

@ -0,0 +1,82 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plAutoUIBlock.h"
#include "max.h"
#include "iparamb2.h"
#include "plComponentReg.h"
#include "hsUtils.h"
#include "resource.h"
plAutoUIBlock::plAutoUIBlock(plComponentClassDesc *cd, int blockID, const char *name, int version)
{
fName = hsStrcpy(name);
fVersion = version;
fDesc = TRACKED_NEW ParamBlockDesc2(blockID, "Auto", IDS_COMP_AUTO, cd, 0, end);
fIsMultiModifier = false;
}
int plAutoUIBlock::NumParams()
{
return fParams.size();
}
plAutoUIParam *plAutoUIBlock::GetParam(int idx)
{
if (idx < fParams.size())
return fParams[idx];
hsAssert(0, "Param index out of range");
return nil;
}
IParamBlock2 *plAutoUIBlock::CreatePB()
{
return CreateParameterBlock2(fDesc, nil);
}
int plAutoUIBlock::GetBlockID()
{
return fDesc->ID;
}

View File

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

View File

@ -0,0 +1,109 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plAutoUIComp.h"
#include <algorithm>
#include "resource.h"
#include "notify.h"
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
plAutoUIComp::plAutoUIComp(plAutoUIClassDesc *cd)
{
fDesc = TRACKED_NEW ParamBlockDesc2(plComponentBase::kBlkComp, "Auto", IDS_COMP_AUTO, cd, P_AUTO_CONSTRUCT, plComponentBase::kRefComp, end);
cd->autoComp = this;
}
////////////////////////////////////////////////////////////////////////////////
// Get value from control
//
hsBool plAutoUIComp::GetCheckBox(Int16 id, plComponentBase *comp)
{
IParamBlock2 *pblock = comp->GetParamBlockByID(plComponentBase::kBlkComp);
return pblock->GetInt(id);
}
hsScalar plAutoUIComp::GetFloatSpinner(Int16 id, plComponentBase *comp)
{
IParamBlock2 *pblock = comp->GetParamBlockByID(plComponentBase::kBlkComp);
return pblock->GetFloat(id);
}
int plAutoUIComp::GetIntSpinner(Int16 id, plComponentBase *comp)
{
IParamBlock2 *pblock = comp->GetParamBlockByID(plComponentBase::kBlkComp);
return pblock->GetInt(id);
}
TSTR plAutoUIComp::GetEditBox(Int16 id, plComponentBase *comp)
{
IParamBlock2 *pblock = comp->GetParamBlockByID(plComponentBase::kBlkComp);
return pblock->GetStr(id);
}
INode *plAutoUIComp::GetPickNode(Int16 id, plComponentBase *comp, int idx)
{
IParamBlock2 *pblock = comp->GetParamBlockByID(plComponentBase::kBlkComp);
return pblock->GetINode(id, 0, idx);
}
int plAutoUIComp::Count(Int16 id, plComponentBase *comp)
{
IParamBlock2 *pblock = comp->GetParamBlockByID(plComponentBase::kBlkComp);
return pblock->Count(id);
}
//
void plAutoUIComp::BeginEditParams(IObjParam *ip, ReferenceMaker *obj, ULONG flags, Animatable *prev)
{
CreateAutoRollup(((plComponentBase*)obj)->GetParamBlockByID(plComponentBase::kBlkComp));
}
void plAutoUIComp::EndEditParams(IObjParam *ip, ReferenceMaker *obj, ULONG flags, Animatable *prev)
{
DestroyAutoRollup();
}

View File

@ -0,0 +1,118 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAutoUIBase.h"
#include "max.h"
#include "plComponentBase.h"
#include "plComponentReg.h"
class plAutoUIComp : public plAutoUIBase
{
public:
plAutoUIComp(plAutoUIClassDesc *cd);
/////////////////////////////////////////////////////////////////////////////////////
// Get the value of a control. Pass in the id and your 'this' pointer.
//
hsBool GetCheckBox(Int16 id, plComponentBase *comp);
hsScalar GetFloatSpinner(Int16 id, plComponentBase *comp);
int GetIntSpinner(Int16 id, plComponentBase *comp);
TSTR GetEditBox(Int16 id, plComponentBase *comp);
INode* GetPickNode(Int16 id, plComponentBase *comp, int idx);
// Get the count for a parameter that takes an index
int Count(Int16 id, plComponentBase *comp);
/////////////////////////////////////////////////////////////////////////////////////
// Max/internal functions
//
// Called by the ClassDesc.
void BeginEditParams(IObjParam *ip, ReferenceMaker *obj, ULONG flags, Animatable *prev);
void EndEditParams(IObjParam *ip, ReferenceMaker *obj, ULONG flags, Animatable *prev);
};
class plAutoUIClassDesc : public plComponentClassDesc
{
public:
virtual bool IsAutoUI() { return true; }
virtual bool IsObsolete() { return true; }
plAutoUIComp *autoComp;
void BeginEditParams(IObjParam *ip, ReferenceMaker* obj, ULONG flags, Animatable *prev)
{
ClassDesc2::BeginEditParams(ip, obj, flags, prev);
if (autoComp) autoComp->BeginEditParams(ip, obj, flags, prev);
}
void EndEditParams(IObjParam *ip, ReferenceMaker* obj, ULONG flags, Animatable *prev)
{
if (autoComp) autoComp->EndEditParams(ip, obj, flags, prev);
ClassDesc2::EndEditParams(ip, obj, flags, prev);
}
void CreateAutoRollup(IParamBlock2 *pb)
{
if (autoComp)
autoComp->CreateAutoRollup(pb);
}
void DestroyAutoRollup()
{
if (autoComp)
autoComp->DestroyAutoRollup();
}
};
void plExternalComponentReg(ClassDesc *desc);
#define AUTO_CLASS_DESC(classname, varname, longname, shortname, category, id) \
class classname##ClassDesc : public plAutoUIClassDesc \
{ \
FUNC_CLASS_DESC(classname, longname, shortname, category, id) \
classname##ClassDesc() { plExternalComponentReg(this); } \
}; \
DECLARE_CLASS_DESC(classname, varname)
//
void ReleaseGlobals();
//
// Categories
//
#define COMP_TYPE_KAHLO "Kahlo"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,423 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "max.h"
#include "iparamb2.h"
#include "hsTypes.h"
#include "hsTemplates.h"
#include <vector>
class plKey;
class plComponentBase;
class plAutoUIParam
{
protected:
ParamID fID;
char *fName;
HWND fhDlg;
int fHeight;
std::vector<HWND> fControlVec;
ParamID fVisID;
std::vector<std::string> fVisStates;
public:
// Types returned by GetParamType
enum
{
kTypeNone,
kTypeBool,
kTypeFloat,
kTypeInt,
kTypeString,
kTypeSceneObj,
kTypeActivator,
kTypeComponent,
kTypeDynamicText,
kTypeGUIDialog,
kTypeExcludeRegion,
kTypeAnimation,
kTypeBehavior,
kTypeMaterial,
kTypeGUIPopUpMenu,
kTypeGUISkin,
kTypeWaterComponent,
kTypeDropDownList,
kTypeSwimCurrentInterface,
kTypeClusterComponent,
kTypeMaterialAnimation,
kTypeGrassComponent,
};
plAutoUIParam(ParamID id, const char *name);
virtual ~plAutoUIParam();
int Create(HWND hDlg, IParamBlock2 *pb, int yOffset);
virtual int CreateControls(HWND hDlg, IParamBlock2 *pb, int yOffset) = 0;
virtual bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb) = 0;
ParamID GetID() { return fID; }
virtual void Show(int yOffset);
void Hide();
int GetHeight();
void SetVisInfo(ParamID id, std::vector<std::string>* states);
bool CheckVisibility(ParamID id, std::string state);
virtual int GetParamType();
virtual hsBool GetBool(IParamBlock2 *pb);
virtual float GetFloat(IParamBlock2 *pb);
virtual int GetInt(IParamBlock2 *pb);
virtual const char* GetString(IParamBlock2 *pb);
virtual int GetCount(IParamBlock2 *pb);
virtual plKey GetKey(IParamBlock2 *pb, int idx=0);
virtual plComponentBase *GetComponent(IParamBlock2 *pb, int idx=0);
protected:
int ISizeControl(HWND hDlg, HWND hControl, int w, int h, int y, int x=3);
HWND ICreateControl(HWND hDlg, const char *className, const char *wndName=nil, DWORD style=0, DWORD exStyle=0);
void ISetControlFont(HWND hControl);
int IAddStaticText(HWND hDlg, int y, const char *text);
};
class plCheckBoxParam : public plAutoUIParam
{
protected:
HWND fhCheck;
public:
plCheckBoxParam(ParamID id, const char *name);
int CreateControls(HWND hDlg, IParamBlock2 *pb, int yOffset);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
hsBool GetBool(IParamBlock2 *pb);
};
class plSpinnerParam : public plAutoUIParam
{
protected:
HWND fhSpinner;
bool fIsFloat; // True if this is a float spinner, false if it is an int
public:
plSpinnerParam(ParamID id, const char *name, bool isFloat);
int CreateControls(HWND hDlg, IParamBlock2 *pb, int yOffset);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
float GetFloat(IParamBlock2 *pb);
int GetInt(IParamBlock2 *pb);
void Show(int yOffset);
};
class plEditParam : public plAutoUIParam
{
protected:
HWND fhEdit;
int fLines;
public:
plEditParam(ParamID id, const char *name, int lines);
int CreateControls(HWND hDlg, IParamBlock2 *pb, int yOffset);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
const char* GetString(IParamBlock2 *pb);
void Show(int yOffset);
};
class plPickListParam : public plAutoUIParam
{
protected:
HWND fhList;
HWND fhAdd;
HWND fhRemove;
std::vector<Class_ID> fCIDs;
public:
plPickListParam(ParamID id, const char *name, std::vector<Class_ID>* filter);
int CreateControls(HWND hDlg, IParamBlock2 *pb, int yOffset);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
int GetCount(IParamBlock2 *pb);
plKey GetKey(IParamBlock2 *pb, int idx=0);
void Show(int yOffset);
protected:
void IUpdateList(IParamBlock2 *pb);
};
class plPickButtonParam : public plAutoUIParam
{
protected:
ICustButton *fButton;
std::vector<Class_ID> fCIDs;
bool fCanConvertToType;
HWND fhRemove;
public:
plPickButtonParam(ParamID id, const char *name, std::vector<Class_ID>* filter, bool canConvertToType);
int CreateControls(HWND hDlg, IParamBlock2 *pb, int yOffset);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
int GetCount(IParamBlock2 *pb);
plKey GetKey(IParamBlock2 *pb, int idx=0);
void SetPickNode(INode *node, IParamBlock2 *pb);
void Show(int yOffset);
};
class plPickComponentButtonParam : public plPickButtonParam
{
public:
plPickComponentButtonParam(ParamID id, const char *name, std::vector<Class_ID>* filter, bool canConvertToType);
int GetParamType();
plComponentBase* GetComponent(IParamBlock2 *pb, int idx=0);
};
class plPickComponentListParam : public plPickListParam
{
public:
plPickComponentListParam(ParamID id, const char *name, std::vector<Class_ID>* filter);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
plComponentBase *GetComponent(IParamBlock2 *pb, int idx=0);
};
class plPickActivatorButtonParam : public plPickButtonParam
{
public:
plPickActivatorButtonParam(ParamID id, const char *name);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
plComponentBase *GetComponent(IParamBlock2 *pb, int idx=0);
};
class plPickActivatorListParam : public plPickListParam
{
public:
plPickActivatorListParam(ParamID id, const char *name);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
plComponentBase *GetComponent(IParamBlock2 *pb, int idx=0);
};
class plPickDynamicTextButtonParam : public plPickButtonParam
{
public:
plPickDynamicTextButtonParam(ParamID id, const char *name);
int CreateControls(HWND hDlg, IParamBlock2 *pb, int yOffset);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
const char* GetString(IParamBlock2 *pb);
int GetCount(IParamBlock2 *pb);
plKey GetKey(IParamBlock2 *pb, int idx=0);
};
class plPickSingleComponentButtonParam : public plPickButtonParam
{
protected:
int fMyType;
Class_ID fClassToPick;
public:
plPickSingleComponentButtonParam(ParamID id, const char *name, int myType, Class_ID myClassToPick);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
plComponentBase *GetComponent(IParamBlock2 *pb, int idx=0);
};
class plPickExcludeRegionButtonParam : public plPickButtonParam
{
public:
plPickExcludeRegionButtonParam(ParamID id, const char *name);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
plComponentBase *GetComponent(IParamBlock2 *pb, int idx=0);
};
class plPickWaterComponentButtonParam : public plPickButtonParam
{
public:
plPickWaterComponentButtonParam(ParamID id, const char *name);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
plComponentBase *GetComponent(IParamBlock2 *pb, int idx=0);
};
class plPickSwimCurrentInterfaceButtonParam : public plPickButtonParam
{
public:
plPickSwimCurrentInterfaceButtonParam(ParamID id, const char *name);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
plComponentBase *GetComponent(IParamBlock2 *pb, int idx=0);
};
class plPickClusterComponentButtonParam : public plPickButtonParam
{
public:
plPickClusterComponentButtonParam(ParamID id, const char *name);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
plComponentBase *GetComponent(IParamBlock2 *pb, int idx=0);
};
class plPickAnimationButtonParam : public plPickButtonParam
{
public:
plPickAnimationButtonParam(ParamID id, const char *name);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
plComponentBase *GetComponent(IParamBlock2 *pb, int idx=0);
};
class plPickBehaviorButtonParam : public plPickButtonParam
{
public:
plPickBehaviorButtonParam(ParamID id, const char *name);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
plComponentBase *GetComponent(IParamBlock2 *pb, int idx=0);
};
class plPickMaterialButtonParam : public plPickButtonParam
{
public:
plPickMaterialButtonParam(ParamID id, const char *name);
int CreateControls(HWND hDlg, IParamBlock2 *pb, int yOffset);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
const char* GetString(IParamBlock2 *pb);
int GetCount(IParamBlock2 *pb);
plKey GetKey(IParamBlock2 *pb, int idx=0);
};
class plPickMaterialAnimationButtonParam : public plPickButtonParam
{
protected:
hsTArray<plKey> fKeys;
public:
plPickMaterialAnimationButtonParam(ParamID id, const char *name);
int CreateControls(HWND hDlg, IParamBlock2 *pb, int yOffset);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
const char* GetString(IParamBlock2 *pb);
int GetCount(IParamBlock2 *pb);
plKey GetKey(IParamBlock2 *pb, int idx=0);
void CreateKeyArray(IParamBlock2* pb);
void DestroyKeyArray();
};
class plDropDownListParam : public plAutoUIParam
{
protected:
HWND fhList;
std::vector<std::string> fOptions;
public:
plDropDownListParam(ParamID id, const char *name, std::vector<std::string>* options);
int CreateControls(HWND hDlg, IParamBlock2 *pb, int yOffset);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
int GetCount(IParamBlock2 *pb);
const char* GetString(IParamBlock2 *pb);
void Show(int yOffset);
protected:
void IUpdateList(IParamBlock2 *pb);
};
class plPickGrassComponentButtonParam : public plPickButtonParam
{
public:
plPickGrassComponentButtonParam(ParamID id, const char *name);
bool IsMyMessage(UINT msg, WPARAM wParam, LPARAM lParam, IParamBlock2 *pb);
int GetParamType();
plComponentBase *GetComponent(IParamBlock2 *pb, int idx=0);
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,243 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef __PLAVATARCOMPONENT_H__
#define __PLAVATARCOMPONENT_H__
#include "max.h"
#include "../plAvatar/plCritterCommands.h"
#include "../plAvatar/plPuppetCommands.h"
#define AVATAR_CLASS_ID Class_ID(0x49247847, 0xd3908fe)
#define LOD_AVATAR_CLASS_ID Class_ID(0x50100640, 0x72f94120)
#define CRITTER_CLASS_ID Class_ID(0x3bd003b6, 0x66a85756)
#define PUPPET_CLASS_ID Class_ID(0x26545a35, 0x2a5000b)
class plHKPhysical;
class plErrorMsg;
class plArmatureMod;
class plMaxNode;
class plSceneObject;
class plShadowCaster;
class hsGMaterial;
class AvatarCompDlgProc;
extern AvatarCompDlgProc gAvatarCompDlgProc;
/** \class plArmatureComponent
Base class for all the components that creature armatures or, in the case of the
compound controller, simply multi-channel animation controllers (plAGMasterMod.)
*/
class plArmatureComponent : public plComponent
{
private:
void ISetArmatureSORecurse(plMaxNode *node, plSceneObject *so);
plHKPhysical* IConvertArmaturePhysicsProxy(plMaxNode *node, plMaxNode *proxyNode);
protected:
plArmatureMod *fArmMod;
plArmatureComponent() : fArmMod(nil) {}
plArmatureMod* IGenerateMyArmMod(plHKPhysical* myHKPhys, plMaxNode* node);
hsBool IVerifyUsedNode(INode* thisNode, plErrorMsg *pErrMsg, hsBool isHull);
virtual void IAttachModifiers(plMaxNode *node, plErrorMsg *pErrMsg) = 0;
virtual void ISetupClothes(plMaxNode *node, plArmatureMod *mod, plErrorMsg *pErrMsg) {}
virtual void ISetupAvatarRenderPropsRecurse(plMaxNode *node);
virtual void IAttachShadowCastModifiersRecur(plMaxNode* node, plShadowCaster* caster); // Apply supplied shadowcaster modifier
public:
enum {
kBounceEventGroupBoolTab_DEAD = 99,
kReportEventGroupBoolTab_DEAD,
kBounceEventGroupChoice_DEAD,
kReportEventGroupChoice_DEAD,
kBounceGroups,
kReportGroups,
};
// Constants for brain selection UI
enum
{
kBrainHuman,
kBrainCritter,
kMaxBrainType,
};
//static const char *BrainStrings[];
virtual hsBool SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg);
virtual hsBool PreConvert(plMaxNode* node, plErrorMsg* pErrMsg);
virtual hsBool Convert(plMaxNode* node, plErrorMsg* pErrMsg);
void DeleteThis() { delete this; }
};
class plAvatarComponent : public plArmatureComponent
{
private:
void IAttachModifiers(plMaxNode *node, plErrorMsg *pErrMsg);
public:
plAvatarComponent();
// Do not change any of the entries in this list. Only add at the end.
// All existing ones must be kept for backward compatibility.
enum
{
kWeightRadio, //Insert in v1, removed version 3 (14.07.01)
kAgilityRadio, //Insert in v1, " " " "
kModelRoot, //Insert in v1, removed version 2 (05/09/01)
kPhysicsProxyFeet_DEAD, //Insert in v1,
kFriction, //Insert in v3,
kMaxVelocity, //Insert in v3,
kAcceleration, //Insert in v3,
kTurnForce, //Insert in v3,
kWalkAnim, //Insert in v3,
kRunAnim, //Insert in v3,
kUseAnimationsBool, //Insert in v4,
kRootNode, //Insert in v5,
kMeshNode, //Insert in v5,
kClothingGroup, //Insert in v6,
kBrainType, //Insert in v7,
kSkeleton, //Insert in v8,
kPhysicsProxyTorso_DEAD,
kPhysicsProxyHead_DEAD,
kPhysicsHeight,
kPhysicsWidth,
kBodyAgeName,
kBodyFootstepSoundPage,
kAnimationPrefix,
};
virtual void ISetupClothes(plMaxNode *node, plArmatureMod *mod, plErrorMsg *pErrMsg);
hsBool SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg);
hsBool PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { return (plArmatureComponent::PreConvert(node, pErrMsg)); }
hsBool Convert(plMaxNode* node, plErrorMsg* pErrMsg) { return (plArmatureComponent::Convert(node, pErrMsg)); }
void DeleteThis() { delete this; }
};
class plLODAvatarComponent : public plArmatureComponent
{
private:
void IAttachModifiers(plMaxNode *node, plErrorMsg *pErrMsg);
protected:
virtual void ISetupClothes(plMaxNode *node, plArmatureMod *mod, plErrorMsg *pErrMsg);
// Create a single shadowcaster modifier, and apply it to the
// sceneobject hierarchies for each LOD.
virtual void IAttachShadowCastToLODs(plMaxNode* rootNode);
virtual void IAttachShadowCastModifiersRecur(plMaxNode* node, plShadowCaster* caster);
hsGMaterial *fMaterial;
public:
VCharArray fLODLevels; //Initialized in the CTR.
// Do not change any of the entries in this list. Only add at the end.
// All existing ones must be kept for backward compatibility.
enum
{
kPhysicsProxyFeet_DEAD, //Insert in v1,
kFriction, //Insert in v1,
kMaxVelocity, //Insert in v1,
kAcceleration, //Insert in v1,
kTurnForce, //Insert in v1,
kWalkAnim, //Insert in v1,
kRunAnim, //Insert in v1,
kUseAnimationsBool, //Insert in v1,
kLODLevel, //Insert in v1,
kLODState, //Insert in v1,
kRootNodeTab, //Insert in v1,
kMeshNodeTab, //Insert in v1,
kRootNodeAddBtn, //Insert in v1,
kMeshNodeAddBtn, //Insert in v1,
kClothingGroup, //Insert in v2,
kBrainType, //Insert in v3,
kGroupIdx, //Insert in v4,
kBoneList, //Insert in v4,
kGroupTotals, //Insert in v4,
kLastPick, //Insert in v4,
kSkeleton, //Insert in v5,
kMaterial, //Insert in v6,
kPhysicsProxyTorso_DEAD,
kPhysicsProxyHead_DEAD,
kPhysicsHeight,
kPhysicsWidth,
kBodyFootstepSoundPage,
kAnimationPrefix,
};
enum
{
kMaxNumLODLevels = 3,
};
plLODAvatarComponent();
hsBool SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg);
hsBool PreConvert(plMaxNode* node, plErrorMsg* pErrMsg);
hsBool Convert(plMaxNode* node, plErrorMsg* pErrMsg);
void DeleteThis() { delete this; }
void RemoveBone(int index);
void AddSelectedBone();
int GetCurGroupIdx();
int GetStartIndex(int group);
int GetEndIndex(int group);
};
class plAnimatronicComponent : public plLODAvatarComponent
{
};
#endif

View File

@ -0,0 +1,186 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plBehavioralComponents.h"
#include "plComponentReg.h"
#include "resource.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxMain/plPhysicalProps.h"
#include "hsResMgr.h"
#include "../pnKeyedObject/plKey.h"
#include "../plAvatar/plSittingModifier.h"
#include "plResponderComponent.h"
#include "plPickNode.h"
void DummyCodeIncludeFuncBehaviors() {}
class plSittingComponentProc : public ParamMap2UserDlgProc
{
protected:
void IUpdateButtonText(HWND hWnd, IParamBlock2 *pb)
{
INode *node = pb->GetINode(plAvBehaviorSittingComponent::kDetector);
SetWindowText(GetDlgItem(hWnd, IDC_DETECTOR), node ? node->GetName() : "(none)");
}
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
IUpdateButtonText(hWnd, map->GetParamBlock());
return TRUE;
case WM_COMMAND:
IParamBlock2 *pb = map->GetParamBlock();
if (LOWORD(wParam) == IDC_DETECTOR && HIWORD(wParam) == BN_CLICKED)
{
plPick::Activator(pb, plAvBehaviorSittingComponent::kDetector, true);
IUpdateButtonText(hWnd, pb);
return TRUE;
}
break;
}
return FALSE;
}
void DeleteThis() {}
};
static plSittingComponentProc gSittingComponentProc;
CLASS_DESC(plAvBehaviorSittingComponent, gAvBehaviorSittingDesc, "Sitting Behavior", "SitBehavior", COMP_TYPE_AVATAR, BEHAVIORAL_SITTING_CID)
ParamBlockDesc2 gAvBehavioralSittingBk
(
plComponent::kBlkComp, _T("(sittingBehavior"), 0, &gAvBehaviorSittingDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
//Roll out
IDD_COMP_BEHAVIOR_SITTING, IDS_COMP_BEHAVIOR_SITTINGS, 0, 0, &gSittingComponentProc,
// params
plAvBehaviorSittingComponent::kDetector, _T("detector"), TYPE_INODE, 0, 0,
end,
plAvBehaviorSittingComponent::kApproachFront, _T("ApproachFront"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SIT_APP_FRONT,
p_default, FALSE,
end,
plAvBehaviorSittingComponent::kApproachLeft, _T("ApproachLeft"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SIT_APP_LEFT,
p_default, TRUE,
end,
plAvBehaviorSittingComponent::kApproachRight, _T("ApproachRight"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SIT_APP_RIGHT,
p_default, TRUE,
end,
plAvBehaviorSittingComponent::kDisableForward, _T("DisableForward"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SIT_NOFORWARD,
p_default, TRUE,
end,
end
);
plAvBehaviorSittingComponent::plAvBehaviorSittingComponent()
{
fClassDesc = &gAvBehaviorSittingDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plAvBehaviorSittingComponent::SetupProperties(plMaxNode* node, plErrorMsg *pErrMsg)
{
plActivatorBaseComponent::SetupProperties(node, pErrMsg);
// Need a coordinate interface to tell the avatar where to drop trou
node->SetForceLocal(true);
return true;
}
hsBool plAvBehaviorSittingComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
plMaxNode *detectNode = (plMaxNode*)fCompPB->GetINode(kDetector);
plComponentBase *detectComp = detectNode ? detectNode->ConvertToComponent() : nil;
if (detectComp)
{
bool hasFrontApproach = fCompPB->GetInt(ParamID(kApproachFront)) ? true : false;
bool hasLeftApproach = fCompPB->GetInt(ParamID(kApproachLeft)) ? true : false;
bool hasRightApproach = fCompPB->GetInt(ParamID(kApproachRight)) ? true : false;
// Create our key here and give it to the detector so it will notify us
plSittingModifier *sitMod = TRACKED_NEW plSittingModifier(hasFrontApproach, hasLeftApproach, hasRightApproach);
if (fCompPB->GetInt(ParamID(kDisableForward)))
sitMod->fMiscFlags |= plSittingModifier::kDisableForward;
plKey key = node->AddModifier(sitMod, IGetUniqueName(node));
detectComp->AddReceiverKey(key);
fLogicModKeys[node] = key;
}
return true;
}
hsBool plAvBehaviorSittingComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
plKey logicKey = fLogicModKeys[node];
if (logicKey)
{
plSittingModifier *sitMod = plSittingModifier::ConvertNoRef(logicKey->GetObjectPtr());
// XXX sitMod->SetSeekTime(fCompPB->GetFloat(kSeekTimeFloat));
// Get all the keys who want to be notified when the avatar ass hits the seat
hsTArray<plKey> receivers;
IGetReceivers(node, receivers);
for (int i = 0; i < receivers.Count(); i++)
sitMod->AddNotifyKey(receivers[i]);
}
return true;
}

View File

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

View File

@ -0,0 +1,774 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
// BIPEDKILLER
///////////
//
// INCLUDES
//
///////////
// theirs
#include <windowsx.h>
#include "max.h"
#include "resource.h"
#include "CS/bipexp.h"
#include "decomp.h"
#pragma warning(disable: 4786) // disable warnings about excessive STL symbol name length
#include <map>
#include <vector>
#include "hsStlSortUtils.h"
// ours
#include "plComponent.h"
#include "plComponentReg.h"
#include "plMiscComponents.h"
#include "../MaxMain/plMaxNodeBase.h"
#include "../plTransform/hsAffineParts.h"
#include "hsMatrix44.h"
//////////////
//
// LOCAL TYPES
//
//////////////
// NODETMINFO
// A local handy thing to remember a matrix and the time we sampled it
struct nodeTMInfo
{
TimeValue fTime;
Matrix3 fMat3;
};
// PLSAMPLEVEC
// A vector of matrix samples
typedef std::vector<nodeTMInfo *> plSampleVec;
// PLSAMPLEVECMAP
// A map relating bone names to plSampleVecs
typedef std::map<char *, plSampleVec *, stringSorter> plSampleVecMap;
/////////////
//
// PROTOTYPES
//
/////////////
void ProcessNodeRecurse(INode *node, INode *parent, Interface *theInterface);
void ProcessBipedNodeRecurse(INode *bipNode, INode *newParent, Interface *theInterface);
void ProcessNonBipedNodeRecurse(INode *node, INode *parent, Interface *theInterface);
int LimitTransform(INode* node, Matrix3* nodeTM);
void GetParts(Int32 i, std::vector<nodeTMInfo *>& mat3Array, hsAffineParts* parts);
Quat GetRotKey(Int32 i, std::vector<nodeTMInfo *>& mat3Array, hsAffineParts* parts);
Point3 GetPosKey(Int32 i, std::vector<nodeTMInfo *>& mat3Array, hsAffineParts* parts);
ScaleValue GetScaleKey(Int32 i, std::vector<nodeTMInfo *>& mat3Array, hsAffineParts* parts);
Quat MakeRotKey(INode *node, INode *parent, TimeValue t);
Point3 MakePosKey(INode *node, INode *parent, TimeValue t);
ScaleValue MakeScaleKey(INode *node, INode *parent, TimeValue t);
AffineParts GetLocalNodeParts(INode *node, INode *parent, TimeValue t);
bool ExportableAnimationController(INode* node);
bool HasBipController(INode* node);
Quat GetRotKey(Int32 i, std::vector<nodeTMInfo *>& mat3Array);
plSampleVec * SampleNodeMotion(INode* node, INode* parent, int sampleRate, Interface *theInterface);
plSampleVec * SampleNodeMotion(INode * node, INode* parent, int sampleRate, TimeValue start, TimeValue end);
void ReapplyAnimation(INode *node, plSampleVec *samples);
void FreeMotionSamples(plSampleVec *samples);
/////////////////
//
// IMPLEMENTATION
//
/////////////////
// REMOVEBIPED
void RemoveBiped(INode *bipRoot, Interface *theInterface)
{
SuspendAnimate();
AnimateOn();
// remember Max's default controllers (for the user)
ClassDesc* defaultRotCtrl=GetDefaultController(CTRL_ROTATION_CLASS_ID);
ClassDesc* defaultPosCtrl=GetDefaultController(CTRL_POSITION_CLASS_ID);
ClassDesc* defaultScaleCtrl=GetDefaultController(CTRL_SCALE_CLASS_ID);
// change default controllers to linear to create linear controllers
// since we have no tan info
DllDir* dllDir=&theInterface->GetDllDir();
ClassDirectory* classDir=&dllDir->ClassDir();
ClassDesc* rotCtrl = classDir->FindClass( SClass_ID(CTRL_ROTATION_CLASS_ID),
Class_ID(TCBINTERP_ROTATION_CLASS_ID,0)); // was Class_ID(LININTERP_ROTATION_CLASS_ID,0));
ClassDesc* posCtrl = classDir->FindClass( SClass_ID(CTRL_POSITION_CLASS_ID),
Class_ID(LININTERP_POSITION_CLASS_ID, 0));
ClassDesc* scaleCtrl = classDir->FindClass( SClass_ID(CTRL_SCALE_CLASS_ID),
Class_ID(LININTERP_SCALE_CLASS_ID, 0));
SetDefaultController(CTRL_ROTATION_CLASS_ID, rotCtrl);
SetDefaultController(CTRL_POSITION_CLASS_ID, posCtrl);
SetDefaultController(CTRL_SCALE_CLASS_ID, scaleCtrl);
ProcessNodeRecurse(bipRoot, nil, theInterface);
//deinit
ResumeAnimate();
// remember Max's default controllers (for the user)
SetDefaultController(CTRL_ROTATION_CLASS_ID, defaultRotCtrl);
SetDefaultController(CTRL_POSITION_CLASS_ID, defaultPosCtrl);
SetDefaultController(CTRL_SCALE_CLASS_ID, defaultScaleCtrl);
}
// PROCESSNODERECURSE
void ProcessNodeRecurse(INode *node, INode *parent, Interface *theInterface)
{
if(HasBipController(node))
{
ProcessBipedNodeRecurse(node, parent, theInterface);
} else {
ProcessNonBipedNodeRecurse(node, parent, theInterface);
}
}
// PROCESSBIPNODERECURSE
// When we find a Biped-controlled node in our hierarchy, we need to find one non-biped
// child and promote it to the place of the biped node in the hierarchy. The siblings
// of the promoted node will become its children, as will the original children from the
// biped node.
void ProcessBipedNodeRecurse(INode *bipNode, INode *parent, Interface *theInterface)
{
int numChildren = bipNode->NumberOfChildren();
char *bipName = bipNode ? bipNode->GetName() : nil;
INode *replacement = nil;
for (int i = 0; i < numChildren; i++)
{
INode *child = bipNode->GetChildNode(i);
char *childName = child ? child->GetName() : nil;
if( ! HasBipController(child) )
{
replacement = child; // this child is going to be our replacement for this bipnode
// sample the animation (into global space)
plSampleVec *samples = SampleNodeMotion(replacement, bipNode, 1, theInterface);
// detach from the parent (this blows away the animation)
replacement->Detach(0);
// attach the node to the biped's parent.
parent->AttachChild(replacement);
ReapplyAnimation(child, samples);
FreeMotionSamples(samples);
// we only need one replacement for the bip node
break;
}
}
if(replacement)
{
// reparent the siblings to the newly promoted replacement node
numChildren = bipNode->NumberOfChildren();
for (i = 0; i < numChildren; i++)
{
INode *child = bipNode->GetChildNode(i);
if( HasBipController(child) )
{
ProcessBipedNodeRecurse(child, replacement, theInterface);
} else {
child->Detach(0); // remove the (non-bip) child from the bip node
replacement->AttachChild(child); // attach it to the non-bip parent
ProcessNonBipedNodeRecurse(child, replacement, theInterface);
}
}
} else {
// this is an error condition: we've got a bip node that has no non-bip child for us to promote
char buf[256];
sprintf(buf, "Couldn't find non-bip node to transfer motion to for bip node %s\n", bipNode->GetName());
hsStatusMessage(buf);
}
}
// PROCESSNONBIPEDNODERECURSE
// Sample motion for a hierarchy that does not have any Biped controllers in it.
void ProcessNonBipedNodeRecurse(INode *node, INode *parent, Interface *theInterface)
{
if( ! ExportableAnimationController(node) )
{
plSampleVec *samples = SampleNodeMotion(node, parent, 2, theInterface);
ReapplyAnimation(node, samples);
FreeMotionSamples(samples);
}
int numChildren = node->NumberOfChildren();
for (int i = 0; i < numChildren; i++)
{
INode *child = node->GetChildNode(i);
ProcessNodeRecurse(child, node, theInterface);
}
}
// ADJUSTROTKEYS
void AdjustRotKeys(INode *node)
{
Control *controller = node->GetTMController();
Control *rotControl = controller->GetRotationController();
IKeyControl *rotKeyCont = GetKeyControlInterface(rotControl);
int numKeys = rotKeyCont->GetNumKeys();
for(int i = 0; i < numKeys; i++)
{
ITCBKey key;
rotKeyCont->GetKey(i, &key);
key.cont = 0;
rotKeyCont->SetKey(i, &key);
}
}
#define boolTrue = (0 == 0);
#define boolFalse = (0 == 1);
// *** todo: generalize this for rotation keys as well.
int CompareKeys(ILinPoint3Key &a, ILinPoint3Key &b)
{
int result = a.val.Equals(b.val, .001);
#if 0
hsStatusMessageF("COMPAREKEYS(point): (%f %f %f) vs (%f, %f, %f) = %s\n", a.val.x, a.val.y, a.val.z, b.val.x, b.val.y, b.val.z, result ? "yes" : "no");
#endif
return result;
}
template<class T>
void ReduceKeys(INode *node, IKeyControl *keyCont)
{
keyCont->SortKeys(); // ensure the keys are sorted by time
int to; // the next key we're setting
int from; // the next key we're examining
int origNumKeys = keyCont->GetNumKeys();
int finalNumKeys = origNumKeys;
for (to = 1, from = 1; from < origNumKeys - 1; to++, from++)
{
T prevKey, curKey, nextKey;
keyCont->GetKey(from - 1, &prevKey);
keyCont->GetKey(from, &curKey);
keyCont->GetKey(from + 1, &nextKey);
if (CompareKeys(curKey, prevKey) && CompareKeys(curKey, nextKey))
finalNumKeys--; // skip it
else
keyCont->SetKey(to, &curKey); // copy current key
}
// copy the last one without peeking ahead
T lastKey;
keyCont->GetKey(from, &lastKey);
keyCont->SetKey(to, &lastKey);
keyCont->SetNumKeys(finalNumKeys);
keyCont->SortKeys();
}
void EliminateScaleKeys(INode *node, IKeyControl *keyCont)
{
int numKeys = keyCont->GetNumKeys();
ILinScaleKey last;
keyCont->GetKey(numKeys - 1, &last);
keyCont->SetKey(1, &last); // move the last to the second
keyCont->SetNumKeys(2);
}
// REAPPLYANIMATION
// Now that we've reparented a node within the hierarchy, re-apply all its animation.
void ReapplyAnimation(INode *node, plSampleVec *samples)
{
Control *controller = node->GetTMController();
Control *rotControl = NewDefaultRotationController(); // we set the default rotation controller type above in RemoveBiped()
Control *posControl = NewDefaultPositionController(); // '' ''
Control *scaleControl = NewDefaultScaleController(); // '' ''
controller->SetRotationController(rotControl);
controller->SetPositionController(posControl);
controller->SetScaleController(scaleControl);
for(int i = 0; i < samples->size(); i++)
{
nodeTMInfo *info = (*samples)[i];
Matrix3 m = info->fMat3;
TimeValue t = info->fTime;
#if 1
node->SetNodeTM(t, m);
#else
AffineParts parts;
INode *parent = node->GetParentNode();
Matrix3 parentTM = parent->GetNodeTM(t);
Matrix3 invParentTM = Inverse(parentTM);
m *= invParentTM;
decomp_affine(m, &parts);
Quat q(parts.q.x, parts.q.y, parts.q.z, parts.q.w);
Point3 p(parts.t.x, parts.t.y, parts.t.z);
rotControl->SetValue(t, q);
posControl->SetValue(t, p);
#endif
}
IKeyControl *posKeyCont = GetKeyControlInterface(posControl);
IKeyControl *scaleKeyCont = GetKeyControlInterface(scaleControl);
ReduceKeys<ILinPoint3Key>(node, posKeyCont);
EliminateScaleKeys(node, scaleKeyCont);
// grrrr ReduceKeys<ILinScaleKey>(node, scaleKeyCont);
}
// HASBIPCONTROLLER
bool HasBipController(INode* node)
{
if (!node)
return false;
Control* c = node->GetTMController();
if (c && ((c->ClassID()== BIPSLAVE_CONTROL_CLASS_ID) ||
(c->ClassID()== BIPBODY_CONTROL_CLASS_ID) ||
(c->ClassID()== FOOTPRINT_CLASS_ID)) )
return true;
return false;
}
// EXPORTABLEANIMATIONCONTROLLER
bool ExportableAnimationController(INode* node)
{
bool result = false;
if(node)
{
Control *c = node->GetTMController();
if(c)
{
Class_ID id = c->ClassID();
if(id == Class_ID(LININTERP_ROTATION_CLASS_ID, 0)
|| id == Class_ID(PRS_CONTROL_CLASS_ID, 0)
|| id == Class_ID(LININTERP_POSITION_CLASS_ID, 0)
|| id == Class_ID(TCBINTERP_FLOAT_CLASS_ID, 0)
|| id == Class_ID(TCBINTERP_POSITION_CLASS_ID, 0)
|| id == Class_ID(TCBINTERP_ROTATION_CLASS_ID, 0)
|| id == Class_ID(TCBINTERP_POINT3_CLASS_ID, 0)
|| id == Class_ID(TCBINTERP_SCALE_CLASS_ID, 0))
{
result = true;
}
}
}
return result;
}
// SAMPLENODEMOTION
// top level function for sampling all the motion on a single node
plSampleVec * SampleNodeMotion(INode* node, INode* parent, int sampleRate, Interface *theInterface)
{
Interval interval = theInterface->GetAnimRange();
TimeValue start = interval.Start(); // in ticks
TimeValue end = interval.End();
sampleRate *= GetTicksPerFrame(); // convert sample rate to ticks
return SampleNodeMotion(node, parent, sampleRate, start, end);
}
// SAMPLENODEMOTION
// sample all the motion on a single node
// intended for use in the context of a full tree traversal
plSampleVec * SampleNodeMotion(INode * node, INode* parent, int sampleRate, TimeValue start, TimeValue end)
{
plSampleVec *result = TRACKED_NEW plSampleVec;
bool done = false;
for(int i = start; ! done; i += sampleRate)
{
if (i > end) i = end;
if (i == end) done = true;
// Get key time
TimeValue keyTime = i;
int frameNum= keyTime / GetTicksPerFrame();
// get localTM
nodeTMInfo * nti = TRACKED_NEW nodeTMInfo;
nti->fTime = keyTime;
Matrix3 localTM = node->GetNodeTM(keyTime);
nti->fMat3 = localTM;
result->push_back(nti);
}
return result;
}
// FREEMOTIONSAMPLES
void FreeMotionSamples(plSampleVec *samples)
{
int count = samples->size();
for(int i = 0; i < count; i++)
{
delete (*samples)[i];
}
delete samples;
}
// LIMITTRANSFORM
// Check if this node is marked as having a constrained transform.
// Meaning ignore part of the transform for this node and push it down to its kids.
int LimitTransform(INode* node, Matrix3* nodeTM)
{
/* NOT sure if we want to support this functionality: probably eventually.
hsBool32 noRotX=false,noRotY=false,noRotZ=false;
hsBool32 noRot=gUserPropMgr.UserPropExists(node,"BEHNoRot") || MatWrite::HasToken(node->GetName(), "norot");
if (!noRot)
{
noRotX=gUserPropMgr.UserPropExists(node,"BEHNoRotX") || MatWrite::HasToken(node->GetName(), "norotx");
noRotY=gUserPropMgr.UserPropExists(node,"BEHNoRotY") || MatWrite::HasToken(node->GetName(), "noroty");
noRotZ=gUserPropMgr.UserPropExists(node,"BEHNoRotZ") || MatWrite::HasToken(node->GetName(), "norotz");
}
hsBool32 noTransX=false,noTransY=false,noTransZ=false;
hsBool32 noTrans=gUserPropMgr.UserPropExists(node,"BEHNoTrans") || MatWrite::HasToken(node->GetName(), "notrans");
if (!noTrans)
{
noTransX=gUserPropMgr.UserPropExists(node,"BEHNoTransX") || MatWrite::HasToken(node->GetName(), "notransx");
noTransY=gUserPropMgr.UserPropExists(node,"BEHNoTransY") || MatWrite::HasToken(node->GetName(), "notransy");
noTransZ=gUserPropMgr.UserPropExists(node,"BEHNoTransZ") || MatWrite::HasToken(node->GetName(), "notransz");
}
if (noRot || noTrans ||
noRotX || noRotY || noRotZ ||
noTransX || noTransY || noTransZ)
{
Matrix3 tm(true); // identity
Quat q(*nodeTM); // matrix to quat
float eulerAng[3];
QuatToEuler(q, eulerAng); // to euler
// rotation
if (!noRot && !noRotX)
tm.RotateX(eulerAng[0]);
if (!noRot && !noRotY)
tm.RotateY(eulerAng[1]);
if (!noRot && !noRotZ)
tm.RotateZ(eulerAng[2]);
// translation
Point3 trans=nodeTM->GetTrans();
if (noTrans || noTransX)
trans.x=0;
if (noTrans || noTransY)
trans.y=0;
if (noTrans || noTransZ)
trans.z=0;
tm.Translate(trans);
// copy back
*nodeTM = tm;
return true;
}
*/
return false;
}
/*
//////////
// ARCHIVE
//////////
// Stuff we're not using but that looks kind of handy and which we might use again at some point.
/////////////////////////////////
/////////////////////////////////
/// SAMPLETREEMOTION
/// Sample motion for all of the non-bip bones in the heirarchy.
/// Need to sample the motion before rearranging the hierarchy and then
/// apply it after rearranging; hence the intermediate storage format.
// SAMPLETREEMOTION
// Sample all the (non-bip) motion in the whole tree
plSampleVecMap *SampleTreeMotion(INode* node, INode* parent, int sampleRate, Interface *theInterface)
{
Interval interval = theInterface->GetAnimRange();
TimeValue start = interval.Start(); // in ticks
TimeValue end = interval.End();
plSampleVecMap *ourMap = TRACKED_NEW plSampleVecMap();
sampleRate *= GetTicksPerFrame(); // convert sample rate to ticks
SampleTreeMotionRecurse(node, parent, sampleRate, start, end, ourMap);
return ourMap;
}
// SAMPLETREEMOTIONRECURSE
void SampleTreeMotionRecurse(INode * node, INode* parent, int sampleRate,
TimeValue start, TimeValue end, plSampleVecMap *ourMap)
{
// if it's not a bip, sample the fuck out of it
if(!HasBipController(node))
{
char *nodeName = node->GetName();
char *nameCopy = TRACKED_NEW char[strlen(nodeName) + 1];
strcpy(nameCopy, nodeName);
plSampleVec *branch = SampleNodeMotion(node, parent, sampleRate, start, end);
(*ourMap)[nameCopy] = branch;
}
// whether it's a bip or not, paw through its children
for(int i = 0; i < node->NumberOfChildren(); i++)
{
INode *child = node->GetChildNode(i);
SampleTreeMotionRecurse(child, node, sampleRate, start, end, ourMap);
}
}
// GETPARTS
void GetParts(Int32 i, std::vector<nodeTMInfo *>& mat3Array, hsAffineParts* parts)
{
hsAssert(parts, "nil parts");
// decomp matrix
gemAffineParts ap;
hsMatrix44 tXform = plMaxNodeBase::Matrix3ToMatrix44(mat3Array[i]->fMat3);
decomp_affine(tXform.fMap, &ap);
AP_SET((*parts), ap);
}
// MAKEROTKEY
Quat MakeRotKey(INode *node, INode *parent, TimeValue t)
{
AffineParts parts = GetLocalNodeParts(node, parent, t);
Quat q(parts.q.x, parts.q.y, parts.q.z, parts.q.w);
if( parts.f < 0.f )
{
// q = Quat(parts.q.x, parts.q.y, parts.q.z, -parts.q.w);
}
else
{
// q=Quat(-parts.q.x, -parts.q.y, -parts.q.z, parts.q.w);
}
return q;
}
Quat GetRotKey(Int32 i, std::vector<nodeTMInfo *>& mat3Array)
{
Matrix3 m = mat3Array[i]->fMat3;
AffineParts parts;
decomp_affine(m, &parts);
Quat q(parts.q.x, parts.q.y, parts.q.z, parts.q.w);
return q;
}
// GETROTKEY
Quat GetRotKey(Int32 i, std::vector<nodeTMInfo *>& mat3Array, hsAffineParts* parts)
{
hsAffineParts myParts;
if (!parts)
{
parts=&myParts;
GetParts(i, mat3Array, parts);
}
Quat q;
if( parts->fF < 0.f )
{
q = Quat(parts->fQ.fX, parts->fQ.fY, parts->fQ.fZ, -parts->fQ.fW); // ??? why are we inverting W?
#if 0
if( false)
{
Point3 ax;
float ang;
AngAxisFromQ(q, &ang, ax);
//ang -= hsScalarPI;
ax = -ax;
q = QFromAngAxis(ang, ax);
}
#endif
}
else
{
q=Quat(-parts->fQ.fX, -parts->fQ.fY, -parts->fQ.fZ, parts->fQ.fW);
}
return q;
}
// MAKEPOSKEY
Point3 MakePosKey(INode *node, INode *parent, TimeValue t)
{
AffineParts parts = GetLocalNodeParts(node, parent, t);
return Point3(parts.t.x, parts.t.y, parts.t.z);
}
// GETPOSKEY
Point3 GetPosKey(Int32 i, std::vector<nodeTMInfo *>& mat3Array, hsAffineParts* parts)
{
hsAffineParts myParts;
if (!parts)
{
parts=&myParts;
GetParts(i, mat3Array, parts);
}
return Point3(parts->fT.fX, parts->fT.fY, parts->fT.fZ);
}
// MAKESCALEKEY
ScaleValue MakeScaleKey(INode *node, INode *parent, TimeValue t)
{
Matrix3 m1 = node->GetNodeTM(t);
hsMatrix44 hsM = plMaxNodeBase::Matrix3ToMatrix44(m1);
gemAffineParts ap;
hsAffineParts hsParts;
decomp_affine(hsM.fMap, &ap);
AP_SET(hsParts, ap);
Point3 sAx1;
sAx1=Point3(hsParts.fK.fX, hsParts.fK.fY, hsParts.fK.fZ);
if( hsParts.fF < 0.f )
{
sAx1=-sAx1;
}
Quat sQ1(hsParts.fU.fX, hsParts.fU.fY, hsParts.fU.fZ, hsParts.fU.fW);
// return ScaleValue(sAx, sQ);
AffineParts parts = GetLocalNodeParts(node, parent, t);
Point3 sAx(parts.k.x, parts.k.y, parts.k.z);
if( parts.f < 0.f )
{
sAx=-sAx;
}
Quat sQ(parts.u.x, parts.u.y, parts.u.z, parts.u.w);
return ScaleValue(sAx, sQ);
}
// GETSCALEKEY
ScaleValue GetScaleKey(Int32 i, std::vector<nodeTMInfo *>& mat3Array, hsAffineParts* parts)
{
hsAffineParts myParts;
if (!parts)
{
parts=&myParts;
GetParts(i, mat3Array, parts);
}
Point3 sAx;
sAx=Point3(parts->fK.fX, parts->fK.fY, parts->fK.fZ);
if( parts->fF < 0.f )
{
sAx=-sAx;
}
Quat sQ(parts->fU.fX, parts->fU.fY, parts->fU.fZ, parts->fU.fW);
return ScaleValue(sAx, sQ);
}
// GETLOCALNODEPARTS
AffineParts GetLocalNodeParts(INode *node, INode *parent, TimeValue t)
{
Matrix3 localTM = node->GetNodeTM(t); // world transform of source node
INode *parent2 = node->GetParentNode();
// localize it
Matrix3 parentTMX = parent->GetNodeTM(t);
Matrix3 parentTM = parent2->GetNodeTM(t);
Matrix3 invParent = Inverse(parentTM);
localTM *= invParent;
AffineParts parts;
decomp_affine(localTM, &parts);
return parts;
}
*/

View File

@ -0,0 +1,205 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "max.h"
#include "meshdlib.h"
#include "dummy.h"
#include "resource.h"
#include "plComponent.h"
#include "plComponentReg.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "../MaxMain/plMaxNode.h"
#include "hsTypes.h"
#include "plBlowComponent.h"
#include "../pfAnimation/plBlower.h"
#include "plFlexibilityComponent.h"
// Blow component first, related Flexibility component at EOF.
// Preliminary setup bookkeeping
void DummyCodeIncludeFuncBlow()
{
}
CLASS_DESC(plBlowComponent, gBlowCompDesc, "Wind Bone", "Blow", COMP_TYPE_DISTRIBUTOR, BLOW_COMP_CID)
ParamBlockDesc2 gBlowBk
(
plComponent::kBlkComp, _T("Blow"), 0, &gBlowCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_BLOW, IDS_COMP_BLOWS, 0, 0, nil,
plBlowComponent::kStrength, _T("Strength"), TYPE_FLOAT, 0, 0,
p_default, 100.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_BLOW_STRENGTH, IDC_COMP_BLOW_STRENGTH_SPIN, 1.0,
end,
plBlowComponent::kSpeed, _T("Speed"), TYPE_FLOAT, 0, 0,
p_default, 100.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_BLOW_SPEED, IDC_COMP_BLOW_SPEED_SPIN, 1.0,
end,
plBlowComponent::kFlutter, _T("Flutter"), TYPE_FLOAT, 0, 0,
p_default, 100.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_BLOW_FLUTTER, IDC_COMP_BLOW_FLUTTER_SPIN, 1.0,
end,
plBlowComponent::kConstancy, _T("Constancy"), TYPE_FLOAT, 0, 0,
p_default, 25.0,
p_range, 0.0, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_BLOW_CONSTANCY, IDC_COMP_BLOW_CONSTANCY_SPIN, 1.0,
end,
end
);
// Component implementation
plBlowComponent::plBlowComponent()
{
fClassDesc = &gBlowCompDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plBlowComponent::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg)
{
node->SetDrawable(false);
node->SetForceLocal(true);
return true;
}
hsBool plBlowComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
return true;
}
hsBool plBlowComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
plBlower* pMod = TRACKED_NEW plBlower;
float strength = fCompPB->GetFloat(kStrength) * 0.01f;
float speed = fCompPB->GetFloat(kSpeed) * 0.01f;
float flutter = fCompPB->GetFloat(kFlutter) * 0.01f;
float constancy = fCompPB->GetFloat(kConstancy) * 0.01f;
pMod->SetMasterPower(pMod->GetMasterPower() * strength);
pMod->SetMasterFrequency(pMod->GetMasterFrequency() * speed);
pMod->SetImpulseRate(pMod->GetImpulseRate() * flutter);
pMod->SetConstancy(constancy);
node->AddModifier(pMod, IGetUniqueName(node));
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Flexibility Component
//
//
//Class that accesses the paramblock below.
//Max desc stuff necessary below.
CLASS_DESC(plFlexibilityComponent, gFlexibilityDesc, "Flexibility", "Flexibility", COMP_TYPE_DISTRIBUTOR, FLEXIBILITY_COMP_CID)
ParamBlockDesc2 gFlexibilityBk
( // KLUDGE: not the defined block ID, but kept for backwards compat.
plComponent::kBlkComp, _T("Flexibility"), 0, &gFlexibilityDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_FLEXIBILITY, IDS_COMP_FLEXIBILITYS, 0, 0, NULL,
plFlexibilityComponent::kFlexibility, _T("Flexibility"), TYPE_FLOAT, 0, 0,
p_default, 100.0,
p_range, 0.f, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_FLEX_FLEX, IDC_COMP_FLEX_FLEX_SPIN, 1.0,
end,
plFlexibilityComponent::kInterRand, _T("InterRand"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.f, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_FLEX_INTER, IDC_COMP_FLEX_INTER_SPIN, 1.0,
end,
plFlexibilityComponent::kIntraRand, _T("IntraRand"), TYPE_FLOAT, 0, 0,
p_default, 100.0,
p_range, 0.f, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_FLEX_INTRA, IDC_COMP_FLEX_INTRA_SPIN, 1.0,
end,
end
);
plFlexibilityComponent::plFlexibilityComponent()
{
fClassDesc = &gFlexibilityDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
Point3 plFlexibilityComponent::GetFlexibility() const
{
// 1.e-2f scale goes from percent to fraction.
// returns (in order),
// the flexibility
// the variation between objects (object still moves as unit)
// the variation within an object (different verts are more or less flexible than others).
return Point3(fCompPB->GetFloat(kFlexibility) * 1.e-2f,
fCompPB->GetFloat(kInterRand) * 1.e-2f, // From percent to fraction.
fCompPB->GetFloat(kIntraRand) * 1.e-2f); // From percent to fraction.
}

View File

@ -0,0 +1,70 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plBlowComponent_inc
#define plBlowComponent_inc
const Class_ID BLOW_COMP_CID(0x2908438f, 0x6c272509);
class plBlowComponent : public plComponent
{
public:
enum {
kStrength,
kSpeed,
kFlutter,
kConstancy
};
public:
plBlowComponent();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); }
};
#endif // plBlowComponent_inc

View File

@ -0,0 +1,174 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plCAnimParamBlock.cpp - Common animation paramblock and associated code //
// //
//// History /////////////////////////////////////////////////////////////////
// //
// 10.3.02 mcn - Created from the gory destruction of the separated anim //
// component and material animations. //
// //
//// Notes ///////////////////////////////////////////////////////////////////
// //
// This file is shared currently between MaxComponent and MaxPlasmaMtl. //
// Since they are in separate plugins currently, you MUST include this //
// .cpp file in both projects so that they can both compile in the code. //
// //
//////////////////////////////////////////////////////////////////////////////
#include "plCAnimParamBlock.h"
#include "../plInterp/plAnimEaseTypes.h"
#include "../MaxPlasmaMtl/plPassMtlBase.h"
//// Static ParamBlock Template //////////////////////////////////////////////
// This is the base paramBlock for all animation paramBlocks. The macro that
// creates the latter just includes this one (defined here to keep the .h
// file simple, among other reasons)
// Since we can't reference plComponent directly, this #define is just so we
// remember what the hell it is. If this changes in plComponentBase.h, change
// it here too.
int plCAnimPB::plPBBaseDec::kPlComponentBlkID = 0;
int plCAnimPB::plPBBaseDec::kPlComponentRefID = 0;
// Maybe plEaseAccessor should be moved here?
static plEaseAccessor sAnimCompEaseAccessor( plCAnimPB::plPBBaseDec::kPlComponentBlkID,
plCAnimPB::kAnimEaseInMin, plCAnimPB::kAnimEaseInMax, plCAnimPB::kAnimEaseInLength,
plCAnimPB::kAnimEaseOutMin, plCAnimPB::kAnimEaseOutMax, plCAnimPB::kAnimEaseOutLength);
ParamBlockDesc2 plCAnimPB::plPBBaseDec::fAnimBlock
(
kPlComponentBlkID, _T( "animation" ), 0, NULL, 0/*P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP*/, kPlComponentRefID,
// map rollups (don't define Procs, they'll just be overridden in the macro defs anyway)
/* 2,
plCAnimPB::kRollMain, IDD_COMP_ANIM, IDS_COMP_ANIM, 0, 0, nil,
plCAnimPB::kRollEase, IDD_COMP_ANIM_EASE, IDS_COMP_ANIM_EASE, 0, APPENDROLL_CLOSED, nil,
*/
// Anim Main rollout
plCAnimPB::kAnimAutoStart, _T("autoStart"), TYPE_BOOL, 0, 0,
p_ui, plCAnimPB::kRollMain, TYPE_SINGLECHEKBOX, IDC_COMP_ANIM_AUTOSTART_CKBX,
p_default, FALSE,
end,
plCAnimPB::kAnimLoop, _T("loop"), TYPE_BOOL, 0, 0,
p_ui, plCAnimPB::kRollMain, TYPE_SINGLECHEKBOX, IDC_COMP_ANIM_LOOP_CKBX,
p_default, FALSE,
end,
plCAnimPB::kAnimName, _T("animName"), TYPE_STRING, 0, 0,
end,
plCAnimPB::kAnimUseGlobal, _T("UseGlobal"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, plCAnimPB::kRollMain, TYPE_SINGLECHEKBOX, IDC_COMP_ANIM_USE_GLOBAL,
end,
plCAnimPB::kAnimGlobalName, _T("GlobalName"), TYPE_STRING, 0, 0,
p_default, _T(""),
end,
plCAnimPB::kAnimLoopName, _T("loopName"), TYPE_STRING, 0, 0,
end,
plCAnimPB::kAnimPhysAnim, _T("PhysAnim"), TYPE_BOOL, 0, 0,
p_default, TRUE,
p_ui, plCAnimPB::kRollMain, TYPE_SINGLECHEKBOX, IDC_COMP_ANIM_PHYSANIM,
end,
// Anim Ease rollout
plCAnimPB::kAnimEaseInType, _T("easeInType"), TYPE_INT, 0, 0,
p_ui, plCAnimPB::kRollEase, TYPE_RADIO, 3, IDC_COMP_ANIM_EASE_IN_NONE, IDC_COMP_ANIM_EASE_IN_CONST_ACCEL, IDC_COMP_ANIM_EASE_IN_SPLINE,
p_vals, plAnimEaseTypes::kNoEase, plAnimEaseTypes::kConstAccel, plAnimEaseTypes::kSpline,
p_default, plAnimEaseTypes::kNoEase,
end,
plCAnimPB::kAnimEaseInLength, _T("easeInLength"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 99.0,
p_ui, plCAnimPB::kRollEase, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_ANIM_EASE_IN_TIME, IDC_COMP_ANIM_EASE_IN_TIME_SPIN, 1.0,
p_accessor, &gAnimCompEaseAccessor,
end,
plCAnimPB::kAnimEaseInMin, _T("easeInMin"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 99.0,
p_ui, plCAnimPB::kRollEase, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_ANIM_EASE_IN_MIN, IDC_COMP_ANIM_EASE_IN_MIN_SPIN, 1.0,
p_accessor, &gAnimCompEaseAccessor,
end,
plCAnimPB::kAnimEaseInMax, _T("easeInMax"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 99.0,
p_ui, plCAnimPB::kRollEase, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_ANIM_EASE_IN_MAX, IDC_COMP_ANIM_EASE_IN_MAX_SPIN, 1.0,
p_accessor, &gAnimCompEaseAccessor,
end,
plCAnimPB::kAnimEaseOutType, _T("easeOutType"), TYPE_INT, 0, 0,
p_ui, plCAnimPB::kRollEase, TYPE_RADIO, 3, IDC_COMP_ANIM_EASE_OUT_NONE, IDC_COMP_ANIM_EASE_OUT_CONST_ACCEL, IDC_COMP_ANIM_EASE_OUT_SPLINE,
p_vals, plAnimEaseTypes::kNoEase, plAnimEaseTypes::kConstAccel, plAnimEaseTypes::kSpline,
p_default, plAnimEaseTypes::kNoEase,
end,
plCAnimPB::kAnimEaseOutLength, _T("easeOutLength"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 99.0,
p_ui, kRollEase, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_ANIM_EASE_OUT_TIME, IDC_COMP_ANIM_EASE_OUT_TIME_SPIN, 1.0,
p_accessor, &gAnimCompEaseAccessor,
end,
plCAnimPB::kAnimEaseOutMin, _T("easeOutMin"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 99.0,
p_ui, plCAnimPB::kRollEase, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_ANIM_EASE_OUT_MIN, IDC_COMP_ANIM_EASE_OUT_MIN_SPIN, 1.0,
p_accessor, &gAnimCompEaseAccessor,
end,
plCAnimPB::kAnimEaseOutMax, _T("easeOutMax"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 99.0,
p_ui, plCAnimPB::kRollEase, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_ANIM_EASE_OUT_MAX, IDC_COMP_ANIM_EASE_OUT_MAX_SPIN, 1.0,
p_accessor, &gAnimCompEaseAccessor,
end,
end
);

View File

@ -0,0 +1,146 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plCAnimParamBlock.h - Common animation paramblock and associated code //
// //
//// History /////////////////////////////////////////////////////////////////
// //
// 10.3.02 mcn - Created from the gory destruction of the separated anim //
// component and material animations. //
// //
//// Notes ///////////////////////////////////////////////////////////////////
// //
// This file is shared currently between MaxComponent and MaxPlasmaMtl. //
// Since the latter links to virtually nothing, this header MUST remain //
// MAX-pure; no reference to components or any other Plasma-specific stuff //
// above basically nucleusLib. Once we merge materials back into the main //
// plugins, this restriction can go away. //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plCAnimParamBlock_h
#define _plCAnimParamBlock_h
#include "Max.h"
#include "iparamb2.h"
#include "iparamm2.h"
/// Note: the namespace is so our enums and such don't clash with anything
/// else
namespace plCAnimPB
{
//// ParamBlock IDs //////////////////////////////////////////////////////////
// IDs for the common paramblock def below
enum Rollouts
{
kRollMain,
kRollEase
};
enum
{
kAnimRadio_DEAD,
kAnimAutoStart, // Start the Animation on load (V2)
kAnimLoop, // Start Looping at Begin Location
kAnimBegin_DEAD,
kAnimEnd_DEAD,
kAnimLoopSegCkBx_DEAD,
kAnimLoopSegBeg_DEAD,
kAnimLoopSegEnd_DEAD,
kAnimName, // Name of the notetrack animation to play
kAnimLoopSegBegBox_DEAD,
kAnimLoopSegEndBox_DEAD,
kAnimUseGlobal,
kAnimGlobalName,
kAnimLoopName, // Name of the notetrack specified loop
kAnimEaseInType,
kAnimEaseOutType,
kAnimEaseInLength,
kAnimEaseOutLength,
kAnimEaseInMin,
kAnimEaseInMax,
kAnimEaseOutMin,
kAnimEaseOutMax,
kAnimPhysAnim,
};
//// Static ParamBlock Accessor //////////////////////////////////////////////
// So we can ensure we only have one definition of our base paramBlock, but
// can access it multiple times without having to worry about which is the
// first. Defined here so the macro can get to it; don't reference it
// directly!
class plPBBaseDec
{
public:
static int kPlComponentBlkID;
static int kPlComponentRefID;
static ParamBlockDesc2 fAnimBlock;
};
//// ParamBlock Macro ////////////////////////////////////////////////////////
// Use this macro to create your paramblock for your animation object. This
// way, all the paramblocks for animation info will be identical!
//
// Ex. Usage: kDefineAnimPB( gAnimBlock, &gAnimDesc, PASS_ANIM, PASS_ANIM_EASE, gAnimMainProc, gAnimEaseProc );
#define kDefineAnimPB( blockName, descPtr, mainResIDName, easeResIDName, mainProc, easeProc ) \
static ParamBlockDesc2 blockName##( \
\
plPBBaseDec::kPlComponentBlkID, _T("animation"), 0, descPtr, P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP + P_INCLUDE_PARAMS, plPBBaseDec::kPlComponentRefID, \
2, /* # rollouts */ \
plCAnimPB::kRollMain, IDD_##mainResIDName, IDS_##mainResIDName, 0, 0, mainProc, \
plCAnimPB::kRollEase, IDD_##easeResIDName, IDS_##easeResIDName, 0, 0, easeProc, \
&plPBBaseDec::fAnimBlock, /* ParamBlock to include */ \
end, \
);
}; // namespace
#endif //_plCAnimParamBlock_h

View File

@ -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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plCameraComponent.h"
#include "resource.h"
#include "plComponent.h"
#include "plComponentReg.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plSimulationInterface.h"
#include "../pnKeyedObject/hsKeyedObject.h"
#include "../pnKeyedObject/plKey.h"
#include "../plPhysical/plCollisionDetector.h" // MM
#include "../pnMessage/plObjRefMsg.h"
#include "../pnMessage/plCameraMsg.h"
#include "hsResMgr.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxConvert/plConvert.h"
#include "../MaxMain/plPhysicalProps.h"
#include "../plHavok1/plHKPhysicsGroups.h"
void DummyCodeIncludeFuncCamera() {}
OBSOLETE_CLASS_DESC(plCameraCmdComponent, gCameraCmdDesc, "(ex)Camera Command Region", "CameraCmdRegion", COMP_TYPE_MISC, CAMERACMD_CID)
enum
{
kCommand,
kOffsetX,
kOffsetY,
kOffsetZ,
kCustomBoundListStuff,
kSmooth,
};
class plCameraCmdComponentProc;
extern plCameraCmdComponentProc gCameraCmdComponentProc;
enum
{
kCommandSetOffset,
kCommandSetFP,
kCommandSetFixedCam,
};
ParamBlockDesc2 gCameraCmdBlock
(
plComponent::kBlkComp, _T("cameraComp"), 0, &gCameraCmdDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_CAMERACMD, IDS_COMP_CAMERACMD, 0, 0, &gCameraCmdComponentProc,
kCommand, _T("Command"), TYPE_INT, 0, 0,
p_default, kCommandSetFixedCam,
end,
kOffsetX, _T("X Offset"), TYPE_FLOAT, P_ANIMATABLE, 0,
p_range, 0.0f, 50.0f,
p_default, 0.0f,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_CAMERACMD_OFFSETX, IDC_CAMERACMD_SPIN_OFFSETX, SPIN_AUTOSCALE,
end,
kOffsetY, _T("Y Offset"), TYPE_FLOAT, P_ANIMATABLE, 0,
p_range, 0.0f, 50.0f,
p_default, 10.0f,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_CAMERACMD_OFFSETY, IDC_CAMERACMD_SPIN_OFFSETY, SPIN_AUTOSCALE,
end,
kOffsetZ, _T("Z Offset"), TYPE_FLOAT, P_ANIMATABLE, 0,
p_range, 0.0f, 50.0f,
p_default, 3.0f,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_CAMERACMD_OFFSETZ, IDC_CAMERACMD_SPIN_OFFSETZ, SPIN_AUTOSCALE,
end,
kCustomBoundListStuff, _T("FixedCamera"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_CAMERACMD_PICKSTATE_BASE,
p_sclassID, CAMERA_CLASS_ID,
p_prompt, IDS_COMP_PHYS_CHOSEN_BASE,
end,
kSmooth, _T("useCut"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_CAMERACMD_CUT,
end,
end
);
plCameraCmdComponent::plCameraCmdComponent()
{
fClassDesc = &gCameraCmdDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
// Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool plCameraCmdComponent::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg)
{
return true;
}
hsBool plCameraCmdComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
return true;
}
hsBool plCameraCmdComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
return true;
}
class plCameraCmdComponentProc : public ParamMap2UserDlgProc
{
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return false;
}
void DeleteThis() {}
protected:
void IEnableControls(IParamMap2 *map, int type)
{
}
void IAddComboItem(HWND hCombo, const char *name, int id)
{
}
void ISetComboSel(HWND hCombo, int type)
{
}
};
static plCameraCmdComponentProc gCameraCmdComponentProc;

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,254 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_CAMERA_COMPONENTS_H
#define PL_CAMERA_COMPONENTS_H
#define FIXEDCAM_CID Class_ID(0x60f30a2a, 0x32d110e8)
#define AUTOCAM_CID Class_ID(0x65961f03, 0x775b77e6)
#define AVATAR_POA_CID Class_ID(0x1fe2720, 0x43857066)
#define OBJECT_POA_CID Class_ID(0x5c77163c, 0x78711171)
#define DEFAULTCAM_CID Class_ID(0x75bb1256, 0x49bf34c6)
#define TRANSCAM_CID Class_ID(0x5951682f, 0x1c310006)
#define LIMITPAN_CID Class_ID(0x18360ad4, 0x7dc74837)
#define FPCAM_CID Class_ID(0x1efe4e3e, 0x5b7369e4)
#define CAMERAZOOM_CID Class_ID(0x57b061be, 0x7c4f38db)
#define FOLLOWCAM_CID Class_ID(0x227c19a9, 0x55d809d6)
#define ANIMCAM_CMD_CID Class_ID(0x435913bf, 0x116c19fc)
#define CAM_REGION_CID Class_ID(0x60e27303, 0x1cf148a8)
#define CAM_IGNORE_SUB_CID Class_ID(0x33ae4c0d, 0x2b9d6513)
#include "plComponent.h"
#include <map>
struct PreTrans;
class plMaxNode;
class plErrorMsg;
class plCameraModifier1;
class plCameraBrain1;
class plRailCameraMod;
class plLimitPanComponent : public plComponent
{
public:
plLimitPanComponent();
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
};
class plCameraZoomComponent : public plComponent
{
public:
plCameraZoomComponent();
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
};
class plTransOverrideComponent : public plComponent
{
public:
plTransOverrideComponent();
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool DeInit(plMaxNode *node, plErrorMsg *pErrMsg);
typedef std::map<plMaxNode*, PreTrans*> TransitionKeys;
TransitionKeys fTransKeys;
const TransitionKeys& GetTransKeys();
};
class plPOAAvatarComponent : public plComponent
{
public:
plPOAAvatarComponent();
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) { return true; }
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
};
class plPOAObjectComponent : public plComponent
{
public:
plPOAObjectComponent();
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
plKey GetObjectKey();
};
class plMakeDefaultCamComponent : public plComponent
{
public:
plMakeDefaultCamComponent();
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) { return true; }
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
};
class plCameraBaseComponent : public plComponent
{
public:
plCameraBaseComponent(){;}
virtual hsBool SetupProperties(plMaxNode* pNode, plErrorMsg* pErrMsg);
virtual hsBool PreConvert(plMaxNode* pNode, plErrorMsg* pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
plCameraModifier1* ICreateCameraModifier(plMaxNode* pNode, plErrorMsg* pErrMsg);
plCameraModifier1* ICreateFocalPointObject(plMaxNode* pNode, plErrorMsg* pErrMsg);
hsBool IsValidNodeType(plMaxNode *pNode);
void ISetLimitPan(plMaxNode* pNode, plCameraBrain1* pBrain);
void ISetLimitZoom(plMaxNode* pNode, plCameraBrain1* pBrain);
void ISetIgnoreSubworld(plMaxNode* pNode, plCameraBrain1* pBrain);
hsBool ISetPOA(plMaxNode* pNode, plCameraBrain1* pBrain, plErrorMsg* pErrMsg);
typedef std::map<plMaxNode*, plCameraModifier1*> ModKeys;
ModKeys fModKeys;
const ModKeys& GetModKeys();
};
class plCamera1Component : public plCameraBaseComponent
{
public:
plCamera1Component();
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
};
class plCameraIgnoreSub : public plComponent
{
public:
plCameraIgnoreSub();
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) { return true; }
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
};
class plAutoCamComponent : public plCameraBaseComponent
{
public:
plAutoCamComponent();
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
};
class plFPCamComponent : public plCameraBaseComponent
{
public:
plFPCamComponent();
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
};
class plRailCameraComponent : public plCameraBaseComponent
{
private:
hsBool fValid;
plRailCameraMod* fLineMod;
hsBool IMakeLineMod(plMaxNode* pNode, plErrorMsg* pErrMsg);
public:
plRailCameraComponent();
virtual hsBool SetupProperties(plMaxNode* pNode, plErrorMsg* pErrMsg);
virtual hsBool PreConvert(plMaxNode* pNode, plErrorMsg* pErrMsg);
};
class plCircleCameraComponent : public plCameraBaseComponent
{
private:
hsBool fValid;
public:
plCircleCameraComponent();
virtual hsBool PreConvert(plMaxNode* pNode, plErrorMsg* pErrMsg);
};
class plFollowCamComponent : public plCameraBaseComponent
{
public:
plFollowCamComponent();
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
};
class plCameraAnimCmdComponent : public plComponent
{
hsBool fIgnoreFOV;
public:
plCameraAnimCmdComponent();
virtual hsBool SetupProperties(plMaxNode* pNode, plErrorMsg* pErrMsg){ return true; }
virtual hsBool PreConvert(plMaxNode* pNode, plErrorMsg* pErrMsg);
virtual hsBool Convert(plMaxNode* pNode, plErrorMsg* pErrMsg);
hsBool IgnoreFOV() { return fIgnoreFOV; }
};
#endif

View File

@ -0,0 +1,621 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plClickDragComponent.h"
#include "resource.h"
#include "plComponent.h"
#include "plComponentReg.h"
#include "plAnimComponent.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnKeyedObject/hsKeyedObject.h"
#include "../pnKeyedObject/plKey.h"
#include "../plPhysical/plCollisionDetector.h" // MM
#include "../plModifier/plLogicModifier.h"
#include "../plModifier/plAxisAnimModifier.h"
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
#include "../plPhysical/plPickingDetector.h"
#include "../pfConditional/plActivatorConditionalObject.h"
#include "../pfConditional/plFacingConditionalObject.h"
#include "../pfConditional/plObjectInBoxConditionalObject.h"
#include "../pnMessage/plObjRefMsg.h"
#include "../pnMessage/plNotifyMsg.h"
#include "../pnMessage/plCursorChangeMsg.h"
#include "../pnMessage/plEventCallbackMsg.h"
#include "../plMessage/plAnimCmdMsg.h"
#include "hsResMgr.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxConvert/plConvert.h"
#include "plResponderComponent.h"
#include "plgDispatch.h"
#include "../MaxMain/plPhysicalProps.h"
#include "plNotetrackAnim.h"
#include "../plPhysical/plSimDefs.h"
void DummyCodeIncludeFuncClickDrag() {}
CLASS_DESC(plClickDragComponent, gClickDragDesc, "Dragable", "Dragable", COMP_TYPE_DETECTOR, CLICK_DRAG_CID)
enum
{
kClickDragDirectional,
kClickDragDegrees,
kClickDragUseProxy,
kClickDragProxy,
kClickDragUseRegion,
kClickDragProxyRegion,
kClickDragUseX,
kClickDragUseY,
kClickDragAnimX,
kClickDragAnimY,
kClickDragUseLoopX,
kClickDragUseLoopY,
kClickDragLoopAnimX,
kClickDragLoopAnimY,
kClickDragToggle,
kClickDragAllOrNothing,
kClickDragOneShot,
kClikDragBoundsType,
kClikDragEnabled,
};
class plClickDragComponentProc;
extern plClickDragComponentProc gClickDragComponentProc;
ParamBlockDesc2 gClickDragBlock
(
plComponent::kBlkComp, _T("ClickDragComp"), 0, &gClickDragDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_DETECTOR_CLICK_DRAGGABLE, IDS_COMP_DETECTOR_CLICK_DRAGGABLE, 0, 0, &gClickDragComponentProc,
kClickDragDirectional, _T("directional"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_CLICK_DRAG_OMNI,
end,
kClickDragDegrees, _T("degrees"), TYPE_INT, P_ANIMATABLE, 0,
p_range, 1, 180,
p_default, 180,
p_ui, TYPE_SPINNER, EDITTYPE_POS_INT,
IDC_COMP_CLICK_DRAG_DEG, IDC_COMP_CLICK_DRAG_DEGSPIN, SPIN_AUTOSCALE,
end,
kClickDragUseProxy, _T("useProxy"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_CLICK_DRAG_USEPROXYPHYS,
p_enable_ctrls, 1, kClickDragProxy,
end,
kClickDragProxy, _T("proxyPrimitave"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_CLICK_DRAG_PROXY,
p_sclassID, GEOMOBJECT_CLASS_ID,
p_prompt, IDS_COMP_PHYS_CHOSEN_BASE,
end,
kClickDragProxyRegion, _T("proxyRegion"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_CLICK_DRAG_PROXYREGION,
p_sclassID, GEOMOBJECT_CLASS_ID,
p_prompt, IDS_COMP_PHYS_CHOSEN_BASE,
end,
kClickDragUseX, _T("useXAnim"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_CLICK_DRAG_USEX,
end,
kClickDragAnimX, _T("XanimName"), TYPE_STRING, 0, 0,
end,
kClickDragUseY, _T("useYAnim"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_CLICK_DRAG_USEYANIM,
end,
kClickDragAnimY, _T("YanimName"), TYPE_STRING, 0, 0,
end,
kClickDragUseLoopX, _T("useLoopXAnim"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_CLICK_DRAG_USE_LOOPX,
end,
kClickDragUseLoopY, _T("useLoopYAnim"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_CLICK_DRAG_USE_LOOPY,
end,
kClickDragAllOrNothing, _T("allOrNot"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_CLICK_DRAG_ALLORNOT,
end,
kClickDragOneShot, _T("oneshot"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_ONESHOT,
end,
kClikDragBoundsType, _T("BoundingConditions"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 4, IDC_RADIO_BSPHERE, IDC_RADIO_BBOX, IDC_RADIO_BHULL, IDC_RADIO_PICKSTATE,
p_vals, plSimDefs::kSphereBounds, plSimDefs::kBoxBounds, plSimDefs::kHullBounds, plSimDefs::kProxyBounds,
p_default, plSimDefs::kHullBounds,
end,
kClikDragEnabled, _T("enabled"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_ENABLE,
p_default, TRUE,
end,
end
);
plClickDragComponent::plClickDragComponent()
{
fClassDesc = &gClickDragDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
const plClickDragComponent::LogicKeys& plClickDragComponent::GetAxisKeys()
{
return fAxisKeys;
}
plKey plClickDragComponent::GetAxisKey(plMaxNode* node)
{
LogicKeys::const_iterator it = fAxisKeys.find(node);
if (it != fAxisKeys.end())
return(it->second);
return nil;
}
void plClickDragComponent::CollectNonDrawables(INodeTab& nonDrawables)
{
INode* boundsNode = fCompPB->GetINode(kClickDragProxy);
if(boundsNode && fCompPB->GetInt(kClickDragUseProxy))
nonDrawables.Append(1, &boundsNode);
boundsNode = fCompPB->GetINode(kClickDragProxyRegion);
if(boundsNode )
nonDrawables.Append(1, &boundsNode);
}
// Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool plClickDragComponent::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg)
{
plActivatorBaseComponent::SetupProperties(node, pErrMsg);
// Phys Props for the Clickable itself.
plMaxNode *boundsNode = nil;
boundsNode = (plMaxNode*)fCompPB->GetINode(kClickDragProxy);
if(boundsNode && fCompPB->GetInt(kClickDragUseProxy))
if(boundsNode->CanConvert())
{
boundsNode->SetDrawable(false);
plPhysicalProps *physProps = boundsNode->GetPhysicalProps();
// only if movable will it have mass (then it will keep track of movements in PhysX)
if ( boundsNode->IsMovable() || boundsNode->IsTMAnimatedRecur() )
physProps->SetMass(1.0, boundsNode, pErrMsg);
physProps->SetGroup( plSimDefs::kGroupStatic, boundsNode, pErrMsg);
// physProps->SetReportGroup( plPhysicsGroups::kLocalAvatars, boundsNode, pErrMsg);
physProps->SetBoundsType(fCompPB->GetInt(kClikDragBoundsType), boundsNode, pErrMsg);
}
else
{
pErrMsg->Set(true, "Clickable Sensor Warning", "The Clickable %s has a Proxy Surface %s that was Ignored.\nThe Sensors geometry will be used instead.", node->GetName(), boundsNode->GetName()).Show();
pErrMsg->Set(false);
}
else
{
plPhysicalProps *physProps = node->GetPhysicalProps();
// only if movable will it have mass (then it will keep track of movements in PhysX)
if ( node->IsMovable() || node->IsTMAnimatedRecur() )
physProps->SetMass(1.0, node, pErrMsg);
physProps->SetGroup( plSimDefs::kGroupStatic, node, pErrMsg);
// physProps->SetReportGroup( plPhysicsGroups::kLocalAvatars, node, pErrMsg);
//node->GetPhysicalProps()->SetAllCollideGroups(0);
physProps->SetBoundsType(fCompPB->GetInt(kClikDragBoundsType), node, pErrMsg);
}
// Phys Properties for the auto-generated Detector Region...
boundsNode = nil;
boundsNode = (plMaxNode*)fCompPB->GetINode(kClickDragProxyRegion);
if(boundsNode)
{
if(boundsNode->CanConvert())
{
plPhysicalProps *physPropsDetector = boundsNode->GetPhysicalProps();
// physPropsDetector->SetAllowLOS(true, boundsNode, pErrMsg);
physPropsDetector->SetProxyNode(boundsNode, node, pErrMsg);
physPropsDetector->SetBoundsType(plSimDefs::kHullBounds, boundsNode, pErrMsg);
// only if movable will it have mass (then it will keep track of movements in PhysX)
if ( boundsNode->IsMovable() || boundsNode->IsTMAnimated() )
physPropsDetector->SetMass(1.0, boundsNode, pErrMsg);
physPropsDetector->SetGroup( plSimDefs::kGroupDetector, boundsNode, pErrMsg );
//boundsNode->GetPhysicalProps()->SetAllCollideGroups(0);
physPropsDetector->SetReportGroup( 1<<plSimDefs::kGroupAvatar, boundsNode, pErrMsg );
}
}
else
{
pErrMsg->Set(true, "Clickable Sensor Error", "The Clickable Sensor %s has a Required Region that is missing.\nThe Export will be aborted", node->GetName()).Show();
// pErrMsg->Set(false);
return false;
}
fAxisKeys.clear();
return true;
}
hsBool plClickDragComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
plActivatorBaseComponent::PreConvert(node, pErrMsg);
plLogicModifier *logic = plLogicModifier::ConvertNoRef(fLogicModKeys[node]->GetObjectPtr());
if (fCompPB->GetInt(kClickDragOneShot))
logic->SetFlag(plLogicModBase::kOneShot);
plLocation loc = node->GetLocation();
plSceneObject *obj = node->GetSceneObject();
// do the same thing for axis animation controllers.
plAxisAnimModifier* pAxis = TRACKED_NEW plAxisAnimModifier;
plKey axisKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), pAxis, loc);
hsgResMgr::ResMgr()->AddViaNotify(axisKey, TRACKED_NEW plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
logic->AddNotifyReceiver(axisKey);
fAxisKeys[node] = axisKey;
return true;
}
hsBool plClickDragComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
plLocation loc = node->GetLocation();
plSceneObject *obj = node->GetSceneObject();
plKey logicKey = fLogicModKeys[node];
plLogicModifier *logic = plLogicModifier::ConvertNoRef(logicKey->GetObjectPtr());
logic->fMyCursor = plCursorChangeMsg::kCursorOpen;
// Create the detector
plDetectorModifier *detector = nil;
detector = TRACKED_NEW plPickingDetector;
// Register the detector
plKey detectorKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), detector, loc);
hsgResMgr::ResMgr()->AddViaNotify(detectorKey, TRACKED_NEW plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
// set up the axis anim controller
plKey axisKey = fAxisKeys[node];
plAxisAnimModifier* pAxis = plAxisAnimModifier::ConvertNoRef(axisKey->GetObjectPtr());
// attach the animation controller to the animation objects:
// find an animation controller:
hsTArray<plKey> receivers;
IGetReceivers(node, receivers);
int i;
for (i = 0; i < receivers.Count(); i++)
pAxis->GetNotify()->AddReceiver(receivers[i]);
pAxis->SetNotificationKey(logicKey);
UInt32 count = node->NumAttachedComponents();
hsBool bHasAnim = false;
plAnimComponentBase* pAnim = nil;
for (i = 0; i < count; i++)
{
plComponentBase *comp = node->GetAttachedComponent(i);
if (comp->ClassID() == ANIM_COMP_CID || comp->ClassID() == ANIM_GROUP_COMP_CID)
{
pAnim = (plAnimComponentBase*)comp;
break;
}
}
if (!pAnim)
{
pErrMsg->Set(true, "WARNING", "Object %s has click-drag component attached but NO animation component!", ((INode*)node)->GetName()).Show();
pErrMsg->Set(false);
}
else
{
if (fCompPB->GetInt(kClickDragUseX))
{
pAxis->SetXAnim( pAnim->GetModKey(node) );
}
else // take out this else when we support multiple channels
if (fCompPB->GetInt(kClickDragUseY))
{
pAxis->SetYAnim( pAnim->GetModKey(node) );
}
pAxis->SetAllOrNothing(fCompPB->GetInt(kClickDragAllOrNothing));
// add callbacks for beginning and end of animation
plEventCallbackMsg* pCall1 = TRACKED_NEW plEventCallbackMsg;
pCall1->fEvent = kBegin;
pCall1->fRepeats = -1;
pCall1->AddReceiver(axisKey);
plEventCallbackMsg* pCall2 = TRACKED_NEW plEventCallbackMsg;
pCall2->fEvent = kEnd;
pCall2->fRepeats = -1;
pCall2->AddReceiver(axisKey);
plAnimCmdMsg* pMsg = TRACKED_NEW plAnimCmdMsg;
const char *tempAnimName = pAnim->GetAnimName();
if (tempAnimName == nil)
{
//pMsg->SetAnimName(ENTIRE_ANIMATION_NAME);
pMsg->SetAnimName(pAnim->GetModKey(node)->GetName());
pAxis->SetAnimLabel(ENTIRE_ANIMATION_NAME);
}
else
{
//pMsg->SetAnimName(tempAnimName);
pMsg->SetAnimName(pAnim->GetModKey(node)->GetName());
pAxis->SetAnimLabel(tempAnimName);
}
pMsg->SetCmd(plAnimCmdMsg::kAddCallbacks);
pMsg->AddCallback(pCall1);
pMsg->AddCallback(pCall2);
hsRefCnt_SafeUnRef( pCall1 );
hsRefCnt_SafeUnRef( pCall2 );
pMsg->AddReceiver( pAnim->GetModKey(node) );
plgDispatch::MsgSend(pMsg);
}
// is this a using a proxy primitive?
plPickingDetector* det2 = nil;
plKey det2Key = nil;
plMaxNode* pProxyNode = (plMaxNode*)fCompPB->GetINode(kClickDragProxy);
if (pProxyNode && fCompPB->GetInt(kClickDragUseProxy))
{
// verify that there is a physical proxy attached to this scene object:
UInt32 count = ((plMaxNodeBase*)pProxyNode)->NumAttachedComponents();
hsBool bHasPhys = false;
// for (UInt32 i = 0; i < count; i++)
// {
// plComponentBase *comp = ((plMaxNodeBase*)pProxyNode)->GetAttachedComponent(i);
// if (comp->ClassID() == Class_ID(0x11e81ee4, 0x36b81450))
// {
// bHasPhys = true;
// break;
// }
// }
// if (!bHasPhys)
// {
// pErrMsg->Set(true, "WARNING", "Object %s listed as draggable component proxy physical for %s but has NO physical component.\n Please attach a proxyTerrain componet!\n Export will continue but this gadget will not function",pProxyNode->GetName(), ((INode*)node)->GetName()).Show();
// pErrMsg->Set(false);
// }
if(pProxyNode->CanConvert())
{
det2 = TRACKED_NEW plPickingDetector;
// Register the detector
det2Key = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), det2, loc);
hsgResMgr::ResMgr()->AddViaNotify(det2Key, TRACKED_NEW plObjRefMsg(((plMaxNode*)pProxyNode)->GetSceneObject()->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
hsgResMgr::ResMgr()->AddViaNotify(logicKey, TRACKED_NEW plObjRefMsg( det2Key, plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
det2->SetProxyKey(node->GetSceneObject()->GetKey());
}
else
{
pErrMsg->Set(true, "Unknown Error", "Invalid proxy physical detector set for draggable %s.", ((INode*)pProxyNode)->GetName()).Show();
pErrMsg->Set(false);
return false;
}
}
// create and register the CONDITIONS for the DETECTOR's Logic Modifier
plActivatorConditionalObject* activatorCond = TRACKED_NEW plActivatorConditionalObject;
plKey activatorKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), activatorCond, loc);
// do we have a required region?
plMaxNode* pProxyRegNode = (plMaxNode*)fCompPB->GetINode(kClickDragProxyRegion);
if (pProxyRegNode)
{
// verify that there is a physical detector attached to this scene object:
UInt32 count = ((plMaxNodeBase*)pProxyRegNode)->NumAttachedComponents();
hsBool bHasPhys = false;
// for (UInt32 i = 0; i < count; i++)
// {
// plComponentBase *comp = ((plMaxNodeBase*)pProxyRegNode)->GetAttachedComponent(i);
// if (comp->ClassID() == Class_ID(0x33b60376, 0x7e5163e0))
// {
// bHasPhys = true;
// break;
// }
// }
// if (!bHasPhys)
// {
// pErrMsg->Set(true, "WARNING", "Object %s listed as draggable component detector region for %s but has NO physical detector component!\n Please attach a detector componet.\n Export will continue but this gadget will not function",((INode*)pProxyRegNode)->GetName(), ((INode*)node)->GetName()).Show();
// pErrMsg->Set(false);
// }
if(pProxyRegNode->CanConvert())
{
// need a player in box condition here...
// first a detector-any for the box
plObjectInVolumeDetector* pCDet = TRACKED_NEW plObjectInVolumeDetector(plCollisionDetector::kTypeAny);
plKey cDetKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), pCDet, loc);
hsgResMgr::ResMgr()->AddViaNotify(cDetKey, TRACKED_NEW plObjRefMsg(((plMaxNode*)pProxyRegNode)->GetSceneObject()->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
pCDet->AddLogicObj(logicKey);
// then an object-in-box condition for the logic mod
plObjectInBoxConditionalObject* boxCond = TRACKED_NEW plObjectInBoxConditionalObject;
plKey boxCondKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), boxCond, loc);
logic->AddCondition(boxCond);
}
else
{
pErrMsg->Set(true, "Problem with region", "Can't convert region component on %s. This component will not be exported.\n", ((INode*)pProxyRegNode)->GetName()).Show();
pErrMsg->Set(false);
return false;
}
}
else
{
pErrMsg->Set(true, "Must specify trigger region", "No required trigger region specified for click-drag component on %s. This component will not be exported.\n", ((INode*)node)->GetName()).Show();
pErrMsg->Set(false);
return false;
}
// How do we feel about player facing
plFacingConditionalObject* facingCond = TRACKED_NEW plFacingConditionalObject;
facingCond->SetDirectional(fCompPB->GetInt(kClickDragDirectional));
int deg = fCompPB->GetInt(kClickDragDegrees);
if (deg > 180)
deg = 180;
hsScalar rad = hsScalarDegToRad(deg);
facingCond->SetTolerance(hsCosine(rad));
plKey facingKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), facingCond, loc);
// link everything up:
if (det2) // set up the remote detector (if any)
{
activatorCond->SetActivatorKey(det2Key);
det2->AddLogicObj(logicKey);
}
else
{
detector->AddLogicObj(logicKey); // send messages to this logic component
activatorCond->SetActivatorKey(detectorKey); // Tells the activator condition to look for stimulus from the detector
}
logic->AddCondition(activatorCond); // add this activator condition
logic->AddCondition(facingCond);
logic->SetDisabled(fCompPB->GetInt(kClikDragEnabled) == 0);
// If this is for the SceneViewer, set the local only flag since the read function will never be called
if (plConvert::Instance().IsForSceneViewer())
logic->SetLocalOnly(true);
return true;
}
hsBool plClickDragComponent::DeInit( plMaxNode *node, plErrorMsg *pErrMsg )
{
fAxisKeys.clear();
return plActivatorBaseComponent::DeInit( node, pErrMsg );
}
#include "plNoteTrackDlgComp.h"
class plClickDragComponentProc : public ParamMap2UserDlgProc
{
protected:
plComponentNoteTrackDlg fNoteTrackDlgX;
plComponentNoteTrackDlg fNoteTrackDlgY;
IParamBlock2 *fPB;
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
fPB = map->GetParamBlock();
fNoteTrackDlgX.Init(GetDlgItem(hWnd, IDC_COMP_CLICK_DRAG_ANIMX),
nil,
kClickDragAnimX,
-1,
fPB,
fPB->GetOwner());
fNoteTrackDlgX.Load();
EnableWindow(GetDlgItem(hWnd, IDC_COMP_CLICK_DRAG_ANIMX), true);
fNoteTrackDlgY.Init(GetDlgItem(hWnd, IDC_COMP_CLICK_DRAG_ANIM_Y),
nil,
kClickDragAnimY,
-1,
fPB,
fPB->GetOwner());
fNoteTrackDlgY.Load();
EnableWindow(GetDlgItem(hWnd, IDC_COMP_CLICK_DRAG_ANIM_Y), true);
return TRUE;
case WM_COMMAND:
if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_COMP_CLICK_DRAG_ANIMX)
{
fNoteTrackDlgX.AnimChanged();
return TRUE;
}
if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_COMP_CLICK_DRAG_ANIM_Y)
{
fNoteTrackDlgY.AnimChanged();
return TRUE;
}
break;
}
return false;
}
void DeleteThis()
{
fNoteTrackDlgX.DeleteCache();
fNoteTrackDlgY.DeleteCache();
}
};
static plClickDragComponentProc gClickDragComponentProc;

View File

@ -0,0 +1,72 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plClickDragComponent_inc
#define plClickDragComponent_inc
#include "plClickableComponent.h"
#define CLICK_DRAG_CID Class_ID(0x61880560, 0x348d72d3)
class plClickDragComponent : public plClickableComponent
{
protected:
LogicKeys fAxisKeys;
public:
plClickDragComponent();
// Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool PreConvert(plMaxNode *node, plErrorMsg* pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool DeInit(plMaxNode *node, plErrorMsg* pErrMsg);
virtual plKey GetAxisKey(plMaxNode* node);
const LogicKeys& GetAxisKeys();
virtual void CollectNonDrawables(INodeTab& nonDrawables);
};
#endif // plClickDragComponent_inc

View File

@ -0,0 +1,425 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plClickableComponent.h"
#include "resource.h"
#include "plComponentReg.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plSimulationInterface.h"
#include "../pnKeyedObject/hsKeyedObject.h"
#include "../pnKeyedObject/plKey.h"
#include "../plPhysical/plCollisionDetector.h" // MM
#include "../plModifier/plLogicModifier.h"
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
#include "../plPhysical/plPickingDetector.h"
#include "../pfConditional/plActivatorConditionalObject.h"
#include "../pfConditional/plFacingConditionalObject.h"
#include "../pfConditional/plObjectInBoxConditionalObject.h"
#include "../pnMessage/plObjRefMsg.h"
#include "../pnMessage/plNotifyMsg.h"
#include "../pnMessage/plCursorChangeMsg.h"
#include "hsResMgr.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxConvert/plConvert.h"
#include "../MaxMain/plPhysicalProps.h"
#include "../plPhysical/plSimDefs.h"
#include "plResponderComponent.h"
#include "../MaxMain/plPhysicalProps.h"
void DummyCodeIncludeFuncClickable() {}
CLASS_DESC(plClickableComponent, gClickableDesc, "Clickable", "Clickable", COMP_TYPE_DETECTOR, CLICKABLE_CID)
enum
{
kClickableDirectional,
kClickableDegrees,
kClickableUseProxy,
kClickableProxy,
kClickableUseRegion,
kClickableProxyRegion,
kClickableToggle_DEAD,
kClickableOneShot,
kClickableBoundsType,
kClickableEnabled,
kClickablePhysical,
kClickableIgnoreProxyRegion,
kClickableFriction,
};
ParamBlockDesc2 gClickableBlock
(
plComponent::kBlkComp, _T("clickable"), 0, &gClickableDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_DETECTOR_CLICKABLE, IDS_COMP_DETECTOR_CLICKABLE, 0, 0, NULL,
kClickableDirectional, _T("directional"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_CLICK_OMNI,
end,
kClickableDegrees, _T("degrees"), TYPE_INT, P_ANIMATABLE, 0,
p_range, 1, 180,
p_default, 180,
p_ui, TYPE_SPINNER, EDITTYPE_POS_INT,
IDC_COMP_CLICK_DEG, IDC_COMP_CLICK_DEGSPIN, SPIN_AUTOSCALE,
end,
kClickableUseProxy, _T("useProxy"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_CLICK_USEPROXY,
p_enable_ctrls, 1, kClickableProxy,
end,
kClickableProxy, _T("proxyPrimitave"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_CLICK_PROXY,
// p_sclassID, GEOMOBJECT_CLASS_ID,
p_prompt, IDS_COMP_PHYS_CHOSEN_BASE,
end,
kClickableProxyRegion, _T("proxyRegion"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_CLICK_PROXYREGION,
// p_sclassID, GEOMOBJECT_CLASS_ID,
p_prompt, IDS_COMP_PHYS_CHOSEN_BASE,
end,
kClickableOneShot, _T("oneshot"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_ONESHOT,
end,
kClickableBoundsType, _T("BoundingConditions"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 4, IDC_RADIO_BSPHERE, IDC_RADIO_BBOX, IDC_RADIO_BHULL, IDC_RADIO_PICKSTATE,
p_vals, plSimDefs::kSphereBounds, plSimDefs::kBoxBounds, plSimDefs::kHullBounds, plSimDefs::kProxyBounds,
p_default, plSimDefs::kHullBounds,
end,
kClickableEnabled, _T("enabled"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_ENABLED,
p_default, TRUE,
end,
kClickablePhysical, _T("physical"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_COLLIDABLE_CHECK,
p_default, TRUE,
end,
kClickableIgnoreProxyRegion, _T("ignoreProxyRegion"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_IGNORE_REGION_CHECK,
p_default, FALSE,
end,
kClickableFriction, _T("friction"), TYPE_FLOAT, 0, 0,
p_range, 0.0f, FLT_MAX,
p_default, 0.0f,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_CLICKABLE_FRIC_EDIT1, IDC_COMP_CLICKABLE_FRIC_SPIN1, SPIN_AUTOSCALE,
end,
end
);
plClickableComponent::plClickableComponent()
{
fClassDesc = &gClickableDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
void plClickableComponent::CollectNonDrawables(INodeTab& nonDrawables)
{
if( fCompPB->GetInt(kClickableUseProxy) )
{
INode* clickNode = fCompPB->GetINode(kClickableProxy);
if( clickNode )
nonDrawables.Append(1, &clickNode);
}
INode* detectNode = fCompPB->GetINode(kClickableProxyRegion);
if( detectNode )
nonDrawables.Append(1, &detectNode);
}
hsBool plClickableComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
plActivatorBaseComponent::SetupProperties(node, pErrMsg);
bool physical = (fCompPB->GetInt(kClickablePhysical) != 0);
//
// Phys Props for the Clickable itself.
//
plMaxNode *clickNode = node;
if (fCompPB->GetInt(kClickableUseProxy))
{
clickNode = (plMaxNode*)fCompPB->GetINode(kClickableProxy);
if (clickNode)
clickNode->SetDrawable(false);
else
clickNode = node;
}
if (clickNode)
{
plPhysicalProps *physProps = clickNode->GetPhysicalProps();
physProps->SetLOSUIItem(true, clickNode, pErrMsg);
if (physical)
{
physProps->SetGroup(plSimDefs::kGroupStatic, clickNode, pErrMsg);
// only if movable will it have mass (then it will keep track of movements in PhysX)
if ( clickNode->IsMovable() || clickNode->IsTMAnimatedRecur() )
physProps->SetMass(1.0, clickNode, pErrMsg);
physProps->SetFriction(fCompPB->GetFloat(kClickableFriction),clickNode,pErrMsg);
}
else
{
physProps->SetGroup(plSimDefs::kGroupLOSOnly, clickNode, pErrMsg);
if(clickNode->IsMovable() || clickNode->IsTMAnimatedRecur())
{
physProps->SetMass(1.0, clickNode, pErrMsg);
}
}
physProps->SetBoundsType(fCompPB->GetInt(kClickableBoundsType), clickNode, pErrMsg);
}
//
// Phys Properties for the auto-generated Detector Region...
//
plMaxNode* detectNode = (plMaxNode*)fCompPB->GetINode(kClickableProxyRegion);
if (detectNode)
{
plPhysicalProps *physPropsDetector = detectNode->GetPhysicalProps();
// physPropsDetector->SetAllowLOS(true, detectNode, pErrMsg);
physPropsDetector->SetProxyNode(detectNode, node, pErrMsg);
physPropsDetector->SetBoundsType(plSimDefs::kHullBounds, detectNode, pErrMsg);
// only if movable will it have mass (then it will keep track of movements in PhysX)
if ( detectNode->IsMovable() || detectNode->IsTMAnimatedRecur() )
physPropsDetector->SetMass(1.0, detectNode, pErrMsg);
physPropsDetector->SetGroup(plSimDefs::kGroupDetector, detectNode, pErrMsg );
physPropsDetector->SetReportGroup(1<<plSimDefs::kGroupAvatar, detectNode, pErrMsg );
}
return true;
}
hsBool plClickableComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
plMaxNode *clickNode = node;
if (fCompPB->GetInt(kClickableUseProxy))
{
clickNode = (plMaxNode*)fCompPB->GetINode(kClickableProxy);
if (clickNode)
clickNode->SetDrawable(false);
else
clickNode = node;
}
clickNode->SetForceLocal(true);
plLocation loc = clickNode->GetLocation();
plSceneObject *obj = clickNode->GetSceneObject();
// Create and register the VolumeGadget's logic component
plLogicModifier *logic = TRACKED_NEW plLogicModifier;
plKey logicKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), logic, clickNode->GetLocation());
hsgResMgr::ResMgr()->AddViaNotify(logicKey, TRACKED_NEW plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
fLogicModKeys[clickNode] = logicKey;
return true;
}
hsBool plClickableComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
bool ignoreProxyRegion = (fCompPB->GetInt(kClickableIgnoreProxyRegion) != 0);
//
// Error checking
//
plMaxNode* clickProxyNode = node;
if (fCompPB->GetInt(kClickableUseProxy))
{
clickProxyNode = (plMaxNode*)fCompPB->GetINode(kClickableProxy);
if (!clickProxyNode || !clickProxyNode->CanConvert())
{
pErrMsg->Set(true,
"Clickable Error",
"The Clickable '%s' on node '%s' is set to use a proxy but doesn't have one, or it didn't convert.\n"
"The node the Clickable is attached to will be used instead.",
GetINode()->GetName(), node->GetName()).Show();
pErrMsg->Set(false);
clickProxyNode = node;
}
}
plMaxNode* detectNode = (plMaxNode*)fCompPB->GetINode(kClickableProxyRegion);
if ((!detectNode || !detectNode->CanConvert()) && (!ignoreProxyRegion))
{
pErrMsg->Set(true,
"Clickable Error",
"The Clickable '%s' on node '%s' has a required region that is missing, or didn't convert.\n"
"The export will be aborted.",
GetINode()->GetName(), node->GetName()).Show();
return false;
}
plLocation loc = clickProxyNode->GetLocation();
plSceneObject *obj = clickProxyNode->GetSceneObject();
plKey logicKey = fLogicModKeys[clickProxyNode];
plLogicModifier *logic = plLogicModifier::ConvertNoRef(logicKey->GetObjectPtr());
logic->fMyCursor = plCursorChangeMsg::kCursorPoised;
if (fCompPB->GetInt(kClickableOneShot))
logic->SetFlag(plLogicModBase::kOneShot);
hsTArray<plKey> receivers;
IGetReceivers(node, receivers);
for (int i = 0; i < receivers.Count(); i++)
logic->AddNotifyReceiver(receivers[i]);
// Create the detector
plDetectorModifier *detector = nil;
detector = TRACKED_NEW plPickingDetector;
// Register the detector
plKey detectorKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), detector, loc);
hsgResMgr::ResMgr()->AddViaNotify(detectorKey, TRACKED_NEW plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
// create and register the CONDITIONS for the DETECTOR's Logic Modifier
plActivatorConditionalObject* activatorCond = TRACKED_NEW plActivatorConditionalObject;
plKey activatorKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), activatorCond, loc);
//
// Create required region
//
// need a player in box condition here...
// first a detector-any for the box
if (!ignoreProxyRegion)
{
plObjectInVolumeDetector* pCDet = TRACKED_NEW plObjectInVolumeDetector(plCollisionDetector::kTypeAny);
plKey pCDetKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), pCDet, loc);
hsgResMgr::ResMgr()->AddViaNotify(pCDetKey, TRACKED_NEW plObjRefMsg(detectNode->GetSceneObject()->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
pCDet->AddLogicObj(logicKey);
// then an object-in-box condition for the logic mod
plObjectInBoxConditionalObject* boxCond = TRACKED_NEW plObjectInBoxConditionalObject;
plKey boxCondKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), boxCond, loc);
logic->AddCondition(boxCond);
}
//
// How do we feel about player facing
//
plFacingConditionalObject* facingCond = TRACKED_NEW plFacingConditionalObject;
facingCond->SetDirectional(fCompPB->GetInt(kClickableDirectional));
int deg = fCompPB->GetInt(kClickableDegrees);
if (deg > 180)
deg = 180;
hsScalar rad = hsScalarDegToRad(deg);
facingCond->SetTolerance(hsCosine(rad));
plKey facingKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), facingCond, loc);
detector->AddLogicObj(logicKey); // send messages to this logic component
activatorCond->SetActivatorKey(detectorKey); // Tells the activator condition to look for stimulus from the detector
logic->AddCondition(activatorCond); // add this activator condition
logic->AddCondition(facingCond);
logic->SetDisabled(!fCompPB->GetInt(kClickableEnabled));
// If this is for the SceneViewer, set the local only flag since the read function will never be called
if (plConvert::Instance().IsForSceneViewer())
logic->SetLocalOnly(true);
return true;
}
//
// special physical you can walk through and click with mouse
//
class plNoBlkClickableComponent : public plComponent
{
public:
plNoBlkClickableComponent();
void DeleteThis() { delete this; }
hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); }
};
OBSOLETE_CLASS_DESC(plNoBlkClickableComponent, gNoBlkClickableDesc, "(ex)Non Physical Clickable Proxy", "(ex)Non Physical Clickable Proxy", COMP_TYPE_PHYSICAL, Class_ID(0x66325afc, 0x253a3760))
ParamBlockDesc2 gNoBlkClickableBlock
(
plComponent::kBlkComp, _T("NonPhysicalClickableProxy"), 0, &gNoBlkClickableDesc, P_AUTO_CONSTRUCT, plComponent::kRefComp,
end
);
plNoBlkClickableComponent::plNoBlkClickableComponent()
{
fClassDesc = &gNoBlkClickableDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plNoBlkClickableComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg)
{
return true;
}

View File

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

View File

@ -0,0 +1,419 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
// max includes
#include "plPickNode.h"
#include "resource.h"
// local
#include "plClimbComponent.h"
#include "plPhysicalComponents.h" // so we can pick terrains
#include "plComponentReg.h"
// other
#include "../MaxMain/plMaxNode.h"
#include "../plMessage/plClimbMsg.h"
#include "../plPhysical/plCollisionDetector.h"
#include "../MaxMain/plPhysicalProps.h"
#include "../plPhysical/plSimDefs.h"
#include "../pnSceneObject/plSceneObject.h"
// stl
#include <map>
/////////////////////////////////////////////////////////////////
//
// THE DUMMY
//
/////////////////////////////////////////////////////////////////
void DummyCodeIncludeFuncClimbTrigger() {}
/////////////////////////////////////////////////////////////////
//
// SOME ENUMS
//
/////////////////////////////////////////////////////////////////
// CLIMBCOMMANDS
enum Commands
{
kMount = 0,
kEnableDismount = 1,
kDisableDismount = 2,
kEnableClimb = 3,
kDisableClimb = 4,
kFallOff = 5,
kRelease = 6,
kMaxCommands = 7
};
// these synchronized ^^^^VVVVV
const char * fCommandStrs[] =
{
"Start Climbing",
"Enable Dismount",
"Disable Dismount",
"Enable Climb",
"Disable Climb",
"Fall Off",
"Let Go"
};
enum Directions
{
kUp = 0,
kDown = 1,
kLeft = 2,
kRight = 3,
kMaxDirections
};
const char * fDirectionStrs[] =
{
"Up",
"Down",
"Left",
"Right"
};
/////////////////////////////////////////////////////////////////
//
// CLASS DESCRIPTOR AND PARAM BLOCK
//
/////////////////////////////////////////////////////////////////
// CLASS DESCRIPTOR
CLASS_DESC(plClimbTriggerComponent, gClimbTriggerDesc, "Avatar ClimbTrigger", "AvatarClimbTrigger", COMP_TYPE_AVATAR, CLIMB_TRIGGER_COMPONENT_CLASS_ID)
// FORWARD REFERENCE OT THE COMPONENT DIALOG PROC
static plClimbTriggerComponentProc gClimbTriggerComponentProc;
// PARAM BLOCK
ParamBlockDesc2 gClimbTriggerBk
(
plComponent::kBlkComp, _T("ClimbTrigger"), 0, &gClimbTriggerDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
//Roll out
IDD_COMP_CLIMB_TRIGGER, IDS_COMP_CLIMB_TRIGGER, 0, 0, &gClimbTriggerComponentProc,
plClimbTriggerComponent::kCommand, _T("Command"), TYPE_INT, 0, 0,
p_default, kMount,
end,
plClimbTriggerComponent::kDirection, _T("Direction"), TYPE_INT, 0, 0,
p_default, kUp,
end,
plClimbTriggerComponent::kWallPicker, _T("WallPicker"), TYPE_INODE, 0, 0,
end,
end
);
/////////////////////////////////////////////////////////////////
//
// PLCLIMBTRIGGER IMPLEMENTATION
//
/////////////////////////////////////////////////////////////////
// CTOR
plClimbTriggerComponent::plClimbTriggerComponent()
{
fClassDesc = &gClimbTriggerDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
extern const plArmatureMod * FindArmatureMod(const plSceneObject *obj);
// CONVERT
hsBool plClimbTriggerComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
plClimbMsg::Command enterCommand; // when entering the region
plClimbMsg::Command exitCommand; // run this command when exiting the region
hsBool enterStatus = false;
hsBool exitStatus = false;
plClimbMsg::Direction direction; // direction is assumed the same for both enter and exit commands
// i.e. enable up, disable up
int iCommand = fCompPB->GetInt(plClimbTriggerComponent::kCommand);
int iDirection = fCompPB->GetInt(plClimbTriggerComponent::kDirection);
switch(iCommand)
{
case kMount:
enterCommand = plClimbMsg::kStartClimbing;
exitCommand = plClimbMsg::kNoCommand;
break;
case kEnableClimb:
enterCommand = plClimbMsg::kEnableClimb;
enterStatus = true;
exitCommand = plClimbMsg::kEnableClimb;
exitStatus = false;
break;
case kDisableClimb:
enterCommand = plClimbMsg::kEnableClimb;
enterStatus = false;
exitCommand = plClimbMsg::kEnableClimb;
exitStatus = true;
break;
case kEnableDismount:
enterCommand = plClimbMsg::kEnableDismount;
enterStatus = true;
exitCommand = plClimbMsg::kEnableDismount;
exitStatus = false;
break;
case kDisableDismount:
enterCommand = plClimbMsg::kEnableDismount;
enterStatus = false;
exitCommand = plClimbMsg::kEnableDismount;
exitStatus = true;
break;
case kFallOff:
enterCommand = plClimbMsg::kFallOff;
exitCommand = plClimbMsg::kNoCommand;
break;
case kRelease:
enterCommand = plClimbMsg::kRelease;
exitCommand = plClimbMsg::kNoCommand;
break;
}
switch(iDirection)
{
case kUp:
direction = plClimbMsg::kUp;
break;
case kDown:
direction = plClimbMsg::kDown;
break;
case kLeft:
direction = plClimbMsg::kLeft;
break;
case kRight:
direction = plClimbMsg::kRight;
break;
}
plKey nilKey = nil;
plKey target = node->GetSceneObject()->GetKey();
plClimbMsg *enterMsg = nil;
if(enterCommand != plClimbMsg::kNoCommand)
{
enterMsg = TRACKED_NEW plClimbMsg(nilKey, nilKey, enterCommand, direction, enterStatus, target);
enterMsg->SetBCastFlag(plMessage::kPropagateToModifiers);
enterMsg->SetBCastFlag(plMessage::kNetPropagate);
enterMsg->SetBCastFlag(plMessage::kNetForce);
}
plClimbMsg *exitMsg = nil;
if(exitCommand != nil)
{
exitMsg = TRACKED_NEW plClimbMsg(nilKey, nilKey, exitCommand, direction, exitStatus, target);
exitMsg->SetBCastFlag(plMessage::kPropagateToModifiers);
exitMsg->SetBCastFlag(plMessage::kNetPropagate);
exitMsg->SetBCastFlag(plMessage::kNetForce);
}
plSimpleRegionSensor *sensMod = TRACKED_NEW plSimpleRegionSensor(enterMsg, exitMsg);
node->AddModifier(sensMod, IGetUniqueName(node));
return true;
}
hsBool plClimbTriggerComponent::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg)
{
node->SetForceLocal(true);
node->SetDrawable(false);
plPhysicalProps *props = node->GetPhysicalProps();
// only if movable will it have mass (then it will keep track of movements in PhysX)
if ( node->IsMovable() || node->IsTMAnimatedRecur() )
props->SetMass(1.0, node, pErrMsg);
props->SetFriction(0.0, node, pErrMsg);
props->SetRestitution(0.0, node, pErrMsg);
props->SetBoundsType(plSimDefs::kExplicitBounds, node, pErrMsg);
props->SetGroup(plSimDefs::kGroupDetector, node, pErrMsg);
props->SetReportGroup(1<<plSimDefs::kGroupAvatar, node, pErrMsg);
// props->SetPinned(true, node, pErrMsg);
return true;
}
/////////////////////////////////////////////////////////////////
//
// DIALOG PROC IMPLEMENTATION
//
/////////////////////////////////////////////////////////////////
BOOL plClimbTriggerComponentProc::DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
IParamBlock2 *pb = pm->GetParamBlock();
HWND hCommandMenu = GetDlgItem(hWnd, IDC_COMP_CLIMB_COMMAND);
HWND hDirectionMenu = GetDlgItem(hWnd, IDC_COMP_CLIMB_DIRECTION);
HWND hPick = GetDlgItem(hWnd, IDC_COMP_WALL_PICK);
INode *curPick = nil;
int curSurface = 0;
switch (msg)
{
case WM_INITDIALOG:
{
int i = 0;
// fill out the command menu
for (i = 0; i < kMaxCommands; i++)
ComboBox_AddString(hCommandMenu, fCommandStrs[i]);
// reflect the current selection
ComboBox_SetCurSel(hCommandMenu, pb->GetInt(ParamID(plClimbTriggerComponent::kCommand)));
// fill out the direction menu
for (i = 0; i < kMaxDirections; i++)
ComboBox_AddString(hDirectionMenu, fDirectionStrs[i]);
// reflect the current selection
ComboBox_SetCurSel(hDirectionMenu, pb->GetInt(ParamID(plClimbTriggerComponent::kDirection)));
// show the name of the currently picked item
curPick = pb->GetINode(ParamID(plClimbTriggerComponent::kWallPicker));
Button_SetText(hPick, (curPick == nil ? "None" : curPick->GetName()));
}
return TRUE;
break;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED)
{
if (LOWORD(wParam) == IDC_COMP_WALL_PICK)
{
// we're picking a new climbing wall
std::vector<Class_ID> pickableClasses;
pickableClasses.push_back(PHYSICS_TERRAIN_CID); // allow picking terrains
pickableClasses.push_back(PHYS_CLIMBABLE_CID); // and climbables
if (plPick::NodeRefKludge(pb, plClimbTriggerComponent::kWallPicker, &pickableClasses, true, false))
{
curPick = pb->GetINode(ParamID(plClimbTriggerComponent::kWallPicker));
Button_SetText(hPick, (curPick == nil ? "None" : curPick->GetName()));
}
return TRUE;
}
}
else if (LOWORD(wParam) == IDC_COMP_CLIMB_COMMAND)
{
HWND hSurface = GetDlgItem(hWnd, IDC_COMP_CLIMB_COMMAND);
curSurface = ComboBox_GetCurSel(hSurface);
pb->SetValue(ParamID(plClimbTriggerComponent::kCommand), 0, curSurface);
}
else if (LOWORD(wParam) == IDC_COMP_CLIMB_DIRECTION)
{
HWND hSurface = GetDlgItem(hWnd, IDC_COMP_CLIMB_DIRECTION);
curSurface = ComboBox_GetCurSel(hSurface);
pb->SetValue(ParamID(plClimbTriggerComponent::kDirection), 0, curSurface);
}
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// CLIMB BLOCKER COMPONENT
//
/////////////////////////////////////////////////////////////////////////////////////////
//Class that accesses the paramblock below.
class plClimbBlockerComponent : public plComponent
{
public:
plClimbBlockerComponent();
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
};
//Max desc stuff necessary below.
CLASS_DESC(plClimbBlockerComponent, gClimbBlockDesc, "Climb Blocker", "ClimbBlocker", COMP_TYPE_AVATAR, Class_ID(0x170000ac, 0x3cee02c5))
ParamBlockDesc2 gClimbBlockBk
(
plComponent::kBlkComp, _T("Climb Blocker"), 0, &gClimbBlockDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_CLIMB_BLOCK, IDS_COMP_CLIMB_BLOCKER, 0, 0, NULL,
end
);
plClimbBlockerComponent::plClimbBlockerComponent()
{
fClassDesc = &gClimbBlockDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool plClimbBlockerComponent::SetupProperties(plMaxNode *node, plErrorMsg *errMsg)
{
node->SetDrawable(false);
plPhysicalProps *props = node->GetPhysicalProps();
// props->SetMass(0.0, node, errMsg);
// props->SetFriction(0.0, node, errMsg);
// props->SetRestitution(0.0, node, errMsg);
props->SetBoundsType(plSimDefs::kExplicitBounds, node, errMsg);
// props->SetPinned(true, node, errMsg);
props->SetLOSBlockCustom(true, node, errMsg);
return true;
}
hsBool plClimbBlockerComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
return true;
}

View File

@ -0,0 +1,80 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_CLIMB_COMPONENT_H
#define PL_CLIMB_COMPONENT_H
#include "plComponent.h"
class plClimbTriggerComponent : public plComponent
{
public:
plClimbTriggerComponent();
virtual void DeleteThis() { delete this; }
virtual hsBool SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
enum // ParamBlock indices
{
kCommand,
kDirection,
kWallPicker
};
private:
};
#define CLIMB_TRIGGER_COMPONENT_CLASS_ID Class_ID(0x69857572, 0x671d0236)
class plClimbTriggerComponentProc : public ParamMap2UserDlgProc
{
public:
plClimbTriggerComponentProc() {}
BOOL DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void DeleteThis() {}
};
#endif

View File

@ -0,0 +1,361 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "max.h"
#include "resource.h"
//#include "hsUtils.h"
#include "hsTemplates.h"
#include "../plResMgr/plKeyFinder.h"
#include "../plResMgr/plPageInfo.h"
#include "hsResMgr.h"
#include "../MaxMain/plMaxNode.h"
#include "plClothingComponent.h"
#include "plComponentReg.h"
#include "../MaxPlasmaMtls/Materials/plClothingMtl.h"
#include "../pnMessage/plRefMsg.h"
#include "../plAvatar/plAvatarClothing.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../MaxConvert/hsMaterialConverter.h"
#include "../MaxConvert/plMeshConverter.h"
#include "plPickMaterialMap.h"
#include "../MaxMain/plMtlCollector.h"
#include "plAvatarComponent.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "../plDrawable/plSharedMesh.h"
#include "../plDrawable/plDrawableSpans.h"
#include "../plDrawable/plMorphSequence.h"
#include "../plScene/plSceneNode.h"
#include "../plDrawable/plGeometrySpan.h"
void DummyCodeIncludeFuncClothing()
{
}
CLASS_DESC(plClothingComponent, gClothingDesc, "Avatar Clothing", "AvatarClothing", COMP_TYPE_MISC, CLOTHING_COMPONENT_CLASS_ID)
static plClothingComponentProc gClothingComponentProc;
class plClothingAccessor : public PBAccessor
{
public:
//! Public Accessor Class, used in ParamBlock2 processing.
/*!
Workhorse for this Accessor Class (derived from Max's PBAccessor).
When one of our parameters that is a ref changes, send out the component ref
changed message. Normally, messages from component refs are ignored since
they pass along all the messages of the ref, which generates a lot of false
converts.
*/
void Set(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
if (id == plClothingComponent::kMeshNodeAddBtn)
{
plClothingComponent *comp = (plClothingComponent *)owner;
IParamBlock2 *pb = comp->GetParamBlockByID(plClothingComponent::kBlkComp);
int state = pb->GetInt(plClothingComponent::kLODState);
INode *node = pb->GetINode(plClothingComponent::kMeshNodeAddBtn);
if (node)
pb->SetValue(plClothingComponent::kMeshNodeTab, 0, node, state);
}
if (id == plClothingComponent::kMeshNodeTab)
{
plComponentBase *comp = (plComponentBase*)owner;
comp->NotifyDependents(FOREVER, PART_ALL, REFMSG_USER_COMP_REF_CHANGED);
}
}
};
plClothingAccessor gClothingAccessor;
ParamBlockDesc2 gClothingBk
(
plComponent::kBlkComp, _T("Clothing"), 0, &gClothingDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
//Roll out
IDD_COMP_CLOTHING, IDS_COMP_CLOTHING, 0, 0, &gClothingComponentProc,
plClothingComponent::kMaterials, _T("ClothingMaterials"), TYPE_MTL_TAB, 0, 0, 0,
end,
plClothingComponent::kGroup, _T("ClothingGroup"), TYPE_INT, 0, 0,
end,
plClothingComponent::kType, _T("ClothingType"), TYPE_INT, 0, 0,
end,
plClothingComponent::kLODState, _T("LODState"), TYPE_INT, 0, 0,
p_default, 0,
end,
plClothingComponent::kMeshNodeTab, _T("MeshObject"), TYPE_INODE_TAB, plLODAvatarComponent::kMaxNumLODLevels, 0, 0,
p_accessor, &gClothingAccessor,
end,
plClothingComponent::kMeshNodeAddBtn, _T("MshNodePicker"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_LOD_CLOTHING_MESH_PICKB,
p_sclassID, GEOMOBJECT_CLASS_ID,
p_prompt, IDS_COMP_AVATAR_PROXYS,
p_accessor, &gClothingAccessor,
end,
end
);
plClothingComponent::plClothingComponent()
{
fClassDesc = &gClothingDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plClothingComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
int i;
for (i = 0; i < fCompPB->Count(kMeshNodeTab); i++)
{
plMaxNode *LODNode = (plMaxNode *)fCompPB->GetINode(kMeshNodeTab, 0, i);
if (LODNode != nil)
{
char *dbgNodeName = LODNode->GetName();
//LODNode->SetCanConvert(false);
LODNode->SetDrawable(false);
LODNode->SetForceShadow(true);
LODNode->SetForceMatShade(true);
if (!LODNode->GetSwappableGeom())
LODNode->SetSwappableGeom(new plSharedMesh);
//UInt32 targetID = fCompPB->GetInt(kType);
//((plMaxNode *)LODNode->GetParentNode())->SetSwappableGeomTarget(targetID);
}
}
return true;
}
hsBool plClothingComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
node->SetupBoneHierarchyPalette();
return true;
}
hsBool plClothingComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
int i, j;
hsTArray<plGeometrySpan*> spanArray;
hsTArray<plKey> keys;
plMaxNode *LODNode = nil;
plMaxNode *locationNode = nil;
if (fCompPB->Count(plClothingComponent::kMaterials) <= 0)
return true;
for (i = 0; i < fCompPB->Count(kMeshNodeTab); i++)
{
spanArray.Reset();
//plSharedMesh *mesh = TRACKED_NEW plSharedMesh;
LODNode = (plMaxNode *)fCompPB->GetINode(kMeshNodeTab, 0, i);
if (LODNode != nil)
{
char *dbgNodeName = LODNode->GetName();
keys.Append(LODNode->GetSwappableGeom()->GetKey());
locationNode = LODNode;
if (fCompPB->GetInt(ParamID(kType)) != plClothingMgr::kTypeFace)
{
// We only save state for the face node.
LODNode->GetSwappableGeom()->fFlags |= plSharedMesh::kDontSaveMorphState;
}
else
{
// The face's weight for the first layer (0) is to be applied to all
// meshes on that node.
LODNode->GetSwappableGeom()->fFlags |= plSharedMesh::kLayer0GlobalToMod;
}
}
else
{
keys.Append(nil);
//delete mesh;
}
}
const plPageInfo* thisInfo = plKeyFinder::Instance().GetLocationInfo(locationNode ? locationNode->GetLocation() : node->GetLocation());
const plLocation &loc = plKeyFinder::Instance().FindLocation("GlobalClothing", thisInfo->GetPage());
for (i = 0; i < fCompPB->Count(plClothingComponent::kMaterials); i++)
{
plClothingMtl *mtl = (plClothingMtl *)fCompPB->GetMtl(ParamID(plClothingComponent::kMaterials), 0, i);
plClothingItem *cloth = hsMaterialConverter::Instance().GenerateClothingItem(mtl, loc);
cloth->fGroup = fCompPB->GetInt(ParamID(kGroup));
cloth->fType = fCompPB->GetInt(ParamID(kType));
plGenRefMsg *refMsg;
for (j = 0; j < keys.GetCount(); j++)
{
if (keys[j] != nil)
{
refMsg = TRACKED_NEW plGenRefMsg(cloth->GetKey(), plRefMsg::kOnCreate, j, -1);
hsgResMgr::ResMgr()->AddViaNotify(keys[j], refMsg, plRefFlags::kActiveRef);
}
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////
BOOL plClothingComponentProc::DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
IParamBlock2 *pb = pm->GetParamBlock();
HWND hList = GetDlgItem(hWnd, IDC_CLOTHING_LIST);
HWND hGroup = GetDlgItem(hWnd, IDC_CLOTHING_GROUP);
HWND hType = GetDlgItem(hWnd, IDC_CLOTHING_TYPE);
HWND hLOD = GetDlgItem(hWnd, IDC_COMP_LOD_CLOTHING_STATE);
switch (msg)
{
case WM_INITDIALOG:
{
ListBox_ResetContent(hList);
int i;
for (i = 0; i < pb->Count(plClothingComponent::kMaterials); i++)
ListBox_AddString(hList, pb->GetMtl(ParamID(plClothingComponent::kMaterials), 0, i)->GetName());
ListBox_SetCurSel(hList, -1);
for (i = 0; i < plClothingMgr::kMaxGroup; i++)
ComboBox_AddString(hGroup, plClothingMgr::GroupStrings[i]);
ComboBox_SetCurSel(hGroup, pb->GetInt(plClothingComponent::kGroup));
for (i = 0; i < plClothingMgr::kMaxType; i++)
ComboBox_AddString(hType, plClothingMgr::TypeStrings[i]);
ComboBox_SetCurSel(hType, pb->GetInt(plClothingComponent::kType));
ComboBox_AddString(hLOD, "High");
ComboBox_AddString(hLOD, "Medium");
ComboBox_AddString(hLOD, "Low");
ComboBox_SetCurSel(hLOD, pb->GetInt(plClothingComponent::kLODState));
}
return TRUE;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED)
{
if (LOWORD(wParam) == IDC_CLOTHING_ADD)
{
Mtl *pickedMtl = plPickMaterialMap::PickMaterial(plMtlCollector::kClothingMtlOnly);
if (pickedMtl != nil)
{
LRESULT stringIdx = ListBox_FindStringExact(hList, -1, pickedMtl->GetName());
if (stringIdx == LB_ERR) // It's not already there, go and add it
{
pb->Append(ParamID(plClothingComponent::kMaterials), 1, &pickedMtl, 0);
ListBox_AddString(hList, pickedMtl->GetName());
}
}
return TRUE;
}
// Remove the currently selected material
else if (LOWORD(wParam) == IDC_CLOTHING_REMOVE)
{
int sel = ListBox_GetCurSel(hList);
if (sel != LB_ERR)
{
pb->Delete(plClothingComponent::kMaterials, sel, 1);
ListBox_DeleteString(hList, sel);
}
return TRUE;
}
else if( LOWORD( wParam ) == IDC_CLOTHING_CLEARMESH )
{
int state = pb->GetInt(plClothingComponent::kLODState);
pb->SetValue(plClothingComponent::kMeshNodeTab, 0, (INode*)nil, state );
pb->Reset(plClothingComponent::kMeshNodeAddBtn);
}
}
else if (LOWORD(wParam) == IDC_CLOTHING_GROUP)
{
int setIdx = ComboBox_GetCurSel(hGroup);
pb->SetValue(plClothingComponent::kGroup, 0, setIdx);
return TRUE;
}
else if (LOWORD(wParam) == IDC_CLOTHING_TYPE)
{
int setIdx = ComboBox_GetCurSel(hType);
pb->SetValue(plClothingComponent::kType, 0, setIdx);
return TRUE;
}
else
{
int state = pb->GetInt(plClothingComponent::kLODState);
INode *node = pb->GetINode(plClothingComponent::kMeshNodeAddBtn);
if (node)
pb->SetValue(plClothingComponent::kMeshNodeTab, 0, node, state);
if(LOWORD(wParam) == IDC_COMP_LOD_CLOTHING_STATE && HIWORD(wParam) == CBN_SELCHANGE)
{
int idx = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0);
pb->SetValue(plClothingComponent::kLODState, 0, idx);
node = pb->GetINode(plClothingComponent::kMeshNodeTab, 0, idx);
if (node)
pb->SetValue(plClothingComponent::kMeshNodeAddBtn, 0, node);
else
pb->Reset(plClothingComponent::kMeshNodeAddBtn);
return TRUE;
}
}
}
return FALSE;
}

View File

@ -0,0 +1,80 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_CLOTHING_COMPONENT_H
#define PL_CLOTHING_COMPONENT_H
#include "plComponent.h"
class plClothingComponent : public plComponent
{
public:
plClothingComponent();
virtual void DeleteThis() { delete this; }
virtual hsBool SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
enum // ParamBlock indices
{
kMaterials,
kGroup,
kType,
kLODState,
kMeshNodeTab,
kMeshNodeAddBtn,
};
};
#define CLOTHING_COMPONENT_CLASS_ID Class_ID(0x2df85c56, 0x27bc2a7a)
class plClothingComponentProc : public ParamMap2UserDlgProc
{
public:
plClothingComponentProc() {}
BOOL DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void DeleteThis() {}
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,148 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plClusterComponent_inc
#define plClusterComponent_inc
const Class_ID CLUSTER_COMP_CID(0x508a10f4, 0x70112d59);
class hsRadixSortElem;
class plExportProgressBar;
class hsBitVector;
class plDistribInstTab;
class plMaxNodeTab;
class hsBitVector;
class plDistribComponent;
class plDistribInstance;
class plClusterGroup;
#include <vector>
using namespace std;
class plDistribCompTab : public Tab<plDistribComponent*>
{
};
class plBox3Tab : public Tab<Box3>
{
};
class plClusterComponent : public plComponent
{
public:
enum {
kClusters = 0,
kOptimization,
kFadeIns,
kFadeOuts,
kWindBone, // Obsolete, moved to DistribComponent
kWindBones,
kAutoGen,
kAutoInstance
};
protected:
float fClusterSize;
// These are temp, only used during processing.
plDistribInstTab** fClusterBins;
int fSizes[3];
plDistribCompTab fDistribTab;
plComponentBase* fLocationComp;
vector<plClusterGroup*> fClusterGroups;
// And more temps used only during Convert
BOOL fSetupDone;
BOOL fAutoGen;
BOOL fExported;
void ICheckWindBone();
BOOL IGetLocation();
void ISetLocation(plMaxNode* node);
void ISetupRenderDependencies();
void IAssignRenderDependencies(hsRadixSortElem*& prevStart, hsRadixSortElem*& prevEnd,
hsRadixSortElem*& currStart, hsRadixSortElem*& currEnd);
BOOL IBuildNodeTab(plDistribInstTab& nodes, plErrorMsg* pErrMsg, plExportProgressBar& bar);
void IClearNodeTab();
void IBuildDistribTab();
void IClearDistribTab();
BOOL IsFlexible() const;
void IRandomizeSkinWeights(Mesh* mesh, const Point3& flex) const;
void IFinishDoneNodes(INodeTab& doneNodes, plBox3Tab& fade, INodeTab& bone, hsBitVector& boneIsParent);
BOOL ICanCluster(plDistribInstance& node);
BOOL ICanCluster(plDistribInstance& node0, plDistribInstance& node1);
BOOL IClusterGroup(plDistribInstTab& nodes, INodeTab& clusters, plExportProgressBar& bar);
INode* IMakeOne(plDistribInstTab& nodes);
Box3 IPartition(plDistribInstTab& nodes);
void IClusterBins(plDistribInstTab& nodes, Box3& box);
int IGetBinCount();
void IDeleteClusterBins();
plDistribInstTab* IGetClusterBin(const Box3& box, const Point3& loc);
public:
plClusterComponent();
void DeleteThis() { delete this; }
void Clear();
BOOL Cluster(plErrorMsg* pErrMsg);
void Select();
BOOL AutoGen(plErrorMsg* pErrMsg);
void AutoClear(plErrorMsg* pErrMsg);
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
int GetNumGroups() { if (fSetupDone) return fClusterGroups.size(); return 0; }
plClusterGroup *GetGroup(int index) { if (fSetupDone) return fClusterGroups[index]; return nil; }
};
#endif // plClusterComponent_inc

View File

@ -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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plComponent.h"
#include "plComponentReg.h" // Needed for the kTargs enum
#include "../MaxMain/plMaxNode.h"

View File

@ -0,0 +1,262 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_COMPONENT_H
#define PL_COMPONENT_H
/************************************************************************************************
**
** Information regarding the development of Components for Plasma 2.0
**
** Date: 3/2/2001
** Version: Plasma 2.00
** Needs: A working knowledge of max sdk (Specifically the ParamBlocks...)
** A working knowledge of C++
**
**
** As the components are heavily reliant on the use of the MAX paramblock, the following methodology
** should be used in their implementation:
**
** In order for the paramblock to not be thrown away during linking, we have started the use of a
** dummy function such as:
**
** void DummyCodeIncludeStartPointFunc()
** {
** }
**
** This is called within the code for the GlobalUtility function, currently.
**
** Next create a derived class from the plComponent class with three public functions,
** being its constunctor, its custom destructor and the converter. Currently, we have the
** converter returning an hsBool to let you know how successful the conversion process has been
** during export to the .prd format.
**
** After the class above has been declared, the param block stuff follows:
**
** (Note all the imformation specifics regarding how to develop the paramblocks can be found
** in the help included in the maxsdk.)
**
** CLASS_DESC is a macro that Max has created that helps stuff your data into a param block. It
** takes in the following formal parameters:
**
** CLASS_DESC(plStartingPointComponent, gStartPtDesc, "StartingPoint", "StartingPointComp", Class_ID(0x2a127b68, 0xdc7367a))
**
** 1st parameter : The C++ class that is going to be accessing this function (assumed to be passed by reference)
** 2nd parameter : The Instance of the class descriptor that will be used specifically for
** the following param block. It is type int.
** 3rd parameter : The Short name description string for this paramblock.
** 4th parameter : The long name description string for this paramblock.
** 5th parameter : The unique CLASS_ID created via the included GEN_ID.exe that comes with maxsdk.
**
** Following this macro, an enum array is useful to store the relatively unique ID constants for the paramblock.
**
** The format of the definitions in this shown below, but basically is in the form of a sequence of fixed specs followed by a variable number of tagged optional specs for each parameter.
**
**
** Next, the actual param block is declared such as the following:
**
** ParamBlockDesc2 gStartPtBk
** (
** 1, _T(""), 0, &gStartPtDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, 0,
**
** //rollout
** IDD_COMP_STARTINGPOINT, IDS_COMP_STARTINGPOINTS, 0, 0, NULL,
**
** // params
** kPlayerStartingPoint, _T("Start Point:"), TYPE_STRING, 0, 0,
** p_ui, TYPE_EDITBOX, IDC_COMP_STARTPOINT,
** end,
**
** end
** );
**
** First is the name of the descriptor method that is to be used, in this case the ParamBlockDesc2
** type. Second is the unique name of this this paramblock. Following, a collection of comma delimited
** parameters ensue. The exact details as well as other flags to use herein can be found in the MaxR4 sdk
** Help file. We shall explain the above parameters to help give you an idea of the layout.
** All paramblocks have the following format:
**
** 1. Required block specs & per-block flags, followed by,
** 2. Optional owning object reference number for the block if auto-construct, followed by,
** 3. Optional parameter map specs if auto-ui, followed by,
** 4. Zero or more parameter specs, comprising:
** a. Required parameter specs, followed by,
** b. Zero or more optional parameter specs, each with is own leading tag,
** the list terminated by an 'end' tag, followed by,
** 5. an 'end' tag
**
** THE BLOCK SPECS:
**
** BlockParameter 1:
** "1" is the permanent block ID for the parameter block2. It must be unique
** to the block. Considering that you can have several blocks stored together in the same window,
** you may want to enum this as well. THIS IS A REQUIRED FIELD.
**
** BlockParameter 2:
** The internal name string. This name is not localized. Internal names are meant
** to be parsable as identifiers. As such they should begin with an alpha character, have only
** alphanumerics, and have no spaces, punctuations, etc. The convention for multi-word names
** is to use studly-caps, eg, paintRadius. THIS IS A REQUIRED FIELD.
**
** BlockParameter 3:
** The resource ID of the localized (sub-anim) name string. It is of type int. THIS IS
** A REQUIRED FIELD.
**
** BlockParameter 4:
** Points to the class descriptor2 of the owning class. This is used to add this
** descriptor to the ClassDesc2's table of block descriptors for the class. Note: This value may
** be passed as NULL for situations where the blocks owning ClassDesc2 is not available for static
** initializations (such as in a separate file). Before using the descriptor for any block
** construction, the ClassDesc2* must be initialized with the method:
**
** void ParamBlockDesc2::SetClassDesc(ClassDesc2* cd);
**
** You can only call this method once on a descriptor and then only if it has been
** constructed initially with a NULL cd.
**
** BlockParameter 5: One or more BYTE flags. In this instance, we are only using:
**
** P_AUTO_CONSTRUCT
** Indicates the parameter block2 will be constructed and referenced automatically
** to its owner in the call to ClassDesc2::MakeAutoParamBlocks(). If this flag is
** set, the parameter block's reference number in the owning object should be given
** immediately following the flag word in the descriptor constructor. See
** <auto_construct_block_refno>.
**
** P_AUTO_UI
** Indicates this block supports automatic UI rollout management in calls to
** ClassDesc2::BeginEditParams(), ClassDesc2::EndEditParams(),ClassDesc2::CreateParamDlg(),
** ClassDesc2::CreateParamDialog(), etc.
**
*8 The <auto_ui_parammap_specs> must be supplied in the descriptor constructor.
**
** BlockParameter 6: Because we used the AUTO_UI the following parameters are REQUIRED.
**
** int dialog_template_ID,
** (in this case IDD_COMP_something from an .rc file)
** int dialog_title_res_ID,
** (in this case IDS_COMP_something from the String Table)
** int flag_mask,
** (This is used by ClassDesc2::BeginEditParams() and ClassDesc2::EndEditParams()
** to determine whether the ParamMap2 shold be created/deleted on this call.
** All the bits in the supplied mask must be on in the Begin/EndEditParams
** flag longword for the action to take place. For this example we have 0.)
** int rollup_flags
** (This flag is used to control rollup creation. You may pass
** APPENDROLL_CLOSED to have the rollup added in the closed (rolled up) state.
** Otherwise pass 0.)
** ParamMap2UserDlgProc* proc
** (If there are controls in the dialog that require special processing this user
** If not used then NULL should be passed.)
**
** THE PARAM SPECS:
**
** Param Parameter 1: ParamID id
** (The permanent, position-independent ID for the parameter. In this case, it is
** the constant kStartingPoint.)
** Param Parameter 2: TCHAR* internal_name
** (The internal name for the parameter. In our case "Start Point:". This is what is written on the
** button, spinner, whizbang, foozle, etc.)
** Param Parameter 3: ParamType type
** (The type of parameter. See List of ParamType Choices. In this case it is TYPE_STRING. It could be
** TYPE_INT, TYPE_FLOAT, etc, etc, etc.)
** Param Parameter 4: [int table_size]
** (If the type is one of the Tab<> types, you need to supply an initial table size
** which can be 0. Which it is in our case above.)
** Param Parameter 5: int flags
** (These flags are ORed together. We don't use any, hence 0. They include useful things such as
** p_SubAnim which allow track view acess...)
** Param Parameter 6: int local_name_res_ID
** (Here lies that relatively unique enum mentioned above. Hence, the kStartingPoint.)
**
** OPTIONAL STUFF:
**
** As param blocks don't necessarily need a visual GUI, any that you include are optional.
**
** p_ui,
** (This declares that a GUI will be instantiated. The parameter hereafter will declare the type.)
** GUI_Type
** (This is the type of GUI that you are going to use. In our case it is a CUSTOM editbox.
**
** NOTE: MAX prefers that you create CUSTOM instances of all GUI resources (such as spinners,
** editboxes, etc)
** )
**
** ID
** (This is the implementor defined name that this GUI is using. It is the name of the object that
** you created a resource of. We created an IDC_COMP_STARTINGPOINT which was of a CustEdit type.)
**
** end
** (This lets the constructor that makes uses to know that you have finished one of the p_ui param
** blocks.)
**
**
** FINAL REQUISITE STUFF:
**
** end
** );
** (This is the conclusion of the Block descriptor. Sort of intuitive...)
**
*************************************************************************************************/
#include "plComponentBase.h"
#include "../MaxExport/plErrorMsg.h"
class plMaxNode;
class plErrorMsg;
class plComponent : public plComponentBase
{
public:
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg) = 0;
// DeInit pass--free up any temp memory you might have allocated here
virtual hsBool DeInit(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,710 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plComponentBase.h"
#include "plComponentReg.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "../MaxMain/plMaxNodeBase.h"
#include "plAutoUIComp.h"
plComponentBase::plComponentBase() : fClassDesc(nil), fCompPB(nil), fTargsPB(nil)
{
}
plComponentBase::~plComponentBase()
{
DeleteAllRefsFromMe();
}
CreateMouseCallBack* plComponentBase::GetCreateMouseCallBack()
{
return NULL;
}
void plComponentBase::BeginEditParams(IObjParam *ip, ULONG flags, Animatable *prev)
{
fClassDesc->BeginEditParams(ip, this, flags, prev);
}
void plComponentBase::EndEditParams(IObjParam *ip, ULONG flags, Animatable *next)
{
fClassDesc->EndEditParams(ip, this, flags, next);
}
int plComponentBase::NumParamBlocks()
{
return 2;
}
IParamBlock2 *plComponentBase::GetParamBlock(int i)
{
if (i == kRefComp)
return fCompPB;
else if (i == kRefTargs)
return fTargsPB;
return nil;
}
IParamBlock2 *plComponentBase::GetParamBlockByID(BlockID id)
{
if (fCompPB && fCompPB->ID() == id)
return fCompPB;
else if (fTargsPB && fTargsPB->ID() == id)
return fTargsPB;
return nil;
}
// So our animatables will show up in the trackview
int plComponentBase::NumSubs()
{
return 1;
}
Animatable *plComponentBase::SubAnim(int i)
{
return fCompPB;
}
TSTR plComponentBase::SubAnimName(int i)
{
return fClassDesc->ClassName();
}
RefTargetHandle plComponentBase::Clone(RemapDir &remap)
{
plComponentBase *obj = (plComponentBase*)fClassDesc->Create(false);
// Do the base clone
BaseClone(this, obj, remap);
// Copy our references
if (fCompPB)
obj->ReplaceReference(kRefComp, fCompPB->Clone(remap));
if (fTargsPB)
obj->ReplaceReference(kRefTargs, fTargsPB->Clone(remap));
return obj;
}
void plComponentBase::BuildMesh(TimeValue t)
{
}
void plComponentBase::FreeCaches()
{
}
void plComponentBase::GetLocalBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box)
{
box.MakeCube(Point3(0,0,0), 0);
}
void plComponentBase::GetWorldBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box)
{
box.MakeCube(Point3(0,0,0), 0);
}
int plComponentBase::Display(TimeValue t, INode *node, ViewExp *vpt, int flags)
{
return 0;
}
int plComponentBase::HitTest(TimeValue t, INode *node, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt)
{
return 0;
}
int plComponentBase::NumRefs()
{
return 2;
}
RefTargetHandle plComponentBase::GetReference(int i)
{
if (i == kRefComp)
return fCompPB;
else if (i == kRefTargs)
return fTargsPB;
return nil;
}
void plComponentBase::SetReference(int i, RefTargetHandle rtarg)
{
if (i == kRefTargs)
fTargsPB = (IParamBlock2*)rtarg;
else if (i == kRefComp)
fCompPB = (IParamBlock2*)rtarg;
}
RefResult plComponentBase::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message)
{
return REF_SUCCEED;
}
IOResult plComponentBase::Save(ISave* isave)
{
return IO_OK;
}
IOResult plComponentBase::Load(ILoad* iload)
{
return IO_OK;
}
void plComponentBase::AddTargetsToList(INodeTab& list)
{
int i;
for( i = 0; i < NumTargets(); i++ )
{
INode* targ = GetTarget(i);
if( targ )
list.Append(1, &targ);
}
}
UInt32 plComponentBase::NumTargets()
{
if (fTargsPB)
return fTargsPB->Count(kTargs);
return 0;
}
plMaxNodeBase *plComponentBase::GetTarget(UInt32 i)
{
if (fTargsPB && i < NumTargets())
return (plMaxNodeBase*)fTargsPB->GetINode(kTargs, 0, i);
return nil;
}
void plComponentBase::AddTarget(plMaxNodeBase *target)
{
if (!target)
return;
// Make sure we don't already ref this
UInt32 count = fTargsPB->Count(kTargs);
for (UInt32 i = 0; i < count; i++)
{
if (fTargsPB->GetINode(kTargs, 0, i) == target)
return;
}
// Add it to our list
fTargsPB->Append(kTargs, 1, (INode**)&target);
NotifyDependents(FOREVER, (PartID)target, REFMSG_USER_TARGET_ADD);
}
void plComponentBase::DeleteTarget(plMaxNodeBase *target)
{
if (!target)
return;
UInt32 count = fTargsPB->Count(kTargs);
for (UInt32 i = 0; i < count; i++)
{
if (fTargsPB->GetINode(kTargs, 0, i) == target)
{
fTargsPB->Delete(kTargs, i, 1);
NotifyDependents(FOREVER, (PartID)target, REFMSG_USER_TARGET_DELETE);
return;
}
}
}
void plComponentBase::DeleteAllTargets()
{
while (fTargsPB->Count(kTargs) > 0)
{
INode *node = fTargsPB->GetINode(kTargs);
if (node)
NotifyDependents(FOREVER, (PartID)node, REFMSG_USER_TARGET_DELETE);
fTargsPB->Delete(kTargs, 0, 1);
}
}
bool plComponentBase::IsTarget(plMaxNodeBase *node)
{
if (!node)
return false;
for (int i = 0; i < fTargsPB->Count(kTargs); i++)
if (fTargsPB->GetINode(kTargs, 0, i) == node)
return true;
return false;
}
const char* plComponentBase::IGetUniqueName(plMaxNodeBase* target)
{
static char nameBuf[256];
// Make sure we've actually got multiple *used* targets. (Some could be nil)
int numUsedTargs = 0;
int thisTargIdx = -1;
for (int i = 0; i < fTargsPB->Count(kTargs); i++)
{
plMaxNodeBase* thisTarg = (plMaxNodeBase*)fTargsPB->GetINode(kTargs, 0, i);
if (thisTarg)
numUsedTargs++;
if (thisTarg == target)
thisTargIdx = i;
// If we've figured out whether or not we have multiple targets, and we
// found which target this one is, we can break out early
if (numUsedTargs > 1 && thisTargIdx != -1)
break;
}
hsAssert(thisTargIdx != -1, "Bad target for IGetUniqueName");
if (numUsedTargs > 1)
_snprintf(nameBuf, sizeof(nameBuf), "%s_%d", GetINode()->GetName(), thisTargIdx);
else
strncpy(nameBuf, GetINode()->GetName(), sizeof(nameBuf));
return nameBuf;
}
plMaxNodeBase *plComponentBase::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 (plMaxNodeBase*)item->maker;
item = item->next;
}
return nil;
}
hsBool plComponentBase::IsExternal()
{
return CanConvertToType(EXT_COMPONENT_CLASSID);
}
bool plComponentBase::IsCurMsgLocal()
{
// Was the last notification a message propagated up from a target?
// Ignore it if so.
if (fTargsPB->LastNotifyParamID() != -1)
return false;
// Was the last notification from a ref in the component PB? If so, assume
// it was a propagated message from the ref. Real changes to that ref
// parameter will be signalled with a user ref message.
if (fCompPB->LastNotifyParamID() != -1)
{
ParamID id = fCompPB->LastNotifyParamID();
if (is_ref(fCompPB->GetParamDef(id)))
return false;
}
return true;
}
bool plComponentBase::IsObsolete()
{
return ((plComponentClassDesc*)fClassDesc)->IsObsolete();
}
bool DoesPBReferenceNode(IParamBlock2* pb, INode* node);
static bool CheckRef(ReferenceTarget* targ, INode* node)
{
if (!targ)
return false;
if (targ->SuperClassID() == BASENODE_CLASS_ID)
{
if ((INode*)targ == node)
return true;
}
else if (targ->SuperClassID() == PARAMETER_BLOCK2_CLASS_ID)
{
return DoesPBReferenceNode((IParamBlock2*)targ, node);
}
return false;
}
static bool DoesPBReferenceNode(IParamBlock2* pb, INode* node)
{
for (int i = 0; i < pb->NumParams(); i++)
{
ParamID id = pb->IndextoID(i);
ParamType2 type = pb->GetParameterType(id);
if (type == TYPE_INODE)
{
if (pb->GetINode(id) == node)
return true;
}
if (type == TYPE_INODE_TAB)
{
for (int iNode = 0; iNode < pb->Count(id); iNode++)
{
if (pb->GetINode(id, 0, iNode) == node)
return true;
}
}
if (type == TYPE_REFTARG)
{
ReferenceTarget* targ = pb->GetReferenceTarget(id);
bool ret = CheckRef(targ, node);
if (ret)
return true;
}
if (type == TYPE_REFTARG_TAB)
{
for (int iRef = 0; iRef < pb->Count(id); iRef++)
{
ReferenceTarget* targ = pb->GetReferenceTarget(id, 0, iRef);
bool ret = CheckRef(targ, node);
if (ret)
return true;
}
}
}
return false;
}
bool plComponentBase::DoReferenceNode(INode* node)
{
if (!fCompPB)
return false;
return DoesPBReferenceNode(fCompPB, node);
}
void plComponentBase::CreateRollups()
{
if (!fCompPB)
return;
ParamBlockDesc2 *pd = fCompPB->GetDesc();
plComponentClassDesc *cd = (plComponentClassDesc*)pd->cd;
// This is a plAutoUIComp, we need to treat it differently
if (cd->IsAutoUI())
{
plAutoUIClassDesc *cd = (plAutoUIClassDesc*)pd->cd;
cd->CreateAutoRollup(fCompPB);
}
// We're using a normal param block with auto UI
else if (pd->flags & P_AUTO_UI)
{
if (pd->flags & P_MULTIMAP)
{
int nMaps = pd->map_specs.Count();
for (int i = 0; i < nMaps; i++)
{
ParamBlockDesc2::map_spec spec = pd->map_specs[i];
// Create the rollout
IParamMap2 *map = CreateCPParamMap2(spec.map_id,
fCompPB,
GetCOREInterface(),
hInstance,
MAKEINTRESOURCE(spec.dlg_template),
GetString(spec.title),
spec.rollup_flags,
spec.dlgProc,
NULL,
ROLLUP_CAT_STANDARD);
// Save the rollout in the paramblock
fCompPB->SetMap(map, spec.map_id);
}
}
else
{
// Create the rollout
IParamMap2 *map = CreateCPParamMap2(0,
fCompPB,
GetCOREInterface(),
hInstance,
MAKEINTRESOURCE(pd->dlg_template),
GetString(pd->title),
pd->flags,
pd->dlgProc,
NULL,
ROLLUP_CAT_STANDARD);
// Save the rollout in the paramblock
fCompPB->SetMap(map);
}
}
fCompPB->ReleaseDesc();
}
void plComponentBase::DestroyRollups()
{
if (!fCompPB)
return;
ParamBlockDesc2 *pd = fCompPB->GetDesc();
plComponentClassDesc *cd = (plComponentClassDesc*)pd->cd;
// This is a plAutoUIComp, we need to treat it differently
if (cd->IsAutoUI())
{
plAutoUIClassDesc *autoCD = (plAutoUIClassDesc*)pd->cd;
autoCD->DestroyAutoRollup();
}
// We're using a normal param block with auto UI
else if (pd->flags & P_AUTO_UI)
{
if (pd->flags & P_MULTIMAP)
{
int nMaps = pd->map_specs.Count();
for (int i = 0; i < nMaps; i++)
{
MapID id = pd->map_specs[i].map_id;
// Destroy any parammap saved in the rollup
IParamMap2 *map = fCompPB->GetMap(id);
fCompPB->SetMap(nil, id);
if (map)
DestroyCPParamMap2(map);
}
}
else
{
// Destroy any parammap saved in the rollup
IParamMap2 *map = fCompPB->GetMap();
fCompPB->SetMap(nil);
if (map)
DestroyCPParamMap2(map);
}
}
fCompPB->ReleaseDesc();
}
////////////////////////////////////////////////////////////////////////////////
static bool INodeHasComponent(plMaxNodeBase *node, plMaxNodeBase *compNode)
{
UInt32 count = node->NumAttachedComponents();
for (UInt32 i = 0; i < count; i++)
{
if (node->GetAttachedComponent(i)->GetINode() == compNode)
return true;
}
return false;
}
int plSharedComponents(INodeTab& nodes, INodeTab& components)
{
components.ZeroCount();
if (nodes.Count() == 0)
return 0;
plMaxNodeBase *firstNode = (plMaxNodeBase*)nodes[0];
int num = firstNode->NumAttachedComponents();
// Resize the list to it's max size to be more efficient
components.SetCount(num);
int i;
// Put all the components on the first node into a list
for (i = 0; i < num; i++)
components[i] = firstNode->GetAttachedComponent(i)->GetINode();
// Delete any components that aren't on all the other nodes
for (i = 1; i < nodes.Count(); i++)
{
plMaxNodeBase *node = (plMaxNodeBase*)nodes[i];
UInt32 count = node->NumAttachedComponents();
for (int j = components.Count()-1; j >= 0; j--)
{
if (!INodeHasComponent(node, (plMaxNodeBase*)components[j]))
components.Delete(j, 1);
}
}
return components.Count();
}
///////////////////////////////////////////////////////////////////////////////////////////
#include "notify.h"
static void UpdateComponentVisibility(plMaxNodeBase *node)
{
plComponentBase *comp = node->ConvertToComponent();
if (comp)
{
node->Freeze(TRUE);
node->Hide(!comp->AllowUnhide());
}
for (int i = 0; i < node->NumberOfChildren(); i++)
{
plMaxNodeBase *childNode = (plMaxNodeBase*)node->GetChildNode(i);
UpdateComponentVisibility(childNode);
}
}
static void UnlinkComponents(plMaxNodeBase *node)
{
plComponentBase *comp = node->ConvertToComponent();
if (comp)
comp->DeleteAllTargets();
for (int i = 0; i < node->NumberOfChildren(); i++)
{
plMaxNodeBase *child = (plMaxNodeBase*)node->GetChildNode(i);
UnlinkComponents(child);
}
}
static void FindObsoleteComponents(plMaxNodeBase *node, std::vector<plComponentBase*>& obsoleteComps)
{
plComponentBase *comp = node->ConvertToComponent();
if (comp && comp->IsObsolete())
obsoleteComps.push_back(comp);
for (int i = 0; i < node->NumberOfChildren(); i++)
{
plMaxNodeBase *childNode = (plMaxNodeBase*)node->GetChildNode(i);
FindObsoleteComponents(childNode, obsoleteComps);
}
}
static bool gUpdatingComponents = false;
#include <set>
#include "hsUtils.h"
static void ComponentNotify(void *param, NotifyInfo *info)
{
if (info->intcode == NOTIFY_NODE_UNHIDE)
{
if (!gUpdatingComponents)
{
plMaxNodeBase *node = (plMaxNodeBase*)info->callParam;
plComponentBase *comp = node ? node->ConvertToComponent() : nil;
if (comp)
{
node->Hide(!comp->AllowUnhide());
node->Freeze(TRUE);
}
}
}
else if (info->intcode == NOTIFY_FILE_POST_OPEN)
{
plComponentShow::Update();
GetCOREInterface()->ForceCompleteRedraw();
// Also checking bitmap silent mode, since the export script uses that
if (!hsMessageBox_SuppressPrompts && !TheManager->SilentMode())
{
// Get all the obsolete components in the scene
std::vector<plComponentBase*> obsoleteComps;
FindObsoleteComponents((plMaxNodeBase*)GetCOREInterface()->GetRootNode(), obsoleteComps);
// For now, just get the categories (could get the component names)
std::set<const char *> names;
for (int i = 0; i < obsoleteComps.size(); i++)
{
const char *name = obsoleteComps[i]->GetObjectName();
names.insert(name);
}
if (obsoleteComps.size() > 0)
{
char buf[1024];
strcpy(buf, "Components of the following obsolete types\nwere found in this scene. Please delete them.\n\n");
std::set<const char *>::iterator it = names.begin();
for (; it != names.end(); it++)
{
strcat(buf, (*it));
strcat(buf, "\n");
}
hsMessageBox(buf, "Obsolete Components", hsMBoxOk);
}
}
}
// WEIRD HACK - If lots of components are linked to objects when a scene is closed
// the closing goes really slow. I assume it is just repeatedly calling some
// unoptimized section of code (it would probably happen for any large number of
// references). So, at this point if the scene was changed the user would have already
// been prompted to save it, so we can modify the scene by deleting all the component
// references. -Colin
else if (info->intcode == NOTIFY_SYSTEM_SHUTDOWN ||
info->intcode == NOTIFY_FILE_PRE_OPEN)
{
UnlinkComponents((plMaxNodeBase*)GetCOREInterface()->GetRootNode());
}
}
void plComponentShow::Init()
{
RegisterNotification(ComponentNotify, 0, NOTIFY_FILE_POST_OPEN);
RegisterNotification(ComponentNotify, 0, NOTIFY_NODE_UNHIDE);
RegisterNotification(ComponentNotify, 0, NOTIFY_SYSTEM_SHUTDOWN);
RegisterNotification(ComponentNotify, 0, NOTIFY_FILE_PRE_OPEN);
}
void plComponentShow::Update()
{
gUpdatingComponents = true;
UpdateComponentVisibility((plMaxNodeBase*)GetCOREInterface()->GetRootNode());
gUpdatingComponents = false;
}

View File

@ -0,0 +1,403 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_COMPONENT_BASE_H
#define PL_COMPONENT_BASE_H
#include "Max.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "hsTypes.h"
#include "../pnKeyedObject/plKey.h"
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
#define COMPONENT_CLASSID Class_ID(0x758e5142, 0x66c748a)
#define EXT_COMPONENT_CLASSID Class_ID(0x6c277b63, 0x6c626b3f)
class plMaxNodeBase;
class plKey;
class plMaxNode;
class plAGAnim;
class plComponentBase : public HelperObject
{
protected:
ClassDesc2 *fClassDesc; // Must set in derived classes constructor
IParamBlock2 *fCompPB; // The derived component's paramblock (optional)
IParamBlock2 *fTargsPB; // Nodes this component is attached to
// Get a unique name based on this components name and the index of this target
// Return value points to a static, so don't try to hold on to it
const char* IGetUniqueName(plMaxNodeBase* target);
public:
// Permanent Block ID's
enum
{
kBlkComp,
kBlkTargs = 10, // To avoid any conflicts with legacy blocks
};
// Ref numbers
enum
{
kRefComp,
kRefTargs,
};
plComponentBase();
virtual ~plComponentBase();
void DeleteThis() { delete this; }
UInt32 NumTargets();
plMaxNodeBase *GetTarget(UInt32 i);
virtual void AddTarget(plMaxNodeBase *target);
virtual void DeleteTarget(plMaxNodeBase *target);
virtual void DeleteAllTargets();
bool IsTarget(plMaxNodeBase *node);
plMaxNodeBase *GetINode();
virtual void AddReceiverKey(plKey key, plMaxNode* node=nil) {;}
virtual plKey GetLogicKey(plMaxNode* node) {return nil;}
// Return true if you want to allow yourself to be unhidden. This is for components
// with animatable parameters they want to expose in the TrackView.
virtual bool AllowUnhide() { return false; }
// Collect up all the non-runtime renderable geometry that's going to wind up
// physical proxies, trigger boxes, soft regions etc. This is normally everything
// that this component is going to call SetDrawable(false) on. The list returned might
// be selected, hidden, have max's renderable property set to false, whatever, you don't
// have to worry about that. All you have to do is, if your component SetDrawable(false)'s
// on anything, try to remember to override this function and add the MaxNodes you're
// making non-drawable to this list when called. Remember, just append to the list.
// If you're going to add everything you're attached to to the list, you can just
// call AddTargetsToList(nonDrawables), so you're overriding function just looks like:
// virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); }
virtual void CollectNonDrawables(INodeTab& nonDrawables) { return; }
virtual void AddTargetsToList(INodeTab& list);
// Return the minimum graphics capability required by objects created by this component.
// Unless a component is generating an object that uses shaders, or has some other
// specific graphics requirement, the default of 0 (meaning no special requirements)
// should not be overriden.
virtual int GetMinCap() { return 0; }
hsBool IsExternal();
// Returns true if the msg that was just sent out was local or from something
// this component ref's. Used by the SceneWatcher to determine if a component
// needs to be reconverted.
virtual bool IsCurMsgLocal();
bool IsObsolete();
// Returns true if this component has a reference to node (being attached doesn't count)
virtual bool DoReferenceNode(INode* node);
virtual void CreateRollups();
virtual void DestroyRollups();
///////////////////////////////////////////////////////////////////////////////////////
// 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 fClassDesc->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);
// So our animatables will show up in the trackview
int NumSubs();
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
virtual hsBool AddToAnim(plAGAnim *anim, plMaxNode *node) { return false; }
// plug-in mouse creation callback
CreateMouseCallBack* GetCreateMouseCallBack();
void BeginEditParams(IObjParam *ip, ULONG flags, Animatable *prev);
void EndEditParams(IObjParam *ip, ULONG flags, Animatable *next);
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 == COMPONENT_CLASSID) ? 1 : 0; }
const char *GetCategory() { return fClassDesc->Category(); }
};
// Look through the nodes in 'nodes' and find components that they all share.
// Store those in 'components'.
// Returns the number of shared components
int plSharedComponents(INodeTab& nodes, INodeTab& components);
// Takes care of the dirty little secrets of components
class plComponentShow
{
public:
static void Init();
// Call this to update the visibility of the components in the scene, ie, if you
// changed the return value of your AllowUnhide function
static void Update();
};
#endif
/************************************************************************************************
**
** Information regarding the development of Components for Plasma 2.0
**
** Date: 3/2/2001
** Version: Plasma 2.00
** Needs: A working knowledge of max sdk (Specifically the ParamBlocks...)
** A working knowledge of C++
**
**
** As the components are heavily reliant on the use of the MAX paramblock, the following methodology
** should be used in their implementation:
**
** In order for the paramblock to not be thrown away during linking, we have started the use of a
** dummy function such as:
**
** void DummyCodeIncludeStartPointFunc()
** {
** }
**
** This is called within the code for the GlobalUtility function, currently.
**
** Next create a derived class from the plComponent class with three public functions,
** being its constunctor, its custom destructor and the converter. Currently, we have the
** converter returning an hsBool to let you know how successful the conversion process has been
** during export to the .prd format.
**
** After the class above has been declared, the param block stuff follows:
**
** (Note all the imformation specifics regarding how to develop the paramblocks can be found
** in the help included in the maxsdk.)
**
** CLASS_DESC is a macro that Max has created that helps stuff your data into a param block. It
** takes in the following formal parameters:
**
** CLASS_DESC(plStartingPointComponent, gStartPtDesc, "StartingPoint", "StartingPointComp", Class_ID(0x2a127b68, 0xdc7367a))
**
** 1st parameter : The C++ class that is going to be accessing this function (assumed to be passed by reference)
** 2nd parameter : The Instance of the class descriptor that will be used specifically for
** the following param block. It is type int.
** 3rd parameter : The Short name description string for this paramblock.
** 4th parameter : The long name description string for this paramblock.
** 5th parameter : The unique CLASS_ID created via the included GEN_ID.exe that comes with maxsdk.
**
** Following this macro, an enum array is useful to store the relatively unique ID constants for the paramblock.
**
** The format of the definitions in this shown below, but basically is in the form of a sequence of fixed specs followed by a variable number of tagged optional specs for each parameter.
**
**
** Next, the actual param block is declared such as the following:
**
** ParamBlockDesc2 gStartPtBk
** (
** 1, _T(""), 0, &gStartPtDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, 0,
**
** //rollout
** IDD_COMP_STARTINGPOINT, IDS_COMP_STARTINGPOINTS, 0, 0, NULL,
**
** // params
** kPlayerStartingPoint, _T("Start Point:"), TYPE_STRING, 0, 0,
** p_ui, TYPE_EDITBOX, IDC_COMP_STARTPOINT,
** end,
**
** end
** );
**
** First is the name of the descriptor method that is to be used, in this case the ParamBlockDesc2
** type. Second is the unique name of this this paramblock. Following, a collection of comma delimited
** parameters ensue. The exact details as well as other flags to use herein can be found in the MaxR4 sdk
** Help file. We shall explain the above parameters to help give you an idea of the layout.
** All paramblocks have the following format:
**
** 1. Required block specs & per-block flags, followed by,
** 2. Optional owning object reference number for the block if auto-construct, followed by,
** 3. Optional parameter map specs if auto-ui, followed by,
** 4. Zero or more parameter specs, comprising:
** a. Required parameter specs, followed by,
** b. Zero or more optional parameter specs, each with is own leading tag,
** the list terminated by an 'end' tag, followed by,
** 5. an 'end' tag
**
** THE BLOCK SPECS:
**
** BlockParameter 1:
** "1" is the permanent block ID for the parameter block2. It must be unique
** to the block. Considering that you can have several blocks stored together in the same window,
** you may want to enum this as well. THIS IS A REQUIRED FIELD.
**
** BlockParameter 2:
** The internal name string. This name is not localized. Internal names are meant
** to be parsable as identifiers. As such they should begin with an alpha character, have only
** alphanumerics, and have no spaces, punctuations, etc. The convention for multi-word names
** is to use studly-caps, eg, paintRadius. THIS IS A REQUIRED FIELD.
**
** BlockParameter 3:
** The resource ID of the localized (sub-anim) name string. It is of type int. THIS IS
** A REQUIRED FIELD.
**
** BlockParameter 4:
** Points to the class descriptor2 of the owning class. This is used to add this
** descriptor to the ClassDesc2's table of block descriptors for the class. Note: This value may
** be passed as NULL for situations where the blocks owning ClassDesc2 is not available for static
** initializations (such as in a separate file). Before using the descriptor for any block
** construction, the ClassDesc2* must be initialized with the method:
**
** void ParamBlockDesc2::SetClassDesc(ClassDesc2* cd);
**
** You can only call this method once on a descriptor and then only if it has been
** constructed initially with a NULL cd.
**
** BlockParameter 5: One or more BYTE flags. In this instance, we are only using:
**
** P_AUTO_CONSTRUCT
** Indicates the parameter block2 will be constructed and referenced automatically
** to its owner in the call to ClassDesc2::MakeAutoParamBlocks(). If this flag is
** set, the parameter block's reference number in the owning object should be given
** immediately following the flag word in the descriptor constructor. See
** <auto_construct_block_refno>.
**
** P_AUTO_UI
** Indicates this block supports automatic UI rollout management in calls to
** ClassDesc2::BeginEditParams(), ClassDesc2::EndEditParams(),ClassDesc2::CreateParamDlg(),
** ClassDesc2::CreateParamDialog(), etc.
**
*8 The <auto_ui_parammap_specs> must be supplied in the descriptor constructor.
**
** BlockParameter 6: Because we used the AUTO_UI the following parameters are REQUIRED.
**
** int dialog_template_ID,
** (in this case IDD_COMP_something from an .rc file)
** int dialog_title_res_ID,
** (in this case IDS_COMP_something from the String Table)
** int flag_mask,
** (This is used by ClassDesc2::BeginEditParams() and ClassDesc2::EndEditParams()
** to determine whether the ParamMap2 shold be created/deleted on this call.
** All the bits in the supplied mask must be on in the Begin/EndEditParams
** flag longword for the action to take place. For this example we have 0.)
** int rollup_flags
** (This flag is used to control rollup creation. You may pass
** APPENDROLL_CLOSED to have the rollup added in the closed (rolled up) state.
** Otherwise pass 0.)
** ParamMap2UserDlgProc* proc
** (If there are controls in the dialog that require special processing this user
** If not used then NULL should be passed.)
**
** THE PARAM SPECS:
**
** Param Parameter 1: ParamID id
** (The permanent, position-independent ID for the parameter. In this case, it is
** the constant kStartingPoint.)
** Param Parameter 2: TCHAR* internal_name
** (The internal name for the parameter. In our case "Start Point:". This is what is written on the
** button, spinner, whizbang, foozle, etc.)
** Param Parameter 3: ParamType type
** (The type of parameter. See List of ParamType Choices. In this case it is TYPE_STRING. It could be
** TYPE_INT, TYPE_FLOAT, etc, etc, etc.)
** Param Parameter 4: [int table_size]
** (If the type is one of the Tab<> types, you need to supply an initial table size
** which can be 0. Which it is in our case above.)
** Param Parameter 5: int flags
** (These flags are ORed together. We don't use any, hence 0. They include useful things such as
** p_SubAnim which allow track view acess...)
** Param Parameter 6: int local_name_res_ID
** (Here lies that relatively unique enum mentioned above. Hence, the kStartingPoint.)
**
** OPTIONAL STUFF:
**
** As param blocks don't necessarily need a visual GUI, any that you include are optional.
**
** p_ui,
** (This declares that a GUI will be instantiated. The parameter hereafter will declare the type.)
** GUI_Type
** (This is the type of GUI that you are going to use. In our case it is a CUSTOM editbox.
**
** NOTE: MAX prefers that you create CUSTOM instances of all GUI resources (such as spinners,
** editboxes, etc)
** )
**
** ID
** (This is the implementor defined name that this GUI is using. It is the name of the object that
** you created a resource of. We created an IDC_COMP_STARTINGPOINT which was of a CustEdit type.)
**
** end
** (This lets the constructor that makes uses to know that you have finished one of the p_ui param
** blocks.)
**
**
** FINAL REQUISITE STUFF:
**
** end
** );
** (This is the conclusion of the Block descriptor. Sort of intuitive...)
**
*************************************************************************************************/

View File

@ -0,0 +1,67 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_COMPONENT_EXT_H
#define PL_COMPONENT_EXT_H
#include "plComponentBase.h"
#include "plComponentTools.h"
#include "../MaxExport/plErrorMsg.h"
class plMaxNodeBase;
class plComponentExt : public plComponentBase
{
public:
int CanConvertToType(Class_ID obtype)
{ return (obtype == EXT_COMPONENT_CLASSID) ? 1 : plComponentBase::CanConvertToType(obtype); }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNodeBase *node, plComponentTools *tools, plErrorMsg *pErrMsg) { return true; }
virtual hsBool PreConvert(plMaxNodeBase *node, plComponentTools *tools, plErrorMsg *pErrMsg) { return true; }
virtual hsBool Convert(plMaxNodeBase *node, plComponentTools *tools, plErrorMsg *pErrMsg) = 0;
// DeInit pass--free up any temp memory you might have allocated here
virtual hsBool DeInit(plMaxNodeBase *node, plComponentTools *tools, plErrorMsg *pErrMsg) { return true; }
};
#endif

View File

@ -0,0 +1,135 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "max.h"
#include "iparamb2.h"
#include <algorithm>
#include "plComponent.h"
#include "plComponentMgr.h"
#include "plComponentReg.h"
/////////
class ComponentMgrClassDesc : public ClassDesc
{
public:
int IsPublic() { return FALSE; }
void* Create(BOOL loading) { return &plComponentMgr::Inst(); }
const TCHAR* ClassName() { return _T("Component Mgr"); }
SClass_ID SuperClassID() { return UTILITY_CLASS_ID; }
Class_ID ClassID() { return COMPONENT_MGR_CID; }
const TCHAR* Category() { return _T(""); }
};
static ComponentMgrClassDesc theComponentMgrCD;
ClassDesc* GetComponentMgrDesc() { return &theComponentMgrCD; }
/////////////
plComponentMgr &plComponentMgr::Inst()
{
static plComponentMgr theInstance;
return theInstance;
}
UInt32 plComponentMgr::Count()
{
return fDescs.size();
}
ClassDesc *plComponentMgr::Get(UInt32 i)
{
if (i < fDescs.size())
return fDescs[i];
else
{
hsAssert(0, "Component index out of range");
return nil;
}
}
UInt32 plComponentMgr::FindClassID(Class_ID id)
{
for (unsigned int i = 0; i < fDescs.size(); i++)
{
if (fDescs[i]->ClassID() == id)
return i;
}
return -1;
}
int IDescCompare(ClassDesc *desc1, ClassDesc *desc2);
void plComponentMgr::Register(ClassDesc *desc)
{
// Organize desc's by category and name
for (unsigned int i = 0; i < fDescs.size(); i++)
{
if (IDescCompare(desc, fDescs[i]) < 0)
{
fDescs.insert(&fDescs[i], desc);
return;
}
}
fDescs.push_back(desc);
}
int IDescCompare(ClassDesc *desc1, ClassDesc *desc2)
{
const char *cat1 = desc1->Category() ? desc1->Category() : "";
const char *cat2 = desc2->Category() ? desc2->Category() : "";
int cmp = strcmp(cat1, cat2);
// Only compare name if categories are the same
if (cmp == 0)
{
const char *name1 = desc1->ClassName() ? desc1->ClassName() : "";
const char *name2 = desc2->ClassName() ? desc2->ClassName() : "";
return strcmp(name1, name2);
}
return cmp;
}

View File

@ -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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_COMPONENTMGR_H
#define PL_COMPONENTMGR_H
#include "hsTypes.h"
#include "max.h"
#include "utilapi.h"
#include <vector>
using namespace std;
class ClassDesc2;
class Class_ID;
#define COMPONENT_MGR_CID Class_ID(0x5b870ba2, 0xb7b1da2)
//
// Manages the ClassDesc's for all components. Each component calls a macro that
// registers it with the component mgr. Then when Max loads the plugin the plugin
// enumeration functions call this to get all the registered ones. This saves us
// from having to go change those functions every time we add a new component.
//
// 8/28/01: Added globals -Colin
//
class hsResMgr;
class plFactory;
class plTimerCallbackManager;
class plTimerShare;
class plComponentMgr : public UtilityObj
{
private:
vector<ClassDesc*> fDescs;
plComponentMgr() {};
public:
static plComponentMgr &Inst();
// Required Max functions
virtual void BeginEditParams(Interface *ip,IUtil *iu) {}
virtual void EndEditParams(Interface *ip,IUtil *iu) {}
virtual void SelectionSetChanged(Interface *ip,IUtil *iu) {}
virtual void DeleteThis() {}
virtual UInt32 Count();
virtual ClassDesc *Get(UInt32 i);
virtual UInt32 FindClassID(Class_ID id);
// Registers a component. Only used by the classdesc macro.
virtual void Register(ClassDesc *desc);
};
#endif //PL_COMPONENTMGR_H

View File

@ -0,0 +1,138 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef __PLCOMPONENT_PROC_BASE_H__
#define __PLCOMPONENT_PROC_BASE_H__
#pragma warning(disable: 4786)
#include "Max.h"
#include "iparamm2.h"
#include <string>
#include <vector>
//
// Const Char* [] Version
//
class plBaseComponentProc : public ParamMap2UserDlgProc
{
protected:
void ILoadComboBox(HWND hComboBox, const char *names[])
{
SendMessage(hComboBox, CB_RESETCONTENT, 0, 0);
for (int i = 0; names[i]; i++)
SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)names[i]);
SendMessage(hComboBox, CB_SETCURSEL, 0, 0);
}
};
class plLCBoxComponentProc : public plBaseComponentProc
{
protected:
void ILoadListBox(HWND hListBox, IParamBlock2 *pb, int param, const char *names[])
{
SendMessage(hListBox, LB_RESETCONTENT, 0, 0);
for (int i = 0; i < pb->Count(param); i++)
{
int idx = pb->GetInt(param, 0, i);
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)names[idx]);
}
}
};
//
// VChar Version (Vector<string>)
//
typedef std::vector<std::string> VStringArray;
class plVSBaseComponentProc : public ParamMap2UserDlgProc
{
protected:
void ILoadComboBox(HWND hComboBox, VStringArray &names)
{
SendMessage(hComboBox, CB_RESETCONTENT, 0, 0);
int nNames = 0;
if(names.empty())
return;
else
nNames = names.size();
if(nNames)
for (int i = 0; i < nNames ; i++)
{
const char * name = names[i].c_str();
SendMessage(hComboBox, CB_INSERTSTRING, i, (LPARAM)name);
}
SendMessage(hComboBox, CB_SETCURSEL, 0, 0);
}
void ILoadListBox(HWND hListBox, VStringArray &names, int* GetItemVals, int NumVals)
{
SendMessage(hListBox, LB_RESETCONTENT, 0, 0);
for (int i = 0; i < names.size(); i++)
{
const char* c_name = names[i].c_str();
int idxptr = SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)c_name);
SendMessage(hListBox, LB_SETITEMDATA, (WPARAM) idxptr, (LPARAM) GetItemVals[i]);
}
}
};
#endif

View File

@ -0,0 +1,159 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_COMPONENT_REG_H
#define PL_COMPONENT_REG_H
#include "plComponentMgr.h"
class TargetValidator;
extern TargetValidator gTargetValidator;
enum { kTargs };
class plComponentClassDesc : public ClassDesc2
{
public:
int IsPublic() { return 0; }
SClass_ID SuperClassID() { return HELPER_CLASS_ID; }
HINSTANCE HInstance() { return hInstance; }
BOOL NeedsToSave() { return TRUE; }
virtual bool IsAutoUI() { return false; }
virtual bool IsObsolete() { return false; }
};
//
// This creates the class description for a component.
//
// classname - Name of a plComponent derived class (not a string)
// varname - Name for a static instance of this desc that will be declared
// longname - Public name for the modifier
// shortname - Internal name for the modifier. No spaces. Will be the prefix
// for the Max name of components of this type.
// category - Category this component will show up in in the helper panel. This
// is just a string, but the COMP_TYPE #defines below should be used
// to promote sharing
// id - Max ClassID for the component
//
// The ClassID will automatically be registered with the description manager.
//
#define CLASS_DESC(classname, varname, longname, shortname, category, id) \
class classname##ClassDesc : public plComponentClassDesc \
{ \
FUNC_CLASS_DESC(classname, longname, shortname, category, id) \
CONSTRUCT_DESC(classname) \
}; \
DECLARE_CLASS_DESC(classname, varname)
#define OBSOLETE_CLASS_DESC(classname, varname, longname, shortname, category, id) \
class classname##ClassDesc : public plComponentClassDesc \
{ \
FUNC_CLASS_DESC(classname, longname, shortname, category, id) \
CONSTRUCT_DESC(classname) \
virtual bool IsObsolete() { return true; } \
}; \
DECLARE_CLASS_DESC(classname, varname)
#define FUNC_CLASS_DESC(classname, longname, shortname, category, id) \
public: \
void* Create(BOOL loading) { return new classname##; } \
const TCHAR* ClassName() { return _T(longname); } \
Class_ID ClassID() { return id; } \
const TCHAR* Category() { return _T(category); } \
const TCHAR* InternalName() { return _T(shortname); }
#define CONSTRUCT_DESC(classname) \
classname##ClassDesc() { plComponentMgr::Inst().Register(this); }
#define DECLARE_CLASS_DESC(classname, varname) \
static classname##ClassDesc varname; \
TARG_BLOCK(classname, varname)
//
// OBSOLETE_CLASS macro
// Usually, when you're making a component obsolete, you don't want to bother with any
// class defs or paramBlock defs anymore, you just want them to all be empty. This
// macro simplifies that process greatly: just delete everything about your class
// EXCEPT the CLASS_DESC line, then change CLASS_DESC to OBSOLETE_CLASS. This macro
// will handle the rest for you! -mcn
//
#define OBSOLETE_CLASS( classname, descname, strname, sn, type, classid ) class classname : public plComponent { public: classname##(); hsBool Convert( plMaxNode *n, plErrorMsg *e ) { return true; } }; \
OBSOLETE_CLASS_DESC( classname, descname, strname, sn, type, classid ) \
classname##::##classname() { fClassDesc = &##descname##; fClassDesc->MakeAutoParamBlocks(this); } \
ParamBlockDesc2 classname##blk ( plComponent::kBlkComp, _T("##descname##"), 0, &##descname##, P_AUTO_CONSTRUCT, plComponent::kRefComp, end );
//
// Creates the targets paramblock for a component
//
#define TARG_BLOCK(classname, varname) \
static ParamBlockDesc2 g##classname##TargsBlock \
( \
plComponentBase::kBlkTargs, _T("targets"), 0, &varname, \
P_AUTO_CONSTRUCT, plComponentBase::kRefTargs, \
\
kTargs, _T("targets"), TYPE_INODE_TAB, 0, 0, 0, \
end, \
end \
);
// Component categories
#define COMP_TYPE_MISC "Misc"
#define COMP_TYPE_TYPE "Type"
#define COMP_TYPE_LOGIC "Logic"
#define COMP_TYPE_PHYSICAL "Physics"
#define COMP_TYPE_GRAPHICS "Render"
#define COMP_TYPE_WATER "Water"
#define COMP_TYPE_FOOTPRINT "FootPrint"
#define COMP_TYPE_SHADOW "Shadow"
#define COMP_TYPE_DISTRIBUTOR "Distributor"
#define COMP_TYPE_AUDIO "Audio"
#define COMP_TYPE_PARTICLE "Particle System"
#define COMP_TYPE_AVATAR "Avatar"
#define COMP_TYPE_DETECTOR "Detector"
#define COMP_TYPE_VOLUME "Region"
#define COMP_TYPE_IGNORE "Ignore"
#define COMP_TYPE_PHYS_CONSTRAINTS "Physic Constraints"
#define COMP_TYPE_PHYS_TERRAINS "Navigables"
#define COMP_TYPE_GUI "GUI"
#define COMP_TYPE_CAMERA "Camera"
#define COMP_TYPE_SHADERS "Vertex/Pixel Shaders"
#endif //PL_COMPONENT_REG_H

View File

@ -0,0 +1,86 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "max.h"
#include "../pnModifier/plModifier.h"
#include "plComponentTools.h"
plKey plComponentTools::AddModifier(plMaxNodeBase *node, plModifier *mod)
{
return fAddModFunc(node, mod);
}
plKey plComponentTools::GetNewKey(const char *name, plModifier *mod, plLocation loc)
{
return fNewKey(name, mod, loc);
}
void plComponentTools::SetActivatorKey(plMaxNodeBase *activatorNode, plMaxNodeBase *responderNode, plMaxNodeBase *convertNode, plResponderModifier *responderLogic)
{
fActivator(activatorNode, responderNode, convertNode, responderLogic);
}
plKey plComponentTools::GetAnimCompModKey(plComponentBase *comp, plMaxNodeBase *node)
{
return fAnimKey(comp, node);
}
/*
plKey plComponentTools::GetAnimCompLightModKey(plComponentBase *comp, plMaxNodeBase *node)
{
return fAnimLightKey(comp, node);
}
*/
const char *plComponentTools::GetAnimCompAnimName(plComponentBase *comp)
{
return fAnimName(comp);
}
int plComponentTools::GetMaterialAnimModKey(Mtl* mtl, plMaxNodeBase* node, const char *segName, hsTArray<plKey>& keys)
{
return fMatMod(mtl, node, segName, keys);
}
int plComponentTools::GetSoundNameAndIndex(plComponentBase* comp, plMaxNodeBase* node, const char*& name)
{
return fSndNameAndIdx(comp, node, name);
}

View File

@ -0,0 +1,116 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_COMPONENT_TOOLS_H
#define PL_COMPONENT_TOOLS_H
#include "hsTypes.h"
#include "hsTemplates.h"
#include "../pnKeyedObject/plKey.h"
class INode;
class plModifier;
class plKey;
class plLocation;
class plResponderModifier;
class plComponentBase;
class plMaxNodeBase;
typedef plKey (*PAddModFunc) (plMaxNodeBase *, plModifier *);
typedef plKey (*PGetNewKeyFunc) (const char*, plModifier*, plLocation);
typedef void (*PSetActivatorKeyFunc) (plMaxNodeBase*, plMaxNodeBase*, plMaxNodeBase*, plResponderModifier*);
typedef plKey (*PGetAnimModKeyFunc) (plComponentBase*, plMaxNodeBase*);
typedef const char* (*PGetAnimNameFunc) (plComponentBase*);
typedef int (*PGetMaterialAnimModKeyFunc) (Mtl* mtl, plMaxNodeBase* node, const char *segName, hsTArray<plKey>& keys);
typedef int (*PGetSoundNameAndIndex) (plComponentBase*, plMaxNodeBase* node, const char*& name);
//
// A "toolbox" for external components to do their conversion with. The idea
// is to give components the functions they need without pulling in every source
// file.
//
class plComponentTools
{
protected:
PAddModFunc fAddModFunc;
PGetNewKeyFunc fNewKey;
PSetActivatorKeyFunc fActivator;
PGetAnimModKeyFunc fAnimKey;
// PGetAnimModKeyFunc fAnimLightKey;
PGetAnimNameFunc fAnimName;
PGetMaterialAnimModKeyFunc fMatMod;
PGetSoundNameAndIndex fSndNameAndIdx;
plComponentTools() {}
public:
plComponentTools(PAddModFunc addMod,
PGetNewKeyFunc NewKey,
PSetActivatorKeyFunc activator,
PGetAnimModKeyFunc animKey,
// PGetAnimModKeyFunc animLightKey,
PGetAnimNameFunc animName,
PGetMaterialAnimModKeyFunc matMod,
PGetSoundNameAndIndex sndNameAndIdx)
: fAddModFunc(addMod),
fNewKey(NewKey),
fActivator(activator),
fAnimKey(animKey),
// fAnimLightKey(animLightKey),
fAnimName(animName),
fMatMod(matMod),
fSndNameAndIdx(sndNameAndIdx)
{}
plKey AddModifier(plMaxNodeBase *node, plModifier *mod);
plKey GetNewKey(const char *name, plModifier *mod, plLocation loc);
void SetActivatorKey(plMaxNodeBase *activatorNode, plMaxNodeBase *responderNode, plMaxNodeBase *convertNode, plResponderModifier *responderLogic);
const char *GetAnimCompAnimName(plComponentBase *comp);
plKey GetAnimCompModKey(plComponentBase *comp, plMaxNodeBase *node);
// plKey GetAnimCompLightModKey(plComponentBase *comp, plMaxNodeBase *node);
int GetMaterialAnimModKey(Mtl* mtl, plMaxNodeBase* node, const char *segName, hsTArray<plKey>& keys);
int GetSoundNameAndIndex(plComponentBase* comp, plMaxNodeBase* node, const char*& name);
};
#endif //PL_COMPONENT_TOOLS_H

View File

@ -0,0 +1,275 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "max.h"
#include "meshdlib.h"
#include "plDicer.h"
static const int kDefFaces = 200;
static const float kDefSize = 1000.f;
plDicer::plDicer()
: fMaxSize(kDefSize, kDefSize, kDefSize),
fMaxFaces(kDefFaces)
{
}
plDicer::~plDicer()
{
}
void plDicer::SetMaxSize(const Point3& size)
{
fMaxSize = size;
}
Point3 plDicer::GetMaxSize() const
{
return fMaxSize;
}
void plDicer::SetMaxFaces(int n)
{
fMaxFaces = n;
}
int plDicer::GetMaxFaces() const
{
return fMaxFaces;
}
BOOL plDicer::Dice(INode* node, INodeTab& out)
{
Object *obj = node->EvalWorldState(TimeValue(0)).obj;
if( !obj )
{
out.Append(1, &node);
return false;
}
if( !obj->CanConvertToType( triObjectClassID ) )
{
out.Append(1, &node);
return false;
}
// Convert to triMesh object
TriObject *meshObj = (TriObject*)obj->ConvertToType(TimeValue(0), triObjectClassID);
if( !meshObj )
{
out.Append(1, &node);
return false;
}
TriObject* newObj = CreateNewTriObject();
newObj->mesh = meshObj->mesh;
plTriObjectTab triList;
if( !IDiceIter(newObj, triList) )
{
delete newObj;
out.Append(1, &node);
return false;
}
IMakeIntoNodes(node, triList, out);
node->Delete(TimeValue(0), true);
return true;
}
BOOL plDicer::IDetach(TriObject* triObj, BitArray& faces, plTriObjectTab& triList)
{
TriObject* newObj = CreateNewTriObject();
Mesh* newMesh = &newObj->mesh;
MeshDelta meshDelta(triObj->mesh);
// meshDelta.Detach(Mesh & m, Mesh *out, BitArray fset, BOOL faces, BOOL del, BOOL elem);
meshDelta.Detach(triObj->mesh, newMesh, faces, true, true, false);
meshDelta.Apply(triObj->mesh);
if( newObj->mesh.getNumFaces() )
triList.Append(1, &newObj);
else
delete newObj;
if( triObj->mesh.getNumFaces() )
{
newObj = CreateNewTriObject();
newObj->mesh = triObj->mesh;
triList.Append(1, &newObj);
}
delete triObj;
return true;
}
BOOL plDicer::IHalf(TriObject* triObj, plTriObjectTab& triList)
{
Mesh& mesh = triObj->mesh;
BitArray faces(mesh.getNumFaces());
int iAxis = 0;
float maxDim = mesh.getBoundingBox().Width()[0];
if( mesh.getBoundingBox().Width()[1] > maxDim )
{
maxDim = mesh.getBoundingBox().Width()[1];
iAxis = 1;
}
if( mesh.getBoundingBox().Width()[2] > maxDim )
{
maxDim = mesh.getBoundingBox().Width()[2];
iAxis = 2;
}
float middle = mesh.getBoundingBox().Center()[iAxis];
int numHi = 0;
int i;
for( i = 0; i < mesh.getNumFaces(); i++ )
{
Point3 p[3];
p[0] = mesh.getVert(mesh.faces[i].getVert(0));
p[1] = mesh.getVert(mesh.faces[i].getVert(1));
p[2] = mesh.getVert(mesh.faces[i].getVert(2));
if( (p[0][iAxis] > middle)
&&(p[1][iAxis] > middle)
&&(p[2][iAxis] > middle) )
{
numHi++;
faces.Set(i);
}
}
if( !numHi || (numHi == mesh.getNumFaces()) )
return false;
return IDetach(triObj, faces, triList);
}
BOOL plDicer::IDice(TriObject* triObj, plTriObjectTab& triList)
{
int oneBigger = -1;
int oneSmaller = -1;
BOOL doChop = false;
// First, does he need chopping?
Mesh& mesh = triObj->mesh;
if( mesh.getNumFaces() > GetMaxFaces() )
{
doChop = true;
}
else
{
Box3 bnd = mesh.getBoundingBox();
Point3 wid = bnd.Width();
if( wid.x > GetMaxSize().x )
doChop = true;
if( wid.y > GetMaxSize().y )
doChop = true;
if( wid.z > GetMaxSize().z )
doChop = true;
}
if( !doChop )
return false;
// Okay, we got to chop.
return IHalf(triObj, triList);
}
BOOL plDicer::IDiceIter(TriObject* triObj, plTriObjectTab& triList)
{
triList.ZeroCount();
plTriObjectTab inList;
plTriObjectTab cutList;
inList.Append(1, &triObj);
while( inList.Count() )
{
int i;
for( i = 0; i < inList.Count(); i++ )
{
if( !IDice(inList[i], cutList) )
{
triList.Append(1, &inList[i]);
}
}
inList = cutList;
cutList.ZeroCount();
}
return triList.Count() > 0;
}
BOOL plDicer::IMakeIntoNodes(INode* node, plTriObjectTab& triList, INodeTab& out)
{
NameMaker *nn = GetCOREInterface()->NewNameMaker();
TSTR nodeName(node->GetName());
int i;
for( i = 0; i < triList.Count(); i++ )
{
INode* outNode = GetCOREInterface()->CreateObjectNode(triList[i]);
outNode->SetNodeTM(TimeValue(0), node->GetNodeTM(TimeValue(0)));
outNode->CopyProperties(node);
outNode->SetMtl(node->GetMtl());
outNode->SetObjOffsetPos(node->GetObjOffsetPos());
outNode->SetObjOffsetRot(node->GetObjOffsetRot());
outNode->SetObjOffsetScale(node->GetObjOffsetScale());
nn->MakeUniqueName(nodeName);
outNode->SetName(nodeName);
out.Append(1, &outNode);
}
return true;
}

View File

@ -0,0 +1,82 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plDicer_inc
#define plDicer_inc
class Point3;
class plTriObjectTab : public Tab<TriObject*>
{
};
class plDicer
{
protected:
int fMaxFaces;
Point3 fMaxSize;
BOOL IDetach(TriObject* triObj, BitArray& faces, plTriObjectTab& meshList);
BOOL IHalf(TriObject* triObj, plTriObjectTab& triList);
BOOL IDice(TriObject* triObj, plTriObjectTab& triList);
BOOL IDiceIter(TriObject* triObj, plTriObjectTab& triList);
BOOL IMakeIntoNodes(INode* node, plTriObjectTab& triList, INodeTab& out);
public:
plDicer();
virtual ~plDicer();
BOOL Dice(INode* node, INodeTab& out);
void SetMaxSize(const Point3& size);
Point3 GetMaxSize() const;
void SetMaxFaces(int n);
int GetMaxFaces() const;
};
#endif // plDicer_inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,225 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plDistribComponent_inc
#define plDistribComponent_inc
const Class_ID DISTRIBUTOR_COMP_CID(0x78143984, 0x3e7c78ec);
#include "../MaxConvert/plDistributor.h"
class plMaxNode;
class plDistributor;
class plDistribInstTab;
class plExportProgressBar;
class plDistTree;
//Class that accesses the paramblock below.
class plDistribComponent : public plComponent
{
public:
enum
{
kRollTemplates,
kRollSpacing,
kRollScale,
kRollOrient,
kRollAngProb,
kRollAltProb,
kRollConform,
kRollBitmap,
kRollFade,
kRollWind,
kRollRandomize,
kRollAction,
kNumRollups
};
enum
{
kTemplates = 0,
// Spacing
kSpacing,
kSpaceRnd,
kDensity,
kSeparation,
// Scale
kScaleLoX,
kScaleLoY,
kScaleLoZ,
kScaleHiX,
kScaleHiY,
kScaleHiZ,
kLockScaleXY,
kLockScaleXYZ,
// Orient
kAlignWgt,
kPolarRange,
kAzimuthRange,
kPolarBunch,
// Angle prob
kAngProbHi,
kAngProbLo,
kAngProbTrans,
// Altitude prob
kAltProbHi,
kAltProbLo,
kAltProbTrans,
// Surface Conformity
kConformType,
kConformMax,
kOffsetMin,
kOffsetMax,
// Bitmap
kProbTexmap,
kProbColorChan,
kRemapFromLo,
kRemapFromHi,
kRemapToLo,
kRemapToHi,
// Fade
kFadeInTran,
kFadeInOpaq,
kFadeOutTran,
kFadeOutOpaq,
kFadeInActive,
// Wind
kWindBone,
kWindBoneActive,
// Randomization
kSeedLocked,
kSeed,
kNextSeed,
// Etc.
kReplicants,
kRollupState,
kFaceNormals,
kNumParams
};
plMeshCacheTab fDistCache;
void ISetProbTexmap(plDistributor& distrib);
INode* IMakeOne(plDistribInstTab& nodes);
BOOL IValidateFade(Box3& fade);
public:
plDistribComponent();
void DeleteThis() { delete this; }
BOOL Distribute(plDistribInstTab& reps, plErrorMsg* pErrMsg, plExportProgressBar& bar, plDistTree* dt=nil);
void Done();
void Clear();
void Preview();
// See notes below
Box3 GetFade();
BOOL IsFlexible() const;
float GetIsoPriority() const;
plDistributor::IsoType GetIsolation() const;
plDistributor::ColorChan GetProbabilityChan() const;
plDistributor::ConformType GetConformity() const;
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
};
// GetFade() notes.
// Fade returned as follows:
// Box3.Min()[0] == fadeInTransparent
// Box3.Min()[1] == fadeInOpaque
// Box3.Max()[0] == fadeOutTransparent
// Box3.Max()[1] == fadeOutOpaque
//
// Box3.Min()[2] == 0 turns off fadein.
// Box3.Max()[2] == 0 turns off fadeout.
//
// In all cases, max(Min()[0],Min()[1]) <= min(Max()[0], Max()[1])
//
// Also, either Min()[0] <= Min()[1] && Max()[0] >= Max()[1]
// or Min()[0] >= Min()[1] && Max()[0] <= Max()[1]
// that is, we either start transparent, go to opaque and back to transparent,
// or we start opaque, go transparent, and back to opaque.
// Makes sense if you think about it.
//
// If Min()[0] == Min()[1], there is no fade in, we start transparent or opaque
// as determined by Max()[0] and Max()[1].
// Same for equal Maxs.
// Naturally, Min()[0] == Min()[1] && Max()[0] == Max()[1] turns the whole thing off.
//
// Also, as a convenience, if the transparent distance is less than the opaque distance
// (signifying a fade out), then the Z component will be -1, else if it's off, zero, else 1.
// In Summario:
// if( box.Min()[0] < box.Min()[1] ) // Transparent less than Opaque
// box.Min()[2] = -1.f;
// else if( box.Min()[0] == box.Min()[1] ) // Tran same as Opaque, disabled
// box.Min()[2] = 0;
// else // Leaves Opaque less than Transparent.
// box.Min()[2] = 1.f;
#endif // plDistribComponent_inc

View File

@ -0,0 +1,891 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "hsWindows.h"
#include <commdlg.h>
#include "max.h"
#include "meshdlib.h"
#include "stdmat.h"
#include "bmmlib.h"
#include "resource.h"
#include "plComponent.h"
#include "plComponentReg.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxExport/plExportProgressBar.h"
#include "../MaxPlasmaMtls/Layers/plLayerTex.h"
#include "hsTypes.h"
#include "../MaxConvert/plDistributor.h"
#include "../MaxConvert/plDistTree.h" // FISH HACK - just testing
#include "plDistribComponent_old.h"
static const int kNumColorChanOptions = 13;
struct plProbChanStringValPair
{
plDistributor::ColorChan fValue;
const char* fString;
};
static plProbChanStringValPair kProbColorChanStrings[kNumColorChanOptions] =
{
{ plDistributor::kRed, "Red" },
{ plDistributor::kGreen, "Green" },
{ plDistributor::kBlue, "Blue" },
{ plDistributor::kAlpha, "Alpha" },
{ plDistributor::kAverageRedGreen, "Avg(R,G)" },
{ plDistributor::kAverageRedGreenTimesAlpha, "Avg(R,G)xA" },
{ plDistributor::kAverage, "Avg(R,G,B)" },
{ plDistributor::kAverageTimesAlpha, "Avg(R,G,B)xA" },
{ plDistributor::kMax, "Max(R,G,B)" },
{ plDistributor::kMaxColor, "Max(R,G,B)" },
{ plDistributor::kMaxColorTimesAlpha, "Max(R,G,B)xA" },
{ plDistributor::kMaxRedGreen, "Max(R,G)" },
{ plDistributor::kMaxRedGreenTimesAlpha, "Max(R,G)xA" }
};
void DummyCodeIncludeFuncDistrib_old()
{
}
/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
class plDistribComponentProc_old : public ParamMap2UserDlgProc
{
private:
void ISetupScaleLock(IParamMap2* map, BOOL onInit=false)
{
IParamBlock2 *pb = map->GetParamBlock();
if( pb->GetInt(plDistribComponent_old::kLockScaleXYZ) )
{
map->Enable(plDistribComponent_old::kLockScaleXY, FALSE);
map->Enable(plDistribComponent_old::kScaleLoY, FALSE);
map->Enable(plDistribComponent_old::kScaleHiY, FALSE);
map->Enable(plDistribComponent_old::kScaleLoZ, FALSE);
map->Enable(plDistribComponent_old::kScaleHiZ, FALSE);
}
else if( pb->GetInt(plDistribComponent_old::kLockScaleXY) )
{
map->Enable(plDistribComponent_old::kLockScaleXY, TRUE);
map->Enable(plDistribComponent_old::kScaleLoY, FALSE);
map->Enable(plDistribComponent_old::kScaleHiY, FALSE);
map->Enable(plDistribComponent_old::kScaleLoZ, TRUE);
map->Enable(plDistribComponent_old::kScaleHiZ, TRUE);
}
else
{
map->Enable(plDistribComponent_old::kLockScaleXY, TRUE);
map->Enable(plDistribComponent_old::kScaleLoY, TRUE);
map->Enable(plDistribComponent_old::kScaleHiY, TRUE);
map->Enable(plDistribComponent_old::kScaleLoZ, TRUE);
map->Enable(plDistribComponent_old::kScaleHiZ, TRUE);
}
if( onInit )
{
map->SetTooltip(plDistribComponent_old::kLockScaleXY, TRUE, "Lock scale in X and Y" );
map->SetTooltip(plDistribComponent_old::kLockScaleXYZ, TRUE, "Lock scale in X, Y and Z (uniform scale)" );
}
}
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HWND cbox = NULL;
switch (msg)
{
case WM_INITDIALOG:
cbox = GetDlgItem(hWnd, IDC_COMP_DISTRIB_PROBCOLORCHAN);
int i;
for( i = 0; i < kNumColorChanOptions; i++ )
{
SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)kProbColorChanStrings[i].fString);
}
SendMessage(cbox, CB_SETCURSEL, map->GetParamBlock()->GetInt(plDistribComponent_old::kProbColorChan), 0);
ISetupScaleLock(map, true);
return TRUE;
case WM_COMMAND:
if( (HIWORD(wParam) == BN_CLICKED) && (LOWORD(wParam) == IDC_DISTRIB_CLEAR) )
{
plDistribComponent_old* dc = (plDistribComponent_old*)map->GetParamBlock()->GetOwner();
dc->Clear();
return TRUE;
}
switch( LOWORD(wParam) )
{
case IDC_COMP_DISTRIB_PROBCOLORCHAN:
{
map->GetParamBlock()->SetValue(plDistribComponent_old::kProbColorChan, t, SendMessage(GetDlgItem(hWnd, LOWORD(wParam)), CB_GETCURSEL, 0, 0));
return TRUE;
}
break;
case IDC_COMP_DISTRIB_FADEINACTIVE:
case IDC_COMP_DISTRIB_FADEINTRAN:
case IDC_COMP_DISTRIB_FADEINOPAQ:
case IDC_COMP_DISTRIB_FADEOUTTRAN:
case IDC_COMP_DISTRIB_FADEOUTOPAQ:
case IDC_COMP_DISTRIB_FADEINTRAN_SPIN:
case IDC_COMP_DISTRIB_FADEINOPAQ_SPIN:
case IDC_COMP_DISTRIB_FADEOUTTRAN_SPIN:
case IDC_COMP_DISTRIB_FADEOUTOPAQ_SPIN:
{
plDistribComponent_old* dc = (plDistribComponent_old*)map->GetParamBlock()->GetOwner();
Box3 fade;
if( !dc->IValidateFade(fade) )
{
map->GetParamBlock()->SetValue(plDistribComponent_old::kFadeInTran, t, fade.Min()[0]);
map->GetParamBlock()->SetValue(plDistribComponent_old::kFadeInOpaq, t, fade.Min()[1]);
map->GetParamBlock()->SetValue(plDistribComponent_old::kFadeOutTran, t, fade.Max()[0]);
map->GetParamBlock()->SetValue(plDistribComponent_old::kFadeOutOpaq, t, fade.Max()[1]);
map->Invalidate(plDistribComponent_old::kFadeInTran);
map->Invalidate(plDistribComponent_old::kFadeInOpaq);
map->Invalidate(plDistribComponent_old::kFadeOutTran);
map->Invalidate(plDistribComponent_old::kFadeOutOpaq);
ShowWindow(hWnd, SW_HIDE);
ShowWindow(hWnd, SW_SHOW);
}
return TRUE;
}
break;
#if 0 // Obsolete, now kRndPosRadius is percentage of kSpacing
case IDC_COMP_DISTRIB_RNDPOSRADIUS:
case IDC_COMP_DISTRIB_RNDPOSRADIUS_SPIN:
{
IParamBlock2 *pb = map->GetParamBlock();
float maxRndPosRad = pb->GetFloat(plDistribComponent_old::kSpacing) * 0.5f;
if( pb->GetFloat(plDistribComponent_old::kRndPosRadius) > maxRndPosRad )
{
pb->SetValue(plDistribComponent_old::kRndPosRadius, t, maxRndPosRad);
map->Invalidate(plDistribComponent_old::kRndPosRadius);
ShowWindow(hWnd, SW_HIDE);
ShowWindow(hWnd, SW_SHOW);
}
return TRUE;
}
#endif // Obsolete, now kRndPosRadius is percentage of kSpacing
case IDC_COMP_DISTRIB_LOCKSCALEXY:
case IDC_COMP_DISTRIB_LOCKSCALEXYZ:
ISetupScaleLock(map, false);
return TRUE;
}
break;
}
return false;
}
void DeleteThis() {}
};
static plDistribComponentProc_old gDistribCompProc_old;
//Max desc stuff necessary below.
OBSOLETE_CLASS_DESC(plDistribComponent_old, gDistribCompDesc_old, "Distributor(old)", "Distributor(old)", COMP_TYPE_DISTRIBUTOR, DISTRIBUTOR_COMP_CID_OLD)
class plDistribCompAccessor_old : public PBAccessor
{
public:
void Set(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
if( id == plDistribComponent_old::kTemplates )
{
plDistribComponent_old* comp = (plDistribComponent_old*)owner;
comp->NotifyDependents(FOREVER, PART_ALL, REFMSG_USER_COMP_REF_CHANGED);
}
}
};
plDistribCompAccessor_old gDistribCompAccessor_old;
ParamBlockDesc2 gDistributorBk_old
( // KLUDGE: not the defined block ID, but kept for backwards compat.
plComponent::kBlkComp, _T("Distributor_old"), 0, &gDistribCompDesc_old, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_DISTRIBUTOR, IDS_COMP_DISTRIBUTORS, 0, 0, &gDistribCompProc_old,
plDistribComponent_old::kTemplates, _T("Templates"), TYPE_INODE_TAB, 0, P_CAN_CONVERT, 0,
p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, IDC_ADD_TARGS, 0, IDC_DEL_TARGS,
p_classID, triObjectClassID,
p_accessor, &gDistribCompAccessor_old,
end,
plDistribComponent_old::kSpacing, _T("Spacing"), TYPE_FLOAT, 0, 0,
p_default, 10.0,
p_range, 0.1, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_SPACING, IDC_COMP_DISTRIB_SPACING_SPIN, 1.0,
end,
plDistribComponent_old::kRndPosRadius, _T("Space Range"), TYPE_FLOAT, 0, 0,
p_default, 50.0,
p_range, 0.0, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_RNDPOSRADIUS, IDC_COMP_DISTRIB_RNDPOSRADIUS_SPIN, 1.0,
end,
plDistribComponent_old::kAlignVecX, _T("AlignX"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -1.f, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_COMP_DISTRIB_ALIGNVECX, IDC_COMP_DISTRIB_ALIGNVECX_SPIN, 0.1,
end,
plDistribComponent_old::kAlignVecY, _T("AlignY"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -1.f, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_COMP_DISTRIB_ALIGNVECY, IDC_COMP_DISTRIB_ALIGNVECY_SPIN, 0.1,
end,
plDistribComponent_old::kAlignVecZ, _T("AlignZ"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, -1.f, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_COMP_DISTRIB_ALIGNVECZ, IDC_COMP_DISTRIB_ALIGNVECZ_SPIN, 0.1,
end,
plDistribComponent_old::kAlignWgt, _T("Align Weight"), TYPE_FLOAT, 0, 0,
p_default, 50.0,
p_range, 0.0, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_ALIGNWGT, IDC_COMP_DISTRIB_ALIGNWGT_SPIN, 1.0,
end,
plDistribComponent_old::kPolarRange, _T("Normal Range (Deg)"), TYPE_FLOAT, 0, 0,
p_default, 15.0,
p_range, 0.0, 180.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_POLARRANGE, IDC_COMP_DISTRIB_POLARRANGE_SPIN, 1.0,
end,
plDistribComponent_old::kAzimuthRange, _T("Normal Range (Deg)"), TYPE_FLOAT, 0, 0,
p_default, 180.0,
p_range, 0.0, 180.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_AZIMUTHRANGE, IDC_COMP_DISTRIB_AZIMUTHRANGE_SPIN, 1.0,
end,
plDistribComponent_old::kOverallProb, _T("Overall Probability"), TYPE_FLOAT, 0, 0,
p_default, 100.0,
p_range, 1., 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_OVERALLPROB, IDC_COMP_DISTRIB_OVERALLPROB_SPIN, 1.0,
end,
plDistribComponent_old::kPolarBunch, _T("Normal Bunching"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.0, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_POLARBUNCH, IDC_COMP_DISTRIB_POLARBUNCH_SPIN, 1.0,
end,
plDistribComponent_old::kScaleLoX, _T("ScaleMinX"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_SCALELOX, IDC_COMP_DISTRIB_SCALELOX_SPIN, 1.0,
end,
plDistribComponent_old::kScaleLoY, _T("ScaleMinY"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_SCALELOY, IDC_COMP_DISTRIB_SCALELOY_SPIN, 1.0,
end,
plDistribComponent_old::kScaleLoZ, _T("ScaleMinZ"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_SCALELOZ, IDC_COMP_DISTRIB_SCALELOZ_SPIN, 1.0,
end,
plDistribComponent_old::kScaleHiX, _T("ScaleMaxX"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_SCALEHIX, IDC_COMP_DISTRIB_SCALEHIX_SPIN, 1.0,
end,
plDistribComponent_old::kScaleHiY, _T("ScaleMaxY"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_SCALEHIY, IDC_COMP_DISTRIB_SCALEHIY_SPIN, 1.0,
end,
plDistribComponent_old::kScaleHiZ, _T("ScaleMaxZ"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.1, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_SCALEHIZ, IDC_COMP_DISTRIB_SCALEHIZ_SPIN, 1.0,
end,
plDistribComponent_old::kReplicants, _T("Replicants"), TYPE_INODE_TAB, 0, 0, 0,
p_accessor, &gDistribCompAccessor_old,
end,
plDistribComponent_old::kProbTexmap, _T("ProbTexmap"), TYPE_TEXMAP, 0, 0,
p_ui, TYPE_TEXMAPBUTTON, IDC_COMP_DISTRIB_PROBTEXMAP,
end,
plDistribComponent_old::kProbColorChan, _T("ProbColorChan"), TYPE_INT, 0, 0,
p_default, 0,
end,
plDistribComponent_old::kSeedLocked, _T("Locked"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_DISTRIB_LOCK,
end,
plDistribComponent_old::kSeed, _T("Seed"), TYPE_INT, 0, 0,
p_default, 1,
end,
plDistribComponent_old::kNextSeed, _T("NextSeed"), TYPE_INT, 0, 0,
p_default, 1,
end,
plDistribComponent_old::kRemapFromLo, _T("RemapFromLo"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.0, 255.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_REMAPFROMLO, IDC_COMP_DISTRIB_REMAPFROMLO_SPIN, 1.0,
end,
plDistribComponent_old::kRemapFromHi, _T("RemapFromHi"), TYPE_FLOAT, 0, 0,
p_default, 255.0,
p_range, 0.0, 255.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_REMAPFROMHI, IDC_COMP_DISTRIB_REMAPFROMHI_SPIN, 1.0,
end,
plDistribComponent_old::kRemapToLo, _T("RemapToLo"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.0, 255.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_REMAPTOLO, IDC_COMP_DISTRIB_REMAPTOLO_SPIN, 1.0,
end,
plDistribComponent_old::kRemapToHi, _T("RemapToHi"), TYPE_FLOAT, 0, 0,
p_default, 255.0,
p_range, 0.0, 255.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_REMAPTOHI, IDC_COMP_DISTRIB_REMAPTOHI_SPIN, 1.0,
end,
plDistribComponent_old::kAngProbX, _T("AngProbX"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -1.f, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_COMP_DISTRIB_ANGPROBX, IDC_COMP_DISTRIB_ANGPROBX_SPIN, 0.1,
end,
plDistribComponent_old::kAngProbY, _T("AngProbY"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -1.f, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_COMP_DISTRIB_ANGPROBY, IDC_COMP_DISTRIB_ANGPROBY_SPIN, 0.1,
end,
plDistribComponent_old::kAngProbZ, _T("AngProbZ"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, -1.f, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_COMP_DISTRIB_ANGPROBZ, IDC_COMP_DISTRIB_ANGPROBZ_SPIN, 0.1,
end,
plDistribComponent_old::kAngProbHi, _T("AngProbHi"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.0, 180.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_ANGPROBHI, IDC_COMP_DISTRIB_ANGPROBHI_SPIN, 1.0,
end,
plDistribComponent_old::kAngProbLo, _T("AngProbLo"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.0, 180.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_ANGPROBLO, IDC_COMP_DISTRIB_ANGPROBLO_SPIN, 1.0,
end,
plDistribComponent_old::kFadeInTran, _T("FadeInTran"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_FADEINTRAN, IDC_COMP_DISTRIB_FADEINTRAN_SPIN, 1.0,
end,
plDistribComponent_old::kFadeInOpaq, _T("FadeInOpaq"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_FADEINOPAQ, IDC_COMP_DISTRIB_FADEINOPAQ_SPIN, 1.0,
end,
plDistribComponent_old::kFadeOutTran, _T("FadeOutTran"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_FADEOUTTRAN, IDC_COMP_DISTRIB_FADEOUTTRAN_SPIN, 1.0,
end,
plDistribComponent_old::kFadeOutOpaq, _T("FadeOutOpaq"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTRIB_FADEOUTOPAQ, IDC_COMP_DISTRIB_FADEOUTOPAQ_SPIN, 1.0,
end,
plDistribComponent_old::kFadeInActive, _T("FadeInActive"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_DISTRIB_FADEINACTIVE,
p_enable_ctrls, 2, plDistribComponent_old::kFadeInTran, plDistribComponent_old::kFadeInOpaq,
end,
plDistribComponent_old::kWindBone, _T("WindBone"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_DISTRIB_WINDBONE,
p_prompt, IDS_COMP_CLUSTER_CHOSE_WINDBONE,
end,
plDistribComponent_old::kLockScaleXY, _T("LockScaleXY"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_DISTRIB_LOCKSCALEXY,
end,
plDistribComponent_old::kLockScaleXYZ, _T("LockScaleXYZ"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_DISTRIB_LOCKSCALEXYZ,
end,
plDistribComponent_old::kWindBoneActive, _T("WindBoneActive"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_DISTRIB_WINDBONEACTIVE,
p_enable_ctrls, 1, plDistribComponent_old::kWindBone,
end,
// Make this a combo box in real gig.
plDistribComponent_old::kIsolation, _T("Isolation"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_COMP_DISTRIB_ISOLATION, IDC_COMP_DISTRIB_ISOLATION_SPIN, 0.4,
// p_range, 0, 3,
// p_default, 1,
end,
end
);
plDistribComponent_old::plDistribComponent_old()
{
fClassDesc = &gDistribCompDesc_old;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plDistribComponent_old::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg)
{
int numReps = fCompPB->Count(kTemplates);
int i;
for( i = 0; i < numReps; i++ )
{
plMaxNodeBase* temp = (plMaxNodeBase*)fCompPB->GetINode(kTemplates, TimeValue(0), i);
if( temp )
temp->SetCanConvert(false);
}
return true;
}
BOOL plDistribComponent_old::Distribute(plDistribInstTab& replicants, plExportProgressBar& bar, plDistTree* distTree)
{
return false;
BOOL retVal = true;
GetCOREInterface()->DisableSceneRedraw();
Clear();
plDistributor distrib;
distrib.SetTheInterface(GetCOREInterface());
distrib.SetSpacing(fCompPB->GetFloat(kSpacing));
distrib.SetSpacingRange(fCompPB->GetFloat(kRndPosRadius) * 0.01f * distrib.GetSpacing() * 0.5f);
Point3 align(fCompPB->GetFloat(kAlignVecX), fCompPB->GetFloat(kAlignVecY), fCompPB->GetFloat(kAlignVecZ));
align.FNormalize();
distrib.SetAlignmentVec(align);
distrib.SetAlignmentWeight(fCompPB->GetFloat(kAlignWgt));
distrib.SetPolarRange(fCompPB->GetFloat(kPolarRange));
distrib.SetAzimuthRange(fCompPB->GetFloat(kAzimuthRange));
distrib.SetOverallProb(fCompPB->GetFloat(kOverallProb));
distrib.SetPolarBunch(fCompPB->GetFloat(kPolarBunch));
Point3 scaleLo(fCompPB->GetFloat(kScaleLoX), fCompPB->GetFloat(kScaleLoY), fCompPB->GetFloat(kScaleLoZ));
Point3 scaleHi(fCompPB->GetFloat(kScaleHiX), fCompPB->GetFloat(kScaleHiY), fCompPB->GetFloat(kScaleHiZ));
distrib.SetScaleRange(scaleLo, scaleHi);
ULONG scaleLock = plDistributor::kLockNone;
if( fCompPB->GetInt(kLockScaleXYZ) )
scaleLock = plDistributor::kLockX | plDistributor::kLockY | plDistributor::kLockZ;
else if( fCompPB->GetInt(kLockScaleXY) )
scaleLock = plDistributor::kLockX | plDistributor::kLockY;
distrib.SetScaleLock(scaleLock);
distrib.SetProbabilityChan(kProbColorChanStrings[fCompPB->GetInt(kProbColorChan)].fValue);
ISetProbTexmap(distrib);
// Setup the new params here. FISH...
Point3 probVec(fCompPB->GetFloat(kAngProbX), fCompPB->GetFloat(kAngProbY), fCompPB->GetFloat(kAngProbZ));
distrib.SetAngleProbVec(probVec);
distrib.SetAngleProbHi(fCompPB->GetFloat(kAngProbHi));
distrib.SetAngleProbLo(fCompPB->GetFloat(kAngProbLo));
distrib.SetProbabilityRemapFromLo(fCompPB->GetFloat(kRemapFromLo));
distrib.SetProbabilityRemapFromHi(fCompPB->GetFloat(kRemapFromHi));
distrib.SetProbabilityRemapToLo(fCompPB->GetFloat(kRemapToLo));
distrib.SetProbabilityRemapToHi(fCompPB->GetFloat(kRemapToHi));
if( !fCompPB->GetInt(kSeedLocked) )
fCompPB->SetValue(kSeed, TimeValue(0), fCompPB->GetInt(kNextSeed));
distrib.SetRandSeed(fCompPB->GetInt(kSeed));
distrib.SetFade(GetFade());
if( fCompPB->GetInt(kWindBoneActive) )
distrib.SetBone(fCompPB->GetINode(kWindBone));
distrib.SetRigid(!IsFlexible());
// FISH HACK, get this passed in from Cluster
distrib.SetDistTree(distTree);
distrib.SetIsolation(GetIsolation());
int numReps = fCompPB->Count(kTemplates);
int i;
for( i = 0; i < numReps; i++ )
{
INode* temp = fCompPB->GetINode(kTemplates, TimeValue(0), i);
if( temp )
distrib.AddReplicateNode(temp);
}
int numTarg = NumTargets();
for( i = 0; i < numTarg; i++ )
{
if( GetTarget(i) )
{
if( !distrib.Distribute(GetTarget(i), replicants, fDistCache, bar) )
{
retVal = false;
break;
}
}
}
fCompPB->SetValue(kNextSeed, TimeValue(0), int(distrib.GetRandSeed()));
BOOL redrawDissed = GetCOREInterface()->IsSceneRedrawDisabled();
GetCOREInterface()->EnableSceneRedraw();
GetCOREInterface()->ForceCompleteRedraw(FALSE);
return retVal;
}
void plDistribComponent_old::Done()
{
int i;
for( i = 0; i < fDistCache.Count(); i++ )
{
delete fDistCache[i].fMesh;
}
fDistCache.ZeroCount();
}
BOOL plDistribComponent_old::IsFlexible() const
{
int numReps = fCompPB->Count(kTemplates);
int i;
for( i = 0; i < numReps; i++ )
{
plMaxNode* temp = (plMaxNode*)fCompPB->GetINode(kTemplates, TimeValue(0), i);
if( temp )
{
if( temp->GetFlexibility()[0] > 0 )
return true;
}
}
return false;
}
void plDistribComponent_old::ISetProbTexmap(plDistributor& distrib)
{
distrib.SetProbabilityBitmapTex(nil);
Texmap* tex = fCompPB->GetTexmap(kProbTexmap);
if( tex )
{
BitmapTex* bmt = GetIBitmapTextInterface(tex);
if( bmt )
distrib.SetProbabilityBitmapTex(bmt);
else if( tex->ClassID() == LAYER_TEX_CLASS_ID )
distrib.SetProbabilityLayerTex((plLayerTex*)tex);
}
}
float plDistribComponent_old::GetIsoPriority() const
{
float pri = fCompPB->GetFloat(kSpacing);
pri *= pri;
pri *= fCompPB->GetFloat(kOverallProb) * 0.01f;
return pri;
}
plDistributor::IsoType plDistribComponent_old::GetIsolation() const
{
return (plDistributor::IsoType)fCompPB->GetInt(kIsolation);
}
void plDistribComponent_old::Clear()
{
GetCOREInterface()->DisableSceneRedraw();
// First, clear out any we've already done.
int numReps = fCompPB->Count(kReplicants);
int i;
for( i = 0; i < numReps; i++ )
{
INode* rep = fCompPB->GetINode(kReplicants, TimeValue(0), i);
if( rep )
rep->Delete(TimeValue(0), true);
}
fCompPB->ZeroCount(kReplicants);
GetCOREInterface()->EnableSceneRedraw();
GetCOREInterface()->ForceCompleteRedraw(FALSE);
}
void plDistribComponent_old::Preview()
{
if( !NumTargets() )
return;
GetCOREInterface()->DisableSceneRedraw();
plDistribInstTab replicants;
plExportProgressBar bar;
bar.Start("Preview", NumTargets() << 4);
plDistTree distTree;
Distribute(replicants, bar, &distTree);
IMakeOne(replicants);
Done();
GetCOREInterface()->EnableSceneRedraw();
GetCOREInterface()->ForceCompleteRedraw(FALSE);
}
INode* plDistribComponent_old::IMakeOne(plDistribInstTab& nodes)
{
if( !nodes.Count() )
return nil;
int iStartNode = 0;
NameMaker *nn = GetCOREInterface()->NewNameMaker();
while( iStartNode < nodes.Count() )
{
TriObject* triObj = CreateNewTriObject();
Mesh* outMesh = &triObj->mesh;
*outMesh = *nodes[iStartNode].fMesh;
INode *outNode = GetCOREInterface()->CreateObjectNode(triObj);
Matrix3 l2w = nodes[0].fObjectTM;
Matrix3 w2l = Inverse(l2w);
MeshDelta meshDelta(*outMesh);
int i;
for( i = iStartNode; i < nodes.Count(); i++ )
{
Mesh* nextMesh = nodes[i].fMesh;
Matrix3 relativeTransform = nodes[i].fObjectTM * w2l;
meshDelta.AttachMesh(*outMesh, *nextMesh, relativeTransform, 0);
meshDelta.Apply(*outMesh);
const int kFaceCutoff = 1000;
if( outMesh->getNumFaces() > kFaceCutoff )
break;
}
iStartNode = i;
outNode->SetNodeTM(TimeValue(0), l2w);
outNode->CopyProperties(nodes[0].fNode);
outNode->SetMtl(nodes[0].fNode->GetMtl());
outNode->SetObjOffsetPos(Point3(0,0,0));
Quat identQuat;
identQuat.Identity();
outNode->SetObjOffsetRot(identQuat);
outNode->SetObjOffsetScale(ScaleValue(Point3(1.f, 1.f, 1.f)));
TSTR outName(TSTR("Preview"));
nn->MakeUniqueName(outName);
outNode->SetName(outName);
fCompPB->Append(kReplicants, 1, &outNode);
}
return nil;
}
Box3 plDistribComponent_old::GetFade()
{
Point3 pmin;
if( fCompPB->GetInt(kFadeInActive) )
{
pmin.Set(fCompPB->GetFloat(kFadeInTran), fCompPB->GetFloat(kFadeInOpaq), 0);
if( pmin[0] == pmin[1] )
pmin[2] = 0;
else if( pmin[0] < pmin[1] )
pmin[2] = -1.f;
else
pmin[2] = 1.f;
}
else
{
pmin.Set(0.f,0.f,0.f);
}
Point3 pmax;
pmax.Set(fCompPB->GetFloat(kFadeOutTran), fCompPB->GetFloat(kFadeOutOpaq), 0);
if( pmax[0] == pmax[1] )
pmax[2] = 0;
else if( pmax[0] < pmax[1] )
pmax[2] = -1.f;
else
pmax[2] = 1.f;
return Box3(pmin, pmax);
}
BOOL plDistribComponent_old::IValidateFade(Box3& fade)
{
BOOL retVal = true;
fade = GetFade();
if( fCompPB->GetInt(kFadeInActive) )
{
if( fade.Max()[0] < fade.Max()[1] )
{
if( fade.Min()[0] > fade.Max()[0] )
{
fade.pmin[0] = fade.Max()[0];
retVal = false;
}
if( fade.Min()[1] > fade.Min()[0] )
{
fade.pmin[1] = fade.Min()[0];
retVal = false;
}
}
else if( fade.Max()[0] > fade.Max()[1] )
{
if( fade.Min()[1] > fade.Max()[1] )
{
fade.pmin[1] = fade.Max()[1];
retVal = false;
}
if( fade.Min()[0] > fade.Min()[1] )
{
fade.pmin[0] = fade.Min()[1];
retVal = false;
}
}
}
return retVal;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,183 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plDistribComponent_inc
#define plDistribComponent_inc
const Class_ID DISTRIBUTOR_COMP_CID_OLD(0x490b247f, 0x56f60a0e);
#include "../MaxConvert/plDistributor.h"
class plMaxNode;
class plDistributor;
class plDistribInstTab;
class plExportProgressBar;
class plDistTree;
//Class that accesses the paramblock below.
class plDistribComponent_old : public plComponent
{
public:
enum
{
kTemplates = 0,
kSpacing,
kRndPosRadius,
kAlignVecX,
kAlignVecY,
kAlignVecZ,
kAlignWgt,
kPolarRange,
kAzimuthRange,
kOverallProb,
kPolarBunch,
kScaleLoX,
kScaleLoY,
kScaleLoZ,
kScaleHiX,
kScaleHiY,
kScaleHiZ,
kReplicants,
kProbTexmap,
kProbColorChan,
kSeedLocked,
kSeed,
kNextSeed,
kRemapFromLo,
kRemapFromHi,
kRemapToLo,
kRemapToHi,
kAngProbX,
kAngProbY,
kAngProbZ,
kAngProbHi,
kAngProbLo,
kFadeInTran,
kFadeInOpaq,
kFadeOutTran,
kFadeOutOpaq,
kFadeInActive,
kWindBone,
kLockScaleXY,
kLockScaleXYZ,
kWindBoneActive,
kIsolation,
kNumParams
};
plMeshCacheTab fDistCache;
void ISetProbTexmap(plDistributor& distrib);
INode* IMakeOne(plDistribInstTab& nodes);
BOOL IValidateFade(Box3& fade);
public:
plDistribComponent_old();
void DeleteThis() { delete this; }
BOOL Distribute(plDistribInstTab& reps, plExportProgressBar& bar, plDistTree* dt=nil);
void Done();
void Clear();
void Preview();
// See notes below
Box3 GetFade();
BOOL IsFlexible() const;
float GetIsoPriority() const;
plDistributor::IsoType GetIsolation() const;
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
};
// GetFade() notes.
// Fade returned as follows:
// Box3.Min()[0] == fadeInTransparent
// Box3.Min()[1] == fadeInOpaque
// Box3.Max()[0] == fadeOutTransparent
// Box3.Max()[1] == fadeOutOpaque
//
// Box3.Min()[2] == 0 turns off fadein.
// Box3.Max()[2] == 0 turns off fadeout.
//
// In all cases, max(Min()[0],Min()[1]) <= min(Max()[0], Max()[1])
//
// Also, either Min()[0] <= Min()[1] && Max()[0] >= Max()[1]
// or Min()[0] >= Min()[1] && Max()[0] <= Max()[1]
// that is, we either start transparent, go to opaque and back to transparent,
// or we start opaque, go transparent, and back to opaque.
// Makes sense if you think about it.
//
// If Min()[0] == Min()[1], there is no fade in, we start transparent or opaque
// as determined by Max()[0] and Max()[1].
// Same for equal Maxs.
// Naturally, Min()[0] == Min()[1] && Max()[0] == Max()[1] turns the whole thing off.
//
#endif // plDistribComponent_inc

View File

@ -0,0 +1,225 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plExcludeRegionComponent.h"
#include "max.h"
#include "resource.h"
#include "plComponent.h"
#include "plComponentReg.h"
#include "../MaxMain/plMaxNode.h"
#include "../pnKeyedObject/plKey.h"
#include "../plModifier/plExcludeRegionModifier.h"
#include "../plPhysical/plSimDefs.h"
#include "../MaxMain/plPhysicalProps.h"
void DummyCodeIncludeFuncExcludeRegion() {}
CLASS_DESC(plExcludeRegionComponent, gExcludeRegionDesc, "Exclude Region", "ExclRegion", COMP_TYPE_MISC, XREGION_CID)
enum
{
kXRegionSafePoints,
kXRegionInitiallyCleared,
kXRegionSmartSeek,
kXRegionBlockCameras,
};
ParamBlockDesc2 gExcludeRegionBlock
(
plComponent::kBlkComp, _T("XRegionComp"), 0, &gExcludeRegionDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_XREGION, IDS_COMP_XREGION, 0, 0, NULL,
kXRegionSafePoints, _T("safePoints"), TYPE_INODE_TAB, 0, 0, 0,
p_ui, TYPE_NODELISTBOX, IDC_LIST_SAFE, IDC_ADD_SAFE, 0, IDC_DEL_SAFE,
p_classID, Class_ID(DUMMY_CLASS_ID, 0),
end,
kXRegionInitiallyCleared, _T("initiallyCleared"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_CLEARED,
end,
kXRegionSmartSeek, _T("smartSeek"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_SMARTSEEK ,
end,
kXRegionBlockCameras, _T("blockCameras"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_CAMERA_LOS,
end,
end
);
plExcludeRegionComponent::plExcludeRegionComponent()
{
fClassDesc = &gExcludeRegionDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
plKey plExcludeRegionComponent::GetKey(plMaxNode *node)
{
XRegionKeys::iterator it = fXRegionKeys.find(node);
if (it != fXRegionKeys.end())
return it->second;
return nil;
}
hsBool plExcludeRegionComponent::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg)
{
fXRegionKeys.clear();
fIsValid = false;
int count = fCompPB->Count(kXRegionSafePoints);
for (int i = 0; i < count; i++)
{
plMaxNode *safeNode = (plMaxNode*)fCompPB->GetINode(kXRegionSafePoints, 0, i);
if (safeNode)
{
fIsValid = true;
// Force the dummies to local so we get the right coords
safeNode->SetForceLocal(true);
}
}
if (!fIsValid)
{
pErrMsg->Set(true, "Exclude Region Warning",
"Node %s : No safe points specified, exclude region will not be created.\n",
node->GetName()).Show();
pErrMsg->Set(false);
return false;
}
plPhysicalProps *physProps = node->GetPhysicalProps();
physProps->SetBoundsType(plSimDefs::kHullBounds, node, pErrMsg);
// removed letting exclude regions have weight... there is no need and it causes PhysX to crash!
//physProps->SetMass(1.f, node, pErrMsg);
physProps->SetMass(0.f, node, pErrMsg);
physProps->SetPinned(true, node, pErrMsg);
if (fCompPB->GetInt(kXRegionInitiallyCleared))
{
physProps->SetGroup(plSimDefs::kGroupStatic, node, pErrMsg);
physProps->SetLOSBlockUI(true, node, pErrMsg);
if (fCompPB->GetInt(kXRegionBlockCameras))
physProps->SetLOSBlockCamera(true, node, pErrMsg);
}
else
{
physProps->SetGroup(plSimDefs::kGroupDetector, node, pErrMsg);
physProps->SetReportGroup(1<<plSimDefs::kGroupAvatar, node, pErrMsg);
}
if (!plPhysicCoreComponent::SetupProperties(node, pErrMsg))
{
fIsValid = false;
return false;
}
node->SetDrawable(false);
return true;
}
hsBool plExcludeRegionComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
if (!fIsValid)
return false;
if (!plPhysicCoreComponent::PreConvert(node, pErrMsg))
{
fIsValid = false;
return false;
}
plExcludeRegionModifier *mod = TRACKED_NEW plExcludeRegionModifier;
plKey key = node->AddModifier(mod, IGetUniqueName(node));
fXRegionKeys[node] = key;
return true;
}
hsBool plExcludeRegionComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
if (!fIsValid)
return false;
if (!plPhysicCoreComponent::Convert(node, pErrMsg))
{
fIsValid = false;
return false;
}
plExcludeRegionModifier *mod = plExcludeRegionModifier::ConvertNoRef(fXRegionKeys[node]->GetObjectPtr());
if (fCompPB->GetInt(kXRegionSmartSeek))
mod->UseSmartSeek();
if (fCompPB->GetInt(kXRegionBlockCameras))
mod->SetBlockCameras(true);
int count = fCompPB->Count(kXRegionSafePoints);
for (int i = 0; i < count; i++)
{
plMaxNode *safePoint = (plMaxNode*)fCompPB->GetINode(kXRegionSafePoints, 0, i);
if (safePoint)
{
plKey pKey = safePoint->GetKey();
mod->AddSafePoint(pKey);
}
}
return true;
}
hsBool plExcludeRegionComponent::DeInit(plMaxNode *node, plErrorMsg *pErrMsg)
{
fXRegionKeys.clear();
return true;
}

View File

@ -0,0 +1,75 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plExcludeRegionComponent_h_inc
#define plExcludeRegionComponent_h_inc
#include "plPhysicalComponents.h"
#include "../pnKeyedObject/plKey.h"
#include <map>
class plComponentBase;
#define XREGION_CID Class_ID(0x75903e2, 0x50ac210a)
class plExcludeRegionComponent : public plPhysicCoreComponent
{
protected:
bool fIsValid;
typedef std::map<plMaxNode*,plKey> XRegionKeys;
XRegionKeys fXRegionKeys;
public:
plExcludeRegionComponent();
// Can't call until after PreConvert
plKey GetKey(plMaxNode *node);
hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg);
hsBool PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool DeInit(plMaxNode *node, plErrorMsg *pErrMsg);
virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); }
};
#endif // plExcludeRegionComponent_h_inc

View File

@ -0,0 +1,70 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plFlexibilityComponent_inc
#define plFlexibilityComponent_inc
const Class_ID FLEXIBILITY_COMP_CID(0x6fec783f, 0x705536d3);
class plFlexibilityComponent : public plComponent
{
public:
enum {
kFlexibility,
kInterRand,
kIntraRand
};
public:
plFlexibilityComponent();
void DeleteThis() { delete this; }
Point3 GetFlexibility() const;
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
};
#endif // plFlexibilityComponent_inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,202 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "max.h"
#include "resource.h"
#include "hsConfig.h"
#include <map>
#include "hsResMgr.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "../MaxMain/plMaxNode.h"
#include "plFootstepComponent.h"
#include "plAudioComponents.h"
#include "plComponentReg.h"
#include "../plAvatar/plAvatarClothing.h"
#include "../plAvatar/plArmatureEffects.h"
#include "../plAvatar/plArmatureMod.h"
#include "../pfAudio/plRandomSoundMod.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnMessage/plNodeRefMsg.h"
#include "plPickNode.h"
void DummyCodeIncludeFuncFootstepSound()
{
}
CLASS_DESC(plFootstepSoundComponent, gFootstepSoundDesc, "Avatar FootstepSound", "AvatarFootstepSound", COMP_TYPE_AVATAR, FOOTSTEP_SOUND_COMPONENT_CLASS_ID)
static plFootstepSoundComponentProc gFootstepSoundComponentProc;
ParamBlockDesc2 gFootstepSoundBk
(
plComponent::kBlkComp, _T("FootstepSound"), 0, &gFootstepSoundDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
//Roll out
IDD_COMP_FOOTSTEP_SOUND, IDS_COMP_FOOTSTEP_SOUND, 0, 0, &gFootstepSoundComponentProc,
plFootstepSoundComponent::kSurface, _T("Surface"), TYPE_INT, 0, 0,
p_default, plArmatureEffectsMgr::kFootDirt,
end,
plFootstepSoundComponent::kSurfaceList, _T("SoundGroups"), TYPE_INODE_TAB, plArmatureEffectsMgr::kMaxSurface, 0, 0,
end,
plFootstepSoundComponent::kNodePicker, _T("NodePicker"), TYPE_INODE, 0, 0,
end,
end
);
plFootstepSoundComponent::plFootstepSoundComponent()
{
fClassDesc = &gFootstepSoundDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
extern const plArmatureMod * FindArmatureMod(const plSceneObject *obj);
/*{
int count = obj->GetNumModifiers();
for (int i = 0; i < count; i++)
{
const plModifier *mod = obj->GetModifier(i);
const plArmatureMod * avMod = plArmatureMod::ConvertNoRef(mod);
if(avMod)
return avMod;
}
return nil;
}*/
hsBool plFootstepSoundComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
plGenRefMsg *msg;
plArmatureEffectFootSound *effect = TRACKED_NEW plArmatureEffectFootSound();
// Note: MUST be a hard-coded keyname, since we search for same name in plArmatureMod.cpp
hsgResMgr::ResMgr()->NewKey( "FootstepSounds", effect, node->GetLocation());
int i;
for (i = 0; i < plArmatureEffectsMgr::kMaxSurface; i++)
{
plMaxNode *compNode = (plMaxNode*)fCompPB->GetINode(ParamID(kSurfaceList), 0, i);
if (compNode)
{
plRandomSoundComponent *rsComp = (plRandomSoundComponent *)compNode->ConvertToComponent();
if (rsComp)
{
plRandomSoundMod *mod = rsComp->fSoundMods[node];
if (mod != nil)
{
msg = TRACKED_NEW plGenRefMsg(effect->GetKey(), plRefMsg::kOnCreate, i, -1);
hsgResMgr::ResMgr()->AddViaNotify(mod->GetKey(), msg, plRefFlags::kActiveRef);
}
}
}
}
// Add it to the scene node's generic list, so that all avatars can access it.
plNodeRefMsg* nodeRefMsg = TRACKED_NEW plNodeRefMsg(node->GetRoomKey(), plNodeRefMsg::kOnRequest, -1, plNodeRefMsg::kGeneric);
hsgResMgr::ResMgr()->AddViaNotify(effect->GetKey(), nodeRefMsg, plRefFlags::kActiveRef);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////
BOOL plFootstepSoundComponentProc::DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
IParamBlock2 *pb = pm->GetParamBlock();
HWND hSurface = GetDlgItem(hWnd, IDC_COMP_FOOTSTEP_SOUND_SURFACE);
HWND hPick = GetDlgItem(hWnd, IDC_COMP_FOOTSTEP_SOUND_PICK);
INode *curPick = nil;
int curSurface = 0;
switch (msg)
{
case WM_INITDIALOG:
{
int i;
for (i = 0; i < plArmatureEffectsMgr::kMaxSurface; i++)
ComboBox_AddString(hSurface, plArmatureEffectsMgr::SurfaceStrings[i]);
curSurface = pb->GetInt(ParamID(plFootstepSoundComponent::kSurface));
ComboBox_SetCurSel(hSurface, curSurface);
curPick = pb->GetINode(ParamID(plFootstepSoundComponent::kSurfaceList), 0, curSurface);
Button_SetText(hPick, (curPick == nil ? "None" : curPick->GetName()));
}
return TRUE;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED)
{
if (LOWORD(wParam) == IDC_COMP_FOOTSTEP_SOUND_PICK)
{
std::vector<Class_ID> cids;
cids.push_back(RANDOM_SOUND_COMPONENT_ID);
if (plPick::NodeRefKludge(pb, plFootstepSoundComponent::kNodePicker, &cids, true, false))
{
curPick = pb->GetINode(ParamID(plFootstepSoundComponent::kNodePicker));
curSurface = pb->GetInt(ParamID(plFootstepSoundComponent::kSurface));
pb->SetValue(ParamID(plFootstepSoundComponent::kSurfaceList), 0, curPick, curSurface);
Button_SetText(hPick, (curPick == nil ? "None" : curPick->GetName()));
}
return TRUE;
}
}
else if (LOWORD(wParam) == IDC_COMP_FOOTSTEP_SOUND_SURFACE)
{
curSurface = ComboBox_GetCurSel(hSurface);
curPick = pb->GetINode(ParamID(plFootstepSoundComponent::kSurfaceList), 0, curSurface);
pb->SetValue(ParamID(plFootstepSoundComponent::kSurface), 0, curSurface);
Button_SetText(hPick, (curPick == nil ? "None" : curPick->GetName()));
}
}
return FALSE;
}

View File

@ -0,0 +1,77 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_FOOTSTEP_COMPONENT_H
#define PL_FOOTSTEP_COMPONENT_H
#include "plComponent.h"
class plFootstepSoundComponent : public plComponent
{
public:
plFootstepSoundComponent();
virtual void DeleteThis() { delete this; }
virtual hsBool SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { return true; }
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
enum // ParamBlock indices
{
kSurface,
kSurfaceList,
kNodePicker,
};
};
#define FOOTSTEP_SOUND_COMPONENT_CLASS_ID Class_ID(0x15c93f12, 0x4c3f050f)
class plFootstepSoundComponentProc : public ParamMap2UserDlgProc
{
public:
plFootstepSoundComponentProc() {}
BOOL DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void DeleteThis() {}
};
#endif

View File

@ -0,0 +1,72 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plGUICompClassIDs Header //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plGUICompClassIDs_h
#define _plGUICompClassIDs_h
#define GUI_DIALOG_COMP_CLASS_ID Class_ID(0x2421463d, 0x6ae12c78)
#define GUI_UPDOWNPAIR_CLASSID Class_ID(0x3d313f12, 0x76052516)
#define GUI_BUTTON_CLASSID Class_ID(0x7b9b4e5e, 0x61746c00)
#define GUI_DRAGGABLE_CLASSID Class_ID(0x1fdd3182, 0x4bc76749)
#define GUI_LISTBOX_CLASSID Class_ID(0x173304d2, 0x7d9007b2)
#define GUI_TEXTBOX_CLASSID Class_ID(0x37ec36e4, 0x2d202036)
#define GUI_EDITBOX_CLASSID Class_ID(0x430689d, 0x4a570f9a)
#define GUI_KNOBCTRL_CLASSID Class_ID(0x3072431, 0x4f447a04)
#define GUI_DRAGBAR_CLASSID Class_ID(0x2eca7f27, 0x71e70cd0)
#define GUI_CHECKBOX_CLASSID Class_ID(0x5dba1dd4, 0x7e572d4d)
#define GUI_RADIOGROUP_CLASSID Class_ID(0x641754fe, 0x38d52199)
#define GUI_DYNDISPLAY_CLASSID Class_ID(0x3051b96, 0x3c760bd3)
#define GUI_COLORSCHEME_CLASSID Class_ID(0x2b1401bd, 0x41a35d80)
#define GUI_MULTILINE_CLASSID Class_ID(0x10f749f2, 0x3c6e2fdd)
#define GUI_PROGRESS_CLASSID Class_ID(0x13dc5f4b, 0x73e06e68)
#define GUI_CLICKMAP_CLASSID Class_ID(0x64180f8b, 0x434116df)
#define GUI_SKIN_CLASSID Class_ID(0x6f760c1c, 0x65934ba7)
#define GUI_MENUANCHOR_CLASSID Class_ID(0x3756357e, 0x61573fcc)
#endif //_plGUICompClassIDs_h

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,238 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plGUIComponents Header //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plGUIComponents_h
#define _plGUIComponents_h
#include "../pnKeyedObject/plKey.h"
#include "plGUICompClassIDs.h"
#include "plComponent.h"
//////////////////////////////////////////////////////////////////////////////
//// Component Class Definitions /////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// Dialog Component ////////////////////////////////////////////////////////
class plMaxNode;
class pfGUIDialogMod;
class plErrorMsg;
class plGUIDialogComponent : public plComponent
{
protected:
void IMakeEveryoneOpaqueRecur( plMaxNode *node );
void IMakeEveryoneOpaque( plMaxNode *node );
pfGUIDialogMod *fDialogMod;
plKey fProcReceiver; // non-nil means to send out notifys as our proc
hsBool fSeqNumValidated;
virtual pfGUIDialogMod *IMakeDialog( void );
public:
// I believe booleans should always default to false, hence why this is dontInit instead of init. Byte me.
plGUIDialogComponent( hsBool dontInit = false );
void DeleteThis() { delete this; }
hsBool SetupProperties( plMaxNode *pNode, plErrorMsg *pErrMsg );
hsBool PreConvert( plMaxNode *pNode, plErrorMsg *pErrMsg );
hsBool Convert( plMaxNode *node, plErrorMsg *pErrMsg );
hsBool DeInit(plMaxNode *node, plErrorMsg *pErrMsg) { fProcReceiver = nil; return true;}
pfGUIDialogMod *GetModifier( void ) { return fDialogMod; }
// For those too lazy to get it from the modifier
// ... or can't trust that just because you have a modifier doesn't mean that you have a key :-) :-)
plKey GetModifierKey( void );
// Set this to have the dialog send out notify messages on events. Do it before Convert(). Returns false if it failed.
bool SetNotifyReceiver( plKey key );
static pfGUIDialogMod *GetNodeDialog( plMaxNode *childNode );
enum
{
kRefDialogName,
kRefIsModal,
kRefVersion,
kRefAgeName,
kRefDerivedStart
};
enum
{
kMainRollout,
kTagIDRollout,
kSchemeRollout
};
};
//// Control Component Base Class ////////////////////////////////////////////
class pfGUIControlMod;
class hsGMaterial;
class plGUIControlBase : public plComponent
{
protected:
pfGUIControlMod *fControl;
pfGUIDialogMod *IGetDialogMod( plMaxNode *node );
virtual pfGUIControlMod *IGetNewControl( void ) = 0;
virtual bool IHasProcRollout( void ) { return true; }
virtual bool INeedsDynamicText( void ) { return false; }
virtual bool ICanHaveProxy( void ) { return false; }
const char *ISetSoundIndex( ParamID checkBoxID, ParamID sndCompID, UInt8 guiCtrlEvent, plMaxNode *node );
// When converting, since we get a new instance per component but not per node,
// we need to keep track of which nodes we get PreConverted() on and the controls that
// get created for each. Then, on Convert(), we look up the node in our list and grab
// the right control. A pain, but what are you going to do?
hsTArray<plMaxNode *> fTargetNodes;
hsTArray<pfGUIControlMod *> fTargetControls;
public:
plGUIControlBase() {}
void DeleteThis() { delete this; }
hsBool SetupProperties( plMaxNode *pNode, plErrorMsg *pErrMsg );
hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual void CollectNonDrawables( INodeTab &nonDrawables );
virtual UInt32 GetNumMtls( void ) const { return 0; }
virtual Texmap *GetMtl( UInt32 idx ) { return nil; }
// Given a maxNode that is really a component, will return a pointer to the GUI control modifier
// created for it at export time. Only valid after PreConvert. If you think the control component
// might be applied to more than one sceneObject, then you better supply the sceneObject you're
// asking for as well to make sure you get the right control. If not, just leave the second
// parameter nil, but that can be VERY dangerous if the component results in more than one
// GUI control.
static pfGUIControlMod *GrabControlMod( INode *node, INode *sceneObjectNode = nil );
// Like GrabControlMod, but for when you already have a pointer to some kind of component
static pfGUIControlMod *ConvertCompToControl( plComponentBase *comp, INode *sceneObjectNode );
// Given a MAX object node, returns the one (and hopefully only) pfGUIControlMod attached to the scene object. Valid after PreConvert.
static pfGUIControlMod *GrabControlFromObject( INode *node );
// Given an INode, gives you a pointer to the GUI component if it actually is one, nil otherwise
static plGUIControlBase *GetGUIComp( INode *node );
// Or a plComponentBase...
static plGUIControlBase *GetGUIComp( plComponentBase *base );
enum
{
kBlkProc = plComponent::kBlkComp + 1,
kRollMain = 1,
kRollProc = 32,
kRollProxy = 33
};
enum
{
kRefChoice = 32,
kRefConsoleCmd
};
};
//// Pop-Up Menu Class ///////////////////////////////////////////////////////
class pfGUIPopUpMenu;
class plGUIMenuComponent : public plGUIDialogComponent
{
protected:
virtual pfGUIDialogMod *IMakeDialog( void );
pfGUIPopUpMenu *fConvertedMenu;
plKey fConvertedNode;
public:
plGUIMenuComponent();
void DeleteThis() { delete this; }
virtual hsBool SetupProperties( plMaxNode *pNode, plErrorMsg *pErrMsg );
virtual hsBool PreConvert( plMaxNode *pNode, plErrorMsg *pErrMsg );
virtual hsBool Convert( plMaxNode *node, plErrorMsg *pErrMsg );
virtual hsBool DeInit(plMaxNode *node, plErrorMsg *pErrMsg);
plKey GetConvertedMenuKey( void ) const;
enum
{
kRefSkin = kRefDerivedStart,
kRefNeverClose,
kRefModalOutside,
kRefOpenOnHover,
kRefAlignment,
kRefScaleWithScreenRes
};
/* enum
{
kMainRollout,
kTagIDRollout,
kSchemeRollout
};
*/
};
#endif //_plGUIComponents_h

View File

@ -0,0 +1,318 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include <windowsx.h>
#include "HeadSpin.h"
#include "max.h"
#include "resource.h"
#include "hsTemplates.h"
#include "hsResMgr.h"
#include "plQuality.h"
#include "../pnMessage/plRefMsg.h"
#include "../../PubUtilLib/plSurface/hsGMaterial.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxConvert/hsMaterialConverter.h"
#include "plComponent.h"
#include "plComponentReg.h"
#include "plGrassComponent.h"
#include "../../PubUtilLib/plSurface/plGrassShaderMod.h"
#include "../pnKeyedObject/plUoid.h"
#include "../pnMessage/plObjRefMsg.h"
#include "../MaxMain/plPluginResManager.h"
void DummyCodeIncludeFuncGrassShader()
{
}
class GrassCompDlgProc : public ParamMap2UserDlgProc
{
public:
GrassCompDlgProc() {}
~GrassCompDlgProc() {}
protected:
void ISetToWave(int wave, HWND hWnd, IParamBlock2 *pb, IParamMap2 *map)
{
HWND cbox = GetDlgItem(hWnd, IDC_GRASS_WAVE);
SendMessage(cbox, CB_SETCURSEL, wave, 0);
pb->SetValue(ParamID(plGrassComponent::kWave), 0, wave);
pb->SetValue(ParamID(plGrassComponent::kDistX), 0, pb->GetFloat(ParamID(plGrassComponent::kDistXTab), 0, wave));
pb->SetValue(ParamID(plGrassComponent::kDistY), 0, pb->GetFloat(ParamID(plGrassComponent::kDistYTab), 0, wave));
pb->SetValue(ParamID(plGrassComponent::kDistZ), 0, pb->GetFloat(ParamID(plGrassComponent::kDistZTab), 0, wave));
pb->SetValue(ParamID(plGrassComponent::kDirX), 0, pb->GetFloat(ParamID(plGrassComponent::kDirXTab), 0, wave));
pb->SetValue(ParamID(plGrassComponent::kDirY), 0, pb->GetFloat(ParamID(plGrassComponent::kDirYTab), 0, wave));
pb->SetValue(ParamID(plGrassComponent::kSpeed), 0, pb->GetFloat(ParamID(plGrassComponent::kSpeedTab), 0, wave));
map->Invalidate();
}
public:
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;
int selection;
switch (msg)
{
case WM_INITDIALOG:
cbox = GetDlgItem(hWnd, IDC_GRASS_WAVE);
SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)"1");
SendMessage(cbox, CB_ADDSTRING, 1, (LPARAM)"2");
SendMessage(cbox, CB_ADDSTRING, 2, (LPARAM)"3");
SendMessage(cbox, CB_ADDSTRING, 3, (LPARAM)"4");
selection = pb->GetInt(plGrassComponent::kWave);
ISetToWave(selection, hWnd, pb, map);
return TRUE;
case WM_COMMAND:
case CC_SPINNER_CHANGE:
int wave = SendMessage(GetDlgItem(hWnd, IDC_GRASS_WAVE), CB_GETCURSEL, 0, 0);
if (id == IDC_GRASS_WAVE)
{
if (wave != pb->GetInt(ParamID(plGrassComponent::kWave)))
ISetToWave(wave, hWnd, pb, map);
}
else if (id == IDC_GRASS_DIST_X || id == IDC_GRASS_DIST_X_SPIN)
pb->SetValue(plGrassComponent::kDistXTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDistX)), wave);
else if (id == IDC_GRASS_DIST_Y || id == IDC_GRASS_DIST_Y_SPIN)
pb->SetValue(plGrassComponent::kDistYTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDistY)), wave);
else if (id == IDC_GRASS_DIST_Z || id == IDC_GRASS_DIST_Z_SPIN)
pb->SetValue(plGrassComponent::kDistZTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDistZ)), wave);
else if (id == IDC_GRASS_DIR_X || id == IDC_GRASS_DIR_X_SPIN)
pb->SetValue(plGrassComponent::kDirXTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDirX)), wave);
else if (id == IDC_GRASS_DIR_Y || id == IDC_GRASS_DIR_Y_SPIN)
pb->SetValue(plGrassComponent::kDirYTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDirY)), wave);
else if (id == IDC_GRASS_SPEED || id == IDC_GRASS_SPEED_SPIN)
pb->SetValue(plGrassComponent::kSpeedTab, 0, pb->GetFloat(ParamID(plGrassComponent::kSpeed)), wave);
return TRUE;
}
return FALSE;
}
void DeleteThis() {}
};
static GrassCompDlgProc gGrassCompDlgProc;
CLASS_DESC(plGrassComponent, gGrassDesc, "Grass", "Grass", COMP_TYPE_SHADERS, GRASS_COMPONENT_CLASS_ID)
ParamBlockDesc2 gGrassBk
(
plComponent::kBlkComp, _T("Grass"), 0, &gGrassDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
//Roll out
IDD_COMP_GRASS, IDS_COMP_GRASS_ROLL, 0, 0, &gGrassCompDlgProc,
plGrassComponent::kWave, _T("Wave"), TYPE_INT, 0, 0,
p_default, 0,
end,
plGrassComponent::kDistX, _T("DistX"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_GRASS_DIST_X, IDC_GRASS_DIST_X_SPIN, 0.1,
end,
plGrassComponent::kDistY, _T("DistY"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_GRASS_DIST_Y, IDC_GRASS_DIST_Y_SPIN, 0.1,
end,
plGrassComponent::kDistZ, _T("DistZ"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_GRASS_DIST_Z, IDC_GRASS_DIST_Z_SPIN, 0.1,
end,
plGrassComponent::kDirX, _T("DirX"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_GRASS_DIR_X, IDC_GRASS_DIR_X_SPIN, 0.1,
end,
plGrassComponent::kDirY, _T("DirY"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_GRASS_DIR_Y, IDC_GRASS_DIR_Y_SPIN, 0.1,
end,
plGrassComponent::kSpeed, _T("Speed"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_GRASS_SPEED, IDC_GRASS_SPEED_SPIN, 0.1,
end,
plGrassComponent::kDistXTab, _T("DistXTab"), TYPE_FLOAT_TAB, plGrassShaderMod::kNumWaves, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
end,
plGrassComponent::kDistYTab, _T("DistYTab"), TYPE_FLOAT_TAB, plGrassShaderMod::kNumWaves, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
end,
plGrassComponent::kDistZTab, _T("DistZTab"), TYPE_FLOAT_TAB, plGrassShaderMod::kNumWaves, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
end,
plGrassComponent::kDirXTab, _T("DirXTab"), TYPE_FLOAT_TAB, plGrassShaderMod::kNumWaves, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
end,
plGrassComponent::kDirYTab, _T("DirYTab"), TYPE_FLOAT_TAB, plGrassShaderMod::kNumWaves, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
end,
plGrassComponent::kSpeedTab, _T("SpeedTab"), TYPE_FLOAT_TAB, plGrassShaderMod::kNumWaves, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
end,
end
);
plGrassComponent::plGrassComponent() : fShader(nil)
{
fClassDesc = &gGrassDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plGrassComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
fShader = TRACKED_NEW plGrassShaderMod();
plLoadMask loadMask;
int qual = 1;
int cap = plQuality::kPS_1_1;
plLoadMask::ComputeRepMasks(1, &qual, &cap, &loadMask);
plKey modKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), fShader, node->GetLocation(), loadMask);
int i;
for (i = 0; i < plGrassShaderMod::kNumWaves; i++)
{
fShader->fWaves[i].fDistX = fCompPB->GetFloat(ParamID(kDistXTab), 0, i);
fShader->fWaves[i].fDistY = fCompPB->GetFloat(ParamID(kDistYTab), 0, i);
fShader->fWaves[i].fDistZ = fCompPB->GetFloat(ParamID(kDistZTab), 0, i);
fShader->fWaves[i].fDirX = fCompPB->GetFloat(ParamID(kDirXTab), 0, i);
fShader->fWaves[i].fDirY = fCompPB->GetFloat(ParamID(kDirYTab), 0, i);
fShader->fWaves[i].fSpeed = fCompPB->GetFloat(ParamID(kSpeedTab), 0, i);
}
// Add a ref to the shader.
fShader->GetKey()->RefObject();
return true;
}
hsBool plGrassComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
plObjRefMsg* refMsg = TRACKED_NEW plObjRefMsg(node->GetKey(), plRefMsg::kOnRequest, -1, plObjRefMsg::kModifier);
hsgResMgr::ResMgr()->AddViaNotify(fShader->GetKey(), refMsg, plRefFlags::kActiveRef);
hsTArray<hsGMaterial*> mats;
hsMaterialConverter::Instance().CollectConvertedMaterials(hsMaterialConverter::Instance().GetBaseMtl(node), mats);
hsgResMgr::ResMgr()->SendRef(mats[0]->GetKey(), TRACKED_NEW plGenRefMsg(fShader->GetKey(), plRefMsg::kOnRequest, 0, plGrassShaderMod::kRefMaterial), plRefFlags::kActiveRef);
return TRUE;
}
hsBool plGrassComponent::DeInit(plMaxNode* node, plErrorMsg* pErrMsg)
{
if( fShader )
fShader->GetKey()->UnRefObject();
fShader = nil;
return true;
}
plGrassShaderMod* plGrassComponent::GetShader(INode* node)
{
if( !node )
return nil;
plComponentBase *comp = ((plMaxNodeBase*)node)->ConvertToComponent();
if( !comp )
return nil;
if( comp->ClassID() != GRASS_COMPONENT_CLASS_ID )
return nil;
plGrassComponent *shader = (plGrassComponent*)comp;
return shader->fShader;
}
plGrassShaderMod* plGrassComponent::GetShaderNode(plMaxNode* node)
{
if( !node )
return nil;
int n = node->NumAttachedComponents();
int i;
for( i = 0; i < n; i++ )
{
plComponentBase* comp = node->GetAttachedComponent(i);
if( comp && (comp->ClassID() == GRASS_COMPONENT_CLASS_ID) )
{
plGrassComponent* shader = (plGrassComponent*)comp;
return shader->fShader;
}
}
return nil;
}

View File

@ -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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLGRASSCOMPONENT_INC
#define PLGRASSCOMPONENT_INC
class plGrassShaderMod;
class plGrassComponent : public plComponent
{
protected:
plGrassShaderMod *fShader;
public:
plGrassComponent();
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool DeInit(plMaxNode* node, plErrorMsg* pErrMsg);
virtual void DeleteThis() { delete this; }
// These only work after PreConvert pass
static plGrassShaderMod* GetShader(INode* node); // Node is the component node
static plGrassShaderMod* GetShaderNode(plMaxNode* node); // node is the component's target
enum
{
kWave,
kDistX,
kDistY,
kDistZ,
kDirX,
kDirY,
kSpeed,
kDistXTab,
kDistYTab,
kDistZTab,
kDirXTab,
kDirYTab,
kSpeedTab,
};
};
#define GRASS_COMPONENT_CLASS_ID Class_ID(0x1a422bfe, 0xe0e3f07)
#endif // PLGRASSCOMPONENT_INC

View File

@ -0,0 +1,433 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "max.h"
#include "resource.h"
#include "plComponent.h"
#include "plMiscComponents.h"
#include "plComponentReg.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "../MaxMain/plMaxNode.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../pnSceneObject/plDrawInterface.h"
#include "../plMessage/plSimStateMsg.h"
#include "../pnMessage/plEnableMsg.h"
#include "../MaxMain/plPluginResManager.h"
void DummyCodeIncludeFuncIgnore() {}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Ignore Component
//
//
//Class that accesses the paramblock below.
class plIgnoreComponent : public plComponent
{
public:
plIgnoreComponent();
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual void CollectNonDrawables(INodeTab& nonDrawables);
};
//Max desc stuff necessary below.
CLASS_DESC(plIgnoreComponent, gIgnoreDesc, "Ignore", "Ignore", COMP_TYPE_IGNORE, Class_ID(0x48326288, 0x528a3dea))
enum
{
kIgnoreMeCheckBx
};
ParamBlockDesc2 gIgnoreBk
(
plComponent::kBlkComp, _T("Ignore"), 0, &gIgnoreDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_IGNORE, IDS_COMP_IGNORES, 0, 0, NULL,
kIgnoreMeCheckBx, _T("Ignore"), TYPE_BOOL, 0, 0,
p_default, TRUE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_IGNORE_CKBX,
end,
end
);
plIgnoreComponent::plIgnoreComponent()
{
fClassDesc = &gIgnoreDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
void plIgnoreComponent::CollectNonDrawables(INodeTab& nonDrawables)
{
if (fCompPB->GetInt(kIgnoreMeCheckBx))
{
AddTargetsToList(nonDrawables);
}
}
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool plIgnoreComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg)
{
if (fCompPB->GetInt(kIgnoreMeCheckBx))
pNode->SetCanConvert(false);
return true;
}
hsBool plIgnoreComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// IgnoreLite Component
//
//
//Class that accesses the paramblock below.
class plIgnoreLiteComponent : public plComponent
{
public:
enum {
kSelectedOnly
};
enum LightState {
kTurnOn,
kTurnOff,
kToggle
};
public:
plIgnoreLiteComponent();
void SetState(LightState s);
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) { return true; }
hsBool PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg) { return true; }
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg) { return true; }
};
class plIgnoreLiteProc : public ParamMap2UserDlgProc
{
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_COMMAND:
if( (HIWORD(wParam) == BN_CLICKED) && (LOWORD(wParam) == IDC_COMP_IGNORELITE_ON) )
{
plIgnoreLiteComponent* ilc = (plIgnoreLiteComponent*)map->GetParamBlock()->GetOwner();
ilc->SetState(plIgnoreLiteComponent::kTurnOn);
return TRUE;
}
if( (HIWORD(wParam) == BN_CLICKED) && (LOWORD(wParam) == IDC_COMP_IGNORELITE_OFF) )
{
plIgnoreLiteComponent* ilc = (plIgnoreLiteComponent*)map->GetParamBlock()->GetOwner();
ilc->SetState(plIgnoreLiteComponent::kTurnOff);
return TRUE;
}
if( (HIWORD(wParam) == BN_CLICKED) && (LOWORD(wParam) == IDC_COMP_IGNORELITE_TOGGLE) )
{
plIgnoreLiteComponent* ilc = (plIgnoreLiteComponent*)map->GetParamBlock()->GetOwner();
ilc->SetState(plIgnoreLiteComponent::kToggle);
return TRUE;
}
break;
}
return false;
}
void DeleteThis() {}
};
static plIgnoreLiteProc gIgnoreLiteProc;
//Max desc stuff necessary below.
CLASS_DESC(plIgnoreLiteComponent, gIgnoreLiteDesc, "Control Max Light", "ControlLite", COMP_TYPE_IGNORE, IGNORELITE_CID)
ParamBlockDesc2 gIgnoreLiteBk
(
plComponent::kBlkComp, _T("IgnoreLite"), 0, &gIgnoreLiteDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_IGNORELITE, IDS_COMP_IGNORELITES, 0, 0, &gIgnoreLiteProc,
plIgnoreLiteComponent::kSelectedOnly, _T("SelectedOnly"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_IGNORELITE_SELECTED,
end,
end
);
plIgnoreLiteComponent::plIgnoreLiteComponent()
{
fClassDesc = &gIgnoreLiteDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
void plIgnoreLiteComponent::SetState(LightState s)
{
BOOL selectedOnly = fCompPB->GetInt(kSelectedOnly);
int numTarg = NumTargets();
int i;
for( i = 0; i < numTarg; i++ )
{
plMaxNodeBase* targ = GetTarget(i);
if( targ )
{
if( selectedOnly && !targ->Selected() )
continue;
Object *obj = targ->EvalWorldState(TimeValue(0)).obj;
if (obj && (obj->SuperClassID() == SClass_ID(LIGHT_CLASS_ID)))
{
LightObject* liObj = (LightObject*)obj;
switch( s )
{
case kTurnOn:
liObj->SetUseLight(true);
break;
case kTurnOff:
liObj->SetUseLight(false);
break;
case kToggle:
liObj->SetUseLight(!liObj->GetUseLight());
break;
}
}
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Barney Component
//
//
//Class that accesses the paramblock below.
class plBarneyComponent : public plComponent
{
public:
plBarneyComponent();
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
};
//Max desc stuff necessary below.
CLASS_DESC(plBarneyComponent, gBarneyDesc, "Barney", "Barney", COMP_TYPE_IGNORE, Class_ID(0x376955dc, 0x2fec50ae))
ParamBlockDesc2 gBarneyBk
(
plComponent::kBlkComp, _T("Barney"), 0, &gBarneyDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_BARNEY, IDS_COMP_BARNEYS, 0, 0, NULL,
end
);
plBarneyComponent::plBarneyComponent()
{
fClassDesc = &gBarneyDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool plBarneyComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg)
{
pNode->SetCanConvert(false);
pNode->SetIsBarney(true);
return true;
}
hsBool plBarneyComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// NoShow Component
//
//
//Class that accesses the paramblock below.
class plNoShowComponent : public plComponent
{
public:
enum
{
kShowable,
kAffectDraw,
kAffectPhys
};
public:
plNoShowComponent();
virtual void CollectNonDrawables(INodeTab& nonDrawables);
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
};
const Class_ID COMP_NOSHOW_CID(0x41cb2b85, 0x615932c6);
//Max desc stuff necessary below.
CLASS_DESC(plNoShowComponent, gNoShowDesc, "NoShow", "NoShow", COMP_TYPE_IGNORE, COMP_NOSHOW_CID)
ParamBlockDesc2 gNoShowBk
(
plComponent::kBlkComp, _T("NoShow"), 0, &gNoShowDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_NOSHOW, IDS_COMP_NOSHOW, 0, 0, NULL,
plNoShowComponent::kShowable, _T("Showable"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_NOSHOW_SHOWABLE,
end,
plNoShowComponent::kAffectDraw, _T("AffectDraw"), TYPE_BOOL, 0, 0,
p_default, TRUE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_NOSHOW_AFFECTDRAW,
end,
plNoShowComponent::kAffectPhys, _T("AffectPhys"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_NOSHOW_AFFECTPHYS,
end,
end
);
plNoShowComponent::plNoShowComponent()
{
fClassDesc = &gNoShowDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool plNoShowComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg)
{
if( !fCompPB->GetInt(kShowable) )
{
if( fCompPB->GetInt(kAffectDraw) )
pNode->SetDrawable(false);
if( fCompPB->GetInt(kAffectPhys) )
pNode->SetPhysical(false);
}
return true;
}
hsBool plNoShowComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
plSceneObject* obj = node->GetSceneObject();
if( !obj )
return true;
if( fCompPB->GetInt(kShowable) )
{
if( fCompPB->GetInt(kAffectDraw) )
{
plEnableMsg* eMsg = TRACKED_NEW plEnableMsg(nil, plEnableMsg::kDisable, plEnableMsg::kDrawable);
eMsg->AddReceiver(obj->GetKey());
eMsg->Send();
}
if( fCompPB->GetInt(kAffectPhys) )
{
hsAssert(0, "Who uses this?");
// plEventGroupEnableMsg* pMsg = TRACKED_NEW plEventGroupEnableMsg;
// pMsg->SetFlags(plEventGroupEnableMsg::kCollideOff | plEventGroupEnableMsg::kReportOff);
// pMsg->AddReceiver(obj->GetKey());
// pMsg->Send();
}
#if 0
plDrawInterface* di = node->GetDrawInterface();
if( di &&
{
di->SetProperty(plDrawInterface::kDisable, true);
}
#endif
}
return true;
}
void plNoShowComponent::CollectNonDrawables(INodeTab& nonDrawables)
{
if( fCompPB->GetInt(kAffectDraw) )
AddTargetsToList(nonDrawables);
}

View File

@ -0,0 +1,196 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plImpactGadgetComponent.h"
#include "resource.h"
//#include "plComponent.h"
#include "plComponentReg.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnKeyedObject/hsKeyedObject.h"
#include "../pnKeyedObject/plKey.h"
#include "../plPhysical/plCollisionDetector.h" // MM
#include "../plModifier/plLogicModifier.h"
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
#include "../plPhysical/plPickingDetector.h"
#include "../pfConditional/plActivatorConditionalObject.h"
#include "../pfConditional/plFacingConditionalObject.h"
#include "../pfConditional/plObjectInBoxConditionalObject.h"
#include "../pnMessage/plObjRefMsg.h"
#include "../pnMessage/plNotifyMsg.h"
#include "../pnMessage/plCursorChangeMsg.h"
#include "hsResMgr.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxConvert/plConvert.h"
#include "plResponderComponent.h"
#include "../MaxConvert/hsConverterUtils.h" //Conversion Dependencies
#include "plPhysicalComponents.h"
#include "../pnMessage/plIntRefMsg.h" // Ibid
#include "plComponentProcBase.h"
#include "../MaxMain/plPhysicalProps.h"
void DummyCodeIncludeFuncImpactGadget() {}
// enum
// {
// kImpactObject_DEAD,
// kImpactOneShot,
// kUseImpactNode_DEAD,
// kImpactNode_DEAD,
// kImpactBoundsType_DEAD,
// kImpactBounceChoice_DEAD,
// kImpactBounceBoolTab_DEAD,
// kImpactReportChoice_DEAD,
// kImpactReportBoolTab_DEAD,
// kImpactEnabled,
// kImpactBounceGroups_DEAD,
// kImpactReportGroups,
// kImpactUseVelocity_DEAD,
// kImpactVelocity_DEAD,
// };
//
// #include "plEventGroupUI.h"
// static plEventGroupProc gReportGroupProc(kImpactReportGroups, "Report collisions with these groups", false);
OBSOLETE_CLASS(plImpactGadget, gImpactGadgetDesc, "Collision Sensor", "CollisionSensor", COMP_TYPE_DETECTOR, IMPACTGADGET_CID)
// enum
// {
// kImpactMain,
// kImpactBounce_DEAD,
// kImpactReport,
// };
//
// ParamBlockDesc2 gImpactGadgetBlock
// (
// plComponent::kBlkComp, _T("ImpactGadgetComp"), 0, &gImpactGadgetDesc, P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP, plComponent::kRefComp,
//
// 2,
// kImpactMain, IDD_COMP_DETECTOR_COLLISION, IDS_COMP_DETECTOR_COLLISION, 0, 0, NULL,
// kImpactReport, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_REPORT, 0, APPENDROLL_CLOSED, &gReportGroupProc,
//
// kImpactOneShot, _T("oneshot"), TYPE_BOOL, 0, 0,
// p_ui, kImpactMain, TYPE_SINGLECHEKBOX, IDC_ONESHOT,
// end,
//
// kImpactReportGroups, _T("reportGroups"), TYPE_INT, 0,0,
// end,
//
// kImpactEnabled, _T("enabled"), TYPE_BOOL, 0, 0,
// p_ui, kImpactMain, TYPE_SINGLECHEKBOX, IDC_ENABLED,
// p_default, TRUE,
// end,
//
// end
// );
//
//
// plImpactGadget::plImpactGadget()
// {
// fClassDesc = &gImpactGadgetDesc;
// fClassDesc->MakeAutoParamBlocks(this);
// }
//
// hsBool plImpactGadget::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg)
// {
// plActivatorBaseComponent::SetupProperties(node, pErrMsg);
//
// plPhysicalProps *physProps = node->GetPhysicalProps();
// physProps->SetReportGroup(plEventGroupProc::GetGroups(fCompPB, kImpactReportGroups), node, pErrMsg);
//
// return true;
// }
//
// hsBool plImpactGadget::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
// {
// plLocation loc = node->GetLocation();
// plSceneObject *obj = node->GetSceneObject();
//
// plKey logicKey = fLogicModKeys[node];
// plLogicModifier *logic = plLogicModifier::ConvertNoRef(logicKey->GetObjectPtr());
//
// if (fCompPB->GetInt(kImpactOneShot))
// logic->SetFlag(plLogicModBase::kOneShot);
//
// hsTArray<plKey> receivers;
// IGetReceivers(node, receivers);
// for (int i = 0; i < receivers.Count(); i++)
// logic->AddNotifyReceiver(receivers[i]);
//
// // Get the physical node (where the mod is going to be put)
// plMaxNode* physNode = node->GetPhysicalProps()->GetProxyNode();
// if (!physNode)
// physNode = node;
//
// // Create remote detector
// plCollisionDetector* det = TRACKED_NEW plCollisionDetector;
// det->SetType(plCollisionDetector::kTypeBump);
//
// // Register the detector
// plKey detKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), det, loc);
// hsgResMgr::ResMgr()->AddViaNotify(detKey, TRACKED_NEW plObjRefMsg(physNode->GetSceneObject()->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
//
// // create and register the CONDITIONS for the DETECTOR's Logic Modifier
// plActivatorConditionalObject* activatorCond = TRACKED_NEW plActivatorConditionalObject;
// plKey activatorKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), activatorCond, loc);
//
// // link everything up:
// logic->AddCondition(activatorCond); // add this activator condition
// logic->SetDisabled(fCompPB->GetInt(kImpactEnabled) == 0);
//
// // Set up the remote detector (if any)
// activatorCond->SetActivatorKey(detKey);
// det->AddLogicObj(logicKey);
//
// // If this is for the SceneViewer, set the local only flag since the read function will never be called
// if (plConvert::Instance().IsForSceneViewer())
// logic->SetLocalOnly(true);
//
// return true;
// }

View File

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

View File

@ -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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "plInventoryObjComponent.h" //Inventory Dependencies
#include "resource.h" //Resource Dependencies
#include "hsResMgr.h" // Ibid
#include "plComponent.h" //Component Dependencies
#include "plComponentReg.h" // Ibid
#include "../pnSceneObject/plSceneObject.h" // Ibid
#include "../pnKeyedObject/hsKeyedObject.h" // Ibid
#include "../MaxMain/plMaxNode.h" // Ibid
#include "plResponderComponent.h"
#include "../plPhysical/plCollisionDetector.h" //Modifiers Dependencies
#include "../plModifier/plLogicModifier.h" // Ibid
#include "../plModifier/plAxisAnimModifier.h" // Ibid
#include "../../NucleusLib/pnModifier/plConditionalObject.h" // Ibid
#include "../plPhysical/plPickingDetector.h" // Ibid
#include "../pfConditional/plActivatorConditionalObject.h" // Ibid
#include "../pfConditional/plFacingConditionalObject.h" // Ibid
#include "../pfConditional/plObjectInBoxConditionalObject.h" // Ibid
#include "../pnMessage/plObjRefMsg.h" //Message Dependencies
#include "../pnMessage/plNotifyMsg.h" // Ibid
#include "../pnMessage/plCursorChangeMsg.h" // Ibid
#include "../MaxConvert/plConvert.h"
//
// DummyCodeIncludeFuncInventStuff Function.
// Necessary to keep the compiler from throwing away this file.
// No functions within are inherently called otherwise....
//
//
void DummyCodeIncludeFuncInventStuff() {}
CLASS_DESC(plInventoryObjComponent, gInventoryObjDesc, "(ex)InventoryObj", "(ex)InventoryObj", COMP_TYPE_LOGIC, INVENTORYOBJCOMP_CID)
enum
{
kClickDragDirectional,
kClickDragDegrees,
kClickDragUseProxy,
kClickDragProxy,
kClickDragUseRegion,
kClickDragProxyRegion,
kClickDragUseX,
kClickDragUseY,
kClickDragAnimX,
kClickDragAnimY,
kClickDragUseLoopX,
kClickDragUseLoopY,
kClickDragLoopAnimX,
kClickDragLoopAnimY,
kAgeSpecificCheckBx, //Added in v1
kRespawnAfterLostCheckBx, //Added in v1
kConsumableCheckbx, //Added in v1
kLifeSpan //Added in v1
};
class plInventoryObjComponentProc;
extern plInventoryObjComponentProc gInventoryObjComponentProc;
ParamBlockDesc2 gInventoryObjBlock
(
plComponent::kBlkComp, _T("ClickDragComp"), 0, &gInventoryObjDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_INV_OBJECT, IDS_COMP_INV_OBJECTS, 0, 0, NULL, //&gInventoryObjComponentProc,
kAgeSpecificCheckBx, _T("AgeSpecificObject"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_enable_ctrls, 1, kRespawnAfterLostCheckBx,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_INV_OBJECT_ITINERANTBOOL,
end,
kRespawnAfterLostCheckBx, _T("RespawnAtSPObject"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_INV_OBJECT_RESPAWNBOOL,
end,
kConsumableCheckbx , _T("TemporaryObject"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_enable_ctrls, 1, kLifeSpan,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_INV_OBJECT_CONSUMABLE,
end,
kLifeSpan, _T("LifeSpan"), TYPE_FLOAT, P_ANIMATABLE, 0,
p_default, 0.0,
p_range, 0.0, 100000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_INV_OBJECT_LIFE_EDIT, IDC_COMP_INV_OBJECT_LIFE_SPIN, 1.0f,
end,
end
);
plInventoryObjComponent::plInventoryObjComponent()
{
fClassDesc = &gInventoryObjDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
const plInventoryObjComponent::LogicKeys& plInventoryObjComponent::GetLogicKeys()
{
return fLogicModKeys;
}
// Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool plInventoryObjComponent::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg)
{
fLogicModKeys.clear();
fReceivers.Reset();
return true;
}
plKey plInventoryObjComponent::GetLogicKey(plMaxNode* node)
{
LogicKeys::const_iterator it;
for (it = fLogicModKeys.begin(); it != fLogicModKeys.end(); it++)
{
if (node == it->first)
return(it->second);
}
return nil;
}
hsBool plInventoryObjComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
plLocation loc = node->GetLocation();
plSceneObject *obj = node->GetSceneObject();
// Create and register the ClickDrag's logic component
plLogicModifier *logic = TRACKED_NEW plLogicModifier;
char tmpName[256];
sprintf(tmpName, "%s_%s_LogicModifier", obj->GetKeyName(), GetINode()->GetName());
plKey logicKey = hsgResMgr::ResMgr()->NewKey(tmpName, logic, node->GetLocation());
hsgResMgr::ResMgr()->AddViaNotify(logicKey, TRACKED_NEW plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
fLogicModKeys[node] = logicKey;
return true;
}
void plInventoryObjComponent::AddReceiverKey(plKey key, plMaxNode* node)
{
fReceivers.Append(key);
}
hsBool plInventoryObjComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
return true;
}
#include "plNoteTrackDlgComp.h"
class plInventoryObjComponentProc : public ParamMap2UserDlgProc
{
protected:
plComponentNoteTrackDlg fNoteTrackDlgX;
plComponentNoteTrackDlg fNoteTrackDlgY;
IParamBlock2 *fPB;
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
// fPB = map->GetParamBlock();
/*
// fNoteTrackDlgX.Init(GetDlgItem(hWnd, IDC_COMP_CLICK_DRAG_ANIMX),
// nil,
/// kClickDragAnimX,
/ nil,
fPB,
fPB->GetOwner());
fNoteTrackDlgX.Load();
EnableWindow(GetDlgItem(hWnd, IDC_COMP_CLICK_DRAG_ANIMX), true);
fNoteTrackDlgY.Init(GetDlgItem(hWnd, IDC_COMP_CLICK_DRAG_ANIM_Y),
nil,
kClickDragAnimY,
nil,
fPB,
fPB->GetOwner());
fNoteTrackDlgY.Load();
EnableWindow(GetDlgItem(hWnd, IDC_COMP_CLICK_DRAG_ANIM_Y), true);
*/
return TRUE;
/*
case WM_COMMAND:
if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_COMP_CLICK_DRAG_ANIMX)
{
fNoteTrackDlgX.AnimChanged();
return TRUE;
}
if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_COMP_CLICK_DRAG_ANIM_Y)
{
fNoteTrackDlgY.AnimChanged();
return TRUE;
}
break;
*/
}
return false;
}
void DeleteThis()
{
// fNoteTrackDlgX.DeleteCache();
// fNoteTrackDlgY.DeleteCache();
}
};
static plInventoryObjComponentProc gInventoryObjComponentProc;

View File

@ -0,0 +1,126 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plInventoryObjComponent_inc
#define plInventoryObjComponent_inc
#include "plClickableComponent.h"
#include "hsTemplates.h"
#include <map>
#include "../pnKeyedObject/plKey.h"
class plMaxNode;
#define INVENTORYOBJCOMP_CID Class_ID(0x425e1687, 0x4a126b91)
//! Inventory Object Component Class
/*!
This Class is the rudimentary 'Inventoriable' component. It is derived from the Clickable
component in order to access the mouse controllers to allow mouse state changes when the cursor
is over an object that can be taken.
member functions:
hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool PreConvert(plMaxNode *node, plErrorMsg* pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual void AddReceiverKey(plKey pKey);
virtual plKey GetLogicKey(plMaxNode* node);
const LogicKeys& GetLogicKeys();
\sa SetupProperties(), PreConvert(), AddReceiverKey(), GetLogicKey() and GetLogicKeys()
*/
class plInventoryObjComponent : public plClickableComponent
{
public:
typedef std::map<plMaxNode*, plKey> LogicKeys;
protected:
hsTArray<plKey> fReceivers;
LogicKeys fLogicModKeys;
public:
//! Constructor function for class
/*!
Herein the ClassDesc2 object that is used extensively by the ParamBlock2
has gained accessibiltiy. Auto-Creation of the UI is done here as well.
*/
plInventoryObjComponent();
// Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
//! plInventoryObjComponent PreConvert, takes in two variables and return a hsBool.
/*!
Calls the function MaybeMakeLocal() and Sets Drawable to false.
Takes in two variables, being:
\param node a plMaxNode ptr.
\param pErrMsg a pErrMsg ptr.
\return A hsBool expressing the success of the operation.
\sa DeleteThis(), plPhysicalCoreComponent(), Convert(), GetParamVals(), MaybeMakeLocal() and FixUpPhysical()
*/
hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool PreConvert(plMaxNode *node, plErrorMsg* pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual void AddReceiverKey(plKey key, plMaxNode* node=nil);
virtual plKey GetLogicKey(plMaxNode* node);
const LogicKeys& GetLogicKeys();
};
#endif // plInventoryObjComponent_inc

View File

@ -0,0 +1,805 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "max.h"
#include "resource.h"
#include "plComponent.h"
#include "plComponentReg.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxExport/plExportProgressBar.h"
#include "hsTypes.h"
#include "plLODFadeComponent.h"
#include "../pfSurface/plFadeOpacityMod.h"
#include "../pfSurface/plDistOpacityMod.h"
void DummyCodeIncludeFuncLODFade()
{
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// LODFadeComponent first, similar and related BlendOnto component further on in file.
CLASS_DESC(plLODFadeComponent, gLODFadeCompDesc, "LOD Blend", "LODBlend", COMP_TYPE_GRAPHICS, LODFADE_COMP_CID)
ParamBlockDesc2 gLODFadeBk
(
plComponent::kBlkComp, _T("LODFade"), 0, &gLODFadeCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_LODFADE, IDS_COMP_LODFADE, 0, 0, NULL,
plLODFadeComponent::kHasBase, _T("HasBase"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LODFADE_HASBASE,
end,
plLODFadeComponent::kBase, _T("Base"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_LODFADE_BASE,
p_prompt, IDS_COMP_LODFADE_BASE,
end,
plLODFadeComponent::kDistance, _T("Distance"), TYPE_FLOAT, 0, 0,
p_default, 50.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_LODFADE_DISTANCE, IDC_COMP_LODFADE_DISTANCE_SPIN, 1.0,
end,
plLODFadeComponent::kTransition, _T("Transition"), TYPE_FLOAT, 0, 0,
p_default, 10.0,
p_range, 0.0, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_LODFADE_TRANSITION, IDC_COMP_LODFADE_TRANSITION_SPIN, 1.0,
end,
plLODFadeComponent::kFadeBase, _T("FadeBase"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LODFADE_FADEBASE,
p_enable_ctrls, 1, plLODFadeComponent::kBaseFirst,
end,
plLODFadeComponent::kBaseFirst, _T("BaseFirst"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LODFADE_BASEFIRST,
end,
end
);
void plLODFadeComponent::ISetToFadeBase(plMaxNode* node, plMaxNode* base, plErrorMsg* pErrMsg)
{
if( fCompPB->GetInt(kBaseFirst) )
node->AddRenderDependency(base);
else
base->AddRenderDependency(node);
Box3 fade = base->GetFade();
Point3 maxs = fade.Max();
float fadeInStart = fCompPB->GetFloat(kDistance) - fCompPB->GetFloat(kTransition);
if( fadeInStart < 0 )
fadeInStart = 0;
float fadeInEnd = fCompPB->GetFloat(kDistance);
Point3 mins(fadeInStart, fadeInEnd, -1.f);
fade = Box3(mins, maxs);
base->SetFade(fade);
node->SetNoDeferDraw(true);
base->SetNoDeferDraw(true);
}
hsBool plLODFadeComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
if( fCompPB->GetInt(kHasBase) )
{
plMaxNode* base = (plMaxNode*)fCompPB->GetINode(kBase, TimeValue(0));
if( base )
{
if( fCompPB->GetInt(kFadeBase) )
{
ISetToFadeBase(node, base, pErrMsg);
}
else
{
node->AddRenderDependency(base);
node->SetNoDeferDraw(true);
}
}
}
Box3 fade = node->GetFade();
Point3 mins = fade.Min();
float fadeOutStart = fCompPB->GetFloat(kDistance);
float fadeOutEnd = fadeOutStart + fCompPB->GetFloat(kTransition);
Point3 maxs(fadeOutEnd, fadeOutStart, 1.f);
fade = Box3(mins, maxs);
node->SetFade(fade);
return true;
}
hsBool plLODFadeComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
hsBool plLODFadeComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
plLODFadeComponent::plLODFadeComponent()
{
fClassDesc = &gLODFadeCompDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// BlendOnto component next.
CLASS_DESC(plBlendOntoComponent, gBlendOntoCompDesc, "Blend Onto", "BlendOnto", COMP_TYPE_GRAPHICS, BLENDONTO_COMP_CID)
ParamBlockDesc2 gBlendOntoBk
(
plComponent::kBlkComp, _T("BlendOnto"), 0, &gBlendOntoCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_BLENDONTO, IDS_COMP_BLENDONTO, 0, 0, NULL,
plBlendOntoComponent::kBaseNodes, _T("BaseNodes"), TYPE_INODE_TAB, 0, P_CAN_CONVERT, 0,
p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, IDC_ADD_TARGS, 0, IDC_DEL_TARGS,
p_classID, triObjectClassID,
end,
plBlendOntoComponent::kSortFaces, _T("SortFaces"), TYPE_BOOL, 0, 0,
p_default, TRUE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_BLENDONTO_SORTFACES,
end,
end
);
hsBool plBlendOntoComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
hsBool someBase = false;
int numBase = fCompPB->Count(kBaseNodes);
int i;
for( i = 0; i < numBase; i++ )
{
plMaxNode* base = (plMaxNode*)fCompPB->GetINode(kBaseNodes, TimeValue(0), i);
if( base )
{
node->AddRenderDependency(base);
node->SetNoDeferDraw(true);
if( !fCompPB->GetInt(kSortFaces) )
node->SetNoFaceSort(true);
someBase = true;
}
}
if( !someBase )
{
node->SetBlendToFB(true);
}
return true;
}
hsBool plBlendOntoComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
hsBool plBlendOntoComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
plBlendOntoComponent::plBlendOntoComponent()
{
fClassDesc = &gBlendOntoCompDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// BlendOntoAdv component next.
CLASS_DESC(plBlendOntoAdvComponent, gBlendOntoAdvCompDesc, "Blend Onto Advanced", "BlendOntoAdv", COMP_TYPE_GRAPHICS, BLENDONTOADV_COMP_CID)
ParamBlockDesc2 gBlendOntoAdvBk
(
plComponent::kBlkComp, _T("BlendOntoAdv"), 0, &gBlendOntoAdvCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_BLENDONTOADV, IDS_COMP_BLENDONTOADV, 0, 0, NULL,
plBlendOntoAdvComponent::kBaseNodes, _T("BaseNodes"), TYPE_INODE_TAB, 0, P_CAN_CONVERT, 0,
p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, IDC_ADD_TARGS, 0, IDC_DEL_TARGS,
p_classID, triObjectClassID,
end,
plBlendOntoAdvComponent::kSortFaces, _T("SortFaces"), TYPE_BOOL, 0, 0,
p_default, TRUE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_BLENDONTOADV_SORTFACES,
end,
plBlendOntoAdvComponent::kSortObjects, _T("SortObjects"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_BLENDONTOADV_SORTOBJECTS,
end,
plBlendOntoAdvComponent::kOntoBlending, _T("OntoBlending"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_BLENDONTOADV_ONTOBLENDING,
end,
end
);
hsBool plBlendOntoAdvComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
hsBool someBase = false;
int numBase = fCompPB->Count(kBaseNodes);
int i;
for( i = 0; i < numBase; i++ )
{
plMaxNode* base = (plMaxNode*)fCompPB->GetINode(kBaseNodes, TimeValue(0), i);
if( base )
{
node->AddRenderDependency(base);
if( !fCompPB->GetInt(kOntoBlending) )
node->SetNoDeferDraw(true);
if( !fCompPB->GetInt(kSortFaces) )
node->SetNoFaceSort(true);
someBase = true;
}
}
if( !someBase )
{
node->SetBlendToFB(true);
}
return true;
}
hsBool plBlendOntoAdvComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
hsBool plBlendOntoAdvComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
plBlendOntoAdvComponent::plBlendOntoAdvComponent()
{
fClassDesc = &gBlendOntoAdvCompDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Force drawing before the avatar.
const Class_ID B4AV_COMP_CID(0x14536d5b, 0x17dc623b);
class plB4AvComponent : public plComponent
{
public:
plB4AvComponent();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
};
CLASS_DESC(plB4AvComponent, gB4AvCompDesc, "Draw B4 Avatar", "B4Av", COMP_TYPE_GRAPHICS, B4AV_COMP_CID)
ParamBlockDesc2 gB4AvBk
(
plComponent::kBlkComp, _T("B4Av"), 0, &gB4AvCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_SORT_AS_OPAQUE, IDS_COMP_SORT_AS_OPAQUE, 0, 0, NULL,
end
);
hsBool plB4AvComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
node->SetSortAsOpaque(true);
return true;
}
hsBool plB4AvComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
hsBool plB4AvComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
plB4AvComponent::plB4AvComponent()
{
fClassDesc = &gB4AvCompDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// DistFadeComponent - just feeding them a bit more rope.
CLASS_DESC(plDistFadeComponent, gDistFadeCompDesc, "Distance Fade", "DistFade", COMP_TYPE_GRAPHICS, DISTFADE_COMP_CID)
ParamBlockDesc2 gDistFadeBk
(
plComponent::kBlkComp, _T("DistFade"), 0, &gDistFadeCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_DISTFADE, IDS_COMP_DISTFADE, 0, 0, NULL,
plDistFadeComponent::kFadeInActive, _T("FadeInActive"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_DISTFADE_IN_ACTIVE,
p_enable_ctrls, 2, plDistFadeComponent::kFadeInStart, plDistFadeComponent::kFadeInEnd,
end,
plDistFadeComponent::kFadeInStart, _T("FadeInStart"), TYPE_FLOAT, 0, 0,
p_default, 5.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTFADE_INSTART, IDC_COMP_DISTFADE_INSTART_SPIN, 1.0,
end,
plDistFadeComponent::kFadeInEnd, _T("FadeInEnd"), TYPE_FLOAT, 0, 0,
p_default, 10.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTFADE_INEND, IDC_COMP_DISTFADE_INEND_SPIN, 1.0,
end,
plDistFadeComponent::kFadeOutActive, _T("FadeOutActive"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_DISTFADE_OUT_ACTIVE,
p_enable_ctrls, 2, plDistFadeComponent::kFadeOutStart, plDistFadeComponent::kFadeOutEnd,
end,
plDistFadeComponent::kFadeOutStart, _T("FadeOutStart"), TYPE_FLOAT, 0, 0,
p_default, 50.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTFADE_OUTSTART, IDC_COMP_DISTFADE_OUTSTART_SPIN, 1.0,
end,
plDistFadeComponent::kFadeOutEnd, _T("FadeOutEnd"), TYPE_FLOAT, 0, 0,
p_default, 100.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_DISTFADE_OUTEND, IDC_COMP_DISTFADE_OUTEND_SPIN, 1.0,
end,
end
);
hsBool plDistFadeComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
// If we're turned off, just return.
if( !fCompPB->GetInt(kFadeInActive) && !fCompPB->GetInt(kFadeOutActive) )
return true;
Box3 fade;
Point3 mins(0.f, 0.f, 0.f);
Point3 maxs(0.f, 0.f, 0.f);
if( fCompPB->GetInt(kFadeInActive) )
{
mins[0] = fCompPB->GetFloat(kFadeInStart);
mins[1] = fCompPB->GetFloat(kFadeInEnd);
}
if( fCompPB->GetInt(kFadeOutActive) )
{
maxs[0] = fCompPB->GetFloat(kFadeOutStart);
maxs[1] = fCompPB->GetFloat(kFadeOutEnd);
}
// We're not really sure how the artist has artistically interpreted
// the parameters. What we want is:
// Nearest point where object starts to fade in == mins[0]
// Nearest point where object is opaque == mins[1]
// Farthest point where object is opaque == maxs[1]
// Farthest point where object fades out completely = maxs[0]
//
// If the artist says they want it to start off opaque, fade out, then
// fade back in once it's far away, we'll explain in person why that's stupid,
// and in the meantime prevent them from doing that by assuming they just
// have the parameter order flipped.
//
// So, they've either given us 2 distances or 2 pairs of distances.
// If they've just given 2 distances, we use as is,
// but if they've given 2 pairs, we have to arrange them to fit the
// above model.
//
// So first thing to do is figure out how many (valid) distances we have.
if( (mins[0] == 0) && (mins[1] == 0) && (maxs[0] == 0) && (maxs[1] == 0) )
{
// Okay, they gave no valid distances. Just pretend we were never here.
return true;
}
if( (mins[0] == 0) && (mins[1] == 0) )
{
// maxs must be valid, just go with them.
fade = IFadeFromPoint(maxs);
}
else if( (maxs[0] == 0) && (maxs[1] == 0) )
{
// mins must be valid, just go with them.
fade = IFadeFromPoint(mins);
}
else
{
// They're both "valid". Give it a shot.
fade = IFadeFromPair(mins, maxs);
}
node->SetFade(fade);
return true;
}
void plDistFadeComponent::ISwap(float& p0, float& p1)
{
float t = p0;
p0 = p1;
p1 = t;
}
Box3 plDistFadeComponent::IFadeFromPoint(Point3& mins)
{
Point3 maxs(0.f, 0.f, 0.f);
if( mins[0] < mins[1] )
mins[2] = -1.f;
else if( mins[0] > mins[1] )
mins[2] = 1.f;
else
mins[2] = 0;
return Box3(mins, maxs);
}
Box3 plDistFadeComponent::IFadeFromPair(Point3& mins, Point3& maxs)
{
if( mins[0] > maxs[0] )
{
ISwap(mins[0], maxs[0]);
ISwap(mins[1], maxs[1]);
}
if( mins[0] > mins[1] )
{
ISwap(mins[0], mins[1]);
}
if( maxs[0] < maxs[1] )
{
// Poor confused bastard, take a guess what he wants.
ISwap(maxs[0], maxs[1]);
}
if( mins[0] < mins[1] )
mins[2] = -1.f;
else
mins[2] = 0;
if( maxs[0] > maxs[1] )
maxs[2] = 1.f;
else
maxs[2] = 0;
return Box3(mins, maxs);
}
hsBool plDistFadeComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
hsBool plDistFadeComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
plDistFadeComponent::plDistFadeComponent()
{
fClassDesc = &gDistFadeCompDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// LOS Fade component next.
class plLOSFadeComponent : public plComponent
{
public:
enum
{
kBoundsCenter,
kFadeInTime,
kFadeOutTime
};
public:
plLOSFadeComponent();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
};
CLASS_DESC(plLOSFadeComponent, gLOSFadeCompDesc, "LOS Fade", "LOSFade", COMP_TYPE_GRAPHICS, LOSFADE_COMP_CID)
ParamBlockDesc2 gLOSFadeBk
(
plComponent::kBlkComp, _T("LOSFade"), 0, &gLOSFadeCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_LOSFADE, IDS_COMP_LOSFADE, 0, 0, NULL,
plLOSFadeComponent::kBoundsCenter, _T("BoundsCenter"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_BOUNDSCENTER,
end,
plLOSFadeComponent::kFadeInTime, _T("kFadeInTime"), TYPE_FLOAT, 0, 0,
p_default, 0.5,
p_range, 0.0, 5.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_FADEINTIME, IDC_COMP_FADEINTIME_SPIN, 1.0,
end,
plLOSFadeComponent::kFadeOutTime, _T("kFadeOutTime"), TYPE_FLOAT, 0, 0,
p_default, 1.0,
p_range, 0.0, 5.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_FADEOUTTIME, IDC_COMP_FADEOUTTIME_SPIN, 1.0,
end,
end
);
hsBool plLOSFadeComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
node->SetForceMatShade(true);
node->SetForceLocal(true);
node->SetForceMaterialCopy(true);
return true;
}
hsBool plLOSFadeComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
hsBool plLOSFadeComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg)
{
plFadeOpacityMod* fade = TRACKED_NEW plFadeOpacityMod;
if( fCompPB->GetInt(kBoundsCenter) )
fade->SetFlag(plFadeOpacityMod::kBoundsCenter);
else
fade->ClearFlag(plFadeOpacityMod::kBoundsCenter);
fade->SetFadeUp(fCompPB->GetFloat(kFadeInTime));
fade->SetFadeDown(fCompPB->GetFloat(kFadeOutTime));
node->AddModifier(fade, node->GetKey()->GetName());
return true;
}
plLOSFadeComponent::plLOSFadeComponent()
{
fClassDesc = &gLOSFadeCompDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// GZ Marker Fade component next.
const Class_ID GZFADE_COMP_CID(0x27173270, 0x4f4486f);
class plGZFadeComponent : public plComponent
{
public:
enum
{
kOpaque,
kTransp
};
public:
plGZFadeComponent();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
};
CLASS_DESC(plGZFadeComponent, gGZFadeCompDesc, "GZ Fade", "GZFade", COMP_TYPE_GRAPHICS, GZFADE_COMP_CID)
ParamBlockDesc2 gGZFadeBk
(
plComponent::kBlkComp, _T("GZFade"), 0, &gGZFadeCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_GZFADE, IDS_COMP_GZ_FADE, 0, 0, NULL,
plGZFadeComponent::kOpaque, _T("kOpaque"), TYPE_FLOAT, 0, 0,
p_default, 15.0,
p_range, 0.0, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_GZ_OPAQUE, IDC_COMP_GZ_OPAQUE_SPIN, 1.0,
end,
plGZFadeComponent::kTransp, _T("kTransp"), TYPE_FLOAT, 0, 0,
p_default, 20.0,
p_range, 0.0, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_GZ_TRANSP, IDC_COMP_GZ_TRANSP_SPIN, 1.0,
end,
end
);
hsBool plGZFadeComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
float opaq = fCompPB->GetFloat(kOpaque);
float transp = fCompPB->GetFloat(kTransp);
pErrMsg->Set(transp <= opaq, node->GetName(), "Distance obj goes transparent must be greater than distance it's opaque").CheckAndAsk();
pErrMsg->Set(false);
node->SetForceMatShade(true);
node->SetForceLocal(true);
node->SetForceMaterialCopy(true);
return true;
}
hsBool plGZFadeComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
hsBool plGZFadeComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg)
{
plDistOpacityMod* fade = TRACKED_NEW plDistOpacityMod;
float opaq = fCompPB->GetFloat(kOpaque);
float transp = fCompPB->GetFloat(kTransp);
fade->SetFarDist(opaq, transp);
node->AddModifier(fade, node->GetKey()->GetName());
return true;
}
plGZFadeComponent::plGZFadeComponent()
{
fClassDesc = &gGZFadeCompDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Force dynamic material - keeps the material colors from getting burnt into the verts.
const Class_ID DYNMAT_COMP_CID(0x2ea4671f, 0x163b12ac);
class plDynMatComponent : public plComponent
{
public:
enum
{
kOpaque,
kTransp
};
public:
plDynMatComponent();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
};
CLASS_DESC(plDynMatComponent, gDynMatCompDesc, "Force Dyn Mat", "DynMat", COMP_TYPE_GRAPHICS, DYNMAT_COMP_CID)
ParamBlockDesc2 gDynMatBk
(
plComponent::kBlkComp, _T("DynMat"), 0, &gDynMatCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_DYNMAT, IDS_COMP_DYNMAT, 0, 0, NULL,
end
);
hsBool plDynMatComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
node->SetForceMatShade(true);
return true;
}
hsBool plDynMatComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
hsBool plDynMatComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
plDynMatComponent::plDynMatComponent()
{
fClassDesc = &gDynMatCompDesc;
fClassDesc->MakeAutoParamBlocks(this);
}

View File

@ -0,0 +1,151 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLODFadeComponent_inc
#define plLODFadeComponent_inc
const Class_ID LODFADE_COMP_CID(0x31821ca, 0x49432f20);
const Class_ID BLENDONTO_COMP_CID(0x35d66d72, 0x1e141eff);
const Class_ID BLENDONTOADV_COMP_CID(0x84c41c0, 0x2fc62900);
const Class_ID DISTFADE_COMP_CID(0x348865f7, 0x72f81040);
const Class_ID LOSFADE_COMP_CID(0x6308608a, 0x7fa34929);
class plMaxNode;
class plExportProgressBar;
class plLODFadeComponent : public plComponent
{
public:
enum
{
kHasBase,
kBase,
kDistance,
kTransition,
kFadeBase,
kBaseFirst
};
protected:
void ISetToFadeBase(plMaxNode* node, plMaxNode* base, plErrorMsg* pErrMsg);
public:
plLODFadeComponent();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
};
class plBlendOntoComponent : public plComponent
{
public:
enum
{
kBaseNodes,
kSortFaces
};
public:
plBlendOntoComponent();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
};
class plBlendOntoAdvComponent : public plComponent
{
public:
enum
{
kBaseNodes,
kSortFaces,
kSortObjects,
kOntoBlending
};
public:
plBlendOntoAdvComponent();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
};
class plDistFadeComponent : public plComponent
{
public:
enum
{
kFadeInActive,
kFadeInStart,
kFadeInEnd,
kFadeOutActive,
kFadeOutStart,
kFadeOutEnd
};
protected:
void ISwap(float& p0, float& p1);
Box3 IFadeFromPoint(Point3& mins);
Box3 IFadeFromPair(Point3& mins, Point3& maxs);
public:
plDistFadeComponent();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
};
#endif // plLODFadeComponent_inc

View File

@ -0,0 +1,314 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "max.h"
#include "resource.h"
#include "plComponent.h"
#include "plComponentReg.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "../MaxMain/plMaxNode.h"
#include "hsResMgr.h"
// LightGroup component
#include "../pnSceneObject/plSceneObject.h"
#include "../plGLight/plLightInfo.h"
#include "../plDrawable/plDrawableSpans.h"
#include "../pnSceneObject/plDrawInterface.h"
#include "../MaxPlasmaLights/plRealTimeLightBase.h"
#include "plLightGrpComponent.h"
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// LightGroup Component
//
//
enum
{
kIncludeChars,
kAffectedLightSel,
kTest
};
CLASS_DESC(plLightGrpComponent, gLightGrpDesc, "Light Group", "LightGroup", COMP_TYPE_GRAPHICS, LIGHTGRP_COMP_CID)
ParamBlockDesc2 gLightGrpBk
(
plComponent::kBlkComp, _T("LightGroup"), 0, &gLightGrpDesc, P_AUTO_CONSTRUCT+P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_LIGHTINC, IDS_COMP_LIGHTINCS, 0, 0, nil,
kIncludeChars, _T("Include characters"), TYPE_BOOL, 0, 0,
p_default, TRUE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LIGHTINC_CHARS,
end,
kAffectedLightSel, _T("AffectedLightChoice"), TYPE_INODE, 0, 0,
end,
kTest, _T("TestBox"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LIGHTINC_FILTER,
end,
end
);
plLightGrpComponent::plLightGrpComponent()
: fValid(false)
{
fClassDesc = &gLightGrpDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
class plLightGrpPostLoadCallback : public PostLoadCallback
{
public:
plLightGrpComponent* fLightGrp;
plLightGrpPostLoadCallback(plLightGrpComponent* lg) : fLightGrp(lg) {}
void proc(ILoad *iload)
{
IParamBlock2* compPB = fLightGrp->GetParamBlock(plComponentBase::kBlkComp);
INode* light = compPB->GetINode(kAffectedLightSel);
if( light )
{
fLightGrp->AddTarget((plMaxNodeBase*)light);
compPB->SetValue(kAffectedLightSel, TimeValue(0), (INode*)nil);
}
delete this;
}
};
IOResult plLightGrpComponent::Load(ILoad* iLoad)
{
iLoad->RegisterPostLoadCallback(new plLightGrpPostLoadCallback(this));
return plComponent::Load(iLoad);
}
hsBool plLightGrpComponent::IAddLightsToSpans(plMaxNode* pNode, plErrorMsg* pErrMsg)
{
int i;
for( i = 0; i < fLightInfos.GetCount(); i++ )
{
if( !fLightInfos[i] )
continue;
const plDrawInterface* di = pNode->GetSceneObject()->GetDrawInterface();
int iDraw;
for( iDraw = 0; iDraw < di->GetNumDrawables(); iDraw++ )
{
plDrawableSpans* drawable = plDrawableSpans::ConvertNoRef(di->GetDrawable(iDraw));
if( drawable )
{
UInt32 diIndex = di->GetDrawableMeshIndex(iDraw);
ISendItOff(fLightInfos[i], drawable, diIndex);
}
}
}
return true;
}
hsBool plLightGrpComponent::ISendItOff(plLightInfo* liInfo, plDrawableSpans* drawable, UInt32 diIndex)
{
plDISpanIndex spans = drawable->GetDISpans(diIndex);
if( spans.fFlags & plDISpanIndex::kMatrixOnly )
return false;
if( !fCompPB->GetInt(kTest) )
{
UInt8 liMsgType = liInfo->GetProjection() ? plDrawable::kMsgPermaProjDI : plDrawable::kMsgPermaLightDI;
plGenRefMsg* refMsg = TRACKED_NEW plGenRefMsg(drawable->GetKey(), plRefMsg::kOnCreate, diIndex, liMsgType);
hsgResMgr::ResMgr()->AddViaNotify(liInfo->GetKey(), refMsg, plRefFlags::kPassiveRef);
}
else
{
hsBitVector litSpans;
liInfo->GetAffectedForced(drawable->GetSpaceTree(), litSpans, false);
UInt8 liMsgType = liInfo->GetProjection() ? plDrawable::kMsgPermaProj : plDrawable::kMsgPermaLight;
int i;
for( i = 0; i < spans.GetCount(); i++ )
{
if( litSpans.IsBitSet(spans[i]) )
{
plGenRefMsg* refMsg = TRACKED_NEW plGenRefMsg(drawable->GetKey(), plRefMsg::kOnCreate, spans[i], liMsgType);
hsgResMgr::ResMgr()->AddViaNotify(liInfo->GetKey(), refMsg, plRefFlags::kPassiveRef);
}
}
}
return true;
}
hsBool plLightGrpComponent::IGetLightInfos()
{
if( !fLightInfos.GetCount() )
{
// Already checked that lightnodes are cool. just get the light interfaces.
int i;
for( i = 0; i < fLightNodes.GetCount(); i++ )
{
plMaxNode* lightNode = fLightNodes[i];
plSceneObject* lightSO = lightNode->GetSceneObject();
if( !lightSO )
continue;
plLightInfo* liInfo = plLightInfo::ConvertNoRef(lightSO->GetGenericInterface(plLightInfo::Index()));
if( !liInfo )
continue;
liInfo->SetProperty(plLightInfo::kLPHasIncludes, true);
if( fCompPB->GetInt(kIncludeChars) )
liInfo->SetProperty(plLightInfo::kLPIncludesChars, true);
fLightInfos.Append(liInfo);
}
}
return fValid = (fLightInfos.GetCount() > 0);
}
const hsTArray<plLightInfo*>& plLightGrpComponent::GetLightInfos()
{
IGetLightInfos();
return fLightInfos;
}
plLightGrpComponent* plLightGrpComponent::GetComp(plMaxNode* node)
{
int i;
for( i = 0; i < node->NumAttachedComponents(); i++ )
{
plComponentBase* comp = node->GetAttachedComponent(i);
if( comp && comp->ClassID() == LIGHTGRP_COMP_CID )
return (plLightGrpComponent*)comp;
}
return nil;
}
hsBool plLightGrpComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
const char* dbgNodeName = node->GetName();
if( !fValid )
return true;
if( !IGetLightInfos() )
return true;
if( !node->GetDrawable() )
return true;
if( !node->GetSceneObject() || !node->GetSceneObject()->GetDrawInterface() )
return true;
// If it's shaded as a character, ignore any light groups attached.
if( node->GetItinerant() )
return true;
IAddLightsToSpans(node, pErrMsg);
return true;
}
hsBool plLightGrpComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg)
{
fValid = false;
fLightInfos.Reset();
fLightNodes.Reset();
int i;
for( i = 0; i < NumTargets(); i++ )
{
plMaxNodeBase* liNode = GetTarget(i);
if( liNode && liNode->CanConvert() )
{
Object *obj = liNode->GetObjectRef();
if( obj )
{
Class_ID cid = obj->ClassID();
if( (cid == RTSPOT_LIGHT_CLASSID)
|| (cid == RTOMNI_LIGHT_CLASSID)
|| (cid == RTDIR_LIGHT_CLASSID)
|| (cid == RTPDIR_LIGHT_CLASSID) )
{
fLightNodes.Append((plMaxNode*)liNode);
}
}
}
}
if( !fLightNodes.GetCount() )
return true;
fValid = true;
return true;
}
hsBool plLightGrpComponent::PreConvert(plMaxNode* pNode, plErrorMsg* pErrMsg)
{
if( !fValid )
return true;
fValid = false;
fValid = true;
return true;
}

View File

@ -0,0 +1,82 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLightGrpComponent_inc
#define plLightGrpComponent_inc
const Class_ID LIGHTGRP_COMP_CID(0x42d57a80, 0xd3a3745);
class plMaxNode;
class plLightInfo;
class plErrorMsg;
class plDrawableSpans;
//Class that accesses the paramblock below.
class plLightGrpComponent : public plComponent
{
private:
hsBool fValid;
hsTArray<plMaxNode*> fLightNodes;
hsTArray<plLightInfo*> fLightInfos;
hsBool IAddLightsToSpans(plMaxNode* pNode, plErrorMsg* pErrMsg);
hsBool ISendItOff(plLightInfo* liInfo, plDrawableSpans* drawable, UInt32 diIndex);
hsBool IGetLightInfos();
public:
plLightGrpComponent();
hsBool SetupProperties(plMaxNode* pNode, plErrorMsg* pErrMsg);
hsBool PreConvert(plMaxNode* pNode, plErrorMsg* pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
const hsTArray<plLightInfo*>& GetLightInfos();
IOResult Load(ILoad* iload);
static plLightGrpComponent* GetComp(plMaxNode* node);
};
#endif // plLightGrpComponent_inc

View File

@ -0,0 +1,205 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "max.h"
#include "resource.h"
#include "plComponent.h"
#include "plComponentReg.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "../MaxMain/plMaxNode.h"
#include "hsResMgr.h"
#include "../plDrawable/plGeometrySpan.h"
#include "plLightMapComponent.h"
void DummyCodeIncludeFuncLightMap()
{
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// LightMap Component
//
//
//
//
//Max desc stuff necessary below.
CLASS_DESC(plLightMapComponent, gLightMapDesc, "Light Map", "LightMap", COMP_TYPE_GRAPHICS, LIGHTMAP_COMP_CID)
enum
{
kMapChannel, //Inserted in v1
kResolutionLevelRadio, //Inserted in v1, removed in v2
kResSpinControl, //Inserted in v2
kMapInitColor,
kCompress,
kShared
};
ParamBlockDesc2 gLightMapBk
(
plComponent::kBlkComp, _T("lightMap"), 0, &gLightMapDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_LIGHTMAP, IDS_COMP_LIGHTMAPS, 0, 0, NULL,
kMapChannel, _T("UVW Channel Light Map"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_COMP_LIGHTMAP_EDIT1, IDC_COMP_LIGHTMAP_SPIN1, 0.4,
p_default, 1,
p_range, 1, plGeometrySpan::kMaxNumUVChannels,
end,
//
// kResolutionLevelRadio, _T("Resolution Level"), TYPE_INT, 0, 0,
// p_ui, TYPE_RADIO, 5, IDC_RADIO_LM1, IDC_RADIO_LM2, IDC_RADIO_LM3, IDC_RADIO_LM4, IDC_RADIO_LM5,
// p_vals, 0, 1, 2, 3, 4,
// p_default, 2,
//
//
kResSpinControl, _T("Resolution Spinner"), TYPE_INT, 0, 0,
p_ui, TYPE_SLIDER, EDITTYPE_INT, IDC_COMP_LM_DUMMY, IDC_COMP_LIGHT_SLIDER, 4,
p_range, 0, 4,
p_default, 2,
end,
kMapInitColor, _T("Initial map color"), TYPE_RGBA, 0, 0,
p_ui, TYPE_COLORSWATCH, IDC_COMP_LIGHTMAP_COLOR,
p_default, Color(0,0,0),
end,
kCompress, _T("Compress"), TYPE_BOOL, 0, 0,
p_default, TRUE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LIGHTMAP_COMPRESS,
end,
kShared, _T("Shared"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LIGHTMAP_SHARED,
end,
end
);
plLightMapComponent::plLightMapComponent()
: fLightMapKey(nil)
{
fClassDesc = &gLightMapDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plLightMapComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
return true;
}
hsBool plLightMapComponent::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg)
{
fLightMapKey = nil;
return true;
}
hsBool plLightMapComponent::PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg)
{
return true;
}
float plLightMapComponent::GetScale() const
{
int resBut = fCompPB->GetInt(kResSpinControl);
float res = 1.f;
switch( resBut )
{
case 4:
res = 9.f;
break;
case 3:
res = 3.f;
break;
default:
case 2:
res = 1.f;
break;
case 1:
res = 0.5f;
break;
case 0:
res = 0.25f;
break;
}
return res;
}
UInt32 plLightMapComponent::GetUVWSrc() const
{
return fCompPB->GetInt(kMapChannel)-1;
}
hsBool plLightMapComponent::GetCompress() const
{
return fCompPB->GetInt(kCompress);
}
hsBool plLightMapComponent::GetShared() const
{
return fCompPB->GetInt(kShared);
}
hsColorRGBA plLightMapComponent::GetInitColor() const
{
Color color = fCompPB->GetColor(kMapInitColor);
hsColorRGBA col;
col.Set(color.r, color.g, color.b, 1.f);
return col;
}

View File

@ -0,0 +1,79 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLightMapComponent_inc
#define plLightMapComponent_inc
#include "plComponent.h"
#include "hsColorRGBA.h"
class plMipmap;
const Class_ID LIGHTMAP_COMP_CID(0x1b1d0317, 0x3b3821db);
class plLightMapComponent : public plComponent
{
protected:
plKey fLightMapKey;
public:
plLightMapComponent();
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
void SetLightMapKey(const plKey& key) { fLightMapKey = key; }
plKey GetLightMapKey() const { return fLightMapKey; }
float GetScale() const;
UInt32 GetUVWSrc() const;
hsBool GetCompress() const;
hsBool GetShared() const;
hsColorRGBA GetInitColor() const;
};
#endif // plLightMapComponent_inc

View File

@ -0,0 +1,858 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "max.h"
#include "resource.h"
#include "plComponent.h"
#include "plComponentReg.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "../MaxConvert/hsConverterUtils.h"
#include "../MaxConvert/hsControlConverter.h"
#include "../plInterp/plController.h"
#include "../MaxMain/plMaxNode.h"
#include "../pnKeyedObject/plKey.h"
#include "plgDispatch.h"
#include "../MaxMain/plPluginResManager.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
// Swivel related
#include "../pfAnimation/plViewFaceModifier.h" // ViewFace Comp
// Line Follow related
#include "../plInterp/plAnimPath.h"
#include "../pfAnimation/plLineFollowMod.h"
#include "../pfAnimation/plFollowMod.h"
#include "../pnMessage/plRefMsg.h"
// Stereizer
#include "../pfAnimation/plStereizer.h"
const Class_ID STEREIZE_COMP_CID(0x15066ec7, 0x64ea7381);
const Class_ID LINEFOLLOW_COMP_CID(0x64ec57f6, 0x292d47f6);
const Class_ID SWIVEL_COMP_CID(0x106a466b, 0x1c1700f7);
void DummyCodeIncludeFuncLineFollow()
{
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// LineFollow Component
//
//
enum
{
kFollowModeRadio,
kPathObjectSel,
kFollowObjectSel,
kOffsetActive,
kOffsetDegrees,
kOffsetClampActive,
kOffsetClamp,
kForceToLine,
kSpeedClampActive,
kSpeedClamp
};
// When one of our parameters that is a ref changes, send out the component ref
// changed message. Normally, messages from component refs are ignored since
// they pass along all the messages of the ref, which generates a lot of false
// converts.
class plLineObjAccessor : public PBAccessor
{
public:
void Set(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
if( (id == kFollowObjectSel) || (id == kPathObjectSel) )
{
plComponentBase* comp = (plComponentBase*)owner;
comp->NotifyDependents(FOREVER, PART_ALL, REFMSG_USER_COMP_REF_CHANGED);
}
}
};
plLineObjAccessor gLineObjAccessor;
class plLineFollowComponentProc : public ParamMap2UserDlgProc
{
public:
BOOL DlgProc(TimeValue t, IParamMap2* map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
IParamBlock2* pb = map->GetParamBlock();
map->SetTooltip(kPathObjectSel, TRUE, "Press the button, & select the path source object in one of the Viewports" );
map->SetTooltip(kFollowObjectSel, TRUE, "Press the button, & select the object to follow in one of the Viewports" );
map->SetTooltip(kOffsetDegrees, TRUE, "Positive angle to right, negative to left." );
if( pb->GetInt(kFollowModeRadio) == plLineFollowMod::kFollowObject )
map->Enable(kFollowObjectSel, TRUE);
else
map->Enable(kFollowObjectSel, FALSE);
}
return true;
//////////////////
case WM_COMMAND:
{
if( (LOWORD(wParam) == IDC_RADIO_LISTENER)
|| (LOWORD(wParam) == IDC_RADIO_CAMERA)
|| (LOWORD(wParam) == IDC_RADIO_OBJECT) )
{
IParamBlock2* pb = map->GetParamBlock();
if( pb->GetInt(kFollowModeRadio) == plLineFollowMod::kFollowObject )
map->Enable(kFollowObjectSel, TRUE);
else
map->Enable(kFollowObjectSel, FALSE);
return true;
}
}
}
return false;
}
void DeleteThis() {}
};
static plLineFollowComponentProc gLineFollowProc;
//Class that accesses the paramblock below.
class plLineFollowComponent : public plComponent
{
private:
hsBool fValid;
plLineFollowMod* fLineMod;
hsBool IMakeLineMod(plMaxNode* pNode, plErrorMsg* pErrMsg);
public:
plLineFollowComponent();
hsBool SetupProperties(plMaxNode* pNode, plErrorMsg* pErrMsg);
hsBool PreConvert(plMaxNode* pNode, plErrorMsg* pErrMsg);
hsBool Convert(plMaxNode* node, plErrorMsg* pErrMsg);
plLineFollowMod* GetLineMod(plErrorMsg* pErrMsg);
};
CLASS_DESC(plLineFollowComponent, gLineFollowDesc, "LineFollow", "LineFollow", COMP_TYPE_GRAPHICS, LINEFOLLOW_COMP_CID)
ParamBlockDesc2 gLineFollowBk
(
plComponent::kBlkComp, _T("LineFollow"), 0, &gLineFollowDesc, P_AUTO_CONSTRUCT+P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_LINEFOLLOW, IDS_COMP_LINEFOLLOWS, 0, 0, &gLineFollowProc,
kFollowModeRadio, _T("FollowMode"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_RADIO_LISTENER, IDC_RADIO_CAMERA, IDC_RADIO_OBJECT,
p_vals, plLineFollowMod::kFollowListener, plLineFollowMod::kFollowCamera, plLineFollowMod::kFollowObject,
p_default, plLineFollowMod::kFollowListener,
end,
kPathObjectSel, _T("PathObjectChoice"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_LINE_CHOOSE_PATH,
p_prompt, IDS_COMP_LINE_CHOSE_PATH,
p_accessor, &gLineObjAccessor,
end,
kFollowObjectSel, _T("FollowObjectChoice"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_LINE_CHOOSE_OBJECT,
p_prompt, IDS_COMP_LINE_CHOSE_OBJECT,
p_accessor, &gLineObjAccessor,
end,
kOffsetActive, _T("OffsetActive"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LINE_OFFSETACTIVE,
p_enable_ctrls, 4, kOffsetDegrees, kOffsetClampActive, kOffsetClamp, kForceToLine,
end,
kOffsetDegrees, _T("OffsetDegrees"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -85.0, 85.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_COMP_LINE_OFFSETDEGREES, IDC_COMP_LINE_OFFSETDEGREES_SPIN, 1.0,
end,
kOffsetClampActive, _T("OffsetClampActive"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LINE_OFFSETCLAMPACTIVE,
p_enable_ctrls, 1, kOffsetClamp,
end,
kOffsetClamp, _T("OffsetClamp"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_LINE_OFFSETCLAMP, IDC_COMP_LINE_OFFSETCLAMP_SPIN, 1.0,
end,
kForceToLine, _T("ForceToLine"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LINE_FORCETOLINE,
end,
kSpeedClampActive, _T("SpeedClampActive"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LINE_SPEEDCLAMPACTIVE,
p_enable_ctrls, 1, kSpeedClamp,
end,
kSpeedClamp, _T("SpeedClamp"), TYPE_FLOAT, 0, 0,
p_default, 30.0,
p_range, 3.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_LINE_SPEEDCLAMP, IDC_COMP_LINE_SPEEDCLAMP_SPIN, 1.0,
end,
end
);
plLineFollowComponent::plLineFollowComponent()
: fValid(false),
fLineMod(nil)
{
fClassDesc = &gLineFollowDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plLineFollowComponent::IMakeLineMod(plMaxNode* pNode, plErrorMsg* pErrMsg)
{
plLineFollowMod::FollowMode mode = plLineFollowMod::FollowMode(fCompPB->GetInt(kFollowModeRadio));
plLineFollowMod* lineMod = TRACKED_NEW plLineFollowMod;
hsgResMgr::ResMgr()->NewKey(IGetUniqueName(pNode), lineMod, pNode->GetLocation());
if( plLineFollowMod::kFollowObject == mode )
{
if(fCompPB->GetINode(kFollowObjectSel) != NULL)
{
plMaxNode* targNode = (plMaxNode*)fCompPB->GetINode(kFollowObjectSel);
//plMaxNodeData* pMD = targNode->GetMaxNodeData();
if( targNode->CanConvert() )
{
plSceneObject* targObj = targNode->GetSceneObject();
if( targObj )
{
plGenRefMsg* refMsg = TRACKED_NEW plGenRefMsg(lineMod->GetKey(), plRefMsg::kOnCreate, 0, plLineFollowMod::kRefObject);
hsgResMgr::ResMgr()->AddViaNotify(targObj->GetKey(), refMsg, plRefFlags::kPassiveRef);
lineMod->SetFollowMode(plLineFollowMod::kFollowObject);
}
}
}
}
else
{
lineMod->SetFollowMode(mode);
}
plMaxNode* pathNode = (plMaxNode*)fCompPB->GetINode(kPathObjectSel);
if(!pathNode)
{
pErrMsg->Set(true, "Path Node Failure", "Path Node %s was set to be Ignored or empty. Path Component ignored.", ((INode*)pathNode)->GetName()).Show();
pErrMsg->Set(false);
return false;
}
//hsAssert(pathNode, "If valid is true, this must be set");
Control* maxTm = pathNode->GetTMController();
plCompoundController* tmc = hsControlConverter::Instance().MakeTransformController(maxTm, pathNode);
Matrix3 w2p(true);
Matrix3 l2w = pathNode->GetNodeTM(TimeValue(0));
if( !pathNode->GetParentNode()->IsRootNode() )
w2p = Inverse(pathNode->GetParentNode()->GetNodeTM(TimeValue(0)));
hsMatrix44 loc2Par = pathNode->Matrix3ToMatrix44(l2w * w2p);
gemAffineParts ap;
decomp_affine(loc2Par.fMap, &ap);
hsAffineParts initParts;
AP_SET(initParts, ap);
plAnimPath* animPath = TRACKED_NEW plAnimPath;
animPath->SetController(tmc);
animPath->InitParts(initParts);
lineMod->SetPath(animPath);
if( !pathNode->GetParentNode()->IsRootNode() )
{
plMaxNode* parNode = (plMaxNode*)pathNode->GetParentNode();
plSceneObject* parObj = parNode->GetSceneObject();
if( parObj )
{
plGenRefMsg* refMsg = TRACKED_NEW plGenRefMsg(lineMod->GetKey(), plRefMsg::kOnCreate, 0, plLineFollowMod::kRefParent);
hsgResMgr::ResMgr()->AddViaNotify(parObj->GetKey(), refMsg, plRefFlags::kPassiveRef);
}
}
if( fCompPB->GetInt(kOffsetActive) )
{
lineMod->SetOffsetDegrees(fCompPB->GetFloat(kOffsetDegrees));
if( fCompPB->GetInt(kOffsetClampActive) )
{
lineMod->SetOffsetClamp(fCompPB->GetFloat(kOffsetClamp));
}
lineMod->SetForceToLine(fCompPB->GetInt(kForceToLine));
}
if( fCompPB->GetInt(kSpeedClampActive) )
{
lineMod->SetSpeedClamp(fCompPB->GetFloat(kSpeedClamp));
}
fLineMod = lineMod;
return true;
}
plLineFollowMod* plLineFollowComponent::GetLineMod(plErrorMsg* pErrMsg)
{
if( !fValid )
return nil;
if( !fLineMod )
{
int i;
for( i = 0; i < NumTargets(); i++ )
{
plMaxNode* targ = (plMaxNode*)GetTarget(i);
IMakeLineMod(targ, pErrMsg);
if( fLineMod )
break;
}
}
return fLineMod;
}
hsBool plLineFollowComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg)
{
if( !fValid )
return true;
if( !fLineMod )
{
if( !IMakeLineMod(node, pErrMsg) )
{
fValid = false;
return true;
}
}
node->AddModifier(fLineMod, IGetUniqueName(node));
return true;
}
hsBool plLineFollowComponent::SetupProperties(plMaxNode* pNode, plErrorMsg* pErrMsg)
{
fValid = false;
fLineMod = nil;
if( !fCompPB->GetINode(kPathObjectSel) )
{
return true;
}
plMaxNode* pathNode = (plMaxNode*)fCompPB->GetINode(kPathObjectSel);
if( !pathNode )
{
return true;
}
if( !pathNode->IsTMAnimated() )
{
return true;
}
pathNode->SetCanConvert(false);
if( plLineFollowMod::kFollowObject == fCompPB->GetInt(kFollowModeRadio) )
{
if( !fCompPB->GetINode(kFollowObjectSel) )
{
return true;
}
}
fValid = true;
pNode->SetForceLocal(true);
pNode->SetMovable(true);
return true;
}
hsBool plLineFollowComponent::PreConvert(plMaxNode* pNode, plErrorMsg* pErrMsg)
{
if( !fValid )
return true;
fValid = false;
if( plLineFollowMod::kFollowObject == fCompPB->GetInt(kFollowModeRadio) )
{
plMaxNode* followNode = (plMaxNode*)fCompPB->GetINode(kFollowObjectSel);
if( !followNode->CanConvert() )
{
return true;
}
}
plMaxNode* pathNode = (plMaxNode*)fCompPB->GetINode(kPathObjectSel);
if( !pathNode->GetParentNode()->IsRootNode() )
{
if( !((plMaxNode*)pathNode->GetParentNode())->CanConvert() )
{
return true;
}
}
fValid = true;
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
// The stereizer component is sort of related to LineFollow. Really.
class plStereizeComp : public plComponent
{
public:
enum
{
kLeft,
kAmbientDist,
kTransition,
kSepAngle,
kMaxDist,
kMinDist
};
plLineFollowMod* ISetMaster(plStereizer* stereo, plMaxNode* node, plErrorMsg* pErrMsg);
public:
plStereizeComp();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg);
virtual hsBool PreConvert(plMaxNode* node, plErrorMsg* pErrMsg);
virtual hsBool Convert(plMaxNode* node, plErrorMsg* pErrMsg);
hsBool Bail(plMaxNode* node, const char* msg, plErrorMsg* pErrMsg);
};
CLASS_DESC(plStereizeComp, gStereizeDesc, "Stereo-ize", "Stereize", COMP_TYPE_AUDIO, STEREIZE_COMP_CID)
ParamBlockDesc2 gStereizeBk
(
plComponent::kBlkComp, _T("Stereize"), 0, &gStereizeDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_STEREIZE, IDS_COMP_STEREIZE, 0, 0, NULL,
plStereizeComp::kLeft, _T("Left"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_STEREIZE_LEFT,
end,
plStereizeComp::kAmbientDist, _T("AmbientDist"), TYPE_FLOAT, 0, 0,
p_default, 50.0,
p_range, 0.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_STEREIZE_AMB, IDC_COMP_STEREIZE_AMB_SPIN, 1.0,
end,
plStereizeComp::kTransition, _T("Transition"), TYPE_FLOAT, 0, 0,
p_default, 25.0,
p_range, 1.0, 500.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_STEREIZE_TRANS, IDC_COMP_STEREIZE_TRANS_SPIN, 1.0,
end,
plStereizeComp::kSepAngle, _T("SepAngle"), TYPE_FLOAT, 0, 0,
p_default, 30.0,
p_range, 1.0, 80.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_STEREIZE_ANG, IDC_COMP_STEREIZE_ANG_SPIN, 1.0,
end,
plStereizeComp::kMaxDist, _T("MaxDist"), TYPE_FLOAT, 0, 0,
p_default, 100.0,
p_range, 1.0, 1000.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_STEREIZE_MAXDIST, IDC_COMP_STEREIZE_MAXDIST_SPIN, 1.0,
end,
plStereizeComp::kMinDist, _T("MinDist"), TYPE_FLOAT, 0, 0,
p_default, 5.0,
p_range, 1.0, 50.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_STEREIZE_MINDIST, IDC_COMP_STEREIZE_MINDIST_SPIN, 1.0,
end,
end
);
plStereizeComp::plStereizeComp()
{
fClassDesc = &gStereizeDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plStereizeComp::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
node->SetForceLocal(true);
if( !node->GetParentNode()->IsRootNode() )
((plMaxNode*)node->GetParentNode())->SetForceLocal(true);
return true;
}
hsBool plStereizeComp::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
hsBool plStereizeComp::Bail(plMaxNode* node, const char* msg, plErrorMsg* pErrMsg)
{
pErrMsg->Set(true, node->GetName(), msg).CheckAndAsk();
pErrMsg->Set(false);
return true;
}
hsBool plStereizeComp::Convert(plMaxNode* node, plErrorMsg* pErrMsg)
{
plStereizer* stereo = TRACKED_NEW plStereizer;
stereo->SetAmbientDist(fCompPB->GetFloat(kAmbientDist));
stereo->SetTransition(fCompPB->GetFloat(kTransition));
hsScalar ang = fCompPB->GetFloat(kSepAngle);
if( ang > 80.f )
ang = 80.f;
stereo->SetSepAngle(hsScalarDegToRad(ang));
stereo->SetMaxSepDist(fCompPB->GetFloat(kMaxDist));
stereo->SetMinSepDist(fCompPB->GetFloat(kMinDist));
stereo->SetParentInitPos(node->GetLocalToParent44().GetTranslate());
stereo->SetAsLeftChannel(fCompPB->GetInt(kLeft));
node->AddModifier(stereo, IGetUniqueName(node));
// Do this after AddModifier, cuz that's when stereo gets a plKey.
ISetMaster(stereo, node, pErrMsg);
return true;
}
plLineFollowMod* plStereizeComp::ISetMaster(plStereizer* stereo, plMaxNode* node, plErrorMsg* pErrMsg)
{
int numComp = node->NumAttachedComponents(false);
int i;
for( i = 0; i < numComp; i++ )
{
plComponentBase *comp = node->GetAttachedComponent(i);
if( comp && (comp->ClassID() == LINEFOLLOW_COMP_CID) )
{
plLineFollowComponent* lineComp = (plLineFollowComponent*)comp;
plLineFollowMod* lineMod = lineComp->GetLineMod(pErrMsg);
if( lineMod )
{
lineMod->AddStereizer(stereo->GetKey());
return lineMod;
}
}
}
return nil;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
// The swivel component is also sort of related to LineFollow. And stereizer. Really.
class plSwivelComp : public plComponent
{
public:
enum
{
kFaceTypeRadio,
kFaceObjectSel,
kPivotY,
kOffsetActive,
kOffsetX,
kOffsetY,
kOffsetZ,
kOffsetLocal
};
enum
{
kFaceCamera,
kFaceListener,
kFacePlayer,
kFaceObject
};
public:
plSwivelComp();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg);
virtual hsBool PreConvert(plMaxNode* node, plErrorMsg* pErrMsg);
virtual hsBool Convert(plMaxNode* node, plErrorMsg* pErrMsg);
hsBool Bail(plMaxNode* node, const char* msg, plErrorMsg* pErrMsg);
};
class plSwivelComponentProc : public ParamMap2UserDlgProc
{
public:
BOOL DlgProc(TimeValue t, IParamMap2* map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
IParamBlock2* pb = map->GetParamBlock();
if( pb->GetInt(plSwivelComp::kFaceTypeRadio) == plSwivelComp::kFaceObject )
map->Enable(plSwivelComp::kFaceObjectSel, TRUE);
else
map->Enable(plSwivelComp::kFaceObjectSel, FALSE);
}
return true;
//////////////////
case WM_COMMAND:
{
if( (LOWORD(wParam) == IDC_RADIO_LISTENER)
|| (LOWORD(wParam) == IDC_RADIO_PLAYER)
|| (LOWORD(wParam) == IDC_RADIO_CAMERA)
|| (LOWORD(wParam) == IDC_RADIO_OBJECT) )
{
IParamBlock2* pb = map->GetParamBlock();
if( pb->GetInt(plSwivelComp::kFaceTypeRadio) == plSwivelComp::kFaceObject )
map->Enable(plSwivelComp::kFaceObjectSel, TRUE);
else
map->Enable(plSwivelComp::kFaceObjectSel, FALSE);
return true;
}
}
}
return false;
}
void DeleteThis() {}
};
static plSwivelComponentProc gSwivelProc;
CLASS_DESC(plSwivelComp, gSwivelDesc, "Swivel", "Swivel", COMP_TYPE_GRAPHICS, SWIVEL_COMP_CID)
ParamBlockDesc2 gSwivelBk
(
plComponent::kBlkComp, _T("Swivel"), 0, &gSwivelDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_SWIVEL, IDS_COMP_SWIVEL, 0, 0, &gSwivelProc,
plSwivelComp::kFaceTypeRadio, _T("FaceType"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 4, IDC_RADIO_CAMERA, IDC_RADIO_LISTENER, IDC_RADIO_PLAYER, IDC_RADIO_OBJECT,
p_vals, plSwivelComp::kFaceCamera, plSwivelComp::kFaceListener, plSwivelComp::kFacePlayer, plSwivelComp::kFaceObject,
p_default, plSwivelComp::kFacePlayer,
end,
plSwivelComp::kFaceObjectSel, _T("FaceObjectChoice"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_CHOOSE_OBJECT,
p_prompt, IDS_COMP_CHOOSE_OBJECT,
end,
plSwivelComp::kPivotY, _T("PivotY"), TYPE_BOOL, 0, 0,
p_default, TRUE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_PIVOTY,
end,
plSwivelComp::kOffsetActive, _T("OffsetActive"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_OFFSETACTIVE,
p_enable_ctrls, 4, plSwivelComp::kOffsetX, plSwivelComp::kOffsetY, plSwivelComp::kOffsetZ, plSwivelComp::kOffsetLocal,
end,
plSwivelComp::kOffsetX, _T("X"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.0, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_OFFSETX, IDC_COMP_OFFSETX_SPIN, 1.0,
end,
plSwivelComp::kOffsetY, _T("Y"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.0, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_OFFSETY, IDC_COMP_OFFSETY_SPIN, 1.0,
end,
plSwivelComp::kOffsetZ, _T("Z"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, 0.0, 100.0,
p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
IDC_COMP_OFFSETZ, IDC_COMP_OFFSETZ_SPIN, 1.0,
end,
plSwivelComp::kOffsetLocal, _T("OffsetLocal"), TYPE_BOOL, 0, 0,
p_default, TRUE,
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_OFFSETLOCAL,
end,
end
);
plSwivelComp::plSwivelComp()
{
fClassDesc = &gSwivelDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plSwivelComp::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
node->SetForceLocal(true);
node->SetMovable(true);
return true;
}
hsBool plSwivelComp::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
hsBool plSwivelComp::Bail(plMaxNode* node, const char* msg, plErrorMsg* pErrMsg)
{
pErrMsg->Set(true, node->GetName(), msg).CheckAndAsk();
pErrMsg->Set(false);
return true;
}
hsBool plSwivelComp::Convert(plMaxNode* node, plErrorMsg* pErrMsg)
{
plViewFaceModifier* pMod = TRACKED_NEW plViewFaceModifier;
pMod->SetOrigTransform(node->GetLocalToParent44(), node->GetParentToLocal44());
node->AddModifier(pMod, IGetUniqueName(node));
if( fCompPB->GetInt(kPivotY) )
pMod->SetFlag(plViewFaceModifier::kPivotY);
else
pMod->SetFlag(plViewFaceModifier::kPivotFace);
switch( fCompPB->GetInt(kFaceTypeRadio) )
{
case kFaceCamera:
pMod->SetFollowMode(plViewFaceModifier::kFollowCamera);
break;
case kFaceListener:
pMod->SetFollowMode(plViewFaceModifier::kFollowListener);
break;
case kFacePlayer:
pMod->SetFollowMode(plViewFaceModifier::kFollowPlayer);
break;
case kFaceObject:
{
plMaxNode* targNode = (plMaxNode*)fCompPB->GetINode(kFaceObjectSel);
if( targNode && targNode->CanConvert() )
{
pMod->SetFollowMode(plViewFaceModifier::kFollowObject, targNode->GetKey());
}
else
{
pErrMsg->Set(true, node->GetName(), "Swivel to look at component %s has no Plasma object to look at.", GetINode()->GetName()).Show();
pErrMsg->Set(false);
pMod->SetFollowMode(plViewFaceModifier::kFollowCamera);
}
}
break;
}
pMod->SetOffsetActive(fCompPB->GetInt(kOffsetActive));
if( fCompPB->GetInt(kOffsetActive) )
{
hsVector3 off(fCompPB->GetFloat(kOffsetX), fCompPB->GetFloat(kOffsetY), fCompPB->GetFloat(kOffsetZ));
pMod->SetOffset(off, fCompPB->GetInt(kOffsetLocal));
}
return true;
}

View File

@ -0,0 +1,385 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "Max.h"
#include "notetrck.h"
#include "hsTypes.h"
#include "hsTemplates.h"
#include "plMaxAnimUtils.h"
#include "../MaxExport/plErrorMsg.h"
float TimeValueToGameTime(TimeValue t)
{
int FR = ::GetFrameRate();
int TPF = ::GetTicksPerFrame();
int TPS = TPF*FR;
return float(t)/float(TPS);
}
bool GetSegMapAnimTime(const char *animName, SegmentMap *segMap, SegmentSpec::SegType type, float& begin, float& end)
{
if (segMap)
{
if (animName && segMap->find(animName) != segMap->end())
{
SegmentSpec *spec = (*segMap)[animName];
if (spec->fType == type)
{
if (spec->fStart != -1)
begin = spec->fStart;
if (spec->fEnd != -1)
end = spec->fEnd;
return true;
}
}
}
return false;
}
SegmentMap *GetSharedAnimSegmentMap(std::vector<Animatable*>& anims, plErrorMsg *pErrorMsg)
{
if (anims.empty())
return nil;
SegmentMap *segMap = GetAnimSegmentMap(anims[0], pErrorMsg);
if (!segMap)
return nil;
int i;
for (i = 1; i < anims.size(); i++)
{
SegmentMap *curSegMap = GetAnimSegmentMap(anims[i], pErrorMsg);
// This node doesn't have a segmap, so we can't have any anims shared among all the nodes.
if (!curSegMap)
{
DeleteSegmentMap(segMap);
return nil;
}
if (segMap->begin() == segMap->end())
{
DeleteSegmentMap(segMap);
return nil;
}
SegmentMap::iterator it = segMap->begin();
while (it != segMap->end())
{
if (curSegMap->find(it->second->fName) == curSegMap->end())
{
SegmentMap::iterator del = it;
it++;
segMap->erase(del->second->fName);
}
else
it++;
}
DeleteSegmentMap(curSegMap);
}
return segMap;
}
SegmentSpec::SegmentSpec(float start, float end, char * name, SegType type) :
fStart(start), fEnd(end), fName(name), fType(type), fInitial(-1)
{
}
SegmentSpec::~SegmentSpec()
{
delete [] fName;
}
// constants used for parsing the note tracks
enum NoteType
{
kNoteStartAnim,
kNoteEndAnim,
kNoteStartLoop,
kNoteEndLoop,
kNoteMarker,
kNoteStopPoint,
kNoteInitial,
kNoteUnknown,
kNoteSuppress,
};
SegmentSpec::SegmentSpec()
{
fStart = -1;
fEnd = -1;
fInitial = -1;
fName = nil;
fType = kAnim;
}
bool SegmentSpec::Contains(SegmentSpec *spec)
{
if (!spec)
return false;
if (spec->fType == kMarker || spec->fType == kStopPoint)
return (spec->fStart >= fStart && spec->fStart <= fEnd);
if (fStart == -1 || fEnd == -1)
return false;
if (spec->fStart == -1)
return (fStart < spec->fEnd);
if (spec->fEnd == -1)
return (fEnd > spec->fStart);
if (fStart <= spec->fStart && fEnd >= spec->fEnd)
return true;
return false;
}
bool DoesHaveStopPoints(Animatable *anim)
{
if (!anim || !anim->HasNoteTracks())
return false;
int numTracks = anim->NumNoteTracks();
for (int i = 0; i < numTracks; i++)
{
DefNoteTrack *track = (DefNoteTrack *)anim->GetNoteTrack(i);
int numKeys = track->keys.Count();
for (int j = 0; j < numKeys; j++)
{
char buf[256];
strcpy(buf, track->keys[j]->note);
strlwr(buf);
if (strstr(buf, "@stoppoint"))
return true;
}
}
return false;
}
void GetSegment(const char *note, float time, SegmentMap *segMap, plErrorMsg *pErrMsg)
{
char segName[256];
char segSuffix[256];
int matchedFields = sscanf(note, " %[^@] @ %s ", segName, segSuffix);
if (matchedFields == 2)
{
NoteType type = kNoteUnknown;
if (!stricmp(segSuffix, "start") ||
!stricmp(segSuffix, "begin"))
type = kNoteStartAnim;
else if (!stricmp(segSuffix, "end"))
type = kNoteEndAnim;
else if (!stricmp(segSuffix, "startloop") ||
!stricmp(segSuffix, "loopstart") ||
!stricmp(segSuffix, "beginloop") ||
!stricmp(segSuffix, "loopbegin"))
type = kNoteStartLoop;
else if (!stricmp(segSuffix, "endloop") ||
!stricmp(segSuffix, "loopend"))
type = kNoteEndLoop;
else if (!stricmp(segSuffix, "marker"))
type = kNoteMarker;
else if (!stricmp(segSuffix, "stoppoint"))
type = kNoteStopPoint;
else if (!stricmp(segSuffix, "initial"))
type = kNoteInitial;
else if (!stricmp(segSuffix, "suppress"))
type = kNoteSuppress;
if (type == kNoteUnknown)
{
if (pErrMsg)
{
pErrMsg->Set(true, "NoteTrack Anim Error", "Malformed segment note: %s", segName);
pErrMsg->Show();
pErrMsg->Set();
}
}
else
{
SegmentMap::iterator existing = segMap->find(segName);
SegmentSpec *existingSpec = (existing != segMap->end()) ? (*existing).second : nil;
const char *kErrorTitle = "NoteTrack Anim Error";
if (existingSpec)
{
// an existing spec, but we're processing a start note?
if (type == kNoteStartAnim && pErrMsg)
{
pErrMsg->Set(true, kErrorTitle, "Got out of order start note. No Start given for %s", segName).Show();
pErrMsg->Set();
}
// existing spec, has an end, we're also processing an end?
else if (type == kNoteEndAnim && existingSpec->fEnd != -1 && pErrMsg)
{
pErrMsg->Set(true, kErrorTitle, "Got two ends for the same segment %s", segName).Show();
pErrMsg->Set();
}
else if (type == kNoteStartLoop && existingSpec->fStart != -1 && pErrMsg)
{
pErrMsg->Set(true, kErrorTitle, "Got two loop starts for the same segment, %s", segName).Show();
pErrMsg->Set();
}
else if (type == kNoteEndLoop && existingSpec->fEnd != -1 && pErrMsg)
{
pErrMsg->Set(true, kErrorTitle, "Got two loop ends for the same segment, %s", segName).Show();
pErrMsg->Set();
}
else if (type == kNoteMarker && pErrMsg)
{
pErrMsg->Set(true, kErrorTitle, "Marker has the same name (%s) as another spec in its notetrack", segName).Show();
pErrMsg->Set();
}
else if (type == kNoteStopPoint && pErrMsg)
{
pErrMsg->Set(true, kErrorTitle, "Stop point has the same name (%s) as another spec in its notetrack", segName).Show();
pErrMsg->Set();
}
if (type == kNoteEndAnim || type == kNoteEndLoop)
existingSpec->fEnd = time;
else if (type == kNoteStartLoop)
existingSpec->fStart = time;
else if (type == kNoteInitial)
existingSpec->fInitial = time;
}
else
{
if (type == kNoteEndAnim && pErrMsg)
{
pErrMsg->Set(true, kErrorTitle, "Got an end note without a corresponding start. Ignoring %s", segName).Show();
pErrMsg->Set();
}
else
{
char *nameCopy = TRACKED_NEW char[strlen(segName)+1];
strcpy(nameCopy, segName);
switch (type)
{
case kNoteStartAnim:
(*segMap)[nameCopy] = TRACKED_NEW SegmentSpec(time, -1, nameCopy, SegmentSpec::kAnim);
break;
case kNoteStartLoop:
(*segMap)[nameCopy] = TRACKED_NEW SegmentSpec(time, -1, nameCopy, SegmentSpec::kLoop);
break;
case kNoteEndLoop:
(*segMap)[nameCopy] = TRACKED_NEW SegmentSpec(-1, time, nameCopy, SegmentSpec::kLoop);
break;
case kNoteMarker:
(*segMap)[nameCopy] = TRACKED_NEW SegmentSpec(time, -1, nameCopy, SegmentSpec::kMarker);
break;
case kNoteStopPoint:
(*segMap)[nameCopy] = TRACKED_NEW SegmentSpec(time, -1, nameCopy, SegmentSpec::kStopPoint);
break;
case kNoteSuppress:
(*segMap)[nameCopy] = TRACKED_NEW SegmentSpec(-1, -1, nameCopy, SegmentSpec::kSuppress);
break;
default:
delete [] nameCopy;
break;
}
}
}
}
}
}
// Read through all the notes in all the note tracks on the given node
// Check the contents of each node for a name like "walk@start", i.e. <string>@[start | end]
// For each match, open a segment specification and p
SegmentMap * GetAnimSegmentMap(Animatable *anim, plErrorMsg *pErrMsg)
{
if (!anim->HasNoteTracks())
return nil;
SegmentMap *segMap = TRACKED_NEW SegmentMap();
int numTracks = anim->NumNoteTracks();
for (int i = 0; i < numTracks; i++)
{
DefNoteTrack * track = (DefNoteTrack *)anim->GetNoteTrack(i);
int numKeys = track->keys.Count();
for (int j = 0; j < numKeys; j++)
{
char *note = track->keys[j]->note;
float time = TimeValueToGameTime(track->keys[j]->time);
GetSegment(note, time, segMap, pErrMsg);
}
}
return segMap;
}
void DeleteSegmentMap(SegmentMap *segMap)
{
// If we have a segment map, delete the memory associated with it
if (segMap)
{
for (SegmentMap::iterator i = segMap->begin(); i != segMap->end(); i++)
delete (*i).second;
delete segMap;
}
}

View File

@ -0,0 +1,91 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLMAXANIMUTILS_H
#define PLMAXANIMUTILS_H
#include "hsConfig.h"
#include <map>
#include <vector>
#include "hsStlSortUtils.h"
class plErrorMsg;
class Animatable;
// SEGMENTSPEC
// A simple helper class to hold information captured from the note track about animation segments
class SegmentSpec
{
public:
enum SegType { kAnim, kLoop, kMarker, kStopPoint, kSuppress };
float fStart; // beginning of the segment in game time
float fEnd; // end of the segment in game time
float fInitial; // initial position of the animation (-1 for the start)
char * fName; // name of the segment: controls lifespan of the name
SegType fType;
SegmentSpec();
SegmentSpec(float start, float end, char * name, SegType);
~SegmentSpec();
bool Contains(SegmentSpec *spec);
};
// a table mapping segment names to segment spec objects
typedef std::map<const char *, SegmentSpec*, stringISorter> SegmentMap;
// You can pass in nil for pErrMsg for silent operation
SegmentMap *GetAnimSegmentMap(Animatable *anim, plErrorMsg *pErrMsg);
void DeleteSegmentMap(SegmentMap *segMap);
SegmentMap *GetSharedAnimSegmentMap(std::vector<Animatable*>& anims, plErrorMsg *pErrorMsg);
bool GetSegMapAnimTime(const char *animName, SegmentMap *segMap, SegmentSpec::SegType type, float& begin, float& end);
// For internal use
void GetSegment(const char *note, float time, SegmentMap *segMap, plErrorMsg *pErrMsg);
bool DoesHaveStopPoints(Animatable *anim);
#endif

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,135 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plMiscComponents_inc
#define plMiscComponents_inc
#include "plComponent.h"
#include "Notify.h"
#define ROOM_CID Class_ID(0x70a1570d, 0x472f5647)
#define PAGEINFO_CID Class_ID(0x54ee40f1, 0x4de45acc)
#define IGNORELITE_CID Class_ID(0x6abb5b4b, 0x6ba27af7)
#define RAIL_CAM_CID Class_ID(0x1b097048, 0xc94038b)
#define CIRCLE_CAM_CID Class_ID(0x66f85282, 0x4daa1b8e)
#define IMAGE_LIB_CID Class_ID(0x736c18d3, 0x6a6d5dde)
class plComponentBase;
class plAgeDescription;
const char* LocCompGetPage(plComponentBase* comp);
namespace plPageInfoUtils
{
const char *GetAgeFolder();
Int32 GetSeqNumFromAgeDesc( const char *ageName, const char *pageName );
Int32 CombineSeqNum( int prefix, int suffix );
Int32 GetCommonSeqNumFromNormal( Int32 normalSeqNumber, int whichCommonPage );
plAgeDescription *GetAgeDesc( const char *ageName );
};
// PageInfo component definition, here so other components can get to the static function(s)
class plPageInfoComponent : public plComponent
{
protected:
hsBool fSeqNumValidated;
hsBool fItinerant;
static char fCurrExportedAge[ 256 ];
void IVerifyLatestAgeAsset( const char *ageName, const char *localPath, plErrorMsg *errMsg );
void IUpdateSeqNumbersFromAgeFile( plErrorMsg *errMsg );
public:
plPageInfoComponent();
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool DeInit(plMaxNode *node, plErrorMsg *pErrMsg);
char *GetAgeName();
hsBool GetItinerant() {return fItinerant; }
enum
{
kInfoAge=3,
kInfoPage,
kInfoSeqPrefix,
kInfoSeqSuffix,
kRefVolatile_PageInfoUpdated,
kItinerant
};
static char *GetCurrExportAgeName() { return (char *)&fCurrExportedAge; }
static void NotifyProc(void *param, NotifyInfo *info);
};
//Class that accesses the paramblock below.
class plLayerTex;
class pfImageLibComponent : public plComponent
{
public:
pfImageLibComponent();
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg);
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
enum ParamIDs
{
kRefImageList,
kCompressImage,
};
int GetNumBitmaps( void ) const;
plLayerTex *GetBitmap( int idx );
int AppendBitmap( plLayerTex *tex );
void RemoveBitmap( int idx );
bool GetCompress(int idx);
void SetCompress(int idx, bool compress);
void Validate();
};
#endif // plMiscComponents_inc

View File

@ -0,0 +1,378 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "max.h"
#include "resource.h"
#include "plComponent.h"
#include "plComponentReg.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "plPickNode.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxExport/plExportProgressBar.h"
#include "hsTypes.h"
#include "hsResMgr.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plDrawable/plMorphSequence.h"
#include "../plDrawable/plSharedMesh.h"
const Class_ID MORPHSEQ_COMP_CID(0x37100f0a, 0x2d1f6b87);
const Class_ID MORPHLAY_COMP_CID(0x138b1d44, 0x6c0a7417);
void DummyCodeIncludeFuncMorph()
{
}
class plMorphLayComp : public plComponent
{
protected:
public:
enum
{
kDeltas
};
plMorphLayComp();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
hsBool SetupLayer(plMorphArray& morphArr, plMaxNode* baseNode, hsTArray<plGeometrySpan*>* baseSpans, plErrorMsg* pErrMsg);
};
CLASS_DESC(plMorphLayComp, gMorphLayCompDesc, "Morph Layer", "MorphLay", COMP_TYPE_AVATAR, MORPHLAY_COMP_CID)
ParamBlockDesc2 gMorphLayBk
(
plComponent::kBlkComp, _T("MorphLay"), 0, &gMorphLayCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_MORPHLAY, IDS_COMP_MORPHLAY, 0, 0, nil,
plMorphLayComp::kDeltas, _T("Deltas"), TYPE_INODE_TAB, 0, P_CAN_CONVERT, 0,
p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, IDC_ADD_TARGS, 0, IDC_DEL_TARGS,
p_classID, triObjectClassID,
end,
end
);
plMorphLayComp::plMorphLayComp()
{
fClassDesc = &gMorphLayCompDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plMorphLayComp::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg)
{
const int num = fCompPB->Count(kDeltas);
int i;
for( i = 0; i < num; i++ )
{
plMaxNode* deltaNode = (plMaxNode*)fCompPB->GetINode(kDeltas, TimeValue(0), i);
if( deltaNode )
{
const char* deltaName = deltaNode->GetName();
if( !deltaNode->GetSwappableGeom() )
deltaNode->SetSwappableGeom(new plSharedMesh);
// deltaNode->SetForceLocal(true);
}
}
return true;
}
hsBool plMorphLayComp::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
return true;
}
hsBool plMorphLayComp::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
return true;
}
hsBool plMorphLayComp::SetupLayer(plMorphArray& morphArr, plMaxNode* baseNode, hsTArray<plGeometrySpan*>* baseSpans, plErrorMsg* pErrMsg)
{
const int num = fCompPB->Count(kDeltas);
int i;
// For each delta
for( i = 0; i < num; i++ )
{
plMaxNode* deltaNode = (plMaxNode*)fCompPB->GetINode(kDeltas, TimeValue(0), i);
if( !deltaNode )
continue;
const char* dbgNodeName = deltaNode->GetName();
// Get the GeometrySpans. We ensured they would
// be generated in it's SetupProperties, and they were created
// in the MakeMesh pass.
hsTArray<plGeometrySpan*>* movedSpans = &deltaNode->GetSwappableGeom()->fSpans;
// We want to move the deltas into the same space as the base mesh verts.
// So the first question is, which space do we want to move them from?
// Answer is, we want to take the deltas from where they are relative to their OTM (pivot point),
// and move them into base node's local space.
// The idea is that we want to assume the pivot points of the two objects are aligned, even though
// we don't require that they are. So we transform delta verts to their pivot space, pretend that is the
// same space as baseNode's pivot space, and transform from that to baseNode's local space.
// This is somewhat arbitrary, but it allows the delta meshes to be moved aside relative to the base
// meshes, as well as aligning the Pivot points to align the deltas and base mesh.
// So:
// From deltaLocal to deltaPivot space = deltaVertToPivot * deltaLocalToVert // vertToPivot = OTM
// From deltaPivot to basePivot = skip (pretend they are the same).
// From basePivot to baseLocal = baseVertToLocal * Inverse(baseVertToPivot) // because baseOTM is in baseVertToLocal
// mf
hsMatrix44 bvert2local = baseNode->GetVertToLocal44() * baseNode->Matrix3ToMatrix44(Inverse(baseNode->GetOTM()));
hsMatrix44 dlocal2vert = deltaNode->GetOTM44() * deltaNode->GetLocalToVert44();
hsMatrix44 d2b = bvert2local * dlocal2vert;
hsMatrix44 d2bTInv;
d2b.GetInverse(&d2bTInv);
d2bTInv.GetTranspose(&d2bTInv);
// Error check - movedSpans->GetCount() == baseSpans->GetCount();
if( movedSpans->GetCount() != baseSpans->GetCount() )
{
pErrMsg->Set(true, deltaNode->GetName(), "Delta mesh mismatch with base").CheckAndAsk();
pErrMsg->Set(false);
continue;
}
plMorphDelta delta;
delta.ComputeDeltas(*baseSpans, *movedSpans, d2b, d2bTInv);
morphArr.AddDelta(delta);
}
return morphArr.GetNumDeltas() > 0;
}
class plMorphSeqComp : public plComponent
{
protected:
plMorphLayComp* IGetLayerComp(int i);
public:
enum
{
kLayers,
kBaseNode
};
plMorphSeqComp();
void DeleteThis() { delete this; }
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading
// of properties on the MaxNode, as it's still indeterminant.
virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg);
virtual hsBool DeInit(plMaxNode *node, plErrorMsg *pErrMsg);
};
CLASS_DESC(plMorphSeqComp, gMorphSeqCompDesc, "Morph Sequence", "MorphSeq", COMP_TYPE_AVATAR, MORPHSEQ_COMP_CID)
class plMorphSeqProc : public ParamMap2UserDlgProc
{
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
}
return true;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_ADD_TARGS)
{
std::vector<Class_ID> cids;
cids.push_back(MORPHLAY_COMP_CID);
IParamBlock2 *pb = map->GetParamBlock();
plPick::Node(pb, plMorphSeqComp::kLayers, &cids, false, false);
map->Invalidate(plMorphSeqComp::kLayers);
return TRUE;
}
break;
}
return false;
}
void DeleteThis() {}
};
static plMorphSeqProc gMorphSeqProc;
/////////////////////////////////////////////////////////////////////////////////////
ParamBlockDesc2 gMorphSeqBk
(
plComponent::kBlkComp, _T("MorphSeq"), 0, &gMorphSeqCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
IDD_COMP_MORPHSEQ, IDS_COMP_MORPHSEQ, 0, 0, &gMorphSeqProc,
plMorphSeqComp::kLayers, _T("Layers"), TYPE_INODE_TAB, 0, 0, 0,
p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, 0, 0, IDC_DEL_TARGS,
end,
plMorphSeqComp::kBaseNode, _T("BaseNode"), TYPE_INODE, 0, 0,
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_CHOOSE_OBJECT,
p_sclassID, GEOMOBJECT_CLASS_ID,
p_prompt, IDS_COMP_CHOSE_OBJECT,
end,
end
);
hsBool plMorphSeqComp::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
plMaxNode* baseNode = (plMaxNode*)fCompPB->GetINode(kBaseNode);
if( !baseNode )
{
pErrMsg->Set(true, node->GetName(), "Missing base (neutral) geometry node").CheckAndAsk();
pErrMsg->Set(false);
return true;
}
if( !baseNode->GetSwappableGeom() )
baseNode->SetSwappableGeom(new plSharedMesh);
// baseNode->SetForceLocal(true);
return true;
}
hsBool plMorphSeqComp::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
return true;
}
hsBool plMorphSeqComp::Convert(plMaxNode* node, plErrorMsg* pErrMsg)
{
const char* dbgNodeName = node->GetName();
// Make our plMorphSequence modifier
plMorphSequence* morphSeq = const_cast<plMorphSequence *>(plMorphSequence::ConvertNoRef(node->GetSceneObject()->GetModifierByType(plMorphSequence::Index())));
if (!morphSeq)
{
morphSeq = TRACKED_NEW plMorphSequence;
node->AddModifier(morphSeq, IGetUniqueName(node));
}
// Get our base geometry.
plMaxNode* baseNode = (plMaxNode*)fCompPB->GetINode(kBaseNode);
plSharedMesh* mesh = baseNode->GetSwappableGeom();
hsTArray<plGeometrySpan*>* baseSpans = &mesh->fSpans;
//morphSeq->AddSharedMesh(mesh);
// Error check we have some base geometry.
plMorphDataSet *set = TRACKED_NEW plMorphDataSet;
hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), set, node->GetLocation());
hsgResMgr::ResMgr()->AddViaNotify(set->GetKey(), TRACKED_NEW plGenRefMsg(mesh->GetKey(), plRefMsg::kOnCreate, -1, -1), plRefFlags::kActiveRef);
const int num = fCompPB->Count(kLayers);
int i;
// For each layer that we have
for( i = 0; i < num; i++ )
{
plMorphLayComp* layComp = IGetLayerComp(i);
if( !layComp )
continue;
// Layer is a sequence of geometry deltas. A layer will
// become a plMorphArray.
plMorphArray morphArr;
if( layComp->SetupLayer(morphArr, baseNode, baseSpans, pErrMsg) )
{
//morphSeq->AddLayer(morphArr);
set->fMorphs.Append(morphArr);
}
}
// Error check - should make sure we wound up with something valid,
// as opposed to a million empty deltas or something.
return true;
}
hsBool plMorphSeqComp::DeInit(plMaxNode *node, plErrorMsg *pErrMsg)
{
return true;
}
plMorphLayComp* plMorphSeqComp::IGetLayerComp(int i)
{
plMaxNode* node = (plMaxNode*)fCompPB->GetINode(kLayers, TimeValue(0), i);
if( !node )
return nil;
plComponentBase *comp = ((plMaxNodeBase*)node)->ConvertToComponent();
if( !comp )
return nil;
if( comp->ClassID() == MORPHLAY_COMP_CID )
{
return (plMorphLayComp*)comp;
}
return nil;
}
plMorphSeqComp::plMorphSeqComp()
{
fClassDesc = &gMorphSeqCompDesc;
fClassDesc->MakeAutoParamBlocks(this);
}

Some files were not shown because too many files have changed in this diff Show More