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.
880 lines
22 KiB
C++
880 lines
22 KiB
C++
/***************************************************************************
|
|
*
|
|
* 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 <direct.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
|
|
|
|
#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 <gosFX\gosFX.hpp>
|
|
#endif
|
|
|
|
#if !defined(DLLPLATFORM_DLLPLATFORM_HPP)
|
|
#include "DLLPlatform\DLLPlatform.hpp"
|
|
#endif
|
|
|
|
#if !defined(GOSFX_GOSFX_HPP)
|
|
#include <gosFX\gosFX.hpp>
|
|
#endif
|
|
|
|
void DeleteDirectory(CString dir);
|
|
void ClearDirectory(CString dir);
|
|
|
|
#include <GameOs\TooLOS.hpp>
|
|
|
|
#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;z<MAX_FILES;z++)
|
|
{
|
|
m_sortName[z] = "";
|
|
}
|
|
|
|
GetGamePath();
|
|
|
|
TSTR fullpath,path,filename,extension;
|
|
fullpath = m_ip->GetCurFilePath();
|
|
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;g++)
|
|
{
|
|
m_fileName[g] = "";
|
|
}
|
|
POSITION pos = dlg.GetStartPosition();
|
|
|
|
// Need to sort these names before placing them in m_fileName array
|
|
CStringList list;
|
|
m_fileCount = 0;
|
|
while (pos != NULL)
|
|
{
|
|
m_fileCount++;
|
|
if (m_fileCount >= 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;z<MAX_FILES;z++)
|
|
{
|
|
not_found_offset[z] = -1;
|
|
m_sortName[z] = "";
|
|
}
|
|
//
|
|
// find all the offsets of file names without a number 0-7
|
|
//
|
|
for (int a=0;a<MAX_FILES;a++)
|
|
{
|
|
found = false;
|
|
for (int b=0;b<MAX_FILES;b++)
|
|
{
|
|
CString temp = numbers[b];
|
|
char *search = strstr(m_fileName[a],temp);
|
|
if (search != NULL)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if ((!found) && (m_fileName[a] != ""))
|
|
//if (!found)
|
|
{
|
|
not_found_offset[count_not_found] = a;
|
|
count_not_found++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// sort the numbered file names
|
|
//
|
|
for (int w=0;w<MAX_FILES;w++)
|
|
{
|
|
found = false;
|
|
for (int y=0;y<MAX_FILES;y++)
|
|
{
|
|
//
|
|
// get the text number to search for
|
|
//
|
|
CString temp = numbers[w];
|
|
char *search = NULL;
|
|
TSTR filename, path, extension;
|
|
TSTR fullpath = _T(m_fileName[y]);
|
|
//
|
|
// split off the file name so that we search for the
|
|
// number there instead of the whole path
|
|
//
|
|
SplitFilename(fullpath,&path,&filename,&extension);
|
|
search = strstr(filename,temp);
|
|
//search = strstr(m_fileName[y],temp);
|
|
if (search != NULL)
|
|
{
|
|
found = true;
|
|
m_sortName[current_count] = m_fileName[y];
|
|
current_count++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// add the rest of the non numbered file names to the sorted list
|
|
//
|
|
for (int u=0;u<MAX_FILES;u++)
|
|
{
|
|
if (not_found_offset[u] != -1 && not_found_offset[u] < MAX_FILES)
|
|
{
|
|
m_sortName[current_count] = m_fileName[not_found_offset[u]];
|
|
current_count++;
|
|
}
|
|
}
|
|
|
|
UINT m_lodFar[MAX_FILES]; // array of far lod distances
|
|
UINT m_lodNear[MAX_FILES]; // array of near lod distances
|
|
m_lodNear[0] = 0;
|
|
m_lodFar[0] = m_lodNear[1] = 50;
|
|
m_lodFar[1] = m_lodNear[2] = 100;
|
|
m_lodFar[2] = m_lodNear[3] = 150;
|
|
m_lodFar[3] = m_lodNear[4] = 200;
|
|
m_lodFar[4] = m_lodNear[5] = 250;
|
|
m_lodFar[5] = m_lodNear[6] = 300;
|
|
m_lodFar[6] = m_lodNear[7] = 350;
|
|
m_lodFar[7] = 400;
|
|
|
|
CString export_dir=m_game_path + "\\Content\\Games\\Brb\\Data\\";
|
|
ClearDirectory(export_dir);
|
|
CString batchfilename=export_dir+"BrbBatch.batch";
|
|
|
|
Stuff::NotationFile note_file;
|
|
Page *page = note_file.SetPage("Options");
|
|
page->AppendEntry("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;i<strlen(f);i++)
|
|
{
|
|
if (f[i] == '_')
|
|
break;
|
|
if (f[i] == '.')
|
|
break;
|
|
}
|
|
if (i<strlen(f))
|
|
f1 = f.Substr(0,i);
|
|
if (strlen(f1))
|
|
{
|
|
f1 = p+f1+"_skeleton.max";
|
|
page->SetEntry("LODSkel",f1);
|
|
}
|
|
}
|
|
for (w=0;w<MAX_FILES;w++)
|
|
{
|
|
if (m_sortName[w] != "")
|
|
{
|
|
CString tag;
|
|
|
|
if (exportCharacter == 0)
|
|
{
|
|
tag.Format("LODChar%i",w);
|
|
}
|
|
else
|
|
{
|
|
tag.Format("LODShape%i",w);
|
|
}
|
|
|
|
page->SetEntry(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));
|
|
}
|
|
|
|
} |