/*************************************************************************** * * BRB the BiG ReD ButtoN * *************************************************************************** * * Version : 1.0, Oct 8, 1998 * * Written By Brian Bilicki * *************************************************************************** * * 3DS MAX Plugin, using MFCs to set LOD and preview data in the element render * ***************************************************************************/ #include "stdafx.h" #include #ifdef STRICT // Already defined by stdafx, #undef STRICT // so we avoid warning linking msg #endif #ifdef _MBCS // The same as above #undef _MBCS #endif #if !defined(STUFF_STUFF_HPP) #include "Stuff\Stuff.hpp" #endif #if !defined(MAXPROXIES_MAXPROXIES_HPP) #include "MAXProxies\MAXProxies.hpp" #endif #if !defined(MIDLEVELRENDERER_HPP) #include "MLR\MLR.hpp" #endif #if !defined(ELEMENTPROXIES_ELEMENTPROXIES_HPP) #include "ElementProxies\ElementProxies.hpp" #endif #if !defined(ELEMENTRENDERER_ELEMENTRENDERER_HPP) #include "ElementRenderer\ElementRenderer.hpp" #endif #if !defined(GOSFX_GOSFX_HPP) #include #endif #if !defined(DLLPLATFORM_DLLPLATFORM_HPP) #include "DLLPlatform\DLLPlatform.hpp" #endif #if !defined(GOSFX_GOSFX_HPP) #include #endif void DeleteDirectory(CString dir); void ClearDirectory(CString dir); #include #undef Max #undef Min #include "Max.h" // Include MAX's main header file #include "BRB.h" #include "About.h" #include "EditBatchFile.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 CPlugTestApp theApp; // Global Object representing the application PlugPanel thePlugPanel; // The One and only One Plug Panel object PlugDesc thePlugDesc; void TurnOnExceptions() { gos_MathExceptions( 1, 1 ); } void TurnOffExceptions() { gos_MathExceptions( 0, 0 ); } ///////////////////////////////////////////////////////////////////////////// // CPlugTestApp BEGIN_MESSAGE_MAP(CPlugTestApp, CWinApp) //{{AFX_MSG_MAP(CPlugTestApp) // 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() ///////////////////////////////////////////////////////////////////////////// // CPlugTestApp construction CPlugTestApp::CPlugTestApp() { } LRESULT CALLBACK NullProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { return GameOSWinProc( hWnd, uMsg, wParam, lParam ); } ///////////////////////////////////////////////////////////////////////////// // DLL's InitInstance, called when the DLL is being linked to a client BOOL CPlugTestApp::InitInstance() { HINSTANCE hInstance; AFX_MANAGE_STATE(AfxGetStaticModuleState()); AfxEnableControlContainer(); //Get the DLL's HINSTANCE hInstance = AfxGetResourceHandle(); thePlugPanel.m_hInstance = hInstance; //Init 3DS Max Custom Controls InitCustomControls(hInstance); //Init Win32 Controls InitCommonControls(); InitGameOS( thePlugPanel.m_hInstance, NULL, "\0" ); #if defined(_ARMOR) Stuff::ArmorLevel = 4; // Stuff::MemoryRegistrationEnabled = true; #endif Stuff::InitializeClasses(); Proxies::InitializeClasses(); // // You have to call this to turn the son of a bitch off. // if you wish you can start it up (START_FPU_CHECK) // on your function, but if you don't turn it off, MAX will gack // TurnOffExceptions(); return TRUE; //CWinApp::InitInstance(); } ///////////////////////////////////////////////////////////////////////////// // DLL's ExitInstance, called when the DLL is being unlinked from a client int CPlugTestApp::ExitInstance() { // // Uninit stuff and tools stuff // //Clear_Fpu(); Proxies::TerminateClasses(); Stuff::TerminateClasses(); ExitGameOS(); return CWinApp::ExitInstance(); } ///////////////////////////////////////////////////////////////////////////// // 3DS Max Identification Callbacks DLLEXPORT const TCHAR* LibDescription () { return _T("Big Red Button"); } ///////////////////////////////////////////////////////////////////////////// // Return the Number of Classes present in the DLLs DLLEXPORT int LibNumberClasses () { return 1; //Return 1 because this DLL contains 1 plugin } ///////////////////////////////////////////////////////////////////////////// //Return the i'th Class Description Object DLLEXPORT ClassDesc* LibClassDesc(int i) { switch(i) { case 0: return &thePlugDesc; //Return the Plugin's Description Object break; default: return 0; break; } } ///////////////////////////////////////////////////////////////////////////// // MAX API Version DLLEXPORT ULONG LibVersion () { return (VERSION_3DSMAX); } /*************************************************************************** * * * Plugin Panel Class * * * ***************************************************************************/ // This class is the main class of the plugin (like the Dialog's class for // dialog based application) // // A unique object of this class (called thePlugPanel) is globally instanced // //////////////////////////////////////////////////////////////////////////////// // PlugPanel Dialog Procedure to handle User and System Interactions static BOOL CALLBACK PlugPanelProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); switch (msg) { case WM_INITDIALOG: //Panel's extra initialization thePlugPanel.Init(hWnd); break; case WM_DESTROY: //Panel's extra destruction thePlugPanel.Destroy(hWnd); break; case WM_COMMAND : switch (LOWORD(wParam)) { //Handle Panel's controls case IDC_ABOUT: { CAbout dlg; dlg.DoModal(); break;} case IDC_PREVIEWLOD: { thePlugPanel.OnPreviewLOD(); break;} case IDC_PREVIEWANIM: { thePlugPanel.OnPreviewAnimation(); break;} case IDC_ERFVIEW: { thePlugPanel.OnErfView(); break;} case IDC_EXPORTTOGAME: { thePlugPanel.OnExportToGame(); break;} } break; //////////////////////////////////////////////////////////////////////// //The following lines are not necessary for MAX2 Plugins case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_MOUSEMOVE: thePlugPanel.m_ip->RollupMouseMessage(hWnd, msg, wParam, lParam); break; //////////////////////////////////////////////////////////////////////// // default: return FALSE; } return TRUE; } //////////////////////////////////////////////////////////////////////////////// // Display the Plugin's Panel void PlugPanel::BeginEditParams(Interface* ip, IUtil* iu) { m_ip = ip; //Get the Plugin's Interface m_iu = iu; //Get the Utility Plugin's Interface AFX_MANAGE_STATE(AfxGetStaticModuleState()); //Display the plugin's Rollup Dialog m_hPanel = ip->AddRollupPage(m_hInstance, MAKEINTRESOURCE(IDD_PANEL), PlugPanelProc, _T("Big Red Button"),0); } //////////////////////////////////////////////////////////////////////////////// // Free the Plugins' Panel void PlugPanel::EndEditParams(Interface *ip, IUtil *iu) { m_iu = NULL; m_ip = NULL; //Remove the Rollup Dialog ip->DeleteRollupPage(m_hPanel); m_hPanel = NULL; } //////////////////////////////////////////////////////////////////////////////// // Called when the Preview Animatin Button is pushed void PlugPanel::OnPreviewAnimation() { for (int z=0;zGetCurFilePath(); if (fullpath.Length() == 0) return; SplitFilename(fullpath,&path,&filename,&extension); CString export_dir = m_game_path + "\\Content\\Games\\Brb\\Data\\"; ClearDirectory(export_dir); // // add the export info and export then delete it // AddPreferences(m_ip->GetRootNode()); if (!m_ip->ExportToFile(export_dir+"BRBTestExport.armature",false)) return; if (!m_ip->ExportToFile(export_dir+"BRBTestExport.mw4anim",false)) return; RemovePreferences(m_ip->GetRootNode()); WriteBrbPropFile(EXPORT_ANIM); Stuff::NotationFile ans_file; Page *page = ans_file.SetPage("Test1State"); Check_Object(page); page->SetEntry("AnimType","Cycletype"); page->SetEntry("Start","0.0"); page->SetEntry("Position","0.0"); page->SetEntry("Anim","Content\\Games\\BRB\\DATA\\BRBTestExport"); ans_file.SaveAs(export_dir+"BRBTestExport.AnimScript"); char tpath[MAX_PATH]; getcwd(tpath,MAX_PATH); chdir(m_game_path); //system(m_game_path + "\\BRB.bat"); HINSTANCE hInst = ShellExecute(NULL,"open","brb.bat",NULL,m_game_path,SW_SHOWNORMAL); chdir(tpath); } //////////////////////////////////////////////////////////////////////////////// // Called when the Erf Viewer Button is pushed void PlugPanel::OnErfView() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CString Content_File_Name = ""; TSTR path, filename, extension; TSTR fullpath = m_ip->GetCurFilePath(); if (fullpath.Length() == 0) return; SplitFilename(fullpath,&path,&filename,&extension); GetGamePath(); CString export_dir = m_game_path + "\\Content\\games\\Brb\\Data\\"; ClearDirectory(export_dir); bool texture_dir_exists = gos_CreateDirectory(export_dir); // // add the export info and export then delete it // AddPreferences(m_ip->GetRootNode()); CString new_file_name = export_dir + filename + ".erf"; if (!m_ip->ExportToFile(new_file_name,TRUE)) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); AfxMessageBox(CString("Could Not Export : ") + filename + ".MAX", MB_OK); return; } RemovePreferences(m_ip->GetRootNode()); // Use the registerd tool to open the erf file system("start " + new_file_name); } int PlugPanel::WriteBrbPropFile(ETYPE etype) { TSTR ini_file = m_game_path + "\\Content\\Games\\BRB\\Data\\BRBProps.contents"; Stuff::NotationFile note_file; Page *page = note_file.SetPage("brb_vehicle"); Check_Object(page); switch(etype) { case EXPORT_SHAPE: page->SetEntry("Model","BRBTestExport.data"); page->SetEntry("ExecutionState","NeverExecuteState"); break; case EXPORT_CHARACTER: page->SetEntry("Model","BRBVehicle.data"); page->SetEntry("Armature","BRBTestExport.contents"); page->SetEntry("ExecutionState","AnimatedMotionState"); break; case EXPORT_ANIM: page->SetEntry("Model","BRBMech.data"); page->SetEntry("Armature","BRBTestExport.contents"); page->SetEntry("ExecutionState","AnimatedMotionState"); break; } page->SetEntry("Translation", "0.0 10.0 0.0"); page = note_file.SetPage("PlayerStart"); Check_Object(page); page->SetEntry("Model","Content\\Misc\\DropZone\\DropZone.data"); page->SetEntry("ExecutionState","NeverExecuteState"); // Add the entry for the game axis page = note_file.SetPage("Axis"); Check_Object(page); page->SetEntry("Model", "Axis\\Axis.data"); page->SetEntry("ExecutionState","NeverExecuteState"); page->SetEntry("TileBound", "true"); page->SetEntry("Translation", "-10.0 10.0 0.0"); page->SetEntry("Rotation", "0.0 0.0 0.0"); page->SetEntry("Alignment", "Default"); page->SetEntry("WorldSpaceVelocity", "0.0 0.0 0.0 0.0 0.0 0.0"); page->SetEntry("WorldSpaceAcceleration","0.0 0.0 0.0 0.0 0.0 0.0"); note_file.SaveAs(ini_file); //////////////////////////////////////////////////////////// // FWANG:: seems to have to touch the table file after contents file // has been changed -- don't know why though... 6/19/00 TSTR table_file = m_game_path + "\\Content\\Games\\BRB\\BRBTable.table"; Verify(gos_DoesFileExist(table_file)); if(gos_FileReadOnly(table_file)) { gos_FileSetReadWrite(table_file); } Stuff::NotationFile table_Notefile(table_file); table_Notefile.SaveAs(table_file); return 0; } //////////////////////////////////////////////////////////////////////////////// // Called when the Preview LOD Button is pushed void PlugPanel::OnPreviewLOD() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CString Content_File_Name = ""; static char BASED_CODE filter[] = "MAX Files (*.max)|*.max||"; CFileDialog dlg( TRUE, ".max", Content_File_Name, OFN_ALLOWMULTISELECT, filter ); char *holder = dlg.m_ofn.lpstrFile; dlg.m_ofn.lpstrFile = new char [10000]; Register_Pointer(dlg.m_ofn.lpstrFile); dlg.m_ofn.nMaxFile = 10000; for (int i = 0; i < 10000; ++i) { dlg.m_ofn.lpstrFile[i] = NULL; } // Get game path first GetGamePath(); if (dlg.DoModal() != IDOK) return; for (int g=0;g= MAX_FILES) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); AfxMessageBox("ERROR: Too Many Files!", MB_OK); return; } CString name = dlg.GetNextPathName(pos); if (list.IsEmpty()) list.AddHead(name); else { POSITION pos1 = list.GetHeadPosition(); bool bDone = false; while (pos1) { CString str = list.GetAt(pos1); if (name < str) { list.InsertBefore(pos1,name); bDone = true; break; } list.GetNext(pos1); } if (!bDone) list.AddTail(name); } } m_fileCount = 0; pos = list.GetHeadPosition(); while (pos) { m_fileName[m_fileCount] = list.GetNext(pos); m_fileCount++; } // // create the vars for sorting and the text strings to search for // CString numbers[] = {"_L0","_L1","_L2","_L3","_L4","_L5","_L6","_L7","_L8"}; bool found = false; int current_count = 0; int count_not_found = 0; int not_found_offset[MAX_FILES]; // // clear out the sort array and the not found array // for (int z=0;zAppendEntry("Verbose","1"); page->AppendEntry("BRB","1"); page = note_file.SetPage("BRBTestExport"); Check_Object(page); page->SetEntry("path",export_dir); int exportCharacter = 0; if (0 == exportCharacter) { // Need to specify the skeleton file CStr skelfile = m_sortName[0]; CStr p,f,f1; SplitPathFile(skelfile,&p,&f); p+= "\\"; for (int i=0;iSetEntry("LODSkel",f1); } } for (w=0;wSetEntry(tag,m_sortName[w]); tag.Format("LODDist%i",w); page->SetEntry(tag,(int)m_lodFar[w]); } } note_file.SaveAs(batchfilename); if (m_ip->ExportToFile(batchfilename,true)) { Stuff::NotationFile notefile(batchfilename); Page *page = notefile.GetPage("BRBTestExport"); const char *entry; if (page->GetEntry("LODChar0",&entry)) { exportCharacter=0; } else exportCharacter=-1; if(exportCharacter==0) WriteBrbPropFile(EXPORT_CHARACTER); else WriteBrbPropFile(EXPORT_SHAPE); Stuff::NotationFile ans_file; page = ans_file.SetPage("Test1State"); Check_Object(page); ans_file.SaveAs(export_dir+"BRBTestExport.AnimScript"); char tpath[MAX_PATH]; getcwd(tpath,MAX_PATH); chdir(m_game_path); //system(m_game_path + "\\BRB.bat"); HINSTANCE hInst = ShellExecute(NULL,"open","brb.bat",NULL,m_game_path,SW_SHOWNORMAL); chdir(tpath); } m_ip->ForceCompleteRedraw(); Unregister_Pointer(dlg.m_ofn.lpstrFile); delete[] dlg.m_ofn.lpstrFile; dlg.m_ofn.lpstrFile = holder; } // Called when the Export To Game Button is pushed void PlugPanel::OnExportToGame() { GetGamePath(); CString batchFile = m_game_path + "\\fullexport.batch"; CEditBatchFile dlg(batchFile,m_ip); if (IDOK == dlg.DoModal()) { } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool PlugPanel::AddPreferences(INode *node) { INode *data_node = node; if (node->IsRootNode()) { int i = node->NumberOfChildren(); if (i>0) { data_node = node->GetChildNode(0); } else { return false; } } // // Allocate memory for this chunk // m_exportInfo.bIsBRB = true; size_t size = sizeof(ExportInfo); BYTE *data = new BYTE[size]; Mem_Copy(data, &m_exportInfo, sizeof(ExportInfo), size); // // Add a chunk // data_node->AddAppDataChunk( EXPORTINFO_CLASS_ID, EXPORTINFO_SUPER_CLASS_ID, PERM_DATA_ID, size,data); return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool PlugPanel::RemovePreferences(INode *node) { INode *data_node = node; if (node->IsRootNode()) { int i = node->NumberOfChildren(); if (i>0) { data_node = node->GetChildNode(0); } else { return false; } } // // Remove the chunk if it exists // data_node->RemoveAppDataChunk( EXPORTINFO_CLASS_ID, EXPORTINFO_SUPER_CLASS_ID, PERM_DATA_ID ); return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void __stdcall GetGameOSEnvironment(char* CommandLine) { // //---------------------------------------------------------- // This is where to set GOS environment settings. //---------------------------------------------------------- // Environment.applicationName = "BRBINVIS"; Environment.screenWidth = 640; Environment.screenHeight = 480; Environment.bitDepth = 16; } void PlugPanel::GetGamePath() { TSTR ini_file = m_ip->GetDir(APP_PLUGCFG_DIR); ini_file += "\\Plugins.ini"; Check_Pointer(Stuff::FileStreamManager::Instance); Stuff::NotationFile data_file(ini_file); const char* read_dir; Stuff::Page *page = data_file.FindPage("BRBData"); if (page && page->GetEntry("GameDir", &read_dir)) { m_game_path = read_dir; } } void DeleteDirectory(CString dir) { ClearDirectory(dir); RemoveDirectory(dir); } void ClearDirectory(CString dir) { HANDLE hfl; WIN32_FIND_DATA fd; if(dir[dir.GetLength()-1]=='\\') { dir=dir.Left(dir.GetLength()-1); } fd.dwFileAttributes=NULL; hfl=FindFirstFile(dir+"\\*.*",&fd); if(INVALID_HANDLE_VALUE!=hfl) { do { CString fileName = fd.cFileName; fileName.MakeLower(); if (fd.dwFileAttributes&FILE_ATTRIBUTE_READONLY) { fd.dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY; ::SetFileAttributes(dir+"\\"+fd.cFileName,fd.dwFileAttributes); } if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) { if(strcmp(fd.cFileName,".") && strcmp(fd.cFileName,"..") ) { DeleteDirectory(dir+"\\"+fd.cFileName); } } // delete all the files but .mw4anim file else if (fileName.Find(".mw4anim")<0 && fileName.Find(".animscript")<0) { DeleteFile(dir+"\\"+fd.cFileName); } } while(FindNextFile(hfl,&fd)); } }