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.
481 lines
11 KiB
C++
481 lines
11 KiB
C++
// EditBatchFile.cpp : implementation file
|
|
//
|
|
|
|
#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 "EditBatchFile.h"
|
|
#include <GameOS\ToolOS.hpp>
|
|
|
|
//#include "brb.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
CString g_szbrowsepath;
|
|
static int CALLBACK BrowseCallbackProc1(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
|
{
|
|
RECT rect;
|
|
//
|
|
//Center the browse dialog on the screen...
|
|
//
|
|
switch (uMsg)
|
|
{
|
|
case BFFM_INITIALIZED:
|
|
{
|
|
SendMessage(hWnd,BFFM_SETSELECTION,TRUE,(LPARAM)(LPCTSTR)g_szbrowsepath);
|
|
|
|
if (GetWindowRect(hWnd, &rect))
|
|
{
|
|
SetWindowPos(hWnd,
|
|
HWND_TOP,
|
|
(GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) >> 1,
|
|
(GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) >> 1,
|
|
0,
|
|
0,
|
|
SWP_NOSIZE);
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
CString BrowseDirectory(const char *strCurrent,CWnd *pWnd)
|
|
{
|
|
CString str;
|
|
TCHAR szBuffer[MAX_PATH];
|
|
LPITEMIDLIST pidlBrowse,pidlRoot;
|
|
BROWSEINFO bi;
|
|
|
|
LPMALLOC lpMalloc;
|
|
SHGetMalloc(&lpMalloc);
|
|
ASSERT(lpMalloc);
|
|
bi.hwndOwner = pWnd->GetSafeHwnd();
|
|
// Get the ID for the "My Computer" root folder
|
|
SHGetSpecialFolderLocation(pWnd->GetSafeHwnd(),CSIDL_DRIVES | CSIDL_NETWORK,&pidlRoot);
|
|
|
|
bi.pidlRoot = pidlRoot;
|
|
bi.pszDisplayName = szBuffer;
|
|
|
|
// Localize the descriptive text
|
|
bi.lpszTitle = "Select a Building, Mech, or Vehicle model root folder. This contains the LODs, and skeleton.";
|
|
|
|
// BIF_EDITBOX and BIF_VALIDATE are for versions 4.71 and later, they
|
|
// might be ignored by older versions
|
|
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;// | BIF_EDITBOX;// | BIF_USENEWUI;// | BIF_VALIDATE;
|
|
bi.lParam = (LPARAM)pWnd;
|
|
bi.iImage = NULL;
|
|
bi.lpfn = BrowseCallbackProc1;
|
|
bi.lParam = (LPARAM)strCurrent;
|
|
g_szbrowsepath = strCurrent;
|
|
//
|
|
//Call the Windows shell folder browsing routine...
|
|
//
|
|
pidlBrowse = SHBrowseForFolder(&bi);
|
|
if (NULL != pidlBrowse)
|
|
{
|
|
if (SHGetPathFromIDList(pidlBrowse, szBuffer))
|
|
{
|
|
if ('\\' == szBuffer[lstrlen(szBuffer)-1])
|
|
szBuffer[lstrlen(szBuffer)-1] = '\0';
|
|
str = CString(szBuffer);
|
|
}
|
|
else
|
|
str = "";
|
|
//
|
|
//Free up shell memory used...
|
|
//
|
|
lpMalloc->Free(pidlBrowse);
|
|
}
|
|
else
|
|
str = "";
|
|
lpMalloc->Free(pidlRoot);
|
|
lpMalloc->Release();
|
|
return str;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CEditBatchFile dialog
|
|
|
|
|
|
CEditBatchFile::CEditBatchFile(CString batchfile,Interface *i,CWnd* pParent /*=NULL*/)
|
|
: CDialog(CEditBatchFile::IDD, pParent)
|
|
{
|
|
m_strFileName = batchfile;
|
|
if (::gos_FileReadOnly(batchfile))
|
|
::gos_FileSetReadWrite(batchfile);
|
|
|
|
m_pNotefile = new NotationFile(batchfile);
|
|
Register_Object(m_pNotefile);
|
|
ip = i;
|
|
//{{AFX_DATA_INIT(CEditBatchFile)
|
|
// NOTE: the ClassWizard will add member initialization here
|
|
//}}AFX_DATA_INIT
|
|
}
|
|
|
|
|
|
void CEditBatchFile::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CEditBatchFile)
|
|
DDX_Control(pDX, IDC_LIST1, m_list);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CEditBatchFile, CDialog)
|
|
//{{AFX_MSG_MAP(CEditBatchFile)
|
|
ON_WM_DESTROY()
|
|
ON_BN_CLICKED(IDC_MODIFY, OnModify)
|
|
ON_BN_CLICKED(IDC_ADD, OnAdd)
|
|
ON_BN_CLICKED(IDC_REMOVE, OnRemove)
|
|
ON_BN_CLICKED(IDC_EXPORT, OnExport)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CEditBatchFile message handlers
|
|
|
|
BOOL CEditBatchFile::OnInitDialog()
|
|
{
|
|
CDialog::OnInitDialog();
|
|
|
|
m_list.ResetContent();
|
|
NotationFile::PageIterator *pages = m_pNotefile->MakePageIterator();
|
|
Check_Object(pages);
|
|
Page *page;
|
|
while (page = pages->ReadAndNext())
|
|
{
|
|
CString name = page->GetName();
|
|
int index = m_list.AddString(name);
|
|
//m_list.SetItemData(index,(DWORD)page);
|
|
}
|
|
delete pages;
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
|
// EXCEPTION: OCX Property Pages should return FALSE
|
|
}
|
|
|
|
void CEditBatchFile::OnDestroy()
|
|
{
|
|
CDialog::OnDestroy();
|
|
if (m_pNotefile)
|
|
{
|
|
Unregister_Object(m_pNotefile);
|
|
delete m_pNotefile;
|
|
}
|
|
m_pNotefile = NULL;
|
|
}
|
|
|
|
void CEditBatchFile::CreateBRBBatch(CString strPath,Page *page)
|
|
{
|
|
NotationFile notefile(strPath);
|
|
Page *brbPage = notefile.SetPage("Options");
|
|
brbPage->AppendEntry("Verbose","1");
|
|
brbPage->AppendEntry("BRB","1");
|
|
brbPage = notefile.AddPage(page->GetName());
|
|
Page::NoteIterator *notes = page->MakeNoteIterator();
|
|
Note *note;
|
|
while (note = notes->ReadAndNext())
|
|
{
|
|
const char *entry;
|
|
note->GetEntry(&entry);
|
|
brbPage->AppendEntry(note->GetName(),entry);
|
|
}
|
|
delete notes;
|
|
notefile.Save();
|
|
}
|
|
|
|
bool bDoExport = false;
|
|
void CEditBatchFile::OnModify(/*bool bDoExport*/)
|
|
{
|
|
CString strGamePath;
|
|
{
|
|
TSTR ini_file = 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 *tpage = data_file.FindPage("BRBData");
|
|
if (tpage && tpage->GetEntry("GameDir", &read_dir))
|
|
{
|
|
strGamePath = read_dir;
|
|
}
|
|
}
|
|
CString brbPath = strGamePath+"\\content\\games\\brb\\data";
|
|
CString brbFile = brbPath+"\\BrbBatch.batch";
|
|
|
|
int count = m_list.GetSelCount();
|
|
|
|
if (count>0)
|
|
{
|
|
::gos_DeleteFile(brbFile);
|
|
int *items = new int[count];
|
|
m_list.GetSelItems(count,items);
|
|
for (int x=0;x<count;x++)
|
|
{
|
|
CString str;
|
|
m_list.GetText(items[x],str);
|
|
Page *page = m_pNotefile->FindPage(str);
|
|
if (!bDoExport)
|
|
page->AppendEntry("DoExport","0");
|
|
//Page *page = (Page *)m_list.GetItemData(items[x]);
|
|
CreateBRBBatch(brbFile,page);
|
|
}
|
|
delete items;
|
|
|
|
if (ip->ExportToFile(brbFile,true))
|
|
{
|
|
// Export successful, add the pages data to the fullexport.batch
|
|
NotationFile notefile(brbFile);
|
|
|
|
NotationFile::PageIterator *pages = notefile.MakePageIterator();
|
|
Page *page;
|
|
Check_Object(pages);
|
|
while (page = pages->ReadAndNext())
|
|
{
|
|
m_pNotefile->DeletePage(page->GetName());
|
|
Page *newpage = m_pNotefile->AddPage(page->GetName());
|
|
|
|
Page::NoteIterator *notes = page->MakeNoteIterator();
|
|
Note *note;
|
|
Check_Object(notes);
|
|
while (note = notes->ReadAndNext())
|
|
{
|
|
const char *entry;
|
|
note->GetEntry(&entry);
|
|
if (strnicmp(note->GetName(),"DoExport",8))
|
|
newpage->AppendEntry(note->GetName(),entry);
|
|
}
|
|
delete notes;
|
|
|
|
}
|
|
delete pages;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CEditBatchFile::OnCancel()
|
|
{
|
|
// TODO: Add extra cleanup here
|
|
m_pNotefile->IgnoreChanges();
|
|
CDialog::OnCancel();
|
|
}
|
|
|
|
void CEditBatchFile::OnOK()
|
|
{
|
|
m_pNotefile->Save();
|
|
CDialog::OnOK();
|
|
}
|
|
|
|
void CEditBatchFile::OnAdd()
|
|
{
|
|
CString strGamePath;
|
|
{
|
|
TSTR ini_file = 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 *tpage = data_file.FindPage("BRBData");
|
|
if (tpage && tpage->GetEntry("GameDir", &read_dir))
|
|
{
|
|
strGamePath = read_dir;
|
|
}
|
|
}
|
|
|
|
CString strName;
|
|
CString strBrowse;
|
|
CString strType;
|
|
bool bFind = false;
|
|
while (!bFind)
|
|
{
|
|
strBrowse = BrowseDirectory("",this);
|
|
if (strBrowse.GetLength())
|
|
{
|
|
strName = strBrowse;
|
|
{
|
|
if (stricmp(strName.Right(5),"final")==0)
|
|
strName = strName.Left(strName.GetLength()-6);
|
|
else
|
|
{
|
|
// TODO,BUGBUG: this is only until sage re-structures the art repository
|
|
strBrowse += "\\final";
|
|
}
|
|
int index = strName.ReverseFind('\\');
|
|
if (index>3)
|
|
{
|
|
strType = strName.Left(index);
|
|
strName.Delete(0,index+1);
|
|
}
|
|
|
|
index = strType.ReverseFind('\\');
|
|
if (index>3)
|
|
{
|
|
strType.Delete(0,index+1);
|
|
}
|
|
}
|
|
Page *page = m_pNotefile->FindPage(strName);
|
|
if (page)
|
|
{
|
|
CString str;
|
|
str.Format("A model named %s already exists in Fullexport.batch, please select a different model",strName);
|
|
MessageBox(str,"Add to Fullexport.batch");
|
|
}
|
|
else
|
|
{
|
|
bFind = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// User pressed cancel
|
|
return;
|
|
}
|
|
}
|
|
|
|
int index = m_list.AddString(strName);
|
|
m_list.SetCurSel(index);
|
|
|
|
Page *page = m_pNotefile->AddPage(strName);
|
|
|
|
// Detect class
|
|
int itype = -1;
|
|
CString strClass;
|
|
if (0==stricmp(strType,"Buildings"))
|
|
{
|
|
itype = 0;
|
|
strClass = "MechWarrior4::Building";
|
|
}
|
|
if (0==stricmp(strType,"Mechs"))
|
|
{
|
|
itype = 1;
|
|
strClass = "MechWarrior4::Mech";
|
|
}
|
|
if (0==stricmp(strType,"Vehicles"))
|
|
{
|
|
itype = 2;
|
|
strClass = "MechWarrior4::Vehicle";
|
|
}
|
|
if (itype >=0)
|
|
{
|
|
page->AppendEntry("Class",strClass);
|
|
}
|
|
|
|
CString strPath = strGamePath+"\\content\\"+strType+"\\"+strName+"\\";
|
|
page->AppendEntry("Path",strPath);
|
|
|
|
// Detect skeleton
|
|
bool bSkel = false;
|
|
CString strSkel = strBrowse;
|
|
CString str = strSkel+"\\Skeleton\\"+strName+".max";
|
|
if (::gos_DoesFileExist(str))
|
|
{
|
|
strSkel = str;
|
|
bSkel = true;
|
|
}
|
|
else
|
|
{
|
|
str = strSkel+"\\"+strName+".max";
|
|
if (::gos_DoesFileExist(str))
|
|
{
|
|
strSkel = str;
|
|
bSkel = true;
|
|
}
|
|
}
|
|
if (bSkel)
|
|
{
|
|
page->AppendEntry("LODSkel",strSkel);
|
|
}
|
|
|
|
//Detect LODs
|
|
char lodDist[3][6][5] =
|
|
{
|
|
{"50","100","250","600","1000","1000"},
|
|
{"30","60","100","200","320","1000"},
|
|
{"25","100","500","1000","1000","1000"}
|
|
};
|
|
|
|
BYTE bLod = 0;
|
|
BYTE bDamLod = 0;
|
|
for (int x=0;x<6;x++)
|
|
{
|
|
CString str2 = (0==itype)?"Intact":"Final";
|
|
str.Format("%s\\%s_%s_L%d.max",strBrowse,strName,str2,x);
|
|
if (::gos_DoesFileExist(str))
|
|
{
|
|
bLod |= 1<<x;
|
|
|
|
CString str1 = (itype?"LODChar":"LODShape");
|
|
CString strLod;
|
|
strLod.Format("%s%d",str1,x);
|
|
page->AppendEntry(strLod,str);
|
|
}
|
|
|
|
str.Format("%s\\%s_Final_Dam_L%d.max",strBrowse,strName,x);
|
|
if (::gos_DoesFileExist(str))
|
|
{
|
|
bDamLod |= 1<<x;
|
|
|
|
CString strLod;
|
|
strLod.Format("LODDam%d",x);
|
|
page->AppendEntry(strLod,str);
|
|
}
|
|
|
|
if ((bLod & 1<<x) || (bDamLod & 1<<x))
|
|
{
|
|
str = lodDist[itype][x];
|
|
CString strLod;
|
|
strLod.Format("LODDist%d",x);
|
|
page->AppendEntry(strLod,str);
|
|
}
|
|
}
|
|
|
|
if (bSkel)
|
|
{
|
|
page->AppendEntry("Obb",strSkel);
|
|
}
|
|
|
|
// TODO: Detect Destroyed
|
|
|
|
// TODO: Cage
|
|
|
|
// TODO: Animations (when sage moves around the art repository structure so I can detect them
|
|
|
|
OnModify();
|
|
}
|
|
|
|
void CEditBatchFile::OnRemove()
|
|
{
|
|
int count = m_list.GetSelCount();
|
|
|
|
if (count>0)
|
|
{
|
|
int *items = new int[count];
|
|
m_list.GetSelItems(count,items);
|
|
for (int x=0;x<count;x++)
|
|
{
|
|
CString str;
|
|
m_list.GetText(items[x],str);
|
|
m_pNotefile->DeletePage(str);
|
|
}
|
|
delete items;
|
|
}
|
|
OnInitDialog();
|
|
}
|
|
|
|
void CEditBatchFile::OnExport()
|
|
{
|
|
bDoExport = true;
|
|
OnModify();
|
|
bDoExport = false;
|
|
}
|