#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 #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 #endif #undef Min #undef Max #pragma pack(push,8) #include "Max.h" // Include MAX's main header file #pragma pack(pop) #include #include "MaxProxies\MaxProxyHeaders.hpp" #include #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;xGetCommandPanelRollup(); 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;xDeleteRollupPage(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 int ReduceKeys_MW4( Control *cont,Interval range,float thresh,TimeValue step, KeyReduceStatus *status, T xx) { Interval valid; Tab 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 vals; vals.SetCount((range.End()-range.Start())/step + 1); for (t=range.Start(),i=0; tGetValue(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; tGetValue(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; }