Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

696 lines
17 KiB
C++

#include "stdafx.h"
#ifdef STRICT // Already defined by stdafx,
#undef STRICT // so we avoid warning linking msg
#endif
#ifdef _MBCS // The same as above
#undef _MBCS
#endif
#include <GameOS\GameOS.hpp>
#if !defined(DLLPLATFORM_DLLPLATFORM_HPP)
#include "DLLPlatform\DLLPlatform.hpp"
#endif
#if !defined(STUFF_STUFF_HPP)
#include "Stuff\Stuff.hpp"
#endif
#if !defined(MW4ANIMATIONSYSTEM_HPP)
#include <MW4\MW4AnimationSystem.hpp>
#endif
#undef Min
#undef Max
#pragma pack(push,8)
#include "Max.h" // Include MAX's main header file
#pragma pack(pop)
#include <Stuff\StuffHeaders.hpp>
#include "MaxProxies\MaxProxyHeaders.hpp"
#include <adept\collisionvolume.hpp>
#include "AnimationSuite.h"
#include "About.h"
#include "JointEditDialog.h"
#include "ArmatureExport.h"
#include "siteobject.h"
#include "cvobject.h"
#include "AnimationExport.h"
#include "ErfExport.h"
#include "MLRExport.h"
#include "EBFExport.h"
#include "BatchExport.h"
#include "CvExport.h"
#include "lightexport.h"
#include "erfimport.h"
#include "missionimp.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define DLLEXPORT __declspec(dllexport) // Facilite Function's Exportation Declaration
CAnimExpApp theApp; // Global Object representing the application
AnimExpClassDesc animExpDesc;
JointPreferenceClassDesc jointPreferenceDesc;
OptimizeKeyframeClassDesc optimizeKeyframeDesc;
ReplicateClassDesc replicateExpDesc;
SiteObjectClassDesc siteObjectClassDesc;
LegMirrorClassDesc legmirrorDesc;
HillAdjustClassDesc hillAdjustDesc;
ErfExpClassDesc erfExpDesc;
MLRExpClassDesc MLRExpDesc;
EBFExpClassDesc EBFExpDesc;
BatchExpClassDesc batchExpDesc;
ArmatureExpClassDesc armatureExpDesc;
FallToolClassDesc fallToolDesc;
SkeletonVerifyClassDesc skeletonVerifyDesc;
CvObjectClassDesc cvObjectClassDesc;
CvExpClassDesc cvExpDesc;
CvToolClassDesc cvToolDesc;
LightExpClassDesc lightExpDesc;
ErfImpClassDesc erfImpDesc;
MissionImpClassDesc missionImpDesc;
//HINSTANCE hInstance;
/////////////////////////////////////////////////////////////////////////////
// Prototypes
static BOOL CALLBACK QuickFileProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
/////////////////////////////////////////////////////////////////////////////
// CAnimExpApp
BEGIN_MESSAGE_MAP(CAnimExpApp, CWinApp)
//{{AFX_MSG_MAP(CAnimExpApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAnimExpApp construction
void TurnOnExceptions()
{
gos_MathExceptions( 1, 1 );
}
void TurnOffExceptions()
{
gos_MathExceptions( 0, 0 );
}
CAnimExpApp::CAnimExpApp()
{
}
HGOSHEAP AnimSuiteHeap;
/////////////////////////////////////////////////////////////////////////////
// DLL's InitInstance, called when the DLL is being linked to a client
BOOL CAnimExpApp::InitInstance()
{
TurnOnExceptions();
//_clear87();
AFX_MANAGE_STATE(AfxGetStaticModuleState());
//Get the DLL's HINSTANCE
hInstance = AfxGetResourceHandle();
//Init 3DS Max Custom Controls
InitCustomControls(hInstance);
//Init Win32 Controls
InitCommonControls();
InitGameOS( hInstance, NULL, "\0" );
Stuff::ArmorLevel = 4;
Stuff::InitializeClasses();
Proxies::InitializeClasses();
MAXProxies::InitializeClasses();
MidLevelRenderer::InitializeClasses();
gosFX::InitializeClasses();
ElementRenderer::InitializeClasses();
ElementProxies::InitializeClasses();
// Initialize_MAXStuff();
TurnOffExceptions();
AnimSuiteHeap = gos_CreateMemoryHeap("AnimSuiteHeap");
Check_Pointer(AnimSuiteHeap);
gos_PushCurrentHeap(AnimSuiteHeap);
return TRUE; //CWinApp::InitInstance();
}
/////////////////////////////////////////////////////////////////////////////
// DLL's ExitInstance, called when the DLL is being unlinked from a client
int CAnimExpApp::ExitInstance()
{
gos_PopCurrentHeap();
TurnOnExceptions();
//_clear87();
ElementRenderer::TerminateClasses();
gosFX::TerminateClasses();
MidLevelRenderer::TerminateClasses();
ElementProxies::TerminateClasses();
MAXProxies::TerminateClasses();
Proxies::TerminateClasses();
Stuff::TerminateClasses();
TurnOffExceptions();
ExitGameOS();
return CWinApp::ExitInstance();
}
/////////////////////////////////////////////////////////////////////////////
// 3DS Max Identification Callbacks
DLLEXPORT const TCHAR* LibDescription ()
{
return GetString(IDS_LIBDESCRIPTION);
}
/////////////////////////////////////////////////////////////////////////////
// Return the Number of Classes present in the DLLs
DLLEXPORT int LibNumberClasses ()
{
// Return the number of plugins in the DLL
return 20;
}
/////////////////////////////////////////////////////////////////////////////
// Return the i'th Class Description Object
DLLEXPORT ClassDesc* LibClassDesc(int i)
{
switch(i) {
case 0:
return &animExpDesc;
case 1:
return &jointPreferenceDesc;
case 2:
return &optimizeKeyframeDesc;
case 3:
return &replicateExpDesc;
case 4:
return &siteObjectClassDesc;
case 5:
return &legmirrorDesc;
case 6:
return &hillAdjustDesc;
case 7:
return &erfExpDesc;
case 8:
return &batchExpDesc;
case 9:
return &armatureExpDesc;
case 10:
return &fallToolDesc;
case 11:
return &skeletonVerifyDesc;
case 12:
return &cvObjectClassDesc;
case 13:
return &cvExpDesc;
case 14:
return &cvToolDesc;
case 15:
return &MLRExpDesc;
case 16:
return &EBFExpDesc;
case 17:
return &lightExpDesc;
case 18:
return &erfImpDesc;
case 19:
return &missionImpDesc;
default:
return 0;
break;
}
}
/////////////////////////////////////////////////////////////////////////////
void *SiteObjectClassDesc::Create(BOOL loading)
{
return new SiteObject();
}
/////////////////////////////////////////////////////////////////////////////
void *AnimExpClassDesc::Create(BOOL loading)
{
return new AnimExp();
}
/////////////////////////////////////////////////////////////////////////////
void *ErfExpClassDesc::Create(BOOL loading)
{
return new ErfExp();
}
/////////////////////////////////////////////////////////////////////////////
void *MLRExpClassDesc::Create(BOOL loading)
{
return new MLRExp();
}
/////////////////////////////////////////////////////////////////////////////
void *EBFExpClassDesc::Create(BOOL loading)
{
return new EBFExp();
}
/////////////////////////////////////////////////////////////////////////////
void *ArmatureExpClassDesc::Create(BOOL loading)
{
return new ArmatureExp();
}
/////////////////////////////////////////////////////////////////////////////
void *BatchExpClassDesc::Create(BOOL loading)
{
return new BatchExp();
}
/////////////////////////////////////////////////////////////////////////////
void *CvObjectClassDesc::Create(BOOL loading)
{
return new CvObject();
}
void *CvExpClassDesc::Create(BOOL loading)
{
return new CvExp();
}
void *LightExpClassDesc::Create(BOOL loading)
{
return new LightExp();
}
void *ErfImpClassDesc::Create(BOOL loading)
{
return new ErfImp();
}
void *MissionImpClassDesc::Create(BOOL loading)
{
return new MissionImp();
}
/////////////////////////////////////////////////////////////////////////////
TCHAR *GetString(int id)
{
static TCHAR buf[256];
if (hInstance)
return LoadString(hInstance, id, buf, sizeof(buf)) ? buf : NULL;
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// MAX API Version
DLLEXPORT ULONG LibVersion ()
{
return (VERSION_3DSMAX);
}
//===========================================================================//
DWORD WINAPI fn(LPVOID arg) {
return(0);
}
//===========================================================================//
void __stdcall GetGameOSEnvironment(char* CommandLine)
{
//
//----------------------------------------------------------
// This is where to set GOS environment settings.
//----------------------------------------------------------
//
Environment.applicationName = "AnimationSuite";
Environment.screenWidth = 640;
Environment.screenHeight = 480;
Environment.bitDepth = 16;
}
HWND EnableQuickFile(Interface *ip,HWND hWnd)
{
//Display the plugin's Rollup Dialog
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HINSTANCE loc_hInstance = AfxGetResourceHandle ();
HWND hRet = ip->AddRollupPage(loc_hInstance, MAKEINTRESOURCE(IDD_QUICKFILE_PANEL),
QuickFileProc, _T("Quick File"),(LPARAM)hWnd);
char szKey[100] = "SOFTWARE\\Autodesk\\3D Studio MAX\\Plugins\\QuickFile";
HKEY hKey;
if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE,szKey,&hKey))
{
DWORD wType = REG_SZ;
char szValue[100];
BYTE *pData = (BYTE *)szValue;
DWORD size = 100;
RegQueryValueEx(hKey,"Enabled",0,&wType,(BYTE *)szValue,&size);
// Disable the drop down
if ('0' == szValue[0])
{
IRollupWindow *pRoll = ip->GetCommandPanelRollup();
pRoll->SetPanelOpen(pRoll->GetNumPanels()-1,false);
}
size = 100;
RegQueryValueEx(hKey,"NumFiles",0,&wType,(BYTE *)szValue,&size);
int maxfiles;
sscanf(szValue,"%d",&maxfiles);
for (int x=0;x<maxfiles;x++)
{
char szKey[100];
size = 100;
sprintf(szKey,"%d",x);
RegQueryValueEx(hKey,szKey,0,&wType,(BYTE *)szValue,&size);
char fname[20];
_splitpath((LPCTSTR)szValue,NULL,NULL,fname,NULL);
if (LB_ERR == SendDlgItemMessage(hRet,IDC_QUICKFILE_LISTBOX,LB_FINDSTRINGEXACT,0,(LPARAM)fname))
{
char *psz = strdup((LPCTSTR)szValue);
int index = SendDlgItemMessage(hRet,IDC_QUICKFILE_LISTBOX,LB_ADDSTRING,0,(LPARAM)fname);
SendDlgItemMessage(hRet,IDC_QUICKFILE_LISTBOX,LB_SETITEMDATA,index,(LPARAM)psz);
}
}
}
else
{
IRollupWindow *pRoll = ip->GetCommandPanelRollup();
pRoll->SetPanelOpen(pRoll->GetNumPanels()-1,false);
}
return hRet;
}
void DisableQuickFile(Interface * ip,HWND hWnd)
{
char szKey[100] = "SOFTWARE\\Autodesk\\3D Studio MAX\\Plugins\\QuickFile";
HKEY hKey;
RegCreateKey(HKEY_LOCAL_MACHINE,szKey,&hKey);
IRollupWindow *pRoll = ip->GetCommandPanelRollup();
char *strOpen = pRoll->IsPanelOpen(pRoll->GetNumPanels()-1)?"1":"0";
RegSetValueEx(hKey,"Enabled",0,REG_SZ,(BYTE *)strOpen,strlen(strOpen));
char szValue[MAX_PATH];
int count = SendDlgItemMessage(hWnd,IDC_QUICKFILE_LISTBOX,LB_GETCOUNT,0,0);
sprintf(szValue,"%d",count);
RegSetValueEx(hKey,"NumFiles",0,REG_SZ,(BYTE *)szValue,strlen(szValue));
for (int x = 0;x<count;x++)
{
//SendDlgItemMessage(hWnd,IDC_QUICKFILE_LISTBOX,LB_GETTEXT,x,(LPARAM)buf);
LPARAM lpPath = SendDlgItemMessage(hWnd,IDC_QUICKFILE_LISTBOX,LB_GETITEMDATA,x,0);
char *pPath = (char *)lpPath;
char szKey[100];
sprintf(szKey,"%d",x);
RegSetValueEx(hKey,szKey,0,REG_SZ,(BYTE *)pPath,strlen(pPath));
}
ip->DeleteRollupPage(hWnd);
}
static BOOL CALLBACK QuickFileProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
//static HWND hotherWnd = NULL;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
switch (msg)
{
case WM_INITDIALOG:
{
//hotherWnd = (HWND)lParam;
SetWindowLong(GetDlgItem(hWnd,IDC_QUICKFILE_APPLY),GWL_USERDATA,lParam);
break;
}
case WM_DESTROY:
{
//hotherWnd = NULL;
break;
}
case WM_COMMAND:
{
switch (LOWORD(wParam)) //Handle Panel's controls
{
case IDC_QUICKFILE_LISTBOX:
{
switch (HIWORD(wParam))
{
case LBN_SELCHANGE:
{
HWND hListBox = (HWND)lParam;
HWND hTarget = (HWND)GetWindowLong(GetDlgItem(hWnd,IDC_QUICKFILE_APPLY),GWL_USERDATA);
SendMessage(hTarget,msg,wParam,lParam);
break;
}
}
break;
}
case IDC_QUICKFILE_ADD:
{
HWND hTarget = (HWND)GetWindowLong(GetDlgItem(hWnd,IDC_QUICKFILE_APPLY),GWL_USERDATA);
CFileDialog fd(TRUE,NULL,NULL,OFN_ALLOWMULTISELECT,"Max Files (*.max)|*.max||",CWnd::FromHandle(hTarget));
char *filebuf = new char[MAX_PATH*200];
filebuf[0] = 0;
fd.m_ofn.lpstrFile = filebuf;
fd.m_ofn.nMaxFile = MAX_PATH*200;
if (fd.DoModal()==IDOK)
{
POSITION pos = fd.GetStartPosition();
while (pos)
{
CString path = fd.GetNextPathName(pos);
char fname[20];
_splitpath((LPCTSTR)path,NULL,NULL,fname,NULL);
if (LB_ERR == SendDlgItemMessage(hWnd,IDC_QUICKFILE_LISTBOX,LB_FINDSTRINGEXACT,0,(LPARAM)fname))
{
char *psz = strdup((LPCTSTR)path);
int index = SendDlgItemMessage(hWnd,IDC_QUICKFILE_LISTBOX,LB_ADDSTRING,0,(LPARAM)fname);
SendDlgItemMessage(hWnd,IDC_QUICKFILE_LISTBOX,LB_SETITEMDATA,index,(LPARAM)psz);
}
}
}
break;
}
case IDC_QUICKFILE_REMOVE:
{
int count = SendDlgItemMessage(hWnd,IDC_QUICKFILE_LISTBOX,LB_GETSELCOUNT,0,0);
int *items = new int[count];
int icount = SendDlgItemMessage(hWnd,IDC_QUICKFILE_LISTBOX,LB_GETSELITEMS,count,(LPARAM)items);
// Start from highest index and count down because indices may change from deletion
for (;icount;icount--)
{
char *psz = (char *)SendDlgItemMessage(hWnd,IDC_QUICKFILE_LISTBOX,LB_GETITEMDATA,icount-1,0);
if (psz)
free(psz);
SendDlgItemMessage(hWnd,IDC_QUICKFILE_LISTBOX,LB_DELETESTRING,items[icount],0);
}
delete items;
break;
}
case IDC_QUICKFILE_APPLY:
{
HWND hTarget = (HWND)GetWindowLong(GetDlgItem(hWnd,IDC_QUICKFILE_APPLY),GWL_USERDATA);
SendMessage(hTarget,WM_QUICKFILE_BEGIN,0,0);
int count = SendDlgItemMessage(hWnd,IDC_QUICKFILE_LISTBOX,LB_GETCOUNT,0,0);
char buf[100];
for (;count;count--)
{
SendDlgItemMessage(hWnd,IDC_QUICKFILE_LISTBOX,LB_GETTEXT,count-1,(LPARAM)buf);
LPARAM lpPath = SendDlgItemMessage(hWnd,IDC_QUICKFILE_LISTBOX,LB_GETITEMDATA,count-1,0);
SendMessage(hTarget,WM_QUICKFILE_APPLYFILE,(WPARAM)buf,lpPath);
}
SendMessage(hTarget,WM_QUICKFILE_END,0,0);
break;
}
}
break;
}
default:
{
return FALSE;
}
}
return TRUE;
}
#define NUM_STAT_UPDATES 20
static float ErrorAmount(Point3 v1, Point3 v2)
{
return LengthSquared(v1-v2);
}
static float ErrorAmount(float v1, float v2)
{
float res = v1-v2;
return res*res;
}
static float ErrorAmount(Quat v1, Quat v2)
{
AngAxis res(v2/v1);
return res.angle * res.angle;
}
static float ErrorAmount(ScaleValue v1, ScaleValue v2)
{
return LengthSquared(v1.s-v2.s);
}
template <class T> int ReduceKeys_MW4(
Control *cont,Interval range,float thresh,TimeValue step,
KeyReduceStatus *status, T xx)
{
Interval valid;
Tab<TimeValue> times;
int i,j,offset = cont->GetKeyTimes(times,range,0);
TimeValue t;
int statUp, res;
//if (times.Count() <3) return KEYREDUCE_CONTINUE;
if (!times.Count()) return KEYREDUCE_CONTINUE;
// Init the status callback if we got one.
if (status) status->Init(times.Count()-1);
// The number of keys to process inbetween each update
statUp = times.Count()/NUM_STAT_UPDATES;
if (statUp==0) statUp = 1;
// Square the threshold.
thresh = thresh*thresh;
// Build a table of the origanal values
Tab<T> vals;
vals.SetCount((range.End()-range.Start())/step + 1);
for (t=range.Start(),i=0; t<range.End(); t+=step,i++) {
cont->GetValue(t,&vals[i],valid);
}
// Start at the last key and see if each key can be deleted.
for (i = times.Count()-1; i>=0; i--) {
//theHold.Begin();
Control *old_cont = (Control *)cont->Clone();
// Delete the key..
cont->DeleteKeyByIndex(i+offset);
// Check to see if the path is still within threshold.
BOOL ok = TRUE;
for (t=range.Start(),j=0; t<range.End(); t+=step,j++) {
T val;
cont->GetValue(t,&val,valid);
if (ErrorAmount(val,vals[j]) > thresh) {
ok = FALSE;
break;
}
}
// If it was ok to delete this key, great! otherwise put it back
if (ok) {
//theHold.Accept(0);
} else {
//theHold.Cancel();
cont->Copy(old_cont);
}
delete old_cont;
// Maybe update the status
if (status && !(i%statUp)) {
switch (res = status->Progress(times.Count()-1-i)) {
case KEYREDUCE_ABORT:
case KEYREDUCE_STOP:
return res;
}
}
}
return TRUE;
}
int ApplyKeyReduction_MW4(
Control *cont,Interval range,float thresh,TimeValue step,
KeyReduceStatus *status)
{
if (!cont->NumKeys()) return TRUE;
int res = KEYREDUCE_CONTINUE;
switch (cont->SuperClassID()) {
case CTRL_FLOAT_CLASS_ID:
res = ReduceKeys_MW4(cont,range,thresh,step,status,float(0));
break;
case CTRL_POSITION_CLASS_ID:
case CTRL_POINT3_CLASS_ID:
res = ReduceKeys_MW4(cont,range,thresh,step,status,Point3(0,0,0));
break;
case CTRL_ROTATION_CLASS_ID:
res = ReduceKeys_MW4(cont,range,thresh,step,status,Quat(0.0f,0.0f,0.0f,1.0f));
break;
case CTRL_SCALE_CLASS_ID:
res = ReduceKeys_MW4(cont,range,thresh,step,status,ScaleValue(Point3(1,1,1)));
break;
}
return res;
}