This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Tools/LevelEdit/Utils.cpp

2372 lines
56 KiB
C++
Raw Permalink Normal View History

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/////////////////////////////////////////////////////////////////////////////
//
// Utils.CPP
//
// Module containing usefull misc. utility functions
//
#include "stdafx.h"
#include "mainfrm.h"
#include "leveleditdoc.h"
#include "leveleditview.h"
#include "leveledit.h"
#include "utils.h"
#include "outputform.h"
#include "sceneeditor.h"
#include "nodemgr.h"
#include "node.h"
#include "groupmgr.h"
#include "updatingdbdialog.h"
#include "icons.h"
#include "regkeys.h"
#include "presetmgr.h"
#include "HLod.h"
#include "AABox.h"
#include "definition.h"
#include "verchk.h"
#include "editorsaveload.h"
#include "generatingvisdialog.h"
#include "boxrobj.h"
#include "definitionfactory.h"
#include "definitionfactorymgr.h"
#include "nodecategories.h"
#include "conversationpage.h"
////////////////////////////////////////////////////////////////////////////
//
// Get_Current_Document
//
////////////////////////////////////////////////////////////////////////////
CLevelEditDoc *
Get_Current_Document (void)
{
// Assume failure
CLevelEditDoc *pdoc = NULL;
// Get a pointer to the main window
CMainFrame *pmainwnd = (CMainFrame *)theApp.GetMainWnd ();
// Did we successfully get a pointer to the main window?
if (pmainwnd != NULL) {
// Use the main window pointer to get a pointer
// to the current doc.
//pdoc = (CLevelEditDoc *)pmainwnd->GetActiveDocument ();
pdoc = pmainwnd->Get_Current_Document ();
ASSERT (pdoc);
}
// Return the doc pointer
return pdoc;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Node_Mgr
//
////////////////////////////////////////////////////////////////////////////
NodeMgrClass &
Get_Node_Mgr (void)
{
// Return the node manager pointer
return _TheNodeMgr;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Scene_Editor
//
////////////////////////////////////////////////////////////////////////////
SceneEditorClass *
Get_Scene_Editor (void)
{
SceneEditorClass *peditor = NULL;
CLevelEditDoc *pdoc = ::Get_Current_Document ();
// Were we successful in getting the document pointer?
ASSERT (pdoc != NULL);
if (pdoc != NULL) {
// Get a pointer to the editor
peditor = pdoc->Get_Scene ();
}
// Return the editor pointer
return peditor;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Camera_Mgr
//
////////////////////////////////////////////////////////////////////////////
CameraMgr *
Get_Camera_Mgr (void)
{
CameraMgr *pcameramgr = NULL;
// Get a pointer to the current view
CLevelEditView *pview = ::Get_Main_View ();
// Were we successful in getting the view pointer?
ASSERT (pview != NULL);
if (pview != NULL) {
// Get a pointer to the camera maanager
pcameramgr = pview->Get_Camera_Mgr ();
}
// Return the camera manager pointer
return pcameramgr;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Mouse_Mgr
//
////////////////////////////////////////////////////////////////////////////
MouseMgrClass *
Get_Mouse_Mgr (void)
{
MouseMgrClass *pmousemgr = NULL;
// Get a pointer to the current view
CLevelEditView *pview = ::Get_Main_View ();
// Were we successful in getting the view pointer?
ASSERT (pview != NULL);
if (pview != NULL) {
// Get a pointer to the mouse maanager
pmousemgr = pview->Get_Mouse_Mgr ();
}
// Return the mouse manager pointer
return pmousemgr;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Selection_Mgr
//
////////////////////////////////////////////////////////////////////////////
SelectionMgrClass &
Get_Selection_Mgr (void)
{
// Return the selction manager pointer
return ::Get_Scene_Editor ()->Get_Selection_Mgr ();
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Main_View
//
////////////////////////////////////////////////////////////////////////////
CLevelEditView *
Get_Main_View (void)
{
// Assume failure
CLevelEditView *pview = NULL;
// Get a pointer to the main window
CMainFrame *pmainwnd = (CMainFrame *)theApp.GetMainWnd ();
// Did we successfully get a pointer to the main window?
ASSERT (pmainwnd != NULL);
if (pmainwnd != NULL) {
// Use the main window pointer to get a pointer
// to the current view.
pview = (CLevelEditView *)pmainwnd->GetActiveView ();
ASSERT (pview != NULL);
}
// Return the view pointer
return pview;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_File_Mgr
//
////////////////////////////////////////////////////////////////////////////
FileMgrClass *
Get_File_Mgr (void)
{
FileMgrClass *pfilemgr = NULL;
// Get a pointer to the current document
CLevelEditDoc *pdoc = ::Get_Current_Document ();
// Were we successful in getting the document pointer?
ASSERT (pdoc != NULL);
if (pdoc != NULL) {
// Get a pointer to the file maanager
pfilemgr = pdoc->Get_File_Mgr ();
}
// Return the file manager pointer
return pfilemgr;
}
////////////////////////////////////////////////////////////////////////////
//
// Refresh_Main_View
//
////////////////////////////////////////////////////////////////////////////
void
Refresh_Main_View (void)
{
// Force the view to repaint itself,
// but only if auto updating is turned off
CLevelEditView *pview = Get_Main_View ();
if ((pview != NULL) &&
(pview->Is_Updating () == false) &&
::IsWindow (pview->m_hWnd)) {
pview->Repaint_View ();
pview->Repaint_View ();
}
return ;
}
/////////////////////////////////////////////////////////////
//
// Paint_Gradient
//
////////////////////////////////////////////////////////////////////////////
void
Paint_Gradient
(
HWND hwnd,
BYTE base_red,
BYTE base_green,
BYTE base_blue
)
{
// Get the bounding rectangle so we know how much to paint
RECT rect;
::GetClientRect (hwnd, &rect);
// Determine the width, height, and width per each shade
int width = rect.right-rect.left;
int height = rect.bottom-rect.top;
float width_per_shade = ((float)width) / 256.00F;
// Pull a hack to get the CDC for the window
HDC hdc = ::GetDC (hwnd);
CDC cdc;
cdc.Attach (hdc);
// Loop through each shade and paint its sliver
float posx = 0.00F;
for (int shade = 0; shade < 256; shade ++) {
// Paint this sliver
cdc.FillSolidRect ((int)posx,
0,
(width_per_shade >= 1.00F) ? (int)width_per_shade : 1,
height,
RGB (shade*base_red, shade*base_green, shade*base_blue));
// Increment the current position
posx += width_per_shade;
}
// Release the DC
cdc.Detach ();
::ReleaseDC (hwnd, hdc);
// Validate the contents of the window so the control won't paint itself
::ValidateRect (hwnd, NULL);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Startup_Directory
//
////////////////////////////////////////////////////////////////////////////
CString
Get_Startup_Directory (void)
{
TCHAR path[MAX_PATH];
::GetModuleFileName (NULL, path, sizeof (path));
LPTSTR filename = ::strrchr (path, '\\');
if (filename)
{
// Strip ff the filename
filename[0] = 0;
}
// Return the path to the caller
return CString (path);
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Data_Directory
//
////////////////////////////////////////////////////////////////////////////
CString
Get_Data_Directory (void)
{
// Get the path we were run from
CString path = ::Get_Startup_Directory ();
// Concat the 'data' subdir onto that path
path += "\\Data";
// Return the path to the caller
return path;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Filename_From_Path
//
////////////////////////////////////////////////////////////////////////////
CString
Get_Filename_From_Path (LPCTSTR path)
{
// Find the last occurance of the directory deliminator
LPCTSTR filename = ::strrchr (path, '\\');
if (filename != NULL) {
// Increment past the directory deliminator
filename ++;
} else {
filename = path;
}
// Return the filename part of the path
return CString (filename);
}
////////////////////////////////////////////////////////////////////////////
//
// Strip_Filename_From_Path
//
////////////////////////////////////////////////////////////////////////////
CString
Strip_Filename_From_Path (LPCTSTR path)
{
// Copy the path to a buffer we can modify
TCHAR temp_path[MAX_PATH];
::lstrcpy (temp_path, path);
// Find the last occurance of the directory deliminator
LPTSTR filename = ::strrchr (temp_path, '\\');
if (filename != NULL) {
// Strip off the filename
filename[0] = 0;
} else if ((temp_path[1] != ':') && (temp_path[1] != '\\')) {
temp_path[0] = 0;
}
// Return the path only
return CString (temp_path);
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Subdir_From_Full_Path
//
////////////////////////////////////////////////////////////////////////////
CString
Get_Subdir_From_Full_Path (LPCTSTR path)
{
int last_delim = 0;
int prev_delim = 0;
for (int index = 0; path[index] != 0; index++) {
if (path[index] == '\\') {
prev_delim = last_delim;
last_delim = index + 1;
}
}
// Return the sub-dir name
CString sub_dir = &path[prev_delim];
sub_dir = sub_dir.Left ((last_delim-prev_delim)-1);
return sub_dir;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Subdir_And_Filename_From_Path
//
////////////////////////////////////////////////////////////////////////////
CString
Get_Subdir_And_Filename_From_Path (LPCTSTR path)
{
int last_delim = 0;
int prev_delim = 0;
for (int index = 0; path[index] != 0; index++) {
if (path[index] == '\\') {
prev_delim = last_delim;
last_delim = index + 1;
}
}
// Return the sub-dir and filename
CString sub_dir = &path[prev_delim];
return sub_dir;
}
////////////////////////////////////////////////////////////////////////////
//
// Up_One_Directory
//
////////////////////////////////////////////////////////////////////////////
CString
Up_One_Directory (LPCTSTR path)
{
// Copy the path to a buffer we can modify
TCHAR local_copy[MAX_PATH];
::lstrcpy (local_copy, path);
// Strip off the last subdir in the path
LPTSTR plast_dir = ::strrchr (local_copy, '\\');
if (plast_dir != NULL) {
plast_dir[0] = 0;
}
// Return the new path
return CString (local_copy);
}
////////////////////////////////////////////////////////////////////////////
//
// Get_File_Size
//
////////////////////////////////////////////////////////////////////////////
DWORD
Get_File_Size (LPCTSTR path)
{
DWORD file_size = 0L;
ASSERT (path != NULL);
if (path != NULL) {
// Attempt to open the file
HANDLE hfile = ::CreateFile (path,
0,
0,
NULL,
OPEN_EXISTING,
0L,
NULL);
ASSERT (hfile != INVALID_HANDLE_VALUE);
if (hfile != INVALID_HANDLE_VALUE) {
// Get the size in bytes of the file and return it
// to the caller.
file_size = ::GetFileSize (hfile, NULL);
// Close the file
::CloseHandle (hfile);
hfile = INVALID_HANDLE_VALUE;
}
}
// Return the size in bytes of the file to the caller.
return file_size;
}
////////////////////////////////////////////////////////////////////////////
//
// Output_Message
//
////////////////////////////////////////////////////////////////////////////
void
Output_Message (LPCTSTR message)
{
// Get a pointer to the main window
CMainFrame *pmainwnd = (CMainFrame *)theApp.GetMainWnd ();
// Did we successfully get a pointer to the main window?
ASSERT (pmainwnd != NULL);
if (pmainwnd != NULL) {
FormToolbarClass &toolbar = pmainwnd->Get_Output_Toolbar ();
// Get a pointer to the output window
OutputFormClass *form = (OutputFormClass *)toolbar.Get_Form ();
// Print the message to the window
if ((form != NULL) && IsWindow (form->m_hWnd)) {
form->Output_Message (message);
}
}
TRACE (message);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Is_Path_Relative
//
////////////////////////////////////////////////////////////////////////////
bool
Is_Path_Relative (LPCTSTR path)
{
bool relative = false;
// Param valid?
ASSERT (path != NULL);
if (path != NULL && path[0] != 0) {
// Check for drive designation
relative = bool(path[1] != ':');
// Check for network path
relative &= bool((path[0] != '\\') && (path[1] != '\\'));
}
// Return the true/false result code
return relative;
}
////////////////////////////////////////////////////////////////////////////
//
// Find_File
//
////////////////////////////////////////////////////////////////////////////
bool
Find_File
(
LPCTSTR filename,
LPCTSTR start_dir,
CString &full_path
)
{
bool bfound = false;
// Params valid?
ASSERT (filename != NULL);
ASSERT (start_dir != NULL);
if ((filename != NULL) && (start_dir != NULL)) {
// Make sure the current directory name doesn't end in a
// directory delimiter.
CString current_dir = start_dir;
if (current_dir[::lstrlen (current_dir)-1] == '\\') {
current_dir = current_dir.Left (::lstrlen (current_dir)-1);
}
// Is the file in this directory?
CString dir_test = current_dir + CString ("\\") + filename;
if (::GetFileAttributes (dir_test) != 0xFFFFFFFF) {
// Found it!
bfound = true;
full_path = dir_test;
} else {
WIN32_FIND_DATA find_info = { 0 };
BOOL bcontinue = true;
CString search_mask = current_dir + "\\*.*";
// Loop through all the files in the current directory
for (HANDLE hfilefind = ::FindFirstFile (search_mask, &find_info);
(hfilefind != INVALID_HANDLE_VALUE) && bcontinue && !bfound;
bcontinue = ::FindNextFile (hfilefind, &find_info)) {
// Is this 'file' a subdir of the current directory?
if ((find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(find_info.cFileName[0] != '.')) {
// Build the full path of this sub-dir name
CString sub_dir_path = current_dir + CString ("\\") + find_info.cFileName;
// Recursively call this find function for that subdir
bfound = Find_File (filename, sub_dir_path, full_path);
}
}
// Close the handle we needed for the file find routines
if (hfilefind != INVALID_HANDLE_VALUE) {
::FindClose (hfilefind);
}
}
}
// Return the true/false result code
return bfound;
}
////////////////////////////////////////////////////////////////////////////
//
// Quick_Compare_Files
//
////////////////////////////////////////////////////////////////////////////
int
Quick_Compare_Files
(
LPCTSTR file1,
LPCTSTR file2
)
{
// Assume they are the same
int icompare = 0;
// Params OK?
ASSERT (file1 != NULL);
ASSERT (file2 != NULL);
if ((file1 != NULL) && (file2 != NULL)) {
// Attempt to open file1
HANDLE hfile1 = ::CreateFile (file1,
0,
0,
NULL,
OPEN_EXISTING,
0L,
NULL);
// Attempt to open file2
HANDLE hfile2 = ::CreateFile (file2,
0,
0,
NULL,
OPEN_EXISTING,
0L,
NULL);
if ((hfile1 != INVALID_HANDLE_VALUE) && (hfile2 != INVALID_HANDLE_VALUE)) {
// Get information about these 2 files.
BY_HANDLE_FILE_INFORMATION file1_info = { 0 };
BY_HANDLE_FILE_INFORMATION file2_info = { 0 };
::GetFileInformationByHandle (hfile1, &file1_info);
::GetFileInformationByHandle (hfile2, &file2_info);
// Compare the time these files were last written to
icompare = ::CompareFileTime (&file1_info.ftLastWriteTime, &file2_info.ftLastWriteTime);
} else if ((hfile1 == INVALID_HANDLE_VALUE) && (hfile2 != INVALID_HANDLE_VALUE)) {
icompare = -1;
} else if ((hfile1 != INVALID_HANDLE_VALUE) && (hfile2 == INVALID_HANDLE_VALUE)) {
icompare = 1;
}
if (hfile1 != INVALID_HANDLE_VALUE) {
::CloseHandle (hfile1);
}
if (hfile2 != INVALID_HANDLE_VALUE) {
::CloseHandle (hfile2);
}
}
// Same as strcmp, -1 if file1 is older than file2, 0 if equal, 1 if file1 is newer than file2
return icompare;
}
////////////////////////////////////////////////////////////////////////////
//
// Build_List_From_String
//
////////////////////////////////////////////////////////////////////////////
int
Build_List_From_String
(
LPCTSTR buffer,
LPCTSTR delimiter,
CString **pstring_list
)
{
// Start with zero list entries
int count = 0;
ASSERT (buffer != NULL);
ASSERT (delimiter != NULL);
ASSERT (pstring_list != NULL);
if ((buffer != NULL) &&
(delimiter != NULL) &&
(pstring_list != NULL)) {
int delim_len = ::strlen (delimiter);
// Determine how many entries there will be in the list
for (LPCTSTR entry = buffer;
(entry != NULL) && (entry[1] != 0);
entry = ::strstr (entry, delimiter)) {
// Move past the current delimiter (if necessary)
if ((::strnicmp (entry, delimiter, delim_len) == 0) && (count > 0)) {
entry += delim_len;
}
// Increment the count of entries
count ++;
}
if (count > 0) {
// Allocate enough CString objects to hold all the strings in the list
(*pstring_list) = new CString[count];
// Parse the string and pull out its entries.
count = 0;
for (entry = buffer;
(entry != NULL) && (entry[1] != 0);
entry = ::strstr (entry, delimiter)) {
// Move past the current delimiter (if necessary)
if ((::strnicmp (entry, delimiter, delim_len) == 0) && (count > 0)) {
entry += delim_len;
}
// Copy this entry into its own string
CString entry_string = entry;
int delim_index = entry_string.Find (delimiter);
entry_string = (delim_index >= 0) ? entry_string.Left (delim_index) : entry_string;
//
// Add this entry to our list (even if its an empty string)
//
(*pstring_list)[count++] = entry_string;
}
} else if (delim_len > 0) {
count = 1;
(*pstring_list) = new CString[count];
(*pstring_list)[0] = buffer;
}
}
// Return the number of entries in our list
return count;
}
////////////////////////////////////////////////////////////////////////////
//
// Build_String_From_List
//
////////////////////////////////////////////////////////////////////////////
CString
Build_String_From_List
(
const CString *pstring_list,
int count,
LPCTSTR delimiter
)
{
// Start an empty string
CString composite_string;
ASSERT (delimiter != NULL);
ASSERT (pstring_list != NULL);
if ((delimiter != NULL) &&
(pstring_list != NULL)) {
// Loop through all the entries in our list and add them
// to the composite string
for (int entry_index = 0; entry_index < count; entry_index ++) {
composite_string += pstring_list[entry_index] + CString (delimiter);
}
}
// Return the composite string
return composite_string;
}
////////////////////////////////////////////////////////////////////////////
//
// Constrain_Point_To_Aspect_Ratio
//
////////////////////////////////////////////////////////////////////////////
void
Constrain_Point_To_Aspect_Ratio
(
float &xpos,
float &ypos
)
{
// Get the aspect ratios for the x and y axis
float xaspect = ::Get_Main_View ()->Get_Cursor_Aspect_RatioX ();
float yaspect = ::Get_Main_View ()->Get_Cursor_Aspect_RatioY ();
// Convert the 'window' point to a full screen point.
xpos *= xaspect;
ypos *= yaspect;
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Asset_Name_From_Filename
//
////////////////////////////////////////////////////////////////////////////
CString
Asset_Name_From_Filename (LPCTSTR filename)
{
// Get the filename from this path
CString asset_name = ::Get_Filename_From_Path (filename);
// Find the index of the extension (if exists)
int extension = asset_name.ReverseFind ('.');
// Strip off the extension
if (extension != -1) {
asset_name = asset_name.Left (extension);
}
// Return the name of the asset
return asset_name;
}
////////////////////////////////////////////////////////////////////////////
//
// Filename_From_Asset_Name
//
CString
Filename_From_Asset_Name (LPCTSTR asset_name)
{
// The filename is simply the asset name plus the .w3d extension
CString filename = asset_name + CString (".w3d");
// Return the filename
return filename;
}
////////////////////////////////////////////////////////////////////////////
//
// Message_Box
//
////////////////////////////////////////////////////////////////////////////
UINT
Message_Box
(
HWND hparentwnd,
UINT message_id,
UINT title_id,
UINT style
)
{
UINT ret_code = IDOK;
if (Is_Silent_Mode () == false) {
// Load the message from the strings table
CString message;
CString title;
message.LoadString (message_id);
title.LoadString (title_id);
// Show the message box to the user and return the user's response
ret_code = ::MessageBox (hparentwnd, message, title, style);
}
return ret_code;
}
////////////////////////////////////////////////////////////////////////////
//
// Rotate_Matrix
//
////////////////////////////////////////////////////////////////////////////
void
Rotate_Matrix
(
const Matrix3D &input_mat,
const Matrix3D &rotation_mat,
const Matrix3D &coord_system,
Matrix3D *poutput_mat
)
{
/*
** Translate this node in the specified coordinate system
*/
Matrix3D coord_inv; // inverse of coordinate transform
Matrix3D coord_to_obj; // transform from coord to object
coord_system.Get_Orthogonal_Inverse (coord_inv);
Matrix3D::Multiply (coord_inv, input_mat, &coord_to_obj);
Matrix3D::Multiply (coord_system, rotation_mat, poutput_mat);
Matrix3D::Multiply (*poutput_mat, coord_to_obj, poutput_mat);
if (!poutput_mat->Is_Orthogonal ()) {
poutput_mat->Re_Orthogonalize ();
TRACE ("Matrix wasn't orthogonal.\n");
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_LOD_File_Count
//
////////////////////////////////////////////////////////////////////////////
int
Get_LOD_File_Count
(
LPCTSTR first_lod_filename,
CString *pbase_filename
)
{
CString base_filename = first_lod_filename;
int lod_count = 0;
if ((base_filename.GetLength () > 6) &&
::strcmpi (&first_lod_filename[::lstrlen (first_lod_filename)-6], "L1.W3D") == 0) {
base_filename = base_filename.Left (base_filename.GetLength () - 6);
// Loop through the files in the directory and count up the ones that
// match our LOD-syntax for this object
bool bfound = true;
int lod_index = 1;
while (bfound) {
CString lod_filename;
lod_filename.Format ("%sL%d.w3d", (LPCTSTR)base_filename, lod_index);
lod_index ++;
bfound = (::GetFileAttributes (lod_filename) != 0xFFFFFFFF);
if (bfound) {
lod_count ++;
}
}
}
if (pbase_filename != NULL) {
*pbase_filename = base_filename;
}
// Return the count of LODs we found
return lod_count;
}
////////////////////////////////////////////////////////////////////////////
//
// Browse_For_Folder
//
////////////////////////////////////////////////////////////////////////////
bool
Browse_For_Folder
(
CString &folder,
HWND hparentwnd,
LPCTSTR default_path,
LPCTSTR title,
UINT flags
)
{
bool retval = false;
// Browse for the folder
BROWSEINFO browse_info = { 0 };
browse_info.hwndOwner = hparentwnd;
browse_info.lpszTitle = title;
browse_info.ulFlags = flags;
LPITEMIDLIST pidl = ::SHBrowseForFolder (&browse_info);
if (pidl != NULL) {
// Convert the 'PIDL' into a string
char path[MAX_PATH];
retval = (::SHGetPathFromIDList (pidl, path) == TRUE);
if (retval) {
folder = path;
}
// Fre the 'PIDL'
LPMALLOC pmalloc = NULL;
if (SUCCEEDED (::SHGetMalloc (&pmalloc))) {
pmalloc->Free (pidl);
COM_RELEASE (pmalloc);
}
}
// Return the true/false result code
return retval;
}
////////////////////////////////////////////////////////////////////////////
//
// General_Pump_Messages
//
////////////////////////////////////////////////////////////////////////////
void
General_Pump_Messages (void)
{
// Process any paint messages currently pending in the queue
MSG msg = { 0 };
while (::PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
::DispatchMessage (&msg);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Pump_Messages
//
////////////////////////////////////////////////////////////////////////////
void
Pump_Messages (void)
{
// Process any paint messages currently pending in the queue
MSG msg = { 0 };
while (::PeekMessage (&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) ||
::PeekMessage (&msg, NULL, WM_NCPAINT, WM_NCPAINT, PM_REMOVE) ||
::PeekMessage (&msg, NULL, WM_ERASEBKGND, WM_ERASEBKGND, PM_REMOVE) ||
::PeekMessage (&msg, NULL, WM_SYNCPAINT, WM_SYNCPAINT, PM_REMOVE)) {
::DispatchMessage (&msg);
}
return ;
}
typedef struct
{
LPVOID ThreadProc;
DWORD dwparam1;
DWORD dwparam2;
DWORD dwparam3;
HRESULT *presult;
HWND *phmain_wnd;
HANDLE hevent;
} THREAD_PARAMS;
////////////////////////////////////////////////////////////////////////////
//
// fnWorkerThread
//
////////////////////////////////////////////////////////////////////////////
UINT
fnWorkerThread (LPVOID pParam)
{
THREAD_PARAMS *pthread_params = (THREAD_PARAMS *)pParam;
if (pthread_params != NULL) {
// Call the user function
MY_THREADPROC thread_proc = (MY_THREADPROC)pthread_params->ThreadProc;
(thread_proc) (pthread_params->dwparam1,
pthread_params->dwparam2,
pthread_params->dwparam3,
pthread_params->presult);
// Free the thread params
SAFE_DELETE (pthread_params);
}
return 1;
}
////////////////////////////////////////////////////////////////////////////
//
// Create_Worker_Thread
//
////////////////////////////////////////////////////////////////////////////
void
Create_Worker_Thread
(
MY_THREADPROC fnthread_proc,
DWORD dwparam1,
DWORD dwparam2,
DWORD dwparam3,
HRESULT *presult
)
{
// Create a structure we can pass to the thread proc
THREAD_PARAMS *pthread_params = new THREAD_PARAMS;
pthread_params->ThreadProc = (LPVOID)fnthread_proc;
pthread_params->dwparam1 = dwparam1;
pthread_params->dwparam2 = dwparam2;
pthread_params->dwparam3 = dwparam3;
pthread_params->presult = presult;
pthread_params->phmain_wnd = NULL;
pthread_params->hevent = NULL;
// Kick off our own thread proc
::AfxBeginThread (fnWorkerThread, (LPVOID)pthread_params);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// fnUIThread
//
////////////////////////////////////////////////////////////////////////////
UINT
fnUIThread (LPVOID pParam)
{
THREAD_PARAMS *pthread_params = (THREAD_PARAMS *)pParam;
if (pthread_params != NULL) {
// Call the user function
MY_UITHREADPROC thread_proc = (MY_UITHREADPROC)pthread_params->ThreadProc;
(thread_proc) (pthread_params->dwparam1,
pthread_params->dwparam2,
pthread_params->dwparam3,
pthread_params->presult,
pthread_params->phmain_wnd);
// Let the calling thread return
::SetEvent (pthread_params->hevent);
// Now pump messages until its time to quit the thread
MSG msg = { 0 };
while (::GetMessage (&msg, NULL, 0, 0) > 0) {
::TranslateMessage (&msg);
::DispatchMessage (&msg);
}
// Free the thread params
SAFE_DELETE (pthread_params);
}
return 1;
}
////////////////////////////////////////////////////////////////////////////
//
// Create_UI_Thread
//
////////////////////////////////////////////////////////////////////////////
void
Create_UI_Thread
(
MY_UITHREADPROC fnthread_proc,
DWORD dwparam1,
DWORD dwparam2,
DWORD dwparam3,
HRESULT *presult,
HWND *phmain_wnd
)
{
// Create a structure we can pass to the thread proc
THREAD_PARAMS *pthread_params = new THREAD_PARAMS;
pthread_params->ThreadProc = (LPVOID)fnthread_proc;
pthread_params->dwparam1 = dwparam1;
pthread_params->dwparam2 = dwparam2;
pthread_params->dwparam3 = dwparam3;
pthread_params->presult = presult;
pthread_params->phmain_wnd = phmain_wnd;;
pthread_params->hevent = ::CreateEvent (NULL, FALSE, FALSE, NULL);
// Kick off our own thread proc
::AfxBeginThread (fnUIThread, (LPVOID)pthread_params);
// Now pump messages until the thread has initialized
while (::MsgWaitForMultipleObjects (1,
&(pthread_params->hevent),
FALSE,
INFINITE,
QS_ALLINPUT | QS_ALLEVENTS | QS_ALLPOSTMESSAGE) != WAIT_OBJECT_0) {
// Dispatch all messages in the queue
MSG msg = { 0 };
while (::PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
::TranslateMessage (&msg);
::DispatchMessage (&msg);
}
}
// Make sure we close the event handle
::CloseHandle (pthread_params->hevent);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Frame_Count
//
////////////////////////////////////////////////////////////////////////////
void
Update_Frame_Count
(
int frame,
int max_frames
)
{
// Get a pointer to the main window
CMainFrame *pmainwnd = (CMainFrame *)theApp.GetMainWnd ();
// Did we successfully get a pointer to the main window?
ASSERT (pmainwnd != NULL);
if (pmainwnd != NULL) {
pmainwnd->Update_Ani_Frame (frame, max_frames);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// SetDlgItemFloat
//
////////////////////////////////////////////////////////////////////////////
void
SetDlgItemFloat
(
HWND hdlg,
UINT child_id,
float value
)
{
// Convert the float to a string
CString text;
text.Format ("%.3f", value);
// Pass the string onto the dialog control
::SetDlgItemText (hdlg, child_id, text);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// SetWindowFloat
//
////////////////////////////////////////////////////////////////////////////
void
SetWindowFloat (HWND hwnd, float value)
{
// Convert the float to a string
CString text;
text.Format ("%.3f", value);
// Pass the string onto the window
::SetWindowText (hwnd, text);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// GetWindowFloat
//
////////////////////////////////////////////////////////////////////////////
float
GetWindowFloat (HWND hwnd, bool interpret)
{
// Get the string from the window
TCHAR string_value[20];
::GetWindowText (hwnd, string_value, sizeof (string_value));
//
// Convert the string to a float and return the value
//
float value = 0;
if (interpret) {
value = ((float)::atol (string_value)) / 100.0F;
} else {
value = ::atof (string_value);
}
return value;
}
////////////////////////////////////////////////////////////////////////////
//
// GetDlgItemFloat
//
////////////////////////////////////////////////////////////////////////////
float
GetDlgItemFloat
(
HWND hdlg,
UINT child_id,
bool interpret
)
{
// Get the string from the window
TCHAR string_value[20];
::GetDlgItemText (hdlg, child_id, string_value, sizeof (string_value));
//
// Convert the string to a float and return the value
//
float value = 0;
if (interpret) {
value = ((float)::atol (string_value)) / 100.0F;
} else {
value = ::atof (string_value);
}
return value;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Conversation_Form
//
////////////////////////////////////////////////////////////////////////////
ConversationPageClass *
Get_Conversation_Form (void)
{
//
// Return the form pointer
//
return ConversationPageClass::Get_Instance ();
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Overlap_Form
//
////////////////////////////////////////////////////////////////////////////
OverlapPageClass *
Get_Overlap_Form (void)
{
OverlapPageClass *form = NULL;
//
// Attempt to get a pointer to the form from the dialog bar
//
CMainFrame *main_wnd = (CMainFrame *)::AfxGetMainWnd ();
if (main_wnd != NULL) {
MainDialogBarClass &toolbar = main_wnd->Get_Main_Dialog_Bar ();
form = toolbar.Get_Overlap_Form ();
}
// Return the form pointer
return form;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Instances_Form
//
////////////////////////////////////////////////////////////////////////////
InstancesPageClass *
Get_Instances_Form (void)
{
InstancesPageClass *form = NULL;
//
// Attempt to get a pointer to the form from the dialog bar
//
CMainFrame *main_wnd = (CMainFrame *)::AfxGetMainWnd ();
if (main_wnd != NULL) {
MainDialogBarClass &toolbar = main_wnd->Get_Main_Dialog_Bar ();
form = toolbar.Get_Instances_Form ();
}
// Return the form pointer
return form;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Global_Presets_Form
//
////////////////////////////////////////////////////////////////////////////
PresetsFormClass *
Get_Presets_Form (void)
{
//
// Attempt to get a pointer to the form from the dialog bar
//
MainDialogBarClass &toolbar = ((CMainFrame *)::AfxGetMainWnd ())->Get_Main_Dialog_Bar ();
PresetsFormClass *form = toolbar.Get_Presets_Form ();
// Return the form pointer
return form;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Global_Group_List
//
////////////////////////////////////////////////////////////////////////////
GROUP_LIST &
Get_Global_Group_List (void)
{
// Return the list pointer
return ::Get_Scene_Editor ()->Get_Group_List ();
}
////////////////////////////////////////////////////////////////////////////
//
// Fill_Node_Instance_Combo
//
////////////////////////////////////////////////////////////////////////////
void
Fill_Node_Instance_Combo
(
HWND hcombobox,
NodeClass * default_node
)
{
// Loop through all the nodes in the level, and add them to the combobox
NodeMgrClass &node_mgr = ::Get_Node_Mgr ();
for (NodeClass *node = node_mgr.Get_First ();
node != NULL;
node = node_mgr.Get_Next (node)) {
// Add this node to the combobox
int index = ::SendMessage (hcombobox, CB_ADDSTRING, (WPARAM)0, (LPARAM)node->Get_Name ());
if (index != CB_ERR) {
::SendMessage (hcombobox, CB_SETITEMDATA, (WPARAM)index, (LPARAM)node);
// If this is the default node, then select it...
if (node == default_node) {
::SendMessage (hcombobox, CB_SETCURSEL, (WPARAM)index, 0L);
}
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Fill_Group_Combo
//
////////////////////////////////////////////////////////////////////////////
void
Fill_Group_Combo
(
HWND hcombobox,
GroupMgrClass *pdefault
)
{
// Loop through all the groups in the level, and add them to the combobox
GROUP_LIST &group_list = ::Get_Global_Group_List ();
for (int index = 0; index < group_list.Count (); index ++) {
GroupMgrClass *pgroup = group_list[index];
if (pgroup != NULL) {
// Add this group to the combobox
int index = ::SendMessage (hcombobox, CB_ADDSTRING, (WPARAM)0, (LPARAM)(LPCTSTR)pgroup->Get_Name ());
if (index != CB_ERR) {
::SendMessage (hcombobox, CB_SETITEMDATA, (WPARAM)index, (LPARAM)pgroup);
// If this is the default group, then select it...
if (pgroup == pdefault) {
::SendMessage (hcombobox, CB_SETCURSEL, (WPARAM)index, 0L);
}
}
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Ambient_Light_Form
//
////////////////////////////////////////////////////////////////////////////
LightAmbientFormClass *
Get_Ambient_Light_Form (void)
{
// Attempt to get a pointer to the form from the library object
FormToolbarClass &toolbar = ((CMainFrame *)::AfxGetMainWnd ())->Get_Ambient_Light_Toolbar ();
LightAmbientFormClass *pform = (LightAmbientFormClass *)toolbar.Get_Form ();
// Return the form pointer
return pform;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Global_Image_List
//
////////////////////////////////////////////////////////////////////////////
CImageList *
Get_Global_Image_List (void)
{
// Return the imagelist pointer
return ((CMainFrame *)::AfxGetMainWnd ())->Get_Image_List ();
}
////////////////////////////////////////////////////////////////////////////
//
// Copy_File
//
////////////////////////////////////////////////////////////////////////////
bool
Copy_File
(
LPCTSTR existing_filename,
LPCTSTR new_filename,
bool bforce_copy
)
{
// Assume failure
bool retval = false;
ASSERT (existing_filename != NULL);
ASSERT (new_filename != NULL);
if ((existing_filename != NULL) &&
(new_filename != NULL)) {
// Make sure we aren't copying over ourselves
bool allow_copy = (::lstrcmpi (existing_filename, new_filename) != 0);
// Strip the readonly bit off if necessary
DWORD attributes = ::GetFileAttributes (new_filename);
if (allow_copy &&
(attributes != 0xFFFFFFFF) &&
((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY)) {
if (bforce_copy) {
::SetFileAttributes (new_filename, attributes & (~FILE_ATTRIBUTE_READONLY));
} else {
allow_copy = false;
}
}
// Perform the copy operation!
if (allow_copy) {
retval = (::CopyFile (existing_filename, new_filename, FALSE) == TRUE);
}
}
// Return the true/false result code
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// fnUpdatingVSSThread
//
////////////////////////////////////////////////////////////////////////////
UINT
fnUpdatingVSSThread
(
DWORD dwparam1,
DWORD /*dwparam2*/,
DWORD /*dwparam3*/,
HRESULT* /*presult*/,
HWND* phmain_wnd
)
{
// Create a new instance of the 'updating' dialog
UpdatingDBDialogClass *pdialog = new UpdatingDBDialogClass ((HWND)dwparam1);
pdialog->ShowWindow (SW_SHOW);
// Return the window handle of the main wnd to the calling thread
if (phmain_wnd != NULL) {
(*phmain_wnd) = pdialog->m_hWnd;
}
return 1;
}
////////////////////////////////////////////////////////////////////////////
//
// Show_VSS_Update_Dialog
//
////////////////////////////////////////////////////////////////////////////
HWND
Show_VSS_Update_Dialog (HWND hparent_wnd)
{
// Kick off a UI thread that will display the 'updating' dialog and animation for us
HWND hthread_wnd = NULL;
::Create_UI_Thread (fnUpdatingVSSThread, (DWORD)hparent_wnd, 0, 0, NULL, &hthread_wnd);
return hthread_wnd;
}
////////////////////////////////////////////////////////////////////////////
//
// Kill_VSS_Update_Dialog
//
////////////////////////////////////////////////////////////////////////////
void
Kill_VSS_Update_Dialog (HWND hdlg)
{
// Close out the window
if (::IsWindow (hdlg)) {
::PostMessage (hdlg, WM_USER+101, 0, 0L);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_File_Time
//
////////////////////////////////////////////////////////////////////////////
bool
Get_File_Time
(
LPCTSTR path,
LPFILETIME pcreation_time,
LPFILETIME paccess_time,
LPFILETIME pwrite_time
)
{
// Assume failure
bool retval = false;
// Attempt to open the file
HANDLE hfile = ::CreateFile (path,
0,
0,
NULL,
OPEN_EXISTING,
0L,
NULL);
if (hfile != INVALID_HANDLE_VALUE) {
// Get the mod times for this file
retval = (::GetFileTime (hfile, pcreation_time, paccess_time, pwrite_time) == TRUE);
// Close the file
SAFE_CLOSE (hfile);
}
// Return the true/false result code
return retval;
}
////////////////////////////////////////////////////////////////////////////
//
// Type_To_Icon
//
////////////////////////////////////////////////////////////////////////////
int
Type_To_Icon
(
NODE_TYPE type,
bool btemp
)
{
int index = TEMP_ICON;
// If we aren't looking for a temp icon, then determine
// which icon to use based on the type
if (btemp == false) {
switch (type)
{
case NODE_TYPE_OBJECT:
index = OBJECT_ICON;
break;
case NODE_TYPE_TERRAIN_SECTION:
case NODE_TYPE_TERRAIN:
index = TERRAIN_ICON;
break;
case NODE_TYPE_TILE:
index = TILE_ICON;
break;
case NODE_TYPE_ZONE:
case NODE_TYPE_DAMAGE_ZONE:
index = ZONE_ICON;
break;
case NODE_TYPE_COVER_SPOT:
index = OBJECT_ICON;
break;
case NODE_TYPE_WAYPATH:
case NODE_TYPE_WAYPOINT:
index = WAYPATH_ICON;
break;
case NODE_TYPE_LIGHT:
index = LIGHT_ICON;
break;
case NODE_TYPE_SOUND:
index = SOUND_ICON;
break;
case NODE_TYPE_TRANSITION:
case NODE_TYPE_TRANSITION_CHARACTER:
index = TRANSITION_ICON;
break;
case NODE_TYPE_BUILDING:
index = BUILDING_ICON;
break;
}
}
// Return the icon's index
return index;
}
/////////////////////////////////////////////////////////////////////////////
//
// FileAccessRightsClass
//
/////////////////////////////////////////////////////////////////////////////
FileAccessRightsClass::FileAccessRightsClass
(
LPCTSTR filename,
ACCESS_TYPE type,
bool should_restore
)
: m_Filename (filename),
m_FileAttrs (0xFFFFFFFF),
m_bNeedsRestoring (false)
{
// Does the file exist?
m_FileAttrs = ::GetFileAttributes (m_Filename);
if (m_FileAttrs != 0xFFFFFFFF) {
if ((type == WANTS_READONLY) &&
(m_FileAttrs & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY) {
// Assign the readonly bit to the file
::SetFileAttributes (m_Filename, m_FileAttrs | FILE_ATTRIBUTE_READONLY);
m_bNeedsRestoring = should_restore;
} else if ((type == WANTS_WRITEABLE) &&
(m_FileAttrs & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) {
// Strip the readonly bit from the file
::SetFileAttributes (m_Filename, m_FileAttrs & (~FILE_ATTRIBUTE_READONLY));
m_bNeedsRestoring = should_restore;
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// ~FileAccessRightsClass
//
/////////////////////////////////////////////////////////////////////////////
FileAccessRightsClass::~FileAccessRightsClass (void)
{
// Restore the file's attributes if necessary
if (m_bNeedsRestoring) {
::SetFileAttributes (m_Filename, m_FileAttrs);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// fnEditToFloatProc
//
/////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK
fnEditToFloatProc
(
HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam
)
{
WNDPROC old_proc = (WNDPROC)::GetProp (hwnd, "OLD_WND_PROC");
LRESULT result = 0L;
if (message == WM_SETTEXT) {
//
// Convert the textual value to a long, convert
// the long to a float, and conver the float to
// a string.
//
LPCTSTR string = (LPCTSTR)lparam;
if (::strchr (string, '.') != 0) {
result = ::CallWindowProc (old_proc, hwnd, message, wparam, lparam);
} else {
long value = ::atol ((LPCTSTR)lparam);
float float_value = value / 100.0F;
CString new_text;
new_text.Format ("%.3f", float_value);
result = ::CallWindowProc (old_proc, hwnd, message, wparam, (LPARAM)(LPCTSTR)new_text);
}
} else if (message == WM_GETTEXT) {
//
// Get the value (as text) from the control,
// convert it to a float, convert the float
// to a long, then convert the long back to
// a string.
//
result = ::CallWindowProc (old_proc, hwnd, message, wparam, lparam);
LPCTSTR string = (LPCTSTR)lparam;
if (::strchr (string, '.') != 0) {
float float_value = ::atof (string);
long int_value = long(float_value * 100);
::itoa (int_value, (LPTSTR)lparam, 10);
} else {
long int_value = ::atol (string) * 100;
::itoa (int_value, (LPTSTR)lparam, 10);
}
result = ::lstrlen ((LPTSTR)lparam);
} else if (message == WM_CHAR) {
//
// Check to see if this is one of the characters we allow
// the user to type
//
if ( (wparam >= '0' && wparam <= '9') ||
wparam == '.' ||
wparam == VK_BACK ||
wparam == '-')
{
result = ::CallWindowProc (old_proc, hwnd, message, wparam, lparam);
}
} else if (old_proc != NULL) {
result = ::CallWindowProc (old_proc, hwnd, message, wparam, lparam);
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
//
// Restore_Edit_Ctrl
//
/////////////////////////////////////////////////////////////////////////////
void
Restore_Edit_Ctrl (HWND edit_wnd)
{
LONG orig_proc = (LONG)::GetProp (edit_wnd, "OLD_WND_PROC");
if (orig_proc != 0) {
::SetWindowLong (edit_wnd, GWL_WNDPROC, orig_proc);
::RemoveProp (edit_wnd, "OLD_WND_PROC");
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Make_Edit_Float_Ctrl
//
/////////////////////////////////////////////////////////////////////////////
void
Make_Edit_Float_Ctrl (HWND edit_wnd)
{
Restore_Edit_Ctrl (edit_wnd);
LONG old_proc = ::SetWindowLong (edit_wnd, GWL_WNDPROC, (LONG)fnEditToFloatProc);
SetProp (edit_wnd, "OLD_WND_PROC", (HANDLE)old_proc);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// fnEditToIntProc
//
/////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK
fnEditToIntProc
(
HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam
)
{
WNDPROC old_proc = (WNDPROC)::GetProp (hwnd, "OLD_WND_PROC");
LRESULT result = 0L;
if (message == WM_CHAR) {
//
// Check to see if this is one of the characters we allow
// the user to type
//
if ( (wparam >= '0' && wparam <= '9') ||
wparam == VK_BACK ||
wparam == '-')
{
result = ::CallWindowProc (old_proc, hwnd, message, wparam, lparam);
}
} else if (old_proc != NULL) {
result = ::CallWindowProc (old_proc, hwnd, message, wparam, lparam);
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
//
// Make_Edit_Int_Ctrl
//
/////////////////////////////////////////////////////////////////////////////
void
Make_Edit_Int_Ctrl (HWND edit_wnd)
{
Restore_Edit_Ctrl (edit_wnd);
LONG old_proc = ::SetWindowLong (edit_wnd, GWL_WNDPROC, (LONG)fnEditToIntProc);
SetProp (edit_wnd, "OLD_WND_PROC", (HANDLE)old_proc);
return ;
}
//////////////////////////////////////////////////////////////////////////////
//
// Set_Modified
//
/////////////////////////////////////////////////////////////////////////////
void
Set_Modified (bool modified)
{
::Get_Current_Document ()->SetModifiedFlag (modified);
return ;
}
bool _IsSilent = false;
//////////////////////////////////////////////////////////////////////////////
//
// Is_Silent_Mode
//
/////////////////////////////////////////////////////////////////////////////
bool
Is_Silent_Mode (void)
{
return _IsSilent;
}
//////////////////////////////////////////////////////////////////////////////
//
// Set_Silent_Mode
//
/////////////////////////////////////////////////////////////////////////////
void
Set_Silent_Mode (bool is_silent)
{
_IsSilent = is_silent;
return ;
}
//////////////////////////////////////////////////////////////////////////////
//
// Get_Next_Temp_ID
//
/////////////////////////////////////////////////////////////////////////////
int
Get_Next_Temp_ID (void)
{
//
// Read the next temporary preset ID from the registry
//
int temp_id = theApp.GetProfileInt (CONFIG_KEY, TEMP_ID_VALUE, TEMP_DEF_ID_START);
//
// Make sure the temp ID is in the right range
//
if (temp_id < TEMP_DEF_ID_START) {
temp_id = TEMP_DEF_ID_START;
}
//
// Store the next temp ID value in the registry
//
theApp.WriteProfileInt (CONFIG_KEY, TEMP_ID_VALUE, temp_id+1);
return temp_id;
}
//////////////////////////////////////////////////////////////////////////////
//
// Get_Collision_Box
//
/////////////////////////////////////////////////////////////////////////////
bool
Get_Collision_Box (const RenderObjClass *model, AABoxClass &box)
{
bool retval = false;
if (model != NULL) {
//
// Get the collision box for this render obj
//
RenderObjClass *world_box = model->Get_Sub_Object_By_Name ("WORLDBOX");
// If we didn't finde WorldBox, try to find the LOD named "WorldBox"
// The LOD code generates a unique name for the mesh by appending A,B,C, etc to the name.
// A is the lowest LOD, B is the next, and so on. Our worldbox is specified in the highest
// LOD so we have to construct the name by appending 'A'+LodCount to the name... icky
if ((world_box == NULL) && (model->Class_ID() == RenderObjClass::CLASSID_HLOD))
{
char namebuffer[64];
sprintf(namebuffer,"WorldBox%c",'A' + ((HLodClass *)model)->Get_Lod_Count() - 1);
world_box = model->Get_Sub_Object_By_Name(namebuffer);
/*if (box_obj && box_obj->Class_ID() == RenderObjClass::CLASSID_OBBOX) {
world_box = box_obj;
}*/
}
if (world_box != NULL) {
box = world_box->Get_Bounding_Box ();
world_box->Release_Ref ();
retval = true;
}
}
return retval;
}
//////////////////////////////////////////////////////////////////
//
// Get_Collision_Box
//
// Note: This function returns true if it returns an AABox or
// false if it returns an OBBox
//
//////////////////////////////////////////////////////////////////
bool
Get_Collision_Box (RenderObjClass *render_obj, AABoxClass &aabox, OBBoxClass &obbox)
{
bool is_aabox = true;
aabox.Center.Set (0, 0, 0);
aabox.Extent.Set (0, 0, 0);
obbox.Center.Set (0, 0, 0);
obbox.Extent.Set (0, 0, 0);
if (render_obj != NULL) {
//
// Try to get the "WorldBox" from the model
//
RenderObjClass *world_box = render_obj->Get_Sub_Object_By_Name ("WorldBox");
//
// If we didn't finde WorldBox, try to find the LOD named "WorldBox"
// The LOD code generates a unique name for the mesh by appending A,B,C, etc to the name.
// A is the lowest LOD, B is the next, and so on. Our worldbox is specified in the highest
// LOD so we have to construct the name by appending 'A'+LodCount to the name... icky
//
if ((world_box == NULL) && (render_obj->Class_ID () == RenderObjClass::CLASSID_HLOD)) {
char namebuffer[64];
sprintf(namebuffer,"WorldBox%c",'A' + ((HLodClass *)render_obj)->Get_Lod_Count() - 1);
world_box = render_obj->Get_Sub_Object_By_Name (namebuffer);
}
if (world_box != NULL) {
//
// Determine which type of bounding box to return and OBBox or an AABox
//
if (world_box->Class_ID() == RenderObjClass::CLASSID_OBBOX) {
obbox = ((OBBoxRenderObjClass *)world_box)->Get_Box ();
is_aabox = false;
} else {
aabox = world_box->Get_Bounding_Box ();
is_aabox = true;
}
}
REF_PTR_RELEASE (world_box);
}
return is_aabox;
}
//////////////////////////////////////////////////////////////////////////////
//
// Instance_Definition
//
/////////////////////////////////////////////////////////////////////////////
PersistClass *
Instance_Definition (DefinitionClass *definition)
{
PersistClass *new_object = NULL;
//
// Create the new object
//
if (definition != NULL) {
new_object = definition->Create ();
}
if (new_object == NULL) {
LPCTSTR name = definition->Get_Name ();
CString message;
message.Format ("Unable to create an instance of %s.\nCheck to make sure the preset is properly configured with a model and/or physics object.", name);
//
// Warn the user that we were unable to create the object
//
HWND parent_wnd = ::AfxGetMainWnd ()->m_hWnd;
::MessageBox (parent_wnd, message, "Preset Error", MB_ICONERROR | MB_OK);
}
return new_object;
}
//////////////////////////////////////////////////////////////////////////////
//
// Check_Editor_Version
//
/////////////////////////////////////////////////////////////////////////////
bool
Check_Editor_Version (void)
{
#ifndef PUBLIC_EDITOR_VER
char curr_filename[MAX_PATH];
::GetModuleFileName (NULL, curr_filename, MAX_PATH);
CString filename = "\\\\mobius\\project7\\projects\\renegade\\programming\\tools\\level edit\\";
filename += ::Get_Filename_From_Path (curr_filename);
//
// Check the version of the level editor that is out on the network
// against the version we are running. We don't want people making modifications
// with and older version
//
return (::Compare_EXE_Version ((int)::AfxGetInstanceHandle (), filename) >= 0);
#else
return true;
#endif
}
/////////////////////////////////////////////////////////////////////////////
//
// Perform_Job
//
/////////////////////////////////////////////////////////////////////////////
void
Perform_Job (LPCTSTR filename, bool delete_on_completion)
{
int total = ::GetPrivateProfileInt ("Job Description", "Total", 1, filename);
int index = ::GetPrivateProfileInt ("Job Description", "Index", 0, filename);
CString granularity_string;
::GetPrivateProfileString ("Job Description", "Granularity", "1", granularity_string.GetBufferSetLength (20), 20, filename);
float granularity = ::atof (granularity_string);
CString level_file;
::GetPrivateProfileString ("Job Description", "LVL", "", level_file.GetBufferSetLength (MAX_PATH), MAX_PATH, filename);
CString output_file;
::GetPrivateProfileString ("Job Description", "Output", "", output_file.GetBufferSetLength (MAX_PATH), MAX_PATH, filename);
if (level_file.GetLength () > 0) {
//
// Load the requested level
//
::Get_Main_View ()->Allow_Repaint (false);
EditorSaveLoadClass::Load_Level (level_file);
::Get_Main_View ()->Allow_Repaint (true);
//
// Start VIS
//
#if (1)
::Get_Scene_Editor ()->Generate_Uniform_Sampled_Vis (granularity,false,false,true,index,total);
#else
::Get_Scene_Editor ()->Generate_Edge_Sampled_Vis (granularity,false,true,index,total);
#endif
::Get_Scene_Editor ()->Generate_Manual_Vis (true,index,total);
::Get_Scene_Editor ()->Generate_Light_Vis (true,index,total);
//
// Export VIS to the given file
//
::Get_Scene_Editor ()->Export_VIS (output_file);
}
//
// Delete the job file if necessary
//
if (delete_on_completion) {
::DeleteFile (filename);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Factory_Name
//
/////////////////////////////////////////////////////////////////////////////
LPCTSTR
Get_Factory_Name (uint32 class_id)
{
LPCTSTR name = NULL;
//
// Can we find the requested factory?
//
DefinitionFactoryClass *factory = DefinitionFactoryMgrClass::Find_Factory (class_id);
if (factory == NULL) {
//
// Check to see if this is an abstract factory
//
for (int index = 0; index < PRESET_CATEGORY_COUNT; index ++) {
if (PRESET_CATEGORIES[index].clsid == (int)class_id) {
name = PRESET_CATEGORIES[index].name;
break;
}
}
} else {
name = factory->Get_Name ();
}
return name;
}
/////////////////////////////////////////////////////////////////////////////
//
// Convert_Newline_To_Chars
//
/////////////////////////////////////////////////////////////////////////////
void
Convert_Newline_To_Chars (CString &string)
{
CString retval;
//
// Take a guess as to how large to make the final string
//
int count = string.GetLength ();
//
// Copy characters between the strings
//
for (int index = 0; index < count; index ++) {
if (string[index] == '\n') {
retval += "\\n";
} else {
retval += string[index];
}
}
string = retval;
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Convert_Chars_To_Newline
//
/////////////////////////////////////////////////////////////////////////////
void
Convert_Chars_To_Newline (CString &string)
{
CString retval;
//
// Take a guess as to how large to make the final string
//
int count = string.GetLength ();
//
// Copy characters between the strings
//
for (int index = 0; index < count; index ++) {
if (index + 1 < count && string[index] == '\\' && string[index + 1] == 'n') {
retval += '\n';
index ++;
} else {
retval += string[index];
}
}
string = retval;
return ;
}