/* ** 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 . */ ///////////////////////////////////////////////////////////////////////////// // // 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 ; }