473 lines
11 KiB
C++
473 lines
11 KiB
C++
/*
|
|
** 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/>.
|
|
*/
|
|
|
|
// W3DView.cpp : Defines the class behaviors for the application.
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "w3dview.h"
|
|
|
|
#include "mainfrm.h"
|
|
#include "w3dviewdoc.h"
|
|
#include "w3dviewview.h"
|
|
#include "utils.h"
|
|
#include "colorutils.h"
|
|
#include "verchk.h"
|
|
#include "wwmath.h"
|
|
#include "wwaudio.h"
|
|
#include "viewerassetmgr.h"
|
|
#include "globals.h"
|
|
#include "animatedsoundoptionsdialog.h"
|
|
#include "animatedsoundmgr.h"
|
|
|
|
|
|
#undef STRICT
|
|
#include "ww3d.h"
|
|
#include "AssetMgr.H"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Local prototypes
|
|
//
|
|
BOOL CALLBACK fnTopLevelWindowSearch (HWND hwnd, LPARAM lParam);
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CW3DViewApp
|
|
//
|
|
BEGIN_MESSAGE_MAP(CW3DViewApp, CWinApp)
|
|
//{{AFX_MSG_MAP(CW3DViewApp)
|
|
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
|
|
// NOTE - the ClassWizard will add and remove mapping macros here.
|
|
// DO NOT EDIT what you see in these blocks of generated code!
|
|
//}}AFX_MSG_MAP
|
|
// Standard file based document commands
|
|
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
|
|
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CW3DViewApp construction
|
|
//
|
|
CW3DViewApp::CW3DViewApp (void)
|
|
: m_bInitialized (false)
|
|
{
|
|
// TODO: add construction code here,
|
|
// Place all significant initialization in InitInstance
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// The one and only CW3DViewApp object
|
|
|
|
CW3DViewApp theApp;
|
|
|
|
extern int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow);
|
|
|
|
|
|
int WINAPI
|
|
WinMain
|
|
(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPTSTR lpCmdLine,
|
|
int nCmdShow
|
|
)
|
|
{
|
|
int retcode = 0;
|
|
|
|
#ifndef _DEBUG
|
|
try
|
|
{
|
|
#endif //_DEBUG
|
|
|
|
//::AfxWinInit (hInstance, hPrevInstance, lpCmdLine, nCmdShow);
|
|
//::AfxInitialize (FALSE, _MFC_VER);
|
|
|
|
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
|
|
pModuleState->m_bDLL = (BYTE)FALSE;
|
|
#ifdef _MBCS
|
|
// set correct multi-byte code-page for Win32 apps
|
|
_setmbcp(_MB_CP_ANSI);
|
|
#endif //_MBCS
|
|
|
|
retcode = ::AfxWinMain (hInstance, hPrevInstance, lpCmdLine, nCmdShow);
|
|
|
|
#ifndef _DEBUG
|
|
}
|
|
catch (...)
|
|
{
|
|
|
|
::MessageBox (NULL, "Internal Application Error", "Unrecoverable Error", MB_ICONERROR | MB_OK);
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
return retcode;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
//
|
|
// Do_Version_Check
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
void
|
|
Do_Version_Check (void)
|
|
{
|
|
char curr_filename[MAX_PATH];
|
|
::GetModuleFileName (NULL, curr_filename, MAX_PATH);
|
|
|
|
CString filename = "\\\\cabal\\mis\\r&d\\w3d\\w3dview\\";
|
|
filename += ::Get_Filename_From_Path (curr_filename);
|
|
|
|
//
|
|
// Check the version of the viewer that is out on the network
|
|
// against the version we are running.
|
|
//
|
|
if (Compare_EXE_Version ((int)::AfxGetInstanceHandle (), filename) < 0) {
|
|
::MessageBox (NULL, "There is a newer version of the W3DViewer, please run W3DUpdate to upgrade your local copy.", "Version Info", MB_ICONEXCLAMATION | MB_OK | MB_SETFOREGROUND | MB_SYSTEMMODAL);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// InitInstance
|
|
//
|
|
BOOL CW3DViewApp::InitInstance (void)
|
|
{
|
|
// Standard initialization
|
|
// If you are not using these features and wish to reduce the size
|
|
// of your final executable, you should remove from the following
|
|
// the specific initialization routines you do not need.
|
|
|
|
#ifdef _AFXDLL
|
|
Enable3dControls(); // Call this when using MFC in a shared DLL
|
|
#else
|
|
Enable3dControlsStatic(); // Call this when linking to MFC statically
|
|
#endif
|
|
|
|
Do_Version_Check ();
|
|
|
|
RegisterColorPicker (::AfxGetInstanceHandle ());
|
|
RegisterColorBar (::AfxGetInstanceHandle ());
|
|
|
|
// Is there already an instance of the viewer running?
|
|
HWND hprev_instance = NULL;
|
|
::EnumWindows (fnTopLevelWindowSearch, (LPARAM)&hprev_instance);
|
|
if (hprev_instance == NULL) {
|
|
|
|
// Change the registry key under which our settings are stored.
|
|
// You should modify this string to be something appropriate
|
|
// such as the name of your company or organization.
|
|
SetRegistryKey(_T("Westwood Studios"));
|
|
|
|
//
|
|
// Load standard INI file options (including MRU)
|
|
//
|
|
LoadStdProfileSettings (9);
|
|
|
|
//
|
|
// Initialize the libraries
|
|
//
|
|
WWMath::Init ();
|
|
AnimatedSoundOptionsDialogClass::Load_Animated_Sound_Settings ();
|
|
|
|
//
|
|
// Disable the 3DFX logo
|
|
//
|
|
_putenv ("FX_GLIDE_NO_SPLASH=1");
|
|
|
|
// Register the application's document templates. Document templates
|
|
// serve as the connection between documents, frame windows and views.
|
|
|
|
CSingleDocTemplate* pDocTemplate;
|
|
pDocTemplate = new CSingleDocTemplate(
|
|
IDR_MAINFRAME,
|
|
RUNTIME_CLASS(CW3DViewDoc),
|
|
RUNTIME_CLASS(CMainFrame), // main SDI frame window
|
|
RUNTIME_CLASS(CW3DViewView));
|
|
AddDocTemplate(pDocTemplate);
|
|
|
|
// Enable DDE Execute open
|
|
EnableShellOpen();
|
|
RegisterShellFileTypes(TRUE);
|
|
|
|
// Parse command line for standard shell commands, DDE, file open
|
|
CCommandLineInfo cmdInfo;
|
|
ParseCommandLine(cmdInfo);
|
|
|
|
//
|
|
// Allocate an asset manager
|
|
//
|
|
_TheAssetMgr = new ViewerAssetMgrClass;
|
|
|
|
// Dispatch commands specified on the command line
|
|
if (!ProcessShellCommand(cmdInfo))
|
|
return FALSE;
|
|
|
|
// The one and only window has been initialized, so show and update it.
|
|
m_pMainWnd->ShowWindow(SW_SHOW);
|
|
m_pMainWnd->UpdateWindow();
|
|
::SetProp (*m_pMainWnd, "WW3DVIEWER", (HANDLE)1);
|
|
|
|
// Enable drag/drop open
|
|
m_pMainWnd->DragAcceptFiles();
|
|
m_bInitialized = true;
|
|
} else {
|
|
|
|
// Make the previous instance in the foreground
|
|
::ShowWindow (hprev_instance, SW_NORMAL);
|
|
::BringWindowToTop (hprev_instance);
|
|
::SetForegroundWindow (hprev_instance);
|
|
}
|
|
|
|
return (hprev_instance == NULL);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAboutDlg dialog used for App About
|
|
|
|
class CAboutDlg : public CDialog
|
|
{
|
|
public:
|
|
CAboutDlg();
|
|
|
|
// Dialog Data
|
|
//{{AFX_DATA(CAboutDlg)
|
|
enum { IDD = IDD_ABOUTBOX };
|
|
//}}AFX_DATA
|
|
|
|
// ClassWizard generated virtual function overrides
|
|
//{{AFX_VIRTUAL(CAboutDlg)
|
|
protected:
|
|
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
|
//}}AFX_VIRTUAL
|
|
|
|
// Implementation
|
|
protected:
|
|
//{{AFX_MSG(CAboutDlg)
|
|
virtual BOOL OnInitDialog();
|
|
//}}AFX_MSG
|
|
DECLARE_MESSAGE_MAP()
|
|
};
|
|
|
|
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
|
|
{
|
|
//{{AFX_DATA_INIT(CAboutDlg)
|
|
//}}AFX_DATA_INIT
|
|
}
|
|
|
|
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CAboutDlg)
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
|
|
//{{AFX_MSG_MAP(CAboutDlg)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
// App command to run the dialog
|
|
void CW3DViewApp::OnAppAbout()
|
|
{
|
|
CAboutDlg aboutDlg;
|
|
aboutDlg.DoModal();
|
|
}
|
|
|
|
/*
|
|
**
|
|
*/
|
|
void Debug_Refs(void)
|
|
{
|
|
#ifndef NDEBUG
|
|
TRACE("Detecting Active Refs...\r\n");
|
|
//ODS("At time %s", cMiscUtil::Get_Text_Time());
|
|
RefCountNodeClass * first = RefCountClass::ActiveRefList.First();
|
|
RefCountNodeClass * node = first;
|
|
while (node->Is_Valid())
|
|
{
|
|
RefCountClass * obj = node->Get();
|
|
ActiveRefStruct * ref = &(obj->ActiveRefInfo);
|
|
|
|
bool display = true;
|
|
int count = 0;
|
|
RefCountNodeClass * search = first;
|
|
while (search->Is_Valid()) {
|
|
|
|
if (search == node) { // if this is not the first one
|
|
if (count != 0) {
|
|
display = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
RefCountClass * search_obj = search->Get();
|
|
ActiveRefStruct * search_ref = &(search_obj->ActiveRefInfo);
|
|
|
|
if ( ref->File && search_ref->File &&
|
|
!strcmp(search_ref->File, ref->File) &&
|
|
(search_ref->Line == ref->Line) ) {
|
|
count++;
|
|
} else if ( (ref->File == NULL) && (search_ref->File == NULL) ) {
|
|
count++;
|
|
}
|
|
|
|
search = search->Next();
|
|
}
|
|
|
|
if ( display ) {
|
|
TRACE ( "%d Active Ref: %s %d %p\n", count, ref->File,ref->Line,obj);
|
|
|
|
static int num_printed = 0;
|
|
if (++num_printed > 20) {
|
|
TRACE( "And Many More......\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
node = node->Next();
|
|
}
|
|
TRACE("Done.\r\n");
|
|
//ODS("At time %s", cMiscUtil::Get_Text_Time());
|
|
#endif
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CW3DViewApp
|
|
//
|
|
int
|
|
CW3DViewApp::ExitInstance()
|
|
{
|
|
//
|
|
// Free any resources the WW3D engine allocated
|
|
//
|
|
if (m_bInitialized) {
|
|
|
|
//
|
|
// Shutdown the audio system
|
|
//
|
|
WWAudioClass::Get_Instance ()->Shutdown ();
|
|
|
|
//
|
|
// Shutdown W3D
|
|
//
|
|
WW3DAssetManager::Get_Instance()->Free_Assets ();
|
|
WW3D::Shutdown ();
|
|
|
|
//
|
|
// Shutdown the libraries
|
|
//
|
|
WWMath::Shutdown ();
|
|
AnimatedSoundMgrClass::Shutdown ();
|
|
|
|
//
|
|
// Free the asset manager
|
|
//
|
|
delete _TheAssetMgr;
|
|
_TheAssetMgr = NULL;
|
|
}
|
|
|
|
Debug_Refs ();
|
|
return CWinApp::ExitInstance ();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// fnTopLevelWindowSearch
|
|
//
|
|
BOOL CALLBACK
|
|
fnTopLevelWindowSearch
|
|
(
|
|
HWND hwnd,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
BOOL bcontinue = TRUE;
|
|
|
|
// Is this a viewer window?
|
|
if (::GetProp (hwnd, "WW3DVIEWER") != 0) {
|
|
bcontinue = false;
|
|
(*((HWND *)lParam)) = hwnd;
|
|
}
|
|
|
|
// Return the TRUE/FALSE result code
|
|
return bcontinue;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnInitDialog
|
|
//
|
|
BOOL
|
|
CAboutDlg::OnInitDialog (void)
|
|
{
|
|
// Allow the base class to process this message
|
|
CDialog::OnInitDialog ();
|
|
|
|
// Version 1.0 by default
|
|
DWORD version_major = 1;
|
|
DWORD version_minor = 0;
|
|
|
|
// Get the name and path of the currently executing application
|
|
TCHAR filename[MAX_PATH];
|
|
::GetModuleFileName (NULL, filename, sizeof (filename));
|
|
|
|
// Get the version information for this file
|
|
DWORD dummy_var = 0;
|
|
DWORD version_size = ::GetFileVersionInfoSize (filename, &dummy_var);
|
|
if (version_size > 0) {
|
|
|
|
// Get the file version block
|
|
LPBYTE pblock = new BYTE[version_size];
|
|
if (::GetFileVersionInfo (filename, 0L, version_size, pblock)) {
|
|
|
|
// Query the block for the file version information
|
|
UINT version_len = 0;
|
|
VS_FIXEDFILEINFO *pversion_info = NULL;
|
|
if (::VerQueryValue (pblock, "\\", (LPVOID *)&pversion_info, &version_len)) {
|
|
version_major = pversion_info->dwFileVersionMS;
|
|
version_minor = pversion_info->dwFileVersionLS;
|
|
}
|
|
}
|
|
SAFE_DELETE (pblock);
|
|
}
|
|
|
|
// Put the version string into the dialog
|
|
CString version_string;
|
|
version_string.Format (IDS_VERSION, (version_major >> 16), (version_major & 0xFFFF));
|
|
SetDlgItemText (IDC_VERSION, version_string);
|
|
return TRUE;
|
|
}
|
|
|