Initial commit of Command & Conquer Renegade source code.

This commit is contained in:
LFeenanEA
2025-02-27 16:39:46 +00:00
parent 74ab8fa5e0
commit 58ed459113
4918 changed files with 1366710 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
/*
** 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/>.
*/
// AddToLineupDialog.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "AddToLineupDialog.h"
#include "ViewerScene.h"
#include <rendobj.h>
#include <assetmgr.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAddToLineupDialog dialog
CAddToLineupDialog::CAddToLineupDialog(ViewerSceneClass *scene, CWnd* pParent /*=NULL*/)
: CDialog(CAddToLineupDialog::IDD, pParent),
m_pCScene(scene)
{
//{{AFX_DATA_INIT(CAddToLineupDialog)
m_Object = _T("");
//}}AFX_DATA_INIT
}
void CAddToLineupDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAddToLineupDialog)
DDX_CBString(pDX, IDC_OBJECT, m_Object);
DDV_MaxChars(pDX, m_Object, 64);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAddToLineupDialog, CDialog)
//{{AFX_MSG_MAP(CAddToLineupDialog)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAddToLineupDialog message handlers
BOOL CAddToLineupDialog::OnInitDialog()
{
CDialog::OnInitDialog();
if (m_pCScene)
{
// Get a pointer to the combo box control.
CComboBox *pCombo = (CComboBox*)GetDlgItem(IDC_OBJECT);
ASSERT_VALID(pCombo);
// Populate the combo box with the names of the objects that
// can be added to the lineup.
WW3DAssetManager *assets = WW3DAssetManager::Get_Instance();
ASSERT(assets != NULL);
RenderObjIterator *it = assets->Create_Render_Obj_Iterator();
ASSERT(it != NULL);
for (; !it->Is_Done(); it->Next())
{
if (m_pCScene->Can_Line_Up(it->Current_Item_Class_ID()))
pCombo->AddString(it->Current_Item_Name());
}
assets->Release_Render_Obj_Iterator(it);
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CAddToLineupDialog::OnOK()
{
// Make sure the user actually chose a name.
CComboBox *pCombo = (CComboBox*)GetDlgItem(IDC_OBJECT);
ASSERT_VALID(pCombo);
CString text;
pCombo->GetWindowText(text);
if (text.IsEmpty())
{
::AfxMessageBox("Please select an object, or type in an object name.");
return;
}
CDialog::OnOK();
}

View File

@@ -0,0 +1,69 @@
/*
** 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/>.
*/
#if !defined(AFX_ADDTOLINEUPDIALOG_H__AD8B92C5_25CB_11D4_8A1D_0090272E6F90__INCLUDED_)
#define AFX_ADDTOLINEUPDIALOG_H__AD8B92C5_25CB_11D4_8A1D_0090272E6F90__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// AddToLineupDialog.h : header file
//
class ViewerSceneClass;
/////////////////////////////////////////////////////////////////////////////
// CAddToLineupDialog dialog
class CAddToLineupDialog : public CDialog
{
// Construction
public:
CAddToLineupDialog(ViewerSceneClass *scene, CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CAddToLineupDialog)
enum { IDD = IDD_ADD_TO_LINEUP };
CString m_Object;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAddToLineupDialog)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
ViewerSceneClass * m_pCScene;
// Generated message map functions
//{{AFX_MSG(CAddToLineupDialog)
virtual BOOL OnInitDialog();
virtual void OnOK();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_ADDTOLINEUPDIALOG_H__AD8B92C5_25CB_11D4_8A1D_0090272E6F90__INCLUDED_)

View File

@@ -0,0 +1,197 @@
/*
** 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/>.
*/
// AdvancedAnimSheet.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "W3dViewDoc.h"
#include "AdvancedAnimSheet.h"
#include "AssetMgr.h"
#include "HAnim.h"
#include "HTree.h"
#include "Utils.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// QSort comparison function for HAnimClass pointers.
// Will compare their names.
static int anim_name_compare (const void *arg1, const void *arg2)
{
ASSERT(arg1 != NULL);
ASSERT(arg2 != NULL);
HAnimClass *a1 = *(HAnimClass**)arg1;
HAnimClass *a2 = *(HAnimClass**)arg2;
return _stricmp( a1->Get_Name(), a2->Get_Name() );
}
/////////////////////////////////////////////////////////////////////////////
// CAdvancedAnimSheet
IMPLEMENT_DYNAMIC(CAdvancedAnimSheet, CPropertySheet)
CAdvancedAnimSheet::CAdvancedAnimSheet(CWnd* pParentWnd, UINT iSelectPage)
: CPropertySheet("Advanced Animation", pParentWnd, iSelectPage),
m_MixingPage(this),
m_ReportPage(this),
AnimsValid(false),
AnimCount(0)
{
// Blank out the array of animation pointers.
ZeroMemory(Anims, sizeof(Anims));
// Add the property pages into this property sheet.
AddPage(&m_MixingPage);
AddPage(&m_ReportPage);
}
CAdvancedAnimSheet::~CAdvancedAnimSheet()
{
if (AnimsValid)
{
for (int i = 0; i < AnimCount; i++)
{
MEMBER_RELEASE(Anims[i]);
}
AnimsValid = false;
AnimCount = 0;
}
}
BEGIN_MESSAGE_MAP(CAdvancedAnimSheet, CPropertySheet)
//{{AFX_MSG_MAP(CAdvancedAnimSheet)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAdvancedAnimSheet message handlers
int CAdvancedAnimSheet::GetAnimCount (void)
{
if (AnimsValid)
return AnimCount;
LoadAnims();
if (AnimsValid)
return AnimCount;
else
return 0;
}
HAnimClass ** CAdvancedAnimSheet::GetAnims (void)
{
if (AnimsValid)
return Anims;
LoadAnims();
// Return the array regardless of validity. If the entries are
// invalid, they'll all be NULL, but the array itself is cool.
return Anims;
}
void CAdvancedAnimSheet::LoadAnims (void)
{
// Get the current render object and it's HTree. If it doesn't have
// an HTree, then it's not animating and we're not interested.
RenderObjClass *robj = ::GetCurrentDocument()->GetDisplayedObject();
if (robj == NULL)
return;
const HTreeClass *htree = robj->Get_HTree();
if (htree == NULL)
return;
const char *htree_name = htree->Get_Name();
/*
** Figure out which animations apply to the current object, and
** add each one to the array of animations which we will later sort.
*/
// Get an iterator from the asset manager that we can
// use to enumerate the currently loaded assets
AssetIterator *pAnimEnum = WW3DAssetManager::Get_Instance()->Create_HAnim_Iterator();
ASSERT(pAnimEnum != NULL);
if (pAnimEnum)
{
// Loop through all the animations in the manager
for (pAnimEnum->First(); pAnimEnum->Is_Done() == FALSE; pAnimEnum->Next())
{
LPCTSTR pszAnimName = pAnimEnum->Current_Item_Name();
// Get an instance of the animation object
HAnimClass *pHierarchyAnim = WW3DAssetManager::Get_Instance()->Get_HAnim(pszAnimName);
ASSERT(pHierarchyAnim != NULL);
if (pHierarchyAnim)
{
// Does this animation apply to the current model's HTree?
if (stricmp(htree_name, pHierarchyAnim->Get_HName()) == 0)
{
// Add this Anims pointer to the array.
if (AnimCount < MAX_REPORT_ANIMS)
{
MEMBER_ADD(Anims[AnimCount], pHierarchyAnim);
AnimCount++;
}
else
{
char msg[256];
sprintf(msg, "Error: Only %d animations are supported in this report. "
" There are more than that loaded...", MAX_REPORT_ANIMS);
MessageBox(msg, "Too Many Animations");
break;
}
}
// Release our hold on this animation.
MEMBER_RELEASE(pHierarchyAnim);
}
}
// Free the object
delete pAnimEnum;
pAnimEnum = NULL;
}
/*
** Sort the array of animations in alphabetical order.
*/
qsort(Anims, AnimCount, sizeof(HAnimClass*), anim_name_compare);
AnimsValid = true;
}

View File

@@ -0,0 +1,92 @@
/*
** 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/>.
*/
#if !defined(AFX_ADVANCEDANIMSHEET_H__67C01724_7C0D_11D3_9A3A_0090272E6F90__INCLUDED_)
#define AFX_ADVANCEDANIMSHEET_H__67C01724_7C0D_11D3_9A3A_0090272E6F90__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// AdvancedAnimSheet.h : header file
//
#include "AnimMixingPage.h"
#include "AnimReportPage.h"
#define MAX_REPORT_ANIMS 128
/////////////////////////////////////////////////////////////////////////////
// CAdvancedAnimSheet
class CAdvancedAnimSheet : public CPropertySheet
{
DECLARE_DYNAMIC(CAdvancedAnimSheet)
// Construction
public:
CAdvancedAnimSheet(CWnd *pParentWnd = NULL, UINT iSelectPage = 0);
// Attributes
public:
// Pages in the property sheet.
CAnimMixingPage m_MixingPage;
CAnimReportPage m_ReportPage;
// Indeces of animations selected in the mixing page.
DynamicVectorClass<int> m_SelectedAnims;
// Operations
public:
int GetAnimCount (void);
HAnimClass ** GetAnims (void);
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAdvancedAnimSheet)
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CAdvancedAnimSheet();
// Generated message map functions
protected:
void LoadAnims (void);
HAnimClass *Anims[MAX_REPORT_ANIMS];
int AnimCount;
bool AnimsValid;
//{{AFX_MSG(CAdvancedAnimSheet)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_ADVANCEDANIMSHEET_H__67C01724_7C0D_11D3_9A3A_0090272E6F90__INCLUDED_)

View File

@@ -0,0 +1,126 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : W3DView *
* *
* $Archive:: /Commando/Code/Tools/W3DView/AggregateNameDialog.cpp $Modtime:: $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "StdAfx.H"
#include "W3DView.H"
#include "AggregateNameDialog.H"
#include "W3D_File.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//
// AggregateNameDialogClass
//
AggregateNameDialogClass::AggregateNameDialogClass (CWnd* pParent /*=NULL*/)
: CDialog(AggregateNameDialogClass::IDD, pParent)
{
//{{AFX_DATA_INIT(AggregateNameDialogClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// AggregateNameDialogClass
//
AggregateNameDialogClass::AggregateNameDialogClass
(
UINT resource_id,
const CString &def_name,
CWnd *pParent
)
: m_Name (def_name),
CDialog (resource_id, pParent)
{
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// AggregateNameDialogClass
//
void
AggregateNameDialogClass::DoDataExchange (CDataExchange* pDX)
{
CDialog::DoDataExchange (pDX);
//{{AFX_DATA_MAP(AggregateNameDialogClass)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(AggregateNameDialogClass, CDialog)
//{{AFX_MSG_MAP(AggregateNameDialogClass)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
// OnOK
//
void
AggregateNameDialogClass::OnOK (void)
{
GetDlgItemText (IDC_AGGREGATE_NAME, m_Name);
CDialog::OnOK ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
AggregateNameDialogClass::OnInitDialog (void)
{
// Allow the base class to process this message
CDialog::OnInitDialog ();
// Restrict the amount of text a user can type into the control
SendDlgItemMessage (IDC_AGGREGATE_NAME, EM_LIMITTEXT, (WPARAM)W3D_NAME_LEN-1);
SetDlgItemText (IDC_AGGREGATE_NAME, m_Name);
return TRUE;
}

View File

@@ -0,0 +1,83 @@
/*
** 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/>.
*/
#if !defined(AFX_AGGREGATENAMEDIALOG_H__3F618448_CDEA_11D2_9FFC_00104B791122__INCLUDED_)
#define AFX_AGGREGATENAMEDIALOG_H__3F618448_CDEA_11D2_9FFC_00104B791122__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// AggregateNameDialog.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// AggregateNameDialogClass dialog
class AggregateNameDialogClass : public CDialog
{
// Construction
public:
AggregateNameDialogClass(CWnd* pParent = NULL);
AggregateNameDialogClass(UINT resource_id, const CString &def_name, CWnd* pParent = NULL);
// Dialog Data
//{{AFX_DATA(AggregateNameDialogClass)
enum { IDD = IDD_MAKE_AGGREGATE };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(AggregateNameDialogClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(AggregateNameDialogClass)
virtual void OnOK();
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
////////////////////////////////////////////////////////////////
//
// Public methods
//
const CString & Get_Name (void) const { return m_Name; }
void Set_Name (const CString &name) { m_Name = name; }
private:
////////////////////////////////////////////////////////////////
//
// Private member data
//
CString m_Name;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_AGGREGATENAMEDIALOG_H__3F618448_CDEA_11D2_9FFC_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,248 @@
/*
** 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/>.
*/
// AmbientLightDialog.cpp : implementation file
//
#include "stdafx.h"
#include "W3DView.h"
#include "AmbientLightDialog.h"
#include "MainFrm.H"
#include "W3DViewDoc.H"
#include "ViewerScene.H"
#include "Utils.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAmbientLightDialog dialog
CAmbientLightDialog::CAmbientLightDialog(CWnd* pParent /*=NULL*/)
: CDialog(CAmbientLightDialog::IDD, pParent)
{
//{{AFX_DATA_INIT(CAmbientLightDialog)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CAmbientLightDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAmbientLightDialog)
DDX_Control(pDX, IDC_SLIDER_BLUE, m_blueSlider);
DDX_Control(pDX, IDC_SLIDER_GREEN, m_greenSlider);
DDX_Control(pDX, IDC_SLIDER_RED, m_redSlider);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAmbientLightDialog, CDialog)
//{{AFX_MSG_MAP(CAmbientLightDialog)
ON_WM_HSCROLL()
ON_BN_CLICKED(IDC_GRAYSCALE_CHECK, OnGrayscaleCheck)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
CAmbientLightDialog::OnInitDialog (void)
{
// Allow the base class to process this message
CDialog::OnInitDialog ();
// Center the dialog around the data tree view instead
// of the direct center of the screen
::CenterDialogAroundTreeView (m_hWnd);
m_redSlider.SetRange (0, 100);
m_greenSlider.SetRange (0, 100);
m_blueSlider.SetRange (0, 100);
// Get a pointer to the doc so we can get at the current scene
// pointer.
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc && pCDoc->GetScene ())
{
Vector3 lightSettings = pCDoc->GetScene ()->Get_Ambient_Light ();
// Remember these initial settings so we can restore them
// if the user cancels
m_initialRed = int(lightSettings.X * 100.00F);
m_initialGreen = int(lightSettings.Y * 100.00F);
m_initialBlue = int(lightSettings.Z * 100.00F);
}
if ((m_initialRed == m_initialGreen) &&
(m_initialRed == m_initialBlue))
{
// Check the grayscale checkbox
SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_SETCHECK, (WPARAM)TRUE);
}
// Set the initial slider position
m_redSlider.SetPos (m_initialRed);
m_greenSlider.SetPos (m_initialGreen);
m_blueSlider.SetPos (m_initialBlue);
return TRUE;
}
//////////////////////////////////////////////////////////////
//
// OnHScroll
//
void
CAmbientLightDialog::OnHScroll
(
UINT nSBCode,
UINT nPos,
CScrollBar* pScrollBar
)
{
if (SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_GETCHECK))
{
int iCurrentPos = 0;
if (pScrollBar == GetDlgItem (IDC_SLIDER_RED))
{
iCurrentPos = m_redSlider.GetPos ();
}
else if (pScrollBar == GetDlgItem (IDC_SLIDER_GREEN))
{
iCurrentPos = m_greenSlider.GetPos ();
}
else
{
iCurrentPos = m_blueSlider.GetPos ();
}
// Make all the sliders the same pos
m_redSlider.SetPos (iCurrentPos);
m_greenSlider.SetPos (iCurrentPos);
m_blueSlider.SetPos (iCurrentPos);
}
Vector3 lightSettings;
lightSettings.X = float(m_redSlider.GetPos ()) / 100.00F;
lightSettings.Y = float(m_greenSlider.GetPos ()) / 100.00F;
lightSettings.Z = float(m_blueSlider.GetPos ()) / 100.00F;
// Get a pointer to the document so we can change the scene's light
// settings
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc && pCDoc->GetScene ())
{
// Modify the ambient light for this scene
pCDoc->GetScene ()->Set_Ambient_Light (lightSettings);
}
// Allow the base class to process this message
CDialog::OnHScroll (nSBCode, nPos, pScrollBar);
return ;
}
//////////////////////////////////////////////////////////////
//
// OnCancel
//
void
CAmbientLightDialog::OnCancel (void)
{
Vector3 lightSettings;
lightSettings.X = float(m_initialRed) / 100.00F;
lightSettings.Y = float(m_initialGreen) / 100.00F;
lightSettings.Z = float(m_initialBlue) / 100.00F;
// Get a pointer to the document so we can change the scene's light
// settings
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc && pCDoc->GetScene ())
{
// Modify the ambient light for this scene
pCDoc->GetScene ()->Set_Ambient_Light (lightSettings);
}
// Allow the base class to process this message
CDialog::OnCancel();
return ;
}
//////////////////////////////////////////////////////////////
//
// WindowProc
//
LRESULT
CAmbientLightDialog::WindowProc
(
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
if (message == WM_PAINT)
{
// Paint the gradients for each color
::Paint_Gradient (::GetDlgItem (m_hWnd, IDC_RED_GRADIENT), 1, 0, 0);
::Paint_Gradient (::GetDlgItem (m_hWnd, IDC_GREEN_GRADIENT), 0, 1, 0);
::Paint_Gradient (::GetDlgItem (m_hWnd, IDC_BLUE_GRADIENT), 0, 0, 1);
}
// Allow the base class to process this message
return CDialog::WindowProc (message, wParam, lParam);
}
//////////////////////////////////////////////////////////////
//
// OnGrayscaleCheck
//
void
CAmbientLightDialog::OnGrayscaleCheck (void)
{
if (SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_GETCHECK))
{
// Make the green and blue sliders the same as red
m_greenSlider.SetPos (m_redSlider.GetPos ());
m_blueSlider.SetPos (m_redSlider.GetPos ());
Vector3 lightSettings;
lightSettings.X = float(m_redSlider.GetPos ()) / 100.00F;
lightSettings.Y = float(m_greenSlider.GetPos ()) / 100.00F;
lightSettings.Z = float(m_blueSlider.GetPos ()) / 100.00F;
// Get a pointer to the document so we can change the scene's light
// settings
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc && pCDoc->GetScene ())
{
// Modify the ambient light for this scene
pCDoc->GetScene ()->Set_Ambient_Light (lightSettings);
}
}
return ;
}

View File

@@ -0,0 +1,75 @@
/*
** 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/>.
*/
#if !defined(AFX_AMBIENTLIGHTDIALOG_H__D60CC3CE_5F94_11D2_9FC7_00104B791122__INCLUDED_)
#define AFX_AMBIENTLIGHTDIALOG_H__D60CC3CE_5F94_11D2_9FC7_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// AmbientLightDialog.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CAmbientLightDialog dialog
class CAmbientLightDialog : public CDialog
{
// Construction
public:
CAmbientLightDialog(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CAmbientLightDialog)
enum { IDD = IDD_LIGHT_AMBIENT_DIALOG };
CSliderCtrl m_blueSlider;
CSliderCtrl m_greenSlider;
CSliderCtrl m_redSlider;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAmbientLightDialog)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CAmbientLightDialog)
virtual BOOL OnInitDialog();
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
virtual void OnCancel();
afx_msg void OnGrayscaleCheck();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
int m_initialRed;
int m_initialGreen;
int m_initialBlue;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_AMBIENTLIGHTDIALOG_H__D60CC3CE_5F94_11D2_9FC7_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,169 @@
/*
** 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/>.
*/
// AnimMixingPage.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "W3dViewDoc.h"
#include "AdvancedAnimSheet.h"
#include "AnimMixingPage.h"
#include "RendObj.h"
#include "HTree.h"
#include "HAnim.h"
#include "Utils.h"
#include "AssetMgr.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAnimMixingPage property page
IMPLEMENT_DYNCREATE(CAnimMixingPage, CPropertyPage)
CAnimMixingPage::CAnimMixingPage(CAdvancedAnimSheet *sheet)
: CPropertyPage(CAnimMixingPage::IDD),
m_Sheet(sheet)
{
//{{AFX_DATA_INIT(CAnimMixingPage)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
CAnimMixingPage::~CAnimMixingPage()
{
}
void CAnimMixingPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAnimMixingPage)
DDX_Control(pDX, IDC_ANIMATION_LIST, m_AnimList);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAnimMixingPage, CPropertyPage)
//{{AFX_MSG_MAP(CAnimMixingPage)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAnimMixingPage message handlers
BOOL CAnimMixingPage::OnInitDialog()
{
CPropertyPage::OnInitDialog();
ASSERT(m_Sheet != NULL);
FillListCtrl();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CAnimMixingPage::FillListCtrl (void)
{
// Get the current render object and it's HTree. If it doesn't have
// an HTree, then it's not animating and we're not interested.
RenderObjClass *robj = ::GetCurrentDocument()->GetDisplayedObject();
if (robj == NULL)
return;
const HTreeClass *htree = robj->Get_HTree();
if (htree == NULL)
return;
// Get a sorted array of animations that affect the currently active object.
HAnimClass **anim = m_Sheet->GetAnims();
int anim_count = m_Sheet->GetAnimCount();
// Add an item to the list view for each animation.
int i;
for (i = 0; i < anim_count; i++)
m_AnimList.InsertItem(i, anim[i]->Get_Name());
}
void CAnimMixingPage::OnOK()
{
/*
** Create a new HAnimCombo class containing the animations selected by the user.
*/
int num_selected = m_AnimList.GetSelectedCount();
RenderObjClass *current_obj = ::GetCurrentDocument()->GetDisplayedObject();
const char *obj_name = current_obj->Get_Name();
RenderObjClass *robj = WW3DAssetManager::Get_Instance()->Create_Render_Obj(obj_name);
if (num_selected > 0 && robj != NULL)
{
HAnimClass **anim = m_Sheet->GetAnims();
HAnimComboClass *combo = new HAnimComboClass(num_selected);
ASSERT(combo != NULL);
POSITION pos = m_AnimList.GetFirstSelectedItemPosition();
int array_idx, idx = 0;
while (pos)
{
array_idx = m_AnimList.GetNextSelectedItem(pos);
combo->Set_Motion(idx, anim[array_idx]);
combo->Set_Weight(idx, 1.0f);
combo->Peek_Anim_Combo_Data(idx)->Build_Active_Pivot_Map();
idx++;
}
/*
** Set this new combo to be used by the doc.
*/
::GetCurrentDocument()->PlayAnimation(robj, combo);
robj->Release_Ref();
}
CPropertyPage::OnOK();
}
BOOL CAnimMixingPage::OnKillActive()
{
/*
** Update the parent with info on the current selection.
*/
m_Sheet->m_SelectedAnims.Clear();
m_Sheet->m_SelectedAnims.Resize(m_AnimList.GetSelectedCount());
int selected_idx, i=0;
POSITION pos = m_AnimList.GetFirstSelectedItemPosition();
while (pos)
{
selected_idx = m_AnimList.GetNextSelectedItem(pos);
if (!m_Sheet->m_SelectedAnims.Add(selected_idx))
{
char buf[128];
sprintf(buf, "Failed to insert item %d! Talk to Andre if "\
"you see this message.", i);
MessageBox(buf);
}
i++;
}
return CPropertyPage::OnKillActive();
}

View File

@@ -0,0 +1,77 @@
/*
** 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/>.
*/
#if !defined(AFX_ANIMMIXINGPAGE_H__67C01722_7C0D_11D3_9A3A_0090272E6F90__INCLUDED_)
#define AFX_ANIMMIXINGPAGE_H__67C01722_7C0D_11D3_9A3A_0090272E6F90__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// AnimMixingPage.h : header file
//
class CAdvancedAnimSheet;
/////////////////////////////////////////////////////////////////////////////
// CAnimMixingPage dialog
class CAnimMixingPage : public CPropertyPage
{
DECLARE_DYNCREATE(CAnimMixingPage)
// Construction
public:
CAnimMixingPage(CAdvancedAnimSheet *sheet = NULL);
~CAnimMixingPage();
// Dialog Data
//{{AFX_DATA(CAnimMixingPage)
enum { IDD = IDD_PROP_PAGE_ADVANIM_MIXING };
CListCtrl m_AnimList;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(CAnimMixingPage)
public:
virtual void OnOK();
virtual BOOL OnKillActive();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
void FillListCtrl (void);
CAdvancedAnimSheet *m_Sheet;
// Generated message map functions
//{{AFX_MSG(CAnimMixingPage)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_ANIMMIXINGPAGE_H__67C01722_7C0D_11D3_9A3A_0090272E6F90__INCLUDED_)

View File

@@ -0,0 +1,216 @@
/*
** 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/>.
*/
// AnimReportPage.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "W3DViewDoc.h"
#include "AdvancedAnimSheet.h"
#include "AnimReportPage.h"
#include "HAnim.h"
#include "HTree.h"
#include "Utils.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAnimReportPage property page
IMPLEMENT_DYNCREATE(CAnimReportPage, CPropertyPage)
CAnimReportPage::CAnimReportPage(CAdvancedAnimSheet *sheet)
: CPropertyPage(CAnimReportPage::IDD),
m_Sheet(sheet)
{
//{{AFX_DATA_INIT(CAnimReportPage)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
CAnimReportPage::~CAnimReportPage()
{
}
void CAnimReportPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAnimReportPage)
DDX_Control(pDX, IDC_ANIM_REPORT, m_AnimReport);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAnimReportPage, CPropertyPage)
//{{AFX_MSG_MAP(CAnimReportPage)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAnimReportPage message handlers
BOOL CAnimReportPage::OnInitDialog()
{
CPropertyPage::OnInitDialog();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CAnimReportPage::FillListControl()
{
// Add the first column to the animation report. All bone names will
// go in this column.
m_AnimReport.InsertColumn(0, "Bone Name");
// Get the current render object and it's HTree. If it doesn't have
// an HTree, then it's not animating and we're not interested.
RenderObjClass *robj = ::GetCurrentDocument()->GetDisplayedObject();
if (robj == NULL)
return;
const HTreeClass *htree = robj->Get_HTree();
if (htree == NULL)
return;
// Get a sorted array of animations that affect the currently active object.
HAnimClass **anim = m_Sheet->GetAnims();
int anim_count = m_Sheet->GetAnimCount();
/*
** Create a column in the report view for each animation.
*/
int column_count; // number of columns in the report view (EXCLUDING the bone column)
bool indirect; // true if we have one column per animation selected in the mixing page
if (m_Sheet->m_SelectedAnims.Count() > 0)
{
column_count = m_Sheet->m_SelectedAnims.Count();
indirect = true;
}
else
{
column_count = anim_count;
indirect = false;
}
int i, j;
int anim_idx; // column index, essentially (anim_idx + 1 == column for that anim)
for (i = 0; i < column_count; i++)
{
// Add a new column with the name of this animation as the title.
anim_idx = indirect ? m_Sheet->m_SelectedAnims[i] : i;
if (m_AnimReport.InsertColumn(anim_idx+1, anim[anim_idx]->Get_Name(), LVCFMT_CENTER) == -1)
{
// Failed to add a new column to the list control.
ASSERT(false);
}
}
/*
** Add a row to the report for each bone in the object affected by
** an animation. It's entry (row/col) will contain the animation
** channels with valid animation data.
*/
for (i = 0; i < column_count; i++)
{
// Grab the anim pointer directly.
anim_idx = indirect ? m_Sheet->m_SelectedAnims[i] : i;
HAnimClass *pAnim = anim[anim_idx];
// Which bones does it affect, and how?
int num_bones = robj->Get_Num_Bones();
for (j = 1; j < num_bones; j++) // skip bone 0, which is always the root bone
{
// Add each bone to the report (regardless of animation status)
// if it isn't already there.
int idx = FindItem(htree->Get_Bone_Name(j));
if (idx == -1)
{
// Wasn't present, add a new item for this bone.
idx = m_AnimReport.InsertItem(m_AnimReport.GetItemCount(),
htree->Get_Bone_Name(j));
}
if (pAnim->Is_Node_Motion_Present(j))
{
// Add motion channel info to the appropriate column.
char channels[6]; // strlen("XYZQV")+1
ZeroMemory(channels, sizeof(channels));
MakeChannelStr(j, pAnim, channels);
m_AnimReport.SetItem(idx, i+1, LVIF_TEXT, channels, 0,0,0,0);
}
}
}
// Make the columns sized nicely.
m_AnimReport.SetColumnWidth(0, LVSCW_AUTOSIZE);
for (i = 0; i < column_count; i++)
m_AnimReport.SetColumnWidth(i+1, LVSCW_AUTOSIZE_USEHEADER);
// All done, the report view is set up.
}
int CAnimReportPage::FindItem (const char *item_name)
{
LVFINDINFO lvfi;
lvfi.flags = LVFI_STRING;
lvfi.psz = item_name;
return m_AnimReport.FindItem(&lvfi);
}
void CAnimReportPage::MakeChannelStr (int bone_idx, HAnimClass *hanim, char *channels)
{
if (hanim->Has_X_Translation(bone_idx))
strcat(channels, "X");
if (hanim->Has_Y_Translation(bone_idx))
strcat(channels, "Y");
if (hanim->Has_Z_Translation(bone_idx))
strcat(channels, "Z");
if (hanim->Has_Rotation(bone_idx))
strcat(channels, "Q");
if (hanim->Has_Visibility(bone_idx))
strcat(channels, "V");
}
BOOL CAnimReportPage::OnSetActive()
{
// Delete all info in the report view.
m_AnimReport.DeleteAllItems();
while (m_AnimReport.DeleteColumn(0));
// Fill the list control each time we're set active so that
// a change in selection on the mixing page will have an
// effect on this page.
FillListControl();
return CPropertyPage::OnSetActive();
}

View File

@@ -0,0 +1,78 @@
/*
** 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/>.
*/
#if !defined(AFX_ANIMREPORTPAGE_H__67C01723_7C0D_11D3_9A3A_0090272E6F90__INCLUDED_)
#define AFX_ANIMREPORTPAGE_H__67C01723_7C0D_11D3_9A3A_0090272E6F90__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// AnimReportPage.h : header file
//
class HAnimClass;
class CAdvancedAnimSheet;
/////////////////////////////////////////////////////////////////////////////
// CAnimReportPage dialog
class CAnimReportPage : public CPropertyPage
{
DECLARE_DYNCREATE(CAnimReportPage)
// Construction
public:
CAnimReportPage(CAdvancedAnimSheet *sheet = NULL);
~CAnimReportPage();
// Dialog Data
//{{AFX_DATA(CAnimReportPage)
enum { IDD = IDD_PROP_PAGE_ADVANIM_REPORT };
CListCtrl m_AnimReport;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(CAnimReportPage)
public:
virtual BOOL OnSetActive();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
void FillListControl (void);
int FindItem (const char *item_name);
void MakeChannelStr (int bone_idx, HAnimClass *hanim, char *channels);
CAdvancedAnimSheet *m_Sheet;
// Generated message map functions
//{{AFX_MSG(CAnimReportPage)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_ANIMREPORTPAGE_H__67C01723_7C0D_11D3_9A3A_0090272E6F90__INCLUDED_)

View File

@@ -0,0 +1,258 @@
/*
** 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/>.
*/
// AnimatedSoundOptionsDialog.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "globals.h"
#include "animatedsoundoptionsdialog.h"
#include "ffactory.h"
#include "animatedsoundmgr.h"
#include "wwsaveload.h"
#include "definitionmgr.h"
#include "wwfile.h"
#include "chunkio.h"
#include "wwdebug.h"
#include "restrictedfiledialog.h"
#include "utils.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// AnimatedSoundOptionsDialogClass dialog
AnimatedSoundOptionsDialogClass::AnimatedSoundOptionsDialogClass(CWnd* pParent /*=NULL*/)
: CDialog(AnimatedSoundOptionsDialogClass::IDD, pParent)
{
//{{AFX_DATA_INIT(AnimatedSoundOptionsDialogClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void AnimatedSoundOptionsDialogClass::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(AnimatedSoundOptionsDialogClass)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(AnimatedSoundOptionsDialogClass, CDialog)
//{{AFX_MSG_MAP(AnimatedSoundOptionsDialogClass)
ON_BN_CLICKED(IDC_SOUND_DEFINITION_LIBRARY_BROWSE_BUTTON, OnSoundDefinitionLibraryBrowseButton)
ON_BN_CLICKED(IDC_SOUND_INI_BROWSE_BUTTON, OnSoundIniBrowseButton)
ON_BN_CLICKED(IDC_SOUND_PATH_BROWSE_BUTTON, OnSoundPathBrowseButton)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
// OnSoundDefinitionLibraryBrowseButton
//
/////////////////////////////////////////////////////////////////////////////
void
AnimatedSoundOptionsDialogClass::OnSoundDefinitionLibraryBrowseButton (void)
{
CFileDialog dialog ( TRUE,
".ddb",
"20480.ddb",
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
"Definition Database Files(*.ddb)|*.ddb||",
this);
//
// Prompt the user
//
if (dialog.DoModal () == IDOK) {
SetDlgItemText (IDC_SOUND_DEFINITION_LIBRARY_EDIT, dialog.GetPathName ());
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnSoundIniBrowseButton
//
/////////////////////////////////////////////////////////////////////////////
void
AnimatedSoundOptionsDialogClass::OnSoundIniBrowseButton (void)
{
CFileDialog dialog ( TRUE,
".ini",
"w3danimsound.ini",
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
"INI Files (*.ini)|*.ini||",
this);
//
// Prompt the user
//
if (dialog.DoModal () == IDOK) {
SetDlgItemText (IDC_SOUND_INI_EDIT, dialog.GetPathName ());
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnOK
//
/////////////////////////////////////////////////////////////////////////////
void
AnimatedSoundOptionsDialogClass::OnOK (void)
{
CDialog::OnOK ();
//
// Get the user's response
//
CString sound_def_lib_path;
CString sound_ini_path;
CString sound_data_path;
GetDlgItemText (IDC_SOUND_DEFINITION_LIBRARY_EDIT, sound_def_lib_path);
GetDlgItemText (IDC_SOUND_INI_EDIT, sound_ini_path);
GetDlgItemText (IDC_SOUND_FILE_PATH_EDIT, sound_data_path);
//
// Store this information in the registry
//
theApp.WriteProfileString ("Config", "SoundDefLibPath", sound_def_lib_path);
theApp.WriteProfileString ("Config", "AnimSoundINIPath", sound_ini_path);
theApp.WriteProfileString ("Config", "AnimSoundDataPath", sound_data_path);
Load_Animated_Sound_Settings ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL
AnimatedSoundOptionsDialogClass::OnInitDialog (void)
{
CDialog::OnInitDialog ();
StringClass sound_def_lib_path = theApp.GetProfileString ("Config", "SoundDefLibPath");
StringClass sound_ini_path = theApp.GetProfileString ("Config", "AnimSoundINIPath");
StringClass sound_data_path = theApp.GetProfileString ("Config", "AnimSoundDataPath");
//
// Fill in the default values
//
SetDlgItemText (IDC_SOUND_DEFINITION_LIBRARY_EDIT, sound_def_lib_path);
SetDlgItemText (IDC_SOUND_INI_EDIT, sound_ini_path);
SetDlgItemText (IDC_SOUND_FILE_PATH_EDIT, sound_data_path);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// Load_Animated_Sound_Settings
//
/////////////////////////////////////////////////////////////////////////////
void
AnimatedSoundOptionsDialogClass::Load_Animated_Sound_Settings (void)
{
//
// Start fresh
//
DefinitionMgrClass::Free_Definitions ();
//
// Get the data from the registry
//
StringClass sound_def_lib_path = theApp.GetProfileString ("Config", "SoundDefLibPath");
StringClass sound_ini_path = theApp.GetProfileString ("Config", "AnimSoundINIPath");
StringClass sound_data_path = theApp.GetProfileString ("Config", "AnimSoundDataPath");
//
// Try to load the definitions into the definition mgr
//
FileClass *file = _TheFileFactory->Get_File (sound_def_lib_path);
if (file != NULL) {
file->Open (FileClass::READ);
ChunkLoadClass cload (file);
SaveLoadSystemClass::Load (cload);
file->Close ();
_TheFileFactory->Return_File (file);
} else {
WWDEBUG_SAY (("Failed to load file %s\n", sound_def_lib_path.Peek_Buffer ()));
}
//
// Load the sound settings from the ini file
//
AnimatedSoundMgrClass::Shutdown ();
AnimatedSoundMgrClass::Initialize (sound_ini_path);
//
// Add a sub-directory to the file factory for audio use
//
_TheSimpleFileFactory->Append_Sub_Directory (sound_data_path);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnSoundPathBrowseButton
//
/////////////////////////////////////////////////////////////////////////////
void
AnimatedSoundOptionsDialogClass::OnSoundPathBrowseButton (void)
{
RestrictedFileDialogClass dialog ( TRUE,
".wav",
"test.wav",
OFN_HIDEREADONLY | OFN_EXPLORER,
"Directories|*.wav||",
AfxGetMainWnd ());
dialog.m_ofn.lpstrTitle = "Pick Sound Path";
//
// Prompt the user
//
if (dialog.DoModal () == IDOK) {
CString path = ::Strip_Filename_From_Path (dialog.GetPathName ());
SetDlgItemText (IDC_SOUND_FILE_PATH_EDIT, path);
}
return ;
}

View File

@@ -0,0 +1,81 @@
/*
** 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/>.
*/
#if !defined(AFX_ANIMATEDSOUNDOPTIONSDIALOG_H__5FD0B3D4_3975_4315_B412_44586622684B__INCLUDED_)
#define AFX_ANIMATEDSOUNDOPTIONSDIALOG_H__5FD0B3D4_3975_4315_B412_44586622684B__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// AnimatedSoundOptionsDialog.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// AnimatedSoundOptionsDialogClass dialog
class AnimatedSoundOptionsDialogClass : public CDialog
{
// Construction
public:
AnimatedSoundOptionsDialogClass(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(AnimatedSoundOptionsDialogClass)
enum { IDD = IDD_ANIMATED_SOUND_DIALOG };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(AnimatedSoundOptionsDialogClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(AnimatedSoundOptionsDialogClass)
afx_msg void OnSoundDefinitionLibraryBrowseButton();
afx_msg void OnSoundIniBrowseButton();
virtual void OnOK();
virtual BOOL OnInitDialog();
afx_msg void OnSoundPathBrowseButton();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
///////////////////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////////////////
static void Load_Animated_Sound_Settings (void);
private:
///////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_ANIMATEDSOUNDOPTIONSDIALOG_H__5FD0B3D4_3975_4315_B412_44586622684B__INCLUDED_)

View File

@@ -0,0 +1,125 @@
/*
** 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/>.
*/
// AnimationPropPage.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "AnimationPropPage.h"
#include "RendObj.H"
#include "AssetMgr.H"
#include "Mesh.H"
#include "W3DViewDoc.H"
#include "Utils.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAnimationPropPage property page
IMPLEMENT_DYNCREATE(CAnimationPropPage, CPropertyPage)
////////////////////////////////////////////////////////////////
//
// CAnimationPropPage
//
CAnimationPropPage::CAnimationPropPage (void)
: CPropertyPage(CAnimationPropPage::IDD)
{
//{{AFX_DATA_INIT(CAnimationPropPage)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
////////////////////////////////////////////////////////////////
//
// CAnimationPropPage
//
CAnimationPropPage::~CAnimationPropPage (void)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
CAnimationPropPage::DoDataExchange (CDataExchange* pDX)
{
// Allow the base class to process this message
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAnimationPropPage)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(CAnimationPropPage, CPropertyPage)
//{{AFX_MSG_MAP(CAnimationPropPage)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
CAnimationPropPage::OnInitDialog (void)
{
// Allow the base class to process this message
CPropertyPage::OnInitDialog ();
// Get a pointer to the doc so we can get at the current animation object
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc && pCDoc->GetCurrentAnimation ())
{
HAnimClass *pCAnimation = pCDoc->GetCurrentAnimation ();
// Set the description text at the top of the dialog
CString stringTemp;
stringTemp.Format (IDS_ANI_PROP_DESC, pCAnimation->Get_Name ());
SetDlgItemText (IDC_DESCRIPTION, stringTemp);
// Fill in the number of frames
SetDlgItemInt (IDC_FRAME_COUNT, pCAnimation->Get_Num_Frames ());
// Fill in the frame rate of the animation
stringTemp.Format ("%.2f fps", pCAnimation->Get_Frame_Rate ());
SetDlgItemText (IDC_FRAME_RATE, stringTemp);
// Fill in the total time taken by the animation
stringTemp.Format ("%.3f seconds", pCAnimation->Get_Total_Time ());
SetDlgItemText (IDC_TOTAL_TIME, stringTemp);
// Set the name of the hierarchy this animation belongs to.
SetDlgItemText (IDC_HIERARCHY_NAME, pCAnimation->Get_HName ());
}
return TRUE;
}

View File

@@ -0,0 +1,68 @@
/*
** 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/>.
*/
#if !defined(AFX_ANIMATIONPROPPAGE_H__9B07DA65_62B6_11D2_9FC7_00104B791122__INCLUDED_)
#define AFX_ANIMATIONPROPPAGE_H__9B07DA65_62B6_11D2_9FC7_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// AnimationPropPage.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CAnimationPropPage dialog
class CAnimationPropPage : public CPropertyPage
{
DECLARE_DYNCREATE(CAnimationPropPage)
// Construction
public:
CAnimationPropPage();
~CAnimationPropPage();
// Dialog Data
//{{AFX_DATA(CAnimationPropPage)
enum { IDD = IDD_PROP_PAGE_ANIMATION };
// NOTE - ClassWizard will add data members here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(CAnimationPropPage)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CAnimationPropPage)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_ANIMATIONPROPPAGE_H__9B07DA65_62B6_11D2_9FC7_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,243 @@
/*
** 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/>.
*/
// AnimationSpeed.cpp : implementation file
//
#include "stdafx.h"
#include "W3DView.h"
#include "AnimationSpeed.h"
#include "MainFrm.H"
#include "GraphicView.H"
#include "Utils.H"
#include "W3DViewDoc.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//extern bool CompressQ;
//extern int QnBytes;
/////////////////////////////////////////////////////////////////////////////
// CAnimationSpeed dialog
//////////////////////////////////////////////////////////////
//
// CAnimationSpeed
//
CAnimationSpeed::CAnimationSpeed (CWnd* pParent)
: m_iInitialPercent (0),
CDialog(CAnimationSpeed::IDD, pParent)
{
//{{AFX_DATA_INIT(CAnimationSpeed)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
//////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
CAnimationSpeed::DoDataExchange (CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAnimationSpeed)
DDX_Control(pDX, IDC_SPEED_SLIDER, m_speedSlider);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(CAnimationSpeed, CDialog)
//{{AFX_MSG_MAP(CAnimationSpeed)
ON_WM_HSCROLL()
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_BLEND, OnBlend)
ON_BN_CLICKED(IDC_COMPRESSQ, OnCompressq)
ON_BN_CLICKED(IDC_16BIT, On16bit)
ON_BN_CLICKED(IDC_8BIT, On8bit)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
CAnimationSpeed::OnInitDialog (void)
{
// Allow the base class to process this message
CDialog::OnInitDialog ();
// Center the dialog around the data tree view instead
// of the direct center of the screen
::CenterDialogAroundTreeView (m_hWnd);
// Get a pointer to the doc so we can get at the current scene
// pointer.
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
SendDlgItemMessage (IDC_BLEND, BM_SETCHECK, (WPARAM)pCDoc->GetAnimationBlend ());
CheckDlgButton(IDC_COMPRESSQ, pCDoc->GetChannelQCompression());
CheckRadioButton(IDC_16BIT, IDC_8BIT, IDC_16BIT+2);//-pCDoc->GetChannelQnBytes());
if(pCDoc->GetChannelQCompression()){
GetDlgItem(IDC_16BIT)->EnableWindow(TRUE);
GetDlgItem(IDC_8BIT)->EnableWindow(TRUE);
}else{
GetDlgItem(IDC_16BIT)->EnableWindow(FALSE);
GetDlgItem(IDC_8BIT)->EnableWindow(FALSE);
}
}
// Get a pointer to the main window
CMainFrame *pCMainWnd = (CMainFrame *)::AfxGetMainWnd ();
if (pCMainWnd)
{
// Get a pointer to the graphic view pane
CGraphicView *pCGraphicView = (CGraphicView *)pCMainWnd->GetPane (0, 1);
if (pCGraphicView)
{
// Determine the current display speed
float animationSpeed = pCGraphicView->GetAnimationSpeed ();
// Convert the current display speed to a percentage
m_iInitialPercent = int(animationSpeed*100.00F);
}
}
// Set the range of the slider control
m_speedSlider.SetRange (1, 200);
// Set the initial pos of the slider control
m_speedSlider.SetPos (m_iInitialPercent);
return TRUE;
}
//////////////////////////////////////////////////////////////
//
// OnInitDialog
//
void
CAnimationSpeed::OnHScroll
(
UINT nSBCode,
UINT nPos,
CScrollBar* pScrollBar
)
{
// Get the current position of the slider control
m_iInitialPercent = m_speedSlider.GetPos ();
// Get a pointer to the main window
CMainFrame *pCMainWnd = (CMainFrame *)::AfxGetMainWnd ();
if (pCMainWnd)
{
// Get a pointer to the graphic view pane
CGraphicView *pCGraphicView = (CGraphicView *)pCMainWnd->GetPane (0, 1);
if (pCGraphicView)
{
pCGraphicView->SetAnimationSpeed (((float)m_iInitialPercent) / (100.00F));
}
}
// Allow the base class to process this message
CDialog::OnHScroll (nSBCode, nPos, pScrollBar);
return ;
}
//////////////////////////////////////////////////////////////
//
// OnDestroy
//
void
CAnimationSpeed::OnDestroy (void)
{
m_iInitialPercent = m_speedSlider.GetPos ();
CDialog::OnDestroy();
return ;
}
//////////////////////////////////////////////////////////////
//
// OnBlend
//
void
CAnimationSpeed::OnBlend (void)
{
// Get a pointer to the doc so we can get at the current scene
// pointer.
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
// Turn on/off the blending option
pCDoc->SetAnimationBlend (SendDlgItemMessage (IDC_BLEND, BM_GETCHECK));
}
return ;
}
void CAnimationSpeed::
OnCompressq(){
/* CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if(pCDoc){
bool b_was_compressed = pCDoc->GetChannelQCompression();
bool b_compress = IsDlgButtonChecked(IDC_COMPRESSQ) == BST_CHECKED;
pCDoc->SetChannelQCompression(b_compress);
//Enable/Disable
if(b_compress){
GetDlgItem(IDC_16BIT)->EnableWindow(TRUE);
GetDlgItem(IDC_8BIT)->EnableWindow(TRUE);
}else{
GetDlgItem(IDC_16BIT)->EnableWindow(FALSE);
GetDlgItem(IDC_8BIT)->EnableWindow(FALSE);
}
//Update
if(b_compress != b_was_compressed){
int n_bytes = pCDoc->GetChannelQnBytes();
CompressQ = b_compress;
QnBytes = n_bytes;
}
}
*/
}
void CAnimationSpeed::
On16bit(){
/*
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
pCDoc->SetChannelQnBytes(2);
QnBytes = 2;
*/
}
void CAnimationSpeed::
On8bit(){
/*
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
pCDoc->SetChannelQnBytes(1);
QnBytes = 1;
*/
}

View File

@@ -0,0 +1,73 @@
/*
** 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/>.
*/
#if !defined(AFX_ANIMATIONSPEED_H__D60CC3CD_5F94_11D2_9FC7_00104B791122__INCLUDED_)
#define AFX_ANIMATIONSPEED_H__D60CC3CD_5F94_11D2_9FC7_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// AnimationSpeed.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CAnimationSpeed dialog
class CAnimationSpeed : public CDialog
{
// Construction
public:
CAnimationSpeed(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CAnimationSpeed)
enum { IDD = IDD_DISPLAYSPEED };
CSliderCtrl m_speedSlider;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAnimationSpeed)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CAnimationSpeed)
virtual BOOL OnInitDialog();
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnDestroy();
afx_msg void OnBlend();
afx_msg void OnCompressq();
afx_msg void On16bit();
afx_msg void On8bit();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
int m_iInitialPercent;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_ANIMATIONSPEED_H__D60CC3CD_5F94_11D2_9FC7_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,81 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : W3DView *
* *
* $Archive:: /Commando/Code/Tools/W3DView/AssetInfo.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 2/25/00 4:16p $*
* *
* $Revision:: 4 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "StdAfx.H"
#include "AssetInfo.H"
//#include "HModel.H"
#include "AssetMgr.H"
#include "HTree.H"
/////////////////////////////////////////////////////////////////
//
// Initialize
//
void
AssetInfoClass::Initialize (void)
{
// If this isn't a material, then try to get its hierarchy name (if there is one)
if (m_AssetType != TypeMaterial) {
// Assume we are wrapping an instance as apposed to an asset 'name'.
RenderObjClass *prender_obj = m_pRenderObj;
SAFE_ADD_REF (prender_obj);
// If we are wrapping an asset name, then create an instance of it.
if (prender_obj == NULL) {
prender_obj = WW3DAssetManager::Get_Instance()->Create_Render_Obj (m_Name);
}
if (prender_obj != NULL) {
// Get the hierarchy tree for this object (if one exists)
const HTreeClass *phtree = prender_obj->Get_HTree ();
if (phtree) {
// Get the name of the hierarchy tree
m_HierarchyName = phtree->Get_Name ();
}
}
// Release our hold on the temporary object
MEMBER_RELEASE (prender_obj);
}
return ;
}

View File

@@ -0,0 +1,133 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : W3DView *
* *
* $Archive:: /Commando/Code/Tools/W3DView/AssetInfo.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 3/09/99 2:50p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __ASSET_INFO_H
#define __ASSET_INFO_H
#include "RendObj.H"
#include "Utils.H"
#include "AssetTypes.H"
/////////////////////////////////////////////////////////////////////////////
//
// AssetInfoClass
//
// Class used by the data tree to identify each individual
// entry in the tree.
//
class AssetInfoClass
{
public:
//////////////////////////////////////////////////////////////
//
// Public constructors/destructors
//
AssetInfoClass (void)
: m_AssetType (TypeUnknown),
m_dwUserData (0L),
m_pRenderObj (NULL) { Initialize (); }
AssetInfoClass (LPCTSTR passet_name, ASSET_TYPE type, RenderObjClass *prender_obj = NULL, DWORD user_data = 0L)
: m_Name (passet_name),
m_AssetType (type),
m_dwUserData (user_data),
m_pRenderObj (NULL) { MEMBER_ADD (m_pRenderObj, prender_obj); Initialize (); }
virtual ~AssetInfoClass (void) { MEMBER_RELEASE (m_pRenderObj); }
//////////////////////////////////////////////////////////////
//
// Public methods
//
//
// Inline accessors
//
const CString & Get_Name (void) const { return m_Name; }
const CString & Get_Hierarchy_Name (void) const { return m_HierarchyName; }
const CString & Get_Original_Name (void) const { return m_OriginalName; }
ASSET_TYPE Get_Type (void) const { return m_AssetType; }
DWORD Get_User_Number (void) const { return m_dwUserData; }
const CString & Get_User_String (void) const { return m_UserString; }
RenderObjClass * Get_Render_Obj (void) const { SAFE_ADD_REF (m_pRenderObj); return m_pRenderObj; }
RenderObjClass * Peek_Render_Obj (void) const { return m_pRenderObj; }
void Set_Name (LPCTSTR pname) { m_Name = pname; }
void Set_Hierarchy_Name (LPCTSTR pname) { m_HierarchyName = pname; }
void Set_Type (ASSET_TYPE type) { m_AssetType = type; }
void Set_User_Number (DWORD user_data) { m_dwUserData = user_data; }
void Set_User_String (LPCTSTR string) { m_UserString = string; }
void Set_Render_Obj (RenderObjClass *pobj) { MEMBER_ADD (m_pRenderObj, pobj); }
//
// Information methods
//
bool Can_Asset_Have_Animations (void) const { return bool(m_HierarchyName.GetLength () > 0); }
protected:
//////////////////////////////////////////////////////////////
//
// Protected methods
//
void Initialize (void);
private:
//////////////////////////////////////////////////////////////
//
// Private member data
//
CString m_Name;
CString m_HierarchyName;
CString m_UserString;
CString m_OriginalName;
ASSET_TYPE m_AssetType;
DWORD m_dwUserData;
RenderObjClass * m_pRenderObj;
};
#endif //__ASSET_INFO_H

View File

@@ -0,0 +1,76 @@
/*
** 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/>.
*/
// AssetPropertySheet.cpp : implementation file
//
#include "stdafx.h"
#include "W3DView.h"
#include "AssetPropertySheet.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAssetPropertySheet
IMPLEMENT_DYNAMIC(CAssetPropertySheet, CPropertySheet)
//////////////////////////////////////////////////////////////////////////
//
// CAssetPropertySheet
//
CAssetPropertySheet::CAssetPropertySheet
(
int iCaptionID,
CPropertyPage *pCPropertyPage,
CWnd *pCParentWnd
)
: m_pCPropertyPage (pCPropertyPage),
CPropertySheet (iCaptionID, pCParentWnd)
{
ASSERT (m_pCPropertyPage);
m_psh.dwFlags |= PSH_NOAPPLYNOW;
// Add this page to the property sheet
AddPage (m_pCPropertyPage);
return ;
}
//////////////////////////////////////////////////////////////////////////
//
// :~CAssetPropertySheet
//
CAssetPropertySheet::~CAssetPropertySheet ()
{
return ;
}
BEGIN_MESSAGE_MAP(CAssetPropertySheet, CPropertySheet)
//{{AFX_MSG_MAP(CAssetPropertySheet)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAssetPropertySheet message handlers

View File

@@ -0,0 +1,74 @@
/*
** 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/>.
*/
#if !defined(AFX_ASSETPROPERTYSHEET_H__FB40246D_5DFB_11D2_9FC7_00104B791122__INCLUDED_)
#define AFX_ASSETPROPERTYSHEET_H__FB40246D_5DFB_11D2_9FC7_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// AssetPropertySheet.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CAssetPropertySheet
class CAssetPropertySheet : public CPropertySheet
{
DECLARE_DYNAMIC(CAssetPropertySheet)
// Construction
public:
CAssetPropertySheet (int iCaptionID, CPropertyPage *pCPropertyPage, CWnd *pCParentWnd = NULL);
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAssetPropertySheet)
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CAssetPropertySheet();
// Generated message map functions
protected:
//{{AFX_MSG(CAssetPropertySheet)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
// Private constructors (shouldn't be called)
CAssetPropertySheet(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0) {}
CAssetPropertySheet(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0) {}
CPropertyPage *m_pCPropertyPage;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_ASSETPROPERTYSHEET_H__FB40246D_5DFB_11D2_9FC7_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,64 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : W3DView *
* *
* $Archive:: /Commando/Code/Tools/W3DView/AssetTypes.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 10/11/00 9:36a $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __ASSET_TYPES_H
#define __ASSET_TYPES_H
typedef enum
{
TypeUnknown = -1,
TypeMaterial = 0,
TypeMesh,
TypeHierarchy,
TypeAggregate,
TypeLOD,
TypeAnimation,
TypeCollection,
TypeEmitter,
TypeCompressedAnimation,
TypePrimitives,
TypeSound
} ASSET_TYPE;
#endif //__ASSET_TYPES_H

View File

@@ -0,0 +1,160 @@
/*
** 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/>.
*/
// BackgroundBMPDialog.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "BackgroundBMPDialog.h"
#include "W3DViewDoc.H"
#include "Utils.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CBackgroundBMPDialog dialog
/////////////////////////////////////////////////////////////
//
// CBackgroundBMPDialog
//
CBackgroundBMPDialog::CBackgroundBMPDialog (CWnd* pParent /*=NULL*/)
: CDialog(CBackgroundBMPDialog::IDD, pParent)
{
//{{AFX_DATA_INIT(CBackgroundBMPDialog)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
/////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
CBackgroundBMPDialog::DoDataExchange (CDataExchange* pDX)
{
// Allow the base class to process this message
CDialog::DoDataExchange (pDX);
//{{AFX_DATA_MAP(CBackgroundBMPDialog)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(CBackgroundBMPDialog, CDialog)
//{{AFX_MSG_MAP(CBackgroundBMPDialog)
ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBackgroundBMPDialog message handlers
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
CBackgroundBMPDialog::OnInitDialog (void)
{
// Allow the base class to process this message
CDialog::OnInitDialog ();
// Center the dialog around the data tree view instead
// of the direct center of the screen
::CenterDialogAroundTreeView (m_hWnd);
// Gett a pointer to the current document
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
// Set the initial filename in the edit control
SetDlgItemText (IDC_FILENAME_EDIT, pCDoc->GetBackgroundBMP ());
}
return TRUE;
}
/////////////////////////////////////////////////////////////
//
// OnOK
//
void
CBackgroundBMPDialog::OnOK (void)
{
// Gett a pointer to the current document
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
CString stringBackgroundBMPName;
// Get the filename the user entered
if (GetDlgItemText (IDC_FILENAME_EDIT, stringBackgroundBMPName) > 0)
{
// Ask the doc to create a new background from this BMP
pCDoc->SetBackgroundBMP (stringBackgroundBMPName);
}
else
{
// Ask the doc to clear any existing background BMP
pCDoc->SetBackgroundBMP (NULL);
}
}
// Allow the base class to process this message
CDialog::OnOK ();
return ;
}
/////////////////////////////////////////////////////////////
//
// OnBrowse
//
void
CBackgroundBMPDialog::OnBrowse (void)
{
// Get a pointer to the current document
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
CFileDialog openFileDialog (TRUE,
".tga",
pCDoc->GetBackgroundBMP (),
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
"Targa files (*.tga)|*.tga||",
this);
// Ask the user what Targa file they wish to load
if (openFileDialog.DoModal () == IDOK)
{
// Set the text of the filename edit control
SetDlgItemText (IDC_FILENAME_EDIT, openFileDialog.GetPathName ());
}
}
return ;
}

View File

@@ -0,0 +1,66 @@
/*
** 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/>.
*/
#if !defined(AFX_BACKGROUNDBMPDIALOG_H__5D8C201B_6380_11D2_9FC7_00104B791122__INCLUDED_)
#define AFX_BACKGROUNDBMPDIALOG_H__5D8C201B_6380_11D2_9FC7_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// BackgroundBMPDialog.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CBackgroundBMPDialog dialog
class CBackgroundBMPDialog : public CDialog
{
// Construction
public:
CBackgroundBMPDialog(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CBackgroundBMPDialog)
enum { IDD = IDD_BACKGROUND_BMP };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CBackgroundBMPDialog)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CBackgroundBMPDialog)
virtual BOOL OnInitDialog();
virtual void OnOK();
afx_msg void OnBrowse();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_BACKGROUNDBMPDIALOG_H__5D8C201B_6380_11D2_9FC7_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,250 @@
/*
** 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/>.
*/
// BackgroundColorDialog.cpp : implementation file
//
#include "stdafx.h"
#include "W3DView.h"
#include "BackgroundColorDialog.h"
#include "MainFrm.H"
#include "W3DViewDoc.H"
#include "Utils.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CBackgroundColorDialog dialog
CBackgroundColorDialog::CBackgroundColorDialog(CWnd* pParent /*=NULL*/)
: CDialog(CBackgroundColorDialog::IDD, pParent)
{
//{{AFX_DATA_INIT(CBackgroundColorDialog)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CBackgroundColorDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CBackgroundColorDialog)
DDX_Control(pDX, IDC_SLIDER_BLUE, m_blueSlider);
DDX_Control(pDX, IDC_SLIDER_GREEN, m_greenSlider);
DDX_Control(pDX, IDC_SLIDER_RED, m_redSlider);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CBackgroundColorDialog, CDialog)
//{{AFX_MSG_MAP(CBackgroundColorDialog)
ON_WM_HSCROLL()
ON_BN_CLICKED(IDC_GRAYSCALE_CHECK, OnGrayscaleCheck)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBackgroundColorDialog message handlers
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
CBackgroundColorDialog::OnInitDialog (void)
{
// Allow the base class to process this message
CDialog::OnInitDialog ();
// Center the dialog around the data tree view instead
// of the direct center of the screen
::CenterDialogAroundTreeView (m_hWnd);
m_redSlider.SetRange (0, 100);
m_greenSlider.SetRange (0, 100);
m_blueSlider.SetRange (0, 100);
// Get a pointer to the doc so we can get at the current
// background color
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
// Get the background color from the document
Vector3 colorSettings = pCDoc->GetBackgroundColor ();
// Remember these initial settings so we can restore them
// if the user cancels
m_initialRed = int(colorSettings.X * 100.00F);
m_initialGreen = int(colorSettings.Y * 100.00F);
m_initialBlue = int(colorSettings.Z * 100.00F);
}
if ((m_initialRed == m_initialGreen) &&
(m_initialRed == m_initialBlue))
{
// Check the grayscale checkbox
SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_SETCHECK, (WPARAM)TRUE);
}
// Set the initial slider position
m_redSlider.SetPos (m_initialRed);
m_greenSlider.SetPos (m_initialGreen);
m_blueSlider.SetPos (m_initialBlue);
return TRUE;
}
//////////////////////////////////////////////////////////////
//
// OnHScroll
//
void
CBackgroundColorDialog::OnHScroll
(
UINT nSBCode,
UINT nPos,
CScrollBar* pScrollBar
)
{
if (SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_GETCHECK))
{
int iCurrentPos = 0;
if (pScrollBar == GetDlgItem (IDC_SLIDER_RED))
{
iCurrentPos = m_redSlider.GetPos ();
}
else if (pScrollBar == GetDlgItem (IDC_SLIDER_GREEN))
{
iCurrentPos = m_greenSlider.GetPos ();
}
else
{
iCurrentPos = m_blueSlider.GetPos ();
}
// Make all the sliders the same pos
m_redSlider.SetPos (iCurrentPos);
m_greenSlider.SetPos (iCurrentPos);
m_blueSlider.SetPos (iCurrentPos);
}
Vector3 colorSettings;
colorSettings.X = float(m_redSlider.GetPos ()) / 100.00F;
colorSettings.Y = float(m_greenSlider.GetPos ()) / 100.00F;
colorSettings.Z = float(m_blueSlider.GetPos ()) / 100.00F;
// Get a pointer to the document so we can change the current
// background color
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
// Modify the ambient light for this scene
pCDoc->SetBackgroundColor (colorSettings);
}
// Allow the base class to process this message
CDialog::OnHScroll (nSBCode, nPos, pScrollBar);
return ;
}
//////////////////////////////////////////////////////////////
//
// OnGrayscaleCheck
//
void
CBackgroundColorDialog::OnGrayscaleCheck (void)
{
if (SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_GETCHECK))
{
// Make the green and blue sliders the same as red
m_greenSlider.SetPos (m_redSlider.GetPos ());
m_blueSlider.SetPos (m_redSlider.GetPos ());
Vector3 colorSettings;
colorSettings.X = float(m_redSlider.GetPos ()) / 100.00F;
colorSettings.Y = float(m_greenSlider.GetPos ()) / 100.00F;
colorSettings.Z = float(m_blueSlider.GetPos ()) / 100.00F;
// Get a pointer to the document so we can change the background
// color
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
// Modify the current background color
pCDoc->SetBackgroundColor (colorSettings);
}
}
return ;
}
//////////////////////////////////////////////////////////////
//
// OnCancel
//
void
CBackgroundColorDialog::OnCancel (void)
{
Vector3 colorSettings;
colorSettings.X = float(m_initialRed) / 100.00F;
colorSettings.Y = float(m_initialGreen) / 100.00F;
colorSettings.Z = float(m_initialBlue) / 100.00F;
// Get a pointer to the document so we can change the
// background color
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
// Restore the current background color
pCDoc->SetBackgroundColor (colorSettings);
}
// Allow the base class to process this message
CDialog::OnCancel();
return ;
}
//////////////////////////////////////////////////////////////
//
// WindowProc
//
LRESULT
CBackgroundColorDialog::WindowProc
(
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
if (message == WM_PAINT)
{
// Paint the gradients for each color
::Paint_Gradient (::GetDlgItem (m_hWnd, IDC_RED_GRADIENT), 1, 0, 0);
::Paint_Gradient (::GetDlgItem (m_hWnd, IDC_GREEN_GRADIENT), 0, 1, 0);
::Paint_Gradient (::GetDlgItem (m_hWnd, IDC_BLUE_GRADIENT), 0, 0, 1);
}
// Allow the base class to process this message
return CDialog::WindowProc (message, wParam, lParam);
}

View File

@@ -0,0 +1,75 @@
/*
** 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/>.
*/
#if !defined(AFX_BACKGROUNDCOLORDIALOG_H__AF3CDE8C_61EC_11D2_9FC7_00104B791122__INCLUDED_)
#define AFX_BACKGROUNDCOLORDIALOG_H__AF3CDE8C_61EC_11D2_9FC7_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// BackgroundColorDialog.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CBackgroundColorDialog dialog
class CBackgroundColorDialog : public CDialog
{
// Construction
public:
CBackgroundColorDialog(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CBackgroundColorDialog)
enum { IDD = IDD_BACKGROUND_COLOR };
CSliderCtrl m_blueSlider;
CSliderCtrl m_greenSlider;
CSliderCtrl m_redSlider;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CBackgroundColorDialog)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CBackgroundColorDialog)
virtual BOOL OnInitDialog();
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnGrayscaleCheck();
virtual void OnCancel();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
int m_initialRed;
int m_initialGreen;
int m_initialBlue;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_BACKGROUNDCOLORDIALOG_H__AF3CDE8C_61EC_11D2_9FC7_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,240 @@
/*
** 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/>.
*/
// BackgroundObjectDialog.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "BackgroundObjectDialog.h"
#include "AssetMgr.H"
#include "Utils.H"
#include "W3DViewDoc.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////
//
// CBackgroundObjectDialog
//
CBackgroundObjectDialog::CBackgroundObjectDialog (CWnd* pParent /*=NULL*/)
: CDialog(CBackgroundObjectDialog::IDD, pParent)
{
//{{AFX_DATA_INIT(CBackgroundObjectDialog)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
/////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
CBackgroundObjectDialog::DoDataExchange (CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CBackgroundObjectDialog)
DDX_Control(pDX, IDC_HIERARCHY_LIST, m_heirarchyListCtrl);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(CBackgroundObjectDialog, CDialog)
//{{AFX_MSG_MAP(CBackgroundObjectDialog)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_HIERARCHY_LIST, OnItemChangedHierarchyList)
ON_BN_CLICKED(IDC_CLEAR, OnClear)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBackgroundObjectDialog message handlers
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
CBackgroundObjectDialog::OnInitDialog (void)
{
// Allow the base class to process this message
CDialog::OnInitDialog ();
// Center the dialog around the data tree view instead
// of the direct center of the screen
::CenterDialogAroundTreeView (m_hWnd);
m_heirarchyListCtrl.InsertColumn (0, "Name");
//m_heirarchyListCtrl.InsertColumn (1, "Subobjects");
// Get an iterator from the asset manager that we can
// use to enumerate the currently loaded assets
RenderObjIterator *pObjEnum = WW3DAssetManager::Get_Instance()->Create_Render_Obj_Iterator ();
ASSERT (pObjEnum);
if (pObjEnum)
{
// Loop through all the assets in the manager
for (pObjEnum->First ();
pObjEnum->Is_Done () == FALSE;
pObjEnum->Next ())
{
LPCTSTR pszItemName = pObjEnum->Current_Item_Name ();
// Is this a hierarchy?
if (WW3DAssetManager::Get_Instance()->Render_Obj_Exists (pszItemName) &&
(pObjEnum->Current_Item_Class_ID () == RenderObjClass::CLASSID_HMODEL))
{
// Add this hierarchy to the list
m_heirarchyListCtrl.InsertItem (0, pszItemName);
}
}
// Free the enumerator object we created earlier
delete pObjEnum;
pObjEnum = NULL;
}
// Get a pointer to the doc
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
// Get the name of the current background object
CString stringCurrObject = pCDoc->GetBackgroundObjectName ();
LV_FINDINFO findInfo = { 0 };
findInfo.flags = LVFI_STRING;
findInfo.psz = (LPCTSTR)stringCurrObject;
// Attempt to find this item in the list control
int iIndex = m_heirarchyListCtrl.FindItem (&findInfo);
if (iIndex != -1)
{
// Select the item in the list control
m_heirarchyListCtrl.SetItemState (iIndex, LVNI_SELECTED, LVNI_SELECTED);
SetDlgItemText (IDC_CURR_OBJ, m_heirarchyListCtrl.GetItemText (iIndex, 0));
}
else
{
// Select the first item in the list control
m_heirarchyListCtrl.SetItemState (0, LVNI_SELECTED, LVNI_SELECTED);
SetDlgItemText (IDC_CURR_OBJ, m_heirarchyListCtrl.GetItemText (0, 0));
}
}
// Size the columns so they are large enough to display their contents
m_heirarchyListCtrl.SetColumnWidth (0, LVSCW_AUTOSIZE);
//m_heirarchyListCtrl.SetColumnWidth (1, LVSCW_AUTOSIZE_USEHEADER);
return TRUE;
}
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
void
CBackgroundObjectDialog::OnOK (void)
{
// Get a pointer to the doc
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
// Get the index of the currently selected item.
int iIndex = m_heirarchyListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
if (iIndex != -1)
{
// Get the name of the item from the list control
CString stringItemName = m_heirarchyListCtrl.GetItemText (iIndex, 0);
// Ask the doc to load the background object and display it
pCDoc->SetBackgroundObject (stringItemName);
}
else
{
// Ask the doc to clear the background object
pCDoc->SetBackgroundObject (NULL);
}
// Allow the base class to process this message
CDialog::OnOK ();
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnItemChangedHierarchyList
//
void
CBackgroundObjectDialog::OnItemChangedHierarchyList
(
NMHDR* pNMHDR,
LRESULT* pResult
)
{
// Did the 'state' of the entry change?
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if (pNMListView &&
(pNMListView->uChanged & LVIF_STATE) == LVIF_STATE)
{
// Is the new state a selected state?
if ((pNMListView->uNewState & LVIS_SELECTED) != LVIS_SELECTED)
{
// Is there a selected item in the list control?
if (m_heirarchyListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED) == -1)
{
// Clear the text of the current object static text control
SetDlgItemText (IDC_CURR_OBJ, "");
}
}
else
{
// Set the text of the current object static text control
SetDlgItemText (IDC_CURR_OBJ, m_heirarchyListCtrl.GetItemText (pNMListView->iItem, 0));
}
}
*pResult = 0;
return ;
}
/////////////////////////////////////////////////////////////
//
// OnClear
//
void
CBackgroundObjectDialog::OnClear (void)
{
// Get the current selection (if any)
int iIndex = m_heirarchyListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
if (iIndex != -1)
{
// Clear the selection state from this entry
m_heirarchyListCtrl.SetItemState (iIndex, 0, LVIS_SELECTED);
}
return ;
}

View File

@@ -0,0 +1,67 @@
/*
** 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/>.
*/
#if !defined(AFX_BACKGROUNDOBJECTDIALOG_H__9B07DA63_62B6_11D2_9FC7_00104B791122__INCLUDED_)
#define AFX_BACKGROUNDOBJECTDIALOG_H__9B07DA63_62B6_11D2_9FC7_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// BackgroundObjectDialog.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CBackgroundObjectDialog dialog
class CBackgroundObjectDialog : public CDialog
{
// Construction
public:
CBackgroundObjectDialog(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CBackgroundObjectDialog)
enum { IDD = IDD_BACKGROUND_OBJECT };
CListCtrl m_heirarchyListCtrl;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CBackgroundObjectDialog)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CBackgroundObjectDialog)
virtual BOOL OnInitDialog();
virtual void OnOK();
afx_msg void OnItemChangedHierarchyList(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnClear();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_BACKGROUNDOBJECTDIALOG_H__9B07DA63_62B6_11D2_9FC7_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,539 @@
/*
** 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/>.
*/
// BoneMgrDialog.cpp : implementation file
//
#include "StdAfx.H"
#include "W3DView.H"
#include "BoneMgrDialog.H"
#include "HTree.H"
#include "AssetMgr.H"
#include "Utils.H"
#include "MainFrm.H"
#include "W3DViewDoc.H"
#include "DataTreeView.H"
//#include "HModel.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
///////////////////////////////////////////////////////////////
//
// BoneMgrDialogClass
//
BoneMgrDialogClass::BoneMgrDialogClass
(
RenderObjClass *prender_obj,
CWnd *pparent
)
: m_pBaseModel (prender_obj),
m_pBackupModel (NULL),
m_bAttach (true),
CDialog (BoneMgrDialogClass::IDD, pparent)
{
//{{AFX_DATA_INIT(BoneMgrDialogClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
///////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
BoneMgrDialogClass::DoDataExchange (CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(BoneMgrDialogClass)
DDX_Control(pDX, IDC_OBJECT_COMBO, m_ObjectCombo);
DDX_Control(pDX, IDC_BONE_TREE, m_BoneTree);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(BoneMgrDialogClass, CDialog)
//{{AFX_MSG_MAP(BoneMgrDialogClass)
ON_NOTIFY(TVN_SELCHANGED, IDC_BONE_TREE, OnSelchangedBoneTree)
ON_CBN_SELCHANGE(IDC_OBJECT_COMBO, OnSelchangeObjectCombo)
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_ATTACH_BUTTON, OnAttachButton)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
BoneMgrDialogClass::OnInitDialog (void)
{
// Allow the base class to process this message
CDialog::OnInitDialog ();
// Make a backup of this hierarchy in case we need to restore it.
m_pBackupModel = m_pBaseModel->Clone ();
// Create an icon imagelist for the tree control
CImageList *pimagelist = new CImageList;
pimagelist->Create (16, 16, ILC_COLOR | ILC_MASK, 2, 2);
// Load this icon and add it to our imagelist
pimagelist->Add ((HICON)::LoadImage (::AfxGetResourceHandle (),
MAKEINTRESOURCE (IDI_FOLDER),
IMAGE_ICON,
16,
16,
LR_SHARED));
pimagelist->Add ((HICON)::LoadImage (::AfxGetResourceHandle (),
MAKEINTRESOURCE (IDI_OBJECT),
IMAGE_ICON,
16,
16,
LR_SHARED));
m_BoneTree.SetImageList (pimagelist, TVSIL_NORMAL);
// Get the hierarchy tree for this model so we can enumerate bone's
// and subobjects.
HTREEITEM hfirst_item = NULL;
// Loop through all the bones in this model
int bone_count = m_pBaseModel->Get_Num_Bones ();
for (int index = 0; index < bone_count; index ++) {
const char *pbone_name = m_pBaseModel->Get_Bone_Name (index);
// Add this bone to the tree control
HTREEITEM hbone_item = m_BoneTree.InsertItem (pbone_name, 0, 0);
Fill_Bone_Item (hbone_item, index);
// Is this the first item we've added to the tree?
if (hfirst_item == NULL) {
hfirst_item = hbone_item;
}
}
//
// Sort the tree control
//
m_BoneTree.SortChildren (TVI_ROOT);
// Build a list of all the render objects currently loaded
CW3DViewDoc *pdoc = (CW3DViewDoc *)((CMainFrame *)::AfxGetMainWnd())->GetActiveDocument ();
CDataTreeView *pdata_tree = pdoc->GetDataTreeView ();
DynamicVectorClass <CString> asset_list;
pdata_tree->Build_Render_Object_List (asset_list);
// Add this render object list to the combobox
for (index = 0; index < asset_list.Count (); index ++) {
m_ObjectCombo.AddString (asset_list[index]);
}
// Select the first entry in the combobox
m_ObjectCombo.SetCurSel (0);
OnSelchangeObjectCombo ();
// Select the first item in the tree
m_BoneTree.SelectItem (hfirst_item);
return TRUE;
}
///////////////////////////////////////////////////////////////
//
// Fill_Bone_Item
//
void
BoneMgrDialogClass::Fill_Bone_Item
(
HTREEITEM hbone_item,
int bone_index
)
{
// Create a new instance of the hmodel which we can use
// to compare with the supplied hmodel and determine
// which 'bones-models' are new.
const char *orig_model_name = m_pBaseModel->Get_Base_Model_Name ();
orig_model_name = (orig_model_name == NULL) ? m_pBaseModel->Get_Name () : orig_model_name;
RenderObjClass *porig_model = WW3DAssetManager::Get_Instance()->Create_Render_Obj (orig_model_name);
// Build a list of nodes that are contained in the vanilla model
DynamicVectorClass <RenderObjClass *> orig_node_list;
for (int index = 0;
index < porig_model->Get_Num_Sub_Objects_On_Bone (bone_index);
index ++) {
RenderObjClass *psubobj = porig_model->Get_Sub_Object_On_Bone (index, bone_index);
if (psubobj != NULL) {
orig_node_list.Add (psubobj);
}
}
// Build a list of nodes that are contained in this bone
DynamicVectorClass <RenderObjClass *> node_list;
for (index = 0;
index < m_pBaseModel->Get_Num_Sub_Objects_On_Bone (bone_index);
index ++) {
RenderObjClass *psubobj = m_pBaseModel->Get_Sub_Object_On_Bone (index, bone_index);
if (psubobj != NULL) {
node_list.Add (psubobj);
}
}
if (node_list.Count () > 0) {
// Add the subobjects to the tree control
for (int node_index = 0; node_index < node_list.Count (); node_index ++) {
RenderObjClass *psubobject = node_list[node_index];
ASSERT (psubobject != NULL);
// Is this subobject new? (i.e. not in a 'vanilla' instance?)
if (psubobject != NULL &&
(Is_Object_In_List (psubobject->Get_Name (), orig_node_list) == false)) {
m_BoneTree.InsertItem (psubobject->Get_Name (), 1, 1, hbone_item);
}
}
}
// Free our hold on the render objs in the original node list
for (index = 0; index < orig_node_list.Count (); index ++) {
MEMBER_RELEASE (orig_node_list[index]);
}
// Free our hold on the render objs in the node list
for (index = 0; index < node_list.Count (); index ++) {
MEMBER_RELEASE (node_list[index]);
}
MEMBER_RELEASE (porig_model);
return ;
}
///////////////////////////////////////////////////////////////////////////////////
//
// Is_Object_In_List
//
bool
BoneMgrDialogClass::Is_Object_In_List
(
const char *passet_name,
DynamicVectorClass <RenderObjClass *> &node_list
)
{
// Assume failure
bool retval = false;
// Loop through the nodes in the list until we've found the one
// were are looking for.
for (int node_index = 0; (node_index < node_list.Count ()) && (retval == false); node_index ++) {
RenderObjClass *prender_obj = node_list[node_index];
// Is this the render object we were looking for?
if (prender_obj != NULL &&
::lstrcmpi (prender_obj->Get_Name (), passet_name) == 0) {
retval = true;
}
}
// Return the true/false result code
return retval;
}
///////////////////////////////////////////////////////////////////////////////////
//
// OnSelchangedBoneTree
//
void
BoneMgrDialogClass::OnSelchangedBoneTree
(
NMHDR *pNMHDR,
LRESULT *pResult
)
{
// Make the dialog controls reflect the new selection
NM_TREEVIEW *pNMTreeView = (NM_TREEVIEW *)pNMHDR;
Update_Controls (pNMTreeView->itemNew.hItem);
(*pResult) = 0;
return ;
}
///////////////////////////////////////////////////////////////////////////////////
//
// OnSelchangeObjectCombo
//
void
BoneMgrDialogClass::OnSelchangeObjectCombo (void)
{
// Get the name of the currently selected render object
CString name;
int index = m_ObjectCombo.GetCurSel ();
m_ObjectCombo.GetLBText (index, name);
// Change the text of the 'Attach' button based on whether or not
// this render object is already attached to the current bone.
if (Is_Render_Obj_Already_Attached (name)) {
SetDlgItemText (IDC_ATTACH_BUTTON, "&Remove");
m_bAttach = false;
} else {
SetDlgItemText (IDC_ATTACH_BUTTON, "&Attach");
m_bAttach = true;
}
return ;
}
///////////////////////////////////////////////////////////////////////////////////
//
// Is_Render_Obj_Already_Attached
//
bool
BoneMgrDialogClass::Is_Render_Obj_Already_Attached (const CString &name)
{
// Assume not already attached
bool retval = false;
HTREEITEM htree_item = m_BoneTree.GetSelectedItem ();
HTREEITEM hparent_item = m_BoneTree.GetParentItem (htree_item);
htree_item = (hparent_item != NULL) ? hparent_item : htree_item;
if (htree_item != NULL) {
// Loop through all the children of this bone
for (HTREEITEM hchild_item = m_BoneTree.GetChildItem (htree_item);
(hchild_item != NULL) && (retval == false);
hchild_item = m_BoneTree.GetNextSiblingItem (hchild_item)) {
// Is this the render object we were looking for?
CString child_name = m_BoneTree.GetItemText (hchild_item);
if (name.CompareNoCase (child_name) == 0) {
retval = true;
}
}
}
// Return the true/false result code
return retval;
}
///////////////////////////////////////////////////////////////////////////////////
//
// Update_Controls
//
void
BoneMgrDialogClass::Update_Controls (HTREEITEM selected_item)
{
// Get the name of the currently selected item
CString name = m_BoneTree.GetItemText (selected_item);
bool bis_bone = (m_BoneTree.GetParentItem (selected_item) == NULL);
// Did the user select a bone name?
if (bis_bone) {
m_BoneName = name;
} else {
// Select this render object in the combobox
int index = m_ObjectCombo.FindStringExact (-1, name);
m_ObjectCombo.SetCurSel ((index != CB_ERR) ? index : 0);
// The bone name is the name of the parent item of the selected item.
m_BoneName = m_BoneTree.GetItemText (m_BoneTree.GetParentItem (selected_item));
}
OnSelchangeObjectCombo ();
// Change the text of the group box to reflect the bone name
CString text;
text.Format ("Bone: %s", m_BoneName);
SetDlgItemText (IDC_BONE_GROUPBOX, text);
return ;
}
///////////////////////////////////////////////////////////////////////////////////
//
// OnDestroy
//
void
BoneMgrDialogClass::OnDestroy (void)
{
// Free the state image list we associated with the control
CImageList *pimagelist = m_BoneTree.GetImageList (TVSIL_NORMAL);
m_BoneTree.SetImageList (NULL, TVSIL_NORMAL);
SAFE_DELETE (pimagelist);
// Allow the base class to process this message
CDialog::OnDestroy ();
return ;
}
///////////////////////////////////////////////////////////////////////////////////
//
// OnOK
//
void
BoneMgrDialogClass::OnOK (void)
{
// Simply forget about the backup we made
MEMBER_RELEASE (m_pBackupModel);
// Update the hierarchy's cached information to reflect the new settings
CW3DViewDoc *pdoc = (CW3DViewDoc *)((CMainFrame *)::AfxGetMainWnd())->GetActiveDocument ();
pdoc->Update_Aggregate_Prototype (*m_pBaseModel);
// Allow the base class to process this message
CDialog::OnOK ();
return ;
}
///////////////////////////////////////////////////////////////////////////////////
//
// OnCancel
//
void
BoneMgrDialogClass::OnCancel (void)
{
CWaitCursor wait_cursor;
// Display the backup hierarchy
CW3DViewDoc *pdoc = (CW3DViewDoc *)((CMainFrame *)::AfxGetMainWnd())->GetActiveDocument ();
pdoc->DisplayObject (m_pBackupModel, false, false);
// Allow the base class to process this message
CDialog::OnCancel ();
return ;
}
///////////////////////////////////////////////////////////////////////////////////
//
// OnAttachButton
//
void
BoneMgrDialogClass::OnAttachButton (void)
{
// Get the name of the currently selected render object
CString name;
int index = m_ObjectCombo.GetCurSel ();
m_ObjectCombo.GetLBText (index, name);
// Lookup the currently selected bone item
HTREEITEM hbone_item = Get_Current_Bone_Item ();
// Should we attach or remove the render object?
if (m_bAttach) {
// Create an instance of the render object and attach it to the bone
RenderObjClass *prender_obj = WW3DAssetManager::Get_Instance()->Create_Render_Obj (name);
if (prender_obj != NULL) {
m_pBaseModel->Add_Sub_Object_To_Bone (prender_obj, m_BoneName);
m_BoneTree.InsertItem (name, 1, 1, hbone_item);
MEMBER_RELEASE (prender_obj);
}
} else {
// Loop through all the subobjects on the bone
bool found = false;
int bone_index = m_pBaseModel->Get_Bone_Index (m_BoneName);
int count = m_pBaseModel->Get_Num_Sub_Objects_On_Bone (bone_index);
for (int index = 0; (index < count) && !found; index ++) {
// Is this the subobject we were looking for?
RenderObjClass *psub_obj = m_pBaseModel->Get_Sub_Object_On_Bone (index, bone_index);
if ((psub_obj != NULL) &&
(::lstrcmpi (psub_obj->Get_Name (), name) == 0)) {
// Remove this subobject from the bone
m_pBaseModel->Remove_Sub_Object (psub_obj);
found = true;
}
// Release our hold on this pointer
MEMBER_RELEASE (psub_obj);
}
// Remove the object from our UI
Remove_Object_From_Bone (hbone_item, name);
}
// Refresh the UI state
m_BoneTree.InvalidateRect (NULL, TRUE);
m_BoneTree.UpdateWindow ();
Update_Controls (hbone_item);
return ;
}
///////////////////////////////////////////////////////////////////////////////////
//
// Get_Current_Bone_Item
//
HTREEITEM
BoneMgrDialogClass::Get_Current_Bone_Item (void)
{
// Get the currently selected item and its parent
HTREEITEM htree_item = m_BoneTree.GetSelectedItem ();
HTREEITEM hparent_item = m_BoneTree.GetParentItem (htree_item);
// Return the bone item
return (hparent_item != NULL) ? hparent_item : htree_item;
}
///////////////////////////////////////////////////////////////////////////////////
//
// Remove_Object_From_Bone
//
void
BoneMgrDialogClass::Remove_Object_From_Bone
(
HTREEITEM bone_item,
const CString &name
)
{
// Loop through all the children of this bone
for (HTREEITEM hchild_item = m_BoneTree.GetChildItem (bone_item);
(hchild_item != NULL);
hchild_item = m_BoneTree.GetNextSiblingItem (hchild_item)) {
// Is this the render object we were looking for?
CString child_name = m_BoneTree.GetItemText (hchild_item);
if (name.CompareNoCase (child_name) == 0) {
m_BoneTree.DeleteItem (hchild_item);
break ;
}
}
return ;
}

View File

@@ -0,0 +1,111 @@
/*
** 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/>.
*/
#if !defined(AFX_BONEMGRDIALOG_H__66DA0E58_BFCA_11D2_9FFA_00104B791122__INCLUDED_)
#define AFX_BONEMGRDIALOG_H__66DA0E58_BFCA_11D2_9FFA_00104B791122__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// BoneMgrDialog.h : header file
//
#include "Resource.H"
#include "Vector.H"
// Forward declarations
class HModelClass;
class RenderObjClass;
/////////////////////////////////////////////////////////////////////////////
//
// BoneMgrDialogClass
//
class BoneMgrDialogClass : public CDialog
{
// Construction
public:
BoneMgrDialogClass (RenderObjClass *prender_obj, CWnd* pParent = NULL);
// Dialog Data
//{{AFX_DATA(BoneMgrDialogClass)
enum { IDD = IDD_BONE_MANAGEMENT };
CComboBox m_ObjectCombo;
CTreeCtrl m_BoneTree;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(BoneMgrDialogClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(BoneMgrDialogClass)
virtual BOOL OnInitDialog();
afx_msg void OnSelchangedBoneTree(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnSelchangeObjectCombo();
afx_msg void OnDestroy();
virtual void OnOK();
virtual void OnCancel();
afx_msg void OnAttachButton();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
///////////////////////////////////////////////////////////////////
//
// Public methods
//
protected:
///////////////////////////////////////////////////////////////////
//
// Protected methods
//
void Fill_Bone_Item (HTREEITEM hbone_item, int bone_index);
bool Is_Object_In_List (const char *passet_name, DynamicVectorClass <RenderObjClass *> &node_list);
bool Is_Render_Obj_Already_Attached (const CString &name);
void Update_Controls (HTREEITEM selected_item);
HTREEITEM Get_Current_Bone_Item (void);
void Remove_Object_From_Bone (HTREEITEM bone_item, const CString &name);
private:
///////////////////////////////////////////////////////////////////
//
// Private member data
//
RenderObjClass * m_pBaseModel;
RenderObjClass * m_pBackupModel;
bool m_bAttach;
CString m_BoneName;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_BONEMGRDIALOG_H__66DA0E58_BFCA_11D2_9FFA_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,132 @@
/*
** 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/>.
*/
// CameraDistanceDialog.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "cameradistancedialog.h"
#include "utils.h"
#include "graphicview.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//
// CameraDistanceDialogClass
//
/////////////////////////////////////////////////////////////////////////////
CameraDistanceDialogClass::CameraDistanceDialogClass(CWnd* pParent /*=NULL*/)
: CDialog(CameraDistanceDialogClass::IDD, pParent)
{
//{{AFX_DATA_INIT(CameraDistanceDialogClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////////////////////
void
CameraDistanceDialogClass::DoDataExchange (CDataExchange *pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CameraDistanceDialogClass)
DDX_Control(pDX, IDC_DISTANCE_SPIN, m_DistanceSpinCtrl);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(CameraDistanceDialogClass, CDialog)
//{{AFX_MSG_MAP(CameraDistanceDialogClass)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL
CameraDistanceDialogClass::OnInitDialog (void)
{
CDialog::OnInitDialog ();
CGraphicView *graphic_view = ::Get_Graphic_View ();
::Initialize_Spinner (m_DistanceSpinCtrl, graphic_view->Get_Camera_Distance (), 0, 25000.0F);
::SetDlgItemFloat (m_hWnd, IDC_DISTANCE_EDIT, graphic_view->Get_Camera_Distance ());
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnOK
//
/////////////////////////////////////////////////////////////////////////////
void
CameraDistanceDialogClass::OnOK (void)
{
CDialog::OnOK ();
float distance = ::GetDlgItemFloat (m_hWnd, IDC_DISTANCE_EDIT);
CGraphicView *graphic_view = ::Get_Graphic_View ();
graphic_view->Set_Camera_Distance (distance);
return ;
}
////////////////////////////////////////////////////////////////////
//
// OnNotify
//
////////////////////////////////////////////////////////////////////
BOOL
CameraDistanceDialogClass::OnNotify
(
WPARAM wParam,
LPARAM lParam,
LRESULT *pResult
)
{
//
// Update the spinner control if necessary
//
NMHDR *pheader = (NMHDR *)lParam;
if ((pheader != NULL) && (pheader->code == UDN_DELTAPOS)) {
LPNMUPDOWN pupdown = (LPNMUPDOWN)lParam;
::Update_Spinner_Buddy (pheader->hwndFrom, pupdown->iDelta);
}
// Allow the base class to process this message
return CDialog::OnNotify (wParam, lParam, pResult);
}

View File

@@ -0,0 +1,68 @@
/*
** 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/>.
*/
#if !defined(AFX_CAMERADISTANCEDIALOG_H__548D3315_D582_4B97_8607_31B4659DF498__INCLUDED_)
#define AFX_CAMERADISTANCEDIALOG_H__548D3315_D582_4B97_8607_31B4659DF498__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "resource.h"
/////////////////////////////////////////////////////////////////////////////
//
// CameraDistanceDialogClass
//
/////////////////////////////////////////////////////////////////////////////
class CameraDistanceDialogClass : public CDialog
{
// Construction
public:
CameraDistanceDialogClass(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CameraDistanceDialogClass)
enum { IDD = IDD_CAMERA_DISTANCE };
CSpinButtonCtrl m_DistanceSpinCtrl;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CameraDistanceDialogClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CameraDistanceDialogClass)
virtual BOOL OnInitDialog();
virtual void OnOK();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CAMERADISTANCEDIALOG_H__548D3315_D582_4B97_8607_31B4659DF498__INCLUDED_)

View File

@@ -0,0 +1,402 @@
/*
** 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/>.
*/
// CameraSettingsDialog.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "w3dviewdoc.h"
#include "graphicview.h"
#include "CameraSettingsDialog.h"
#include "utils.h"
#include "camera.h"
#include "viewerscene.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//
// CameraSettingsDialogClass
//
/////////////////////////////////////////////////////////////////////////////
CameraSettingsDialogClass::CameraSettingsDialogClass(CWnd* pParent /*=NULL*/)
: CDialog(CameraSettingsDialogClass::IDD, pParent)
{
//{{AFX_DATA_INIT(CameraSettingsDialogClass)
//}}AFX_DATA_INIT
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////////////////////
void
CameraSettingsDialogClass::DoDataExchange (CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CameraSettingsDialogClass)
DDX_Control(pDX, IDC_LENS_SPIN, m_LensSpin);
DDX_Control(pDX, IDC_FAR_CLIP_SPIN, m_FarClipSpin);
DDX_Control(pDX, IDC_VFOV_SPIN, m_VFOVSpin);
DDX_Control(pDX, IDC_NEAR_CLIP_SPIN, m_NearClipSpin);
DDX_Control(pDX, IDC_HFOV_SPIN, m_HFOVSpin);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(CameraSettingsDialogClass, CDialog)
//{{AFX_MSG_MAP(CameraSettingsDialogClass)
ON_BN_CLICKED(IDC_FOV_CHECK, OnFovCheck)
ON_BN_CLICKED(IDC_CLIP_PLANE_CHECK, OnClipPlaneCheck)
ON_BN_CLICKED(IDC_RESET, OnReset)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL
CameraSettingsDialogClass::OnInitDialog (void)
{
CDialog::OnInitDialog ();
CW3DViewDoc *doc = ::GetCurrentDocument ();
CGraphicView *graphic_view = doc->GetGraphicView ();
CameraClass *camera = graphic_view->GetCamera ();
//
// Enable/disable the group boxes
//
SendDlgItemMessage (IDC_FOV_CHECK, BM_SETCHECK, (WPARAM)doc->Is_FOV_Manual ());
SendDlgItemMessage (IDC_CLIP_PLANE_CHECK, BM_SETCHECK, (WPARAM)doc->Are_Clip_Planes_Manual ());
float znear = 0;
float zfar = 0;
camera->Get_Clip_Planes (znear, zfar);
::Initialize_Spinner (m_NearClipSpin, znear, 0.0F, 999999.0F);
::Initialize_Spinner (m_FarClipSpin, zfar, 1.0F, 999999.0F);
//
// Setup the FOV controls
//
int hfov_deg = (int)RAD_TO_DEG (camera->Get_Horizontal_FOV ());
int vfov_deg = (int)RAD_TO_DEG (camera->Get_Vertical_FOV ());
::Initialize_Spinner (m_HFOVSpin, hfov_deg, 0.0F, 180.0F);
::Initialize_Spinner (m_VFOVSpin, vfov_deg, 0.0F, 180.0F);
//
// Setup the camera lens controls
//
float hfov = camera->Get_Horizontal_FOV ();
const float constant = (18.0F / 1000.0F);
float lens = (constant / (::tan (hfov / 2))) * 1000.0F;
::Initialize_Spinner (m_LensSpin, lens, 1.0F, 200.0F);
OnFovCheck ();
OnClipPlaneCheck ();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnOK
//
/////////////////////////////////////////////////////////////////////////////
void
CameraSettingsDialogClass::OnOK (void)
{
CW3DViewDoc *doc = ::GetCurrentDocument ();
CGraphicView *graphic_view = doc->GetGraphicView ();
CameraClass *camera = graphic_view->GetCamera ();
bool manual_fov = (SendDlgItemMessage (IDC_FOV_CHECK, BM_GETCHECK) == 1);
bool manual_planes = (SendDlgItemMessage (IDC_CLIP_PLANE_CHECK, BM_GETCHECK) == 1);
doc->Set_Manual_FOV (manual_fov);
doc->Set_Manul_Clip_Planes (manual_planes);
if (manual_fov == false) {
graphic_view->Reset_FOV ();
} else {
//
// Update the camera's FOV
//
float hfov_deg = ::GetDlgItemFloat (m_hWnd, IDC_HFOV_EDIT);
float vfov_deg = ::GetDlgItemFloat (m_hWnd, IDC_VFOV_EDIT);
camera->Set_View_Plane (DEG_TO_RAD (hfov_deg), DEG_TO_RAD (vfov_deg));
}
//
// Update the camera's clip planes
//
float znear = ::GetDlgItemFloat (m_hWnd, IDC_NEAR_CLIP_EDIT);
float zfar = ::GetDlgItemFloat (m_hWnd, IDC_FAR_CLIP_EDIT);
camera->Set_Clip_Planes (znear, zfar);
doc->Save_Camera_Settings ();
//
// Update the fog settings. The fog near clip plane should always be equal
// to the camera near clip plane, but the fog far clip plane is scene
// dependant. We will be sure to modify only the near clip plane here.
//
float fog_near, fog_far;
doc->GetScene()->Get_Fog_Range(&fog_near, &fog_far);
doc->GetScene()->Set_Fog_Range(znear, fog_far);
doc->GetScene()->Recalculate_Fog_Planes();
//
// Refresh the camera settings
//
RenderObjClass *render_obj = doc->GetDisplayedObject ();
if (render_obj != NULL) {
graphic_view->Reset_Camera_To_Display_Object (*render_obj);
}
CDialog::OnOK ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnFovCheck
//
/////////////////////////////////////////////////////////////////////////////
void
CameraSettingsDialogClass::OnFovCheck (void)
{
bool manual_fov = (SendDlgItemMessage (IDC_FOV_CHECK, BM_GETCHECK) == 1);
::EnableWindow (m_VFOVSpin, manual_fov);
::EnableWindow (m_HFOVSpin, manual_fov);
::EnableWindow (m_LensSpin, manual_fov);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_VFOV_EDIT), manual_fov);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_HFOV_EDIT), manual_fov);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_LENS_EDIT), manual_fov);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnClipPlaneCheck
//
/////////////////////////////////////////////////////////////////////////////
void
CameraSettingsDialogClass::OnClipPlaneCheck (void)
{
bool manual_planes = (SendDlgItemMessage (IDC_CLIP_PLANE_CHECK, BM_GETCHECK) == 1);
::EnableWindow (m_NearClipSpin, manual_planes);
::EnableWindow (m_FarClipSpin, manual_planes);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_NEAR_CLIP_EDIT), manual_planes);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_FAR_CLIP_EDIT), manual_planes);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnReset
//
/////////////////////////////////////////////////////////////////////////////
void
CameraSettingsDialogClass::OnReset (void)
{
CW3DViewDoc *doc = ::GetCurrentDocument ();
CGraphicView *graphic_view = doc->GetGraphicView ();
CameraClass *camera = graphic_view->GetCamera ();
doc->Set_Manual_FOV (false);
doc->Set_Manul_Clip_Planes (false);
graphic_view->Reset_FOV ();
RenderObjClass *render_obj = doc->GetDisplayedObject ();
if (render_obj != NULL) {
graphic_view->Reset_Camera_To_Display_Object (*render_obj);
}
//
// Update the clip plane controls
//
float znear = 0;
float zfar = 0;
camera->Get_Clip_Planes (znear, zfar);
::SetDlgItemFloat (m_hWnd, IDC_NEAR_CLIP_EDIT, znear);
::SetDlgItemFloat (m_hWnd, IDC_FAR_CLIP_EDIT, zfar);
//
// Update the FOV controls
//
int hfov_deg = (int)RAD_TO_DEG (camera->Get_Horizontal_FOV ());
int vfov_deg = (int)RAD_TO_DEG (camera->Get_Vertical_FOV ());
::SetDlgItemFloat (m_hWnd, IDC_HFOV_EDIT, hfov_deg);
::SetDlgItemFloat (m_hWnd, IDC_VFOV_EDIT, vfov_deg);
//
// Setup the camera lens controls
//
float vfov = camera->Get_Vertical_FOV ();
float lens = ((::atan ((18.0F / 1000.0F)) / vfov) * 2.0F) * 1000.0F;
::SetDlgItemFloat (m_hWnd, IDC_LENS_EDIT, lens);
return ;
}
////////////////////////////////////////////////////////////////////
//
// OnNotify
//
////////////////////////////////////////////////////////////////////
BOOL
CameraSettingsDialogClass::OnNotify
(
WPARAM wParam,
LPARAM lParam,
LRESULT *pResult
)
{
//
// Update the spinner control if necessary
//
NMHDR *header = (NMHDR *)lParam;
if ((header != NULL) && (header->code == UDN_DELTAPOS)) {
LPNMUPDOWN updown_info = (LPNMUPDOWN)lParam;
::Update_Spinner_Buddy (header->hwndFrom, updown_info->iDelta);
//
// Update the FOV settings (they are dependent on each other)
//
if (updown_info->hdr.idFrom == IDC_LENS_SPIN) {
Update_FOV ();
} else if (updown_info->hdr.idFrom == IDC_HFOV_SPIN) {
Update_Camera_Lens ();
}
}
// Allow the base class to process this message
return CDialog::OnNotify (wParam, lParam, pResult);
}
////////////////////////////////////////////////////////////////////
//
// Update_Camera_Lens
//
////////////////////////////////////////////////////////////////////
void
CameraSettingsDialogClass::Update_Camera_Lens (void)
{
//
// Get the current vertical FOV settings
//
float hfov = ::GetDlgItemFloat (m_hWnd, IDC_HFOV_EDIT);
//
// Convert the vertical FOV to a camera lens setting
//
if (hfov > 0) {
const float constant = (18.0F / 1000.0F);
float lens = (constant / (::tan (DEG_TO_RAD (hfov) / 2))) * 1000.0F;
::SetDlgItemFloat (m_hWnd, IDC_LENS_EDIT, lens);
}
return ;
}
////////////////////////////////////////////////////////////////////
//
// Update_FOV
//
////////////////////////////////////////////////////////////////////
void
CameraSettingsDialogClass::Update_FOV (void)
{
//
// Get the current camera lens setting
//
float lens = (::GetDlgItemFloat (m_hWnd, IDC_LENS_EDIT) / 1000.0F);
//
// Convert the camera lens to a FOV
//
if (lens > 0) {
const float constant = (18.0F / 1000.0F);
float hfov = (::atan (constant / lens) * 2.0F);
float vfov = (3 * hfov / 4);
//
// Pass the new FOV settings onto the dialog
//
::SetDlgItemFloat (m_hWnd, IDC_HFOV_EDIT, RAD_TO_DEG (hfov));
::SetDlgItemFloat (m_hWnd, IDC_VFOV_EDIT, RAD_TO_DEG (vfov));
}
return ;
}
////////////////////////////////////////////////////////////////////
//
// Update_FOV
//
////////////////////////////////////////////////////////////////////
BOOL
CameraSettingsDialogClass::OnCommand
(
WPARAM wParam,
LPARAM lParam
)
{
static bool updating = false;
if (updating == false) {
//
// Update the FOV settings if necessary
//
if ( LOWORD (wParam) == IDC_HFOV_EDIT &&
HIWORD (wParam) == EN_UPDATE)
{
updating = true;
Update_Camera_Lens ();
updating = false;
} else if ( LOWORD (wParam) == IDC_LENS_EDIT &&
HIWORD (wParam) == EN_UPDATE)
{
updating = true;
Update_FOV ();
updating = false;
}
}
return CDialog::OnCommand(wParam, lParam);
}

View File

@@ -0,0 +1,82 @@
/*
** 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/>.
*/
#if !defined(AFX_CAMERASETTINGSDIALOG_H__7E43F424_8191_11D3_A064_00104B791122__INCLUDED_)
#define AFX_CAMERASETTINGSDIALOG_H__7E43F424_8191_11D3_A064_00104B791122__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// CameraSettingsDialog.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CameraSettingsDialogClass dialog
class CameraSettingsDialogClass : public CDialog
{
// Construction
public:
CameraSettingsDialogClass(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CameraSettingsDialogClass)
enum { IDD = IDD_CAMERA_SETTINGS };
CSpinButtonCtrl m_LensSpin;
CSpinButtonCtrl m_FarClipSpin;
CSpinButtonCtrl m_VFOVSpin;
CSpinButtonCtrl m_NearClipSpin;
CSpinButtonCtrl m_HFOVSpin;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CameraSettingsDialogClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CameraSettingsDialogClass)
virtual BOOL OnInitDialog();
virtual void OnOK();
afx_msg void OnFovCheck();
afx_msg void OnClipPlaneCheck();
afx_msg void OnReset();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
protected:
///////////////////////////////////////////////////////////////////
// Protected methods
///////////////////////////////////////////////////////////////////
void Update_Camera_Lens (void);
void Update_FOV (void);
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CAMERASETTINGSDIALOG_H__7E43F424_8191_11D3_A064_00104B791122__INCLUDED_)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,252 @@
/*
** 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/>.
*/
#if !defined(AFX_COLORBAR_H__D1243F40_D4D2_11D2_8DDF_00104B6FD9E3__INCLUDED_)
#define AFX_COLORBAR_H__D1243F40_D4D2_11D2_8DDF_00104B6FD9E3__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// ColorBar.h : header file
//
/////////////////////////////////////////////////////////////////////////////
//
// Constants
//
const int MAX_COLOR_POINTS = 15;
//
// Window styles
//
#define CBRS_SUNKEN 0x00000001
#define CBRS_RAISED 0x00000002
#define CBRS_FRAME 0x00000004
#define CBRS_FRAME_MASK CBRS_FRAME | CBRS_RAISED | CBRS_SUNKEN
#define CBRS_HORZ 0x00000008
#define CBRS_VERT 0x00000010
#define CBRS_HAS_SEL 0x00000020
#define CBRS_SHOW_FRAMES 0x00000040
#define CBRS_PAINT_GRAPH 0x00000080
//
// Window messages and notifications
//
#define CBRN_MOVED_POINT 0x0001
#define CBRN_MOVING_POINT 0x0002
#define CBRN_DBLCLK_POINT 0x0003
#define CBRN_SEL_CHANGED 0x0004
#define CBRN_DEL_POINT 0x0005
#define CBRN_DELETED_POINT 0x0006
#define CBRN_INSERTED_POINT 0x0007
#define CBRM_GETCOLOR (WM_USER+101)
#define CBRM_SETCOLOR ( WM_USER+102)
//
// Point styles
//
#define POINT_VISIBLE 0x00000001
#define POINT_CAN_MOVE 0x00000002
//
// Return values for WM_NOTIFY
//
#define STOP_EVENT 0x00000077
/////////////////////////////////////////////////////////////////////////////
//
// Structures
//
// Structure used to send notifications via WM_NOTIFY
typedef struct
{
NMHDR hdr;
int key_index;
float red;
float green;
float blue;
float position;
} CBR_NMHDR;
/////////////////////////////////////////////////////////////////////////////
//
// ColorBarClass
//
class ColorBarClass : public CWnd
{
// Construction
public:
ColorBarClass();
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(ColorBarClass)
public:
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~ColorBarClass();
// Generated message map functions
protected:
//{{AFX_MSG(ColorBarClass)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnPaint();
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnKillFocus(CWnd* pNewWnd);
afx_msg void OnSetFocus(CWnd* pOldWnd);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
friend LRESULT WINAPI fnColorBarProc (HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
public:
/////////////////////////////////////////////////////////////////////////
//
// Public methods
//
bool Insert_Point (int index, float position, float red, float green, float blue, DWORD flags = POINT_VISIBLE | POINT_CAN_MOVE);
bool Insert_Point (CPoint point, DWORD flags = POINT_VISIBLE | POINT_CAN_MOVE);
bool Modify_Point (int index, float position, float red, float green, float blue, DWORD flags = POINT_VISIBLE | POINT_CAN_MOVE);
bool Set_User_Data (int index, DWORD data);
DWORD Get_User_Data (int index);
bool Set_Graph_Percent (int index, float percent);
float Get_Graph_Percent (int index);
bool Delete_Point (int index);
void Clear_Points (void);
int Get_Point_Count (void) const { return m_iColorPoints; }
bool Get_Point (int index, float *position, float *red, float *green, float *blue);
int Marker_From_Point (CPoint point);
void Set_Selection_Pos (float pos);
float Get_Selection_Pos (void) const { return m_SelectionPos; }
void Get_Color (float position, float *red, float *green, float *blue);
void Get_Range (float &min, float &max) const { min = m_MinPos; max = m_MaxPos; }
void Set_Range (float min, float max);
void Set_Redraw (bool redraw = true);
LRESULT Send_Notification (int code, int key);
//////////////////////////////////////////////////////////////////////////
// Static members
//////////////////////////////////////////////////////////////////////////
static ColorBarClass *Get_Color_Bar (HWND window_handle) { return (ColorBarClass *)::GetProp (window_handle, "CLASSPOINTER"); }
protected:
/////////////////////////////////////////////////////////////////////////
//
// Protected data types
//
typedef struct
{
float PosPercent;
int StartPos;
int EndPos;
float StartGraphPercent;
float GraphPercentInc;
float StartRed;
float StartGreen;
float StartBlue;
float RedInc;
float GreenInc;
float BlueInc;
DWORD user_data;
int flags;
} COLOR_POINT;
/////////////////////////////////////////////////////////////////////////
//
// Protected methods
//
void Paint_DIB (void);
void Create_Bitmap (void);
void Free_Bitmap (void);
void Free_Marker_Bitmap (void);
void Paint_Bar_Horz (int x_pos, int y_pos, int width, int height, UCHAR *pbits);
void Paint_Bar_Vert (int x_pos, int y_pos, int width, int height, UCHAR *pbits);
void Update_Point_Info (void);
void Load_Key_Frame_BMP (void);
void Paint_Key_Frame (int x_pos, int y_pos);
void Paint_Screen (HDC hwnd_dc);
void Get_Selection_Rectangle (CRect &rect);
void Move_Selection (CPoint point, bool send_notify = true);
void Move_Selection (float new_pos, bool send_notify = true);
void Repaint (void);
private:
/////////////////////////////////////////////////////////////////////////
//
// Private member data
//
HBITMAP m_hBitmap;
HBITMAP m_KeyFrameDIB;
HDC m_hMemDC;
UCHAR * m_pBits;
UCHAR * m_pKeyFrameBits;
int m_iColorWidth;
int m_iColorHeight;
int m_iBMPWidth;
int m_iBMPHeight;
int m_iMarkerWidth;
int m_iMarkerHeight;
int m_iScanlineSize;
int m_iColorPoints;
float m_MinPos;
float m_MaxPos;
COLOR_POINT m_ColorPoints[MAX_COLOR_POINTS];
CRect m_ColorArea;
int m_iCurrentKey;
bool m_bMoving;
bool m_bMoved;
bool m_bRedraw;
float m_SelectionPos;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_COLORBAR_H__D1243F40_D4D2_11D2_8DDF_00104B6FD9E3__INCLUDED_)

View File

@@ -0,0 +1,985 @@
/*
** 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/>.
*/
/////////////////////////////////////////////////////////////////////////////////
//
// ColorPicker.cpp : implementation file
//
//
#include "stdafx.h"
#include "colorpicker.h"
#include "colorpickerdialogclass.h"
#include <math.h>
#include "utils.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//extern HINSTANCE _hinstance;
/////////////////////////////////////////////////////////////////////////////
//
// ColorPickerClass
//
ColorPickerClass::ColorPickerClass (void)
: m_hBitmap (NULL),
m_iWidth (0),
m_iHeight (0),
m_CurrentPoint (0, 0),
m_CurrentColor (0),
m_bSelecting (false),
m_pBits (NULL),
m_hMemDC (NULL),
m_CurrentHue (0),
CWnd ()
{
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// ~ColorPickerClass
//
ColorPickerClass::~ColorPickerClass (void)
{
if (m_hMemDC != NULL) {
::DeleteObject (m_hMemDC);
m_hMemDC = NULL;
}
Free_Bitmap ();
return ;
}
BEGIN_MESSAGE_MAP(ColorPickerClass, CWnd)
//{{AFX_MSG_MAP(ColorPickerClass)
ON_WM_PAINT()
ON_WM_CREATE()
ON_WM_SIZE()
ON_WM_ERASEBKGND()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
// OnPaint
//
void
ColorPickerClass::OnPaint (void)
{
CPaintDC dc (this);
if (m_hMemDC != NULL) {
HBITMAP hold_bmp = (HBITMAP)::SelectObject (m_hMemDC, m_hBitmap);
CRect rect;
GetClientRect (&rect);
::BitBlt (dc, 0, 0, rect.Width (), rect.Height (), m_hMemDC, 0, 0, SRCCOPY);
::SelectObject (m_hMemDC, hold_bmp);
Paint_Marker ();
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// RegisterColorPicker
//
void
RegisterColorPicker (HINSTANCE hinst)
{
// Has the class already been registered?
WNDCLASS wndclass = { 0 };
if (::GetClassInfo (hinst, "WWCOLORPICKER", &wndclass) == FALSE) {
wndclass.style = CS_GLOBALCLASS | CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
wndclass.lpfnWndProc = fnColorPickerProc;
wndclass.hInstance = hinst;
wndclass.hbrBackground = (HBRUSH)COLOR_3DFACE + 1;
wndclass.hCursor = ::LoadCursor (NULL, IDC_ARROW);
wndclass.lpszClassName = "WWCOLORPICKER";
// Let the windows manager know about this global class
::RegisterClass (&wndclass);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// fnColorPickerProc
//
LRESULT WINAPI
fnColorPickerProc
(
HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam
)
{
//static ColorPickerClass *pwnd = NULL;
//static bool bcreated = false;
switch (message)
{
case WM_CREATE:
{
LPCREATESTRUCT pcreate_info = (LPCREATESTRUCT)lparam;
if (pcreate_info != NULL) {
// Should we create a new class manager for this window?
ColorPickerClass *pwnd = (ColorPickerClass *)pcreate_info->lpCreateParams;
BOOL created = FALSE;
if (pwnd == NULL) {
pwnd = new ColorPickerClass;
created = TRUE;
}
// Pull some hacks to get MFC to use the message map
pwnd->Attach (hwnd);
// Let the window know its being created
pwnd->OnCreate (pcreate_info);
WNDPROC *pOldWndProc = pwnd->GetSuperWndProcAddr ();
if (pOldWndProc) {
WNDPROC pold_proc = (WNDPROC)::SetWindowLong (hwnd, GWL_WNDPROC, (DWORD)::AfxGetAfxWndProc ());
ASSERT (pold_proc != NULL);
(*pOldWndProc) = pold_proc;
}
// Store some information in the window handle
::SetProp (hwnd, "CLASSPOINTER", (HANDLE)pwnd);
::SetProp (hwnd, "CREATED", (HANDLE)created);
}
}
break;
case WM_DESTROY:
{
/*pwnd->Detach ();
WNDPROC *pOldWndProc = pwnd->GetSuperWndProcAddr ();
if (pOldWndProc) {
::SetWindowLong (hwnd, GWL_WNDPROC, (DWORD)(*pOldWndProc));
(*pOldWndProc) = NULL;
}
if (bcreated) {
delete pwnd;
pwnd = NULL;
}*/
// Get the creation information from the window handle
ColorPickerClass *pwnd = (ColorPickerClass *)::GetProp (hwnd, "CLASSPOINTER");
BOOL created = (BOOL)::GetProp (hwnd, "CREATED");
if (pwnd != NULL) {
pwnd->Detach ();
WNDPROC *pOldWndProc = pwnd->GetSuperWndProcAddr ();
if (pOldWndProc) {
::SetWindowLong (hwnd, GWL_WNDPROC, (DWORD)(*pOldWndProc));
(*pOldWndProc) = NULL;
}
if (created) {
delete pwnd;
pwnd = NULL;
}
}
}
break;
}
// Allow default processing to occur
return ::DefWindowProc (hwnd, message, wparam, lparam);
}
/////////////////////////////////////////////////////////////////////////////
//
// OnCreate
//
/////////////////////////////////////////////////////////////////////////////
int
ColorPickerClass::OnCreate (LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
m_hMemDC = ::CreateCompatibleDC (NULL);
Create_Bitmap ();
return 0;
}
/////////////////////////////////////////////////////////////////////////////
//
// Create
//
/////////////////////////////////////////////////////////////////////////////
BOOL
ColorPickerClass::Create
(
LPCTSTR /*lpszClassName*/,
LPCTSTR lpszWindowName,
DWORD dwStyle,
const RECT &rect,
CWnd *pparent_wnd,
UINT nID,
CCreateContext * /*pContext*/
)
{
// Create the window (it will force the message map and everthing)
HWND hparent_wnd = (pparent_wnd != NULL) ? pparent_wnd->m_hWnd : NULL;
HWND hwnd = ::CreateWindow ("WWCOLORPICKER",
lpszWindowName,
dwStyle,
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
hparent_wnd,
(HMENU)nID,
::AfxGetInstanceHandle (),
this);
// Return the true/false result code
return (hwnd != NULL);
}
/////////////////////////////////////////////////////////////////////////////
//
// Create_Bitmap
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerClass::Create_Bitmap (void)
{
// Start fresh
Free_Bitmap ();
CRect rect;
GetClientRect (&rect);
m_iWidth = rect.Width ();
m_iHeight = rect.Height ();
// Set-up the fields of the BITMAPINFOHEADER
BITMAPINFOHEADER bitmap_info;
bitmap_info.biSize = sizeof (BITMAPINFOHEADER);
bitmap_info.biWidth = m_iWidth;
bitmap_info.biHeight = -m_iHeight; // Top-down DIB uses negative height
bitmap_info.biPlanes = 1;
bitmap_info.biBitCount = 24;
bitmap_info.biCompression = BI_RGB;
bitmap_info.biSizeImage = ((m_iWidth * m_iHeight) * 3);
bitmap_info.biXPelsPerMeter = 0;
bitmap_info.biYPelsPerMeter = 0;
bitmap_info.biClrUsed = 0;
bitmap_info.biClrImportant = 0;
// Get a temporary screen DC
HDC hscreen_dc = ::GetDC (NULL);
// Create a bitmap that we can access the bits directly of
m_hBitmap = ::CreateDIBSection (hscreen_dc,
(const BITMAPINFO *)&bitmap_info,
DIB_RGB_COLORS,
(void **)&m_pBits,
NULL,
0L);
// Release our temporary screen DC
::ReleaseDC (NULL, hscreen_dc);
// Paint the color range into this bitmap
Paint_DIB (m_iWidth, m_iHeight, m_pBits);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Fill_Rect
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerClass::Fill_Rect
(
UCHAR *pbits,
const RECT &rect,
COLORREF color,
int scanline_size
)
{
UCHAR red = GetRValue (color);
UCHAR green = GetRValue (color);
UCHAR blue = GetRValue (color);
for (int irow = rect.top; irow < rect.bottom; irow ++) {
int index = irow * scanline_size;
index += (rect.left * 3);
for (int col = rect.left; col < rect.right; col ++) {
pbits[index++] = blue;
pbits[index++] = green;
pbits[index++] = red;
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Color_From_Point
//
/////////////////////////////////////////////////////////////////////////////
COLORREF
ColorPickerClass::Color_From_Point
(
int x,
int y
)
{
COLORREF color = RGB (0,0,0);
// x,y location inside boundaries?
if ((x >= 0) && (x < m_iWidth) &&
(y >= 0) && (y < m_iHeight)) {
// Window's bitmaps are DWORD aligned, so make sure
// we take that into account.
int alignment_offset = (m_iWidth * 3) % 4;
alignment_offset = (alignment_offset != 0) ? (4 - alignment_offset) : 0;
int scanline_size = (m_iWidth * 3) + alignment_offset;
// Read the color value straight from the BMP
int index = (scanline_size * y) + (x * 3);
int blue = m_pBits[index];
int green = m_pBits[index + 1];
int red = m_pBits[index + 2];
// Turn the individual compenents into a color
color = RGB (red, green, blue);
RECT rect;
Calc_Display_Rect (rect);
int width = rect.right-rect.left;
m_CurrentHue = ((float)x) / ((float)width);
}
// Return the color
return color;
}
/////////////////////////////////////////////////////////////////////////////
//
// Polar_To_Rect
//
/////////////////////////////////////////////////////////////////////////////
void
Polar_To_Rect (float radius, float angle, float &x, float &y)
{
x = radius * float(cos(angle));
y = radius * float(sin(angle));
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Rect_To_Polar
//
/////////////////////////////////////////////////////////////////////////////
void
Rect_To_Polar (float x, float y, float &radius, float &angle)
{
if (x == 0 && y == 0) {
radius = 0;
angle = 0;
} else {
radius = (float)::sqrt ((x * x) + (y * y));
angle = (float)::atan2 (y, x);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// RGB_to_Hue
//
/////////////////////////////////////////////////////////////////////////////
void
RGB_to_Hue (int red_val, int green_val, int blue_val, float &hue, float &value)
{
float red_radius = (float)red_val;
float green_radius = (float)green_val;
float blue_radius = (float)blue_val;
float red_angle = 0;
float green_angle = (3.1415926535F * 2.0F) / 3.0F;
float blue_angle = (3.1415926535F * 4.0F) / 3.0F;
struct Color2D
{
float x;
float y;
};
Color2D red = { 0 };
Color2D green = { 0 };
Color2D blue = { 0 };
Color2D result = { 0 };
::Polar_To_Rect (red_radius, red_angle, red.x, red.y);
::Polar_To_Rect (green_radius, green_angle, green.x, green.y);
::Polar_To_Rect (blue_radius, blue_angle, blue.x, blue.y);
result.x = red.x + green.x + blue.x;
result.y = red.y + green.y + blue.y;
float hue_angle = 0;
float hue_radius = 0;
::Rect_To_Polar (result.x, result.y, hue_radius, hue_angle);
hue = hue_angle / (3.14159265359F * 2.0F);
if (hue < 0) {
hue += 1;
} else if (hue > 1) {
hue -= 1;
}
value = (float)::fabs (hue_radius / 255);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Point_From_Color
//
/////////////////////////////////////////////////////////////////////////////
CPoint
ColorPickerClass::Point_From_Color (COLORREF color)
{
// Window's bitmaps are DWORD aligned, so make sure
// we take that into account.
int alignment_offset = (m_iWidth * 3) % 4;
alignment_offset = (alignment_offset != 0) ? (4 - alignment_offset) : 0;
int scanline_size = (m_iWidth * 3) + alignment_offset;
int red = GetRValue (color);
int green = GetGValue (color);
int blue = GetBValue (color);
float hue = 0;
float value = 0;
RGB_to_Hue (red, green, blue, hue, value);
RECT rect;
Calc_Display_Rect (rect);
int width = rect.right-rect.left;
int height = rect.bottom-rect.top;
float whiteness = (float)min (min (red, green), blue);
float percent = whiteness / 255;
float darkness = 0;
//
// Determine what the 'darkness' of the hue should be
//
if (percent != 1) {
float start_red = (red - whiteness) / (1 - percent);
float start_green = (green - whiteness) / (1 - percent);
float start_blue = (blue - whiteness) / (1 - percent);
darkness = max (max (start_red, start_green), start_blue);
}
int x = int(width * hue);
int y = ((255 - (int)darkness) * height) / 255;
// Return the point
return CPoint (x, y);
}
/////////////////////////////////////////////////////////////////////////////
//
// Paint_DIB
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerClass::Paint_DIB
(
int width,
int height,
UCHAR *pbits
)
{
// Window's bitmaps are DWORD aligned, so make sure
// we take that into account.
int alignment_offset = (width * 3) % 4;
alignment_offset = (alignment_offset != 0) ? (4 - alignment_offset) : 0;
int scanline_size = (width * 3) + alignment_offset;
//
// Paint the border (if any)
//
CRect rect (0, 0, width, height);
LONG lstyle = ::GetWindowLong (m_hWnd, GWL_STYLE);
if (lstyle & CPS_SUNKEN) {
::Draw_Sunken_Rect (pbits, rect, scanline_size);
rect.DeflateRect (1, 1);
} else if (lstyle & CPS_RAISED) {
::Draw_Raised_Rect (pbits, rect, scanline_size);
rect.DeflateRect (1, 1);
} else if (lstyle & WS_BORDER) {
::Frame_Rect (pbits, rect, RGB (255, 255, 255), scanline_size);
rect.DeflateRect (1, 1);
}
// Recalc the width and height (it could of changed)
width = rect.Width ();
height = rect.Height ();
// Build an array of column indicies where we will switch color
// components...
int col_remainder = (width % 6);
int channel_switch_cols[6];
for (int channel = 0; channel < 6; channel ++) {
// Each column has at least X/6 pixels
channel_switch_cols[channel] = width / 6;
// Do we need to add a remainder to this col?
// (Occurs when the width isn't evenly divisible by 6)
if (col_remainder > 0) {
channel_switch_cols[channel] += 1;
col_remainder --;
}
// Add the previous column's switching index
if (channel > 0) {
channel_switch_cols[channel] += channel_switch_cols[channel - 1];
}
}
// Start with max red
float red = 255.0F;
float green = 0;
float blue = 0;
// Calculate some starting channel variables
int curr_channel = 0;
float curr_inc = (255.0F / ((float)channel_switch_cols[0]));
float *pcurr_component = &green;
//
// Paint the image
//
for (int icol = rect.left; icol < rect.right; icol ++) {
// Determine how much to 'darken' the current hue by for each row (goes to black)
float red_dec = -((float)(red) / (float)(height-1));
float green_dec = -((float)(green) / (float)(height-1));
float blue_dec = -((float)(blue) / (float)(height-1));
// Start with the normal hue color
float curr_red = red;
float curr_green = green;
float curr_blue = blue;
// Paint all pixels in this row
int bitmap_index = (icol * 3) + (rect.left * scanline_size);
for (int irow = rect.top; irow < rect.bottom; irow ++) {
// Put these values into the bitmap
pbits[bitmap_index] = UCHAR(((int)curr_blue) & 0xFF);
pbits[bitmap_index + 1] = UCHAR(((int)curr_green) & 0xFF);
pbits[bitmap_index + 2] = UCHAR(((int)curr_red) & 0xFF);
// Determine the current red, green, and blue values
curr_red = curr_red + red_dec;
curr_green = curr_green + green_dec;
curr_blue = curr_blue + blue_dec;
// Increment our offset into the bitmap
bitmap_index += scanline_size;
}
// Is it time to switch to a new color channel?
if ((icol - rect.left) == channel_switch_cols[curr_channel]) {
// Recompute values for the new channel
curr_channel ++;
curr_inc = (255.0F / ((float)(channel_switch_cols[curr_channel] - channel_switch_cols[curr_channel-1])));
// Which channel are we painting?
if (curr_channel == 1) {
pcurr_component = &red;
curr_inc = -curr_inc;
} else if (curr_channel == 2) {
pcurr_component = &blue;
} else if (curr_channel == 3) {
pcurr_component = &green;
curr_inc = -curr_inc;
} else if (curr_channel == 4) {
pcurr_component = &red;
} else if (curr_channel == 5) {
pcurr_component = &blue;
curr_inc = -curr_inc;
}
}
// Increment the current color component
(*pcurr_component) = (*pcurr_component) + curr_inc;
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Free_Bitmap
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerClass::Free_Bitmap (void)
{
if (m_hBitmap != NULL) {
::DeleteObject (m_hBitmap);
m_hBitmap = NULL;
m_pBits = NULL;
}
m_iWidth = 0;
m_iHeight = 0;
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnSize
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerClass::OnSize
(
UINT nType,
int cx,
int cy
)
{
// Allow the base class to process this message
CWnd::OnSize (nType, cx, cy);
// Recreate the BMP to reflect the new window size
Create_Bitmap ();
// Determine the new point based on the current color
//m_CurrentColor = RGB (128, 222, 199);
//m_CurrentPoint = Point_From_Color (m_CurrentColor);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnEraseBkgnd
//
/////////////////////////////////////////////////////////////////////////////
BOOL
ColorPickerClass::OnEraseBkgnd (CDC * /*pDC*/)
{
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnLButtonDown
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerClass::OnLButtonDown
(
UINT nFlags,
CPoint point
)
{
SetCapture ();
m_bSelecting = true;
RECT rect;
Calc_Display_Rect (rect);
ClientToScreen (&rect);
::ClipCursor (&rect);
Erase_Marker ();
m_CurrentPoint = point;
m_CurrentColor = Color_From_Point (point.x, point.y);
//
// Notify the parent window that the user double-clicked
// one of the keyframes
//
LONG id = ::GetWindowLong (m_hWnd, GWL_ID);
CP_NMHDR notify_hdr = { 0 };
notify_hdr.hdr.hwndFrom = m_hWnd;
notify_hdr.hdr.idFrom = id;
notify_hdr.hdr.code = CPN_COLORCHANGE;
notify_hdr.red = GetRValue (m_CurrentColor);
notify_hdr.green = GetGValue (m_CurrentColor);
notify_hdr.blue = GetBValue (m_CurrentColor);
notify_hdr.hue = m_CurrentHue;
::SendMessage (::GetParent (m_hWnd),
WM_NOTIFY,
id,
(LPARAM)&notify_hdr);
Paint_Marker ();
// Allow the base class to process this message
CWnd::OnLButtonDown (nFlags, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnLButtonUp
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerClass::OnLButtonUp
(
UINT nFlags,
CPoint point
)
{
if (m_bSelecting) {
::ClipCursor (NULL);
ReleaseCapture ();
m_bSelecting = false;
}
// Allow the base class to process this message
CWnd::OnLButtonUp (nFlags, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnMouseMove
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerClass::OnMouseMove
(
UINT nFlags,
CPoint point
)
{
if (m_bSelecting) {
Erase_Marker ();
m_CurrentPoint = point;
m_CurrentColor = Color_From_Point (point.x, point.y);
//
// Notify the parent window that the user double-clicked
// one of the keyframes
//
LONG id = ::GetWindowLong (m_hWnd, GWL_ID);
CP_NMHDR notify_hdr = { 0 };
notify_hdr.hdr.hwndFrom = m_hWnd;
notify_hdr.hdr.idFrom = id;
notify_hdr.hdr.code = CPN_COLORCHANGE;
notify_hdr.red = GetRValue (m_CurrentColor);
notify_hdr.green = GetGValue (m_CurrentColor);
notify_hdr.blue = GetBValue (m_CurrentColor);
notify_hdr.hue = m_CurrentHue;
::SendMessage (::GetParent (m_hWnd),
WM_NOTIFY,
id,
(LPARAM)&notify_hdr);
Paint_Marker ();
}
// Allow the base class to process this message
CWnd::OnMouseMove (nFlags, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Calc_Display_Rect
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerClass::Calc_Display_Rect (RECT &rect)
{
GetClientRect (&rect);
LONG lstyle = ::GetWindowLong (m_hWnd, GWL_STYLE);
if ((lstyle & CPS_SUNKEN) || (lstyle & CPS_RAISED) || (lstyle & WS_BORDER)) {
rect.left += 1;
rect.right -= 1;
rect.top += 1;
rect.bottom -= 1;
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Erase_Marker
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerClass::Erase_Marker (void)
{
HDC hdc = ::GetDC (m_hWnd);
if (m_hMemDC != NULL) {
HBITMAP hold_bmp = (HBITMAP)::SelectObject (m_hMemDC, m_hBitmap);
CRect rect;
GetClientRect (&rect);
::BitBlt (hdc,
m_CurrentPoint.x - 5,
m_CurrentPoint.y - 5,
11,
11,
m_hMemDC,
m_CurrentPoint.x - 5,
m_CurrentPoint.y - 5,
SRCCOPY);
::SelectObject (m_hMemDC, hold_bmp);
}
::ReleaseDC (m_hWnd, hdc);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Paint_Marker
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerClass::Paint_Marker (void)
{
HDC hdc = ::GetDC (m_hWnd);
if (m_hMemDC != NULL) {
HBITMAP hmarker_bmp = ::LoadBitmap (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDB_MARKER));
HBITMAP hold_bmp = (HBITMAP)::SelectObject (m_hMemDC, hmarker_bmp);
CRect rect;
GetClientRect (&rect);
::BitBlt (hdc,
m_CurrentPoint.x - 5,
m_CurrentPoint.y - 5,
11,
11,
m_hMemDC,
0,
0,
SRCINVERT);
::SelectObject (m_hMemDC, hold_bmp);
::DeleteObject (hmarker_bmp);
}
::ReleaseDC (m_hWnd, hdc);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Select_Color
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerClass::Select_Color (int red, int green, int blue)
{
m_CurrentColor = RGB (red, green, blue);
m_CurrentPoint = Point_From_Color (m_CurrentColor);
m_CurrentColor = Color_From_Point (m_CurrentPoint.x, m_CurrentPoint.y);
// Refresh the window
InvalidateRect (NULL, FALSE);
UpdateWindow ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Current_Color
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerClass::Get_Current_Color (int *red, int *green, int *blue)
{
(*red) = GetRValue (m_CurrentColor);
(*green) = GetGValue (m_CurrentColor);
(*blue) = GetBValue (m_CurrentColor);
return ;
}

View File

@@ -0,0 +1,161 @@
/*
** 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/>.
*/
#if !defined(AFX_COLORPICKER_H__C943A7EC_CAA3_11D2_8DDF_00104B6FD9E3__INCLUDED_)
#define AFX_COLORPICKER_H__C943A7EC_CAA3_11D2_8DDF_00104B6FD9E3__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// ColorPicker.h : header file
//
/////////////////////////////////////////////////////////////////////////////
//
// Constants
//
//
// Window styles
//
#define CPS_SUNKEN 0x00000001
#define CPS_RAISED 0x00000002
//
// Window messages and notifications
//
#define CPN_COLORCHANGE 0x0001
#define CPM_GETCOLOR (WM_USER+101)
#define CPM_SETCOLOR (WM_USER+102)
/////////////////////////////////////////////////////////////////////////////
//
// Structures
//
// Structure used to send notifications via WM_NOTIFY
typedef struct
{
NMHDR hdr;
float red;
float green;
float blue;
float hue;
} CP_NMHDR;
/////////////////////////////////////////////////////////////////////////////
//
// ColorPickerClass window
//
class ColorPickerClass : public CWnd
{
// Construction
public:
ColorPickerClass();
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(ColorPickerClass)
public:
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~ColorPickerClass();
// Generated message map functions
protected:
//{{AFX_MSG(ColorPickerClass)
afx_msg void OnPaint();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
friend LRESULT WINAPI fnColorPickerProc (HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
public:
//////////////////////////////////////////////////////////////////////////
// Public members
//////////////////////////////////////////////////////////////////////////
void Select_Color (int red, int green, int blue);
void Get_Current_Color (int *red, int *green, int *blue);
//////////////////////////////////////////////////////////////////////////
// Static members
//////////////////////////////////////////////////////////////////////////
static ColorPickerClass *Get_Color_Picker (HWND window_handle) { return (ColorPickerClass *)::GetProp (window_handle, "CLASSPOINTER"); }
protected:
/////////////////////////////////////////////////////////////////////////
//
// Private member data
//
void Paint_DIB (int width, int height, UCHAR *pbits);
void Create_Bitmap (void);
void Free_Bitmap (void);
void Fill_Rect (UCHAR *pbits, const RECT &rect, COLORREF color, int scanline_size);
void Frame_Rect (UCHAR *pbits, const RECT &rect, COLORREF color, int scanline_size);
void Draw_Horz_Line (UCHAR *pbits, int x, int y, int len, COLORREF color, int scanline_size);
void Draw_Vert_Line (UCHAR *pbits, int x, int y, int len, COLORREF color, int scanline_size);
COLORREF Color_From_Point (int x, int y);
CPoint Point_From_Color (COLORREF color);
void Paint_Marker (void);
void Erase_Marker (void);
void Calc_Display_Rect (RECT &rect);
private:
/////////////////////////////////////////////////////////////////////////
//
// Private member data
//
HBITMAP m_hBitmap;
HDC m_hMemDC;
UCHAR * m_pBits;
int m_iWidth;
int m_iHeight;
CPoint m_CurrentPoint;
COLORREF m_CurrentColor;
bool m_bSelecting;
float m_CurrentHue;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_COLORPICKER_H__C943A7EC_CAA3_11D2_8DDF_00104B6FD9E3__INCLUDED_)

View File

@@ -0,0 +1,653 @@
/*
** 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/>.
*/
// ColorPickerDialogClass.cpp : implementation file
//
#include "stdafx.h"
#include "colorpickerdialogclass.h"
#include "colorbar.h"
#include "colorpicker.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//extern HINSTANCE _hinstance;
/////////////////////////////////////////////////////////////////////////////
//
// Local constants
//
/////////////////////////////////////////////////////////////////////////////
const DWORD UPDATE_COLOR_BARS = 0x00000001;
const DWORD UPDATE_WHITENESS = 0x00000002;
const DWORD UPDATE_HUE_PICKER = 0x00000004;
/*class MyManageStateClass
{
public:
MyManageStateClass (void)
{
m_hResHandle = ::AfxGetResourceHandle ();
::AfxSetResourceHandle (_hinstance);
}
~MyManageStateClass (void) { ::AfxSetResourceHandle (m_hResHandle); }
private:
HINSTANCE m_hResHandle;
};*/
//#define MY_MANAGE_STATE() MyManageStateClass _xmystate;
HWND
Create_Color_Picker_Form (HWND parent, int red, int green, int blue)
{
//MY_MANAGE_STATE ()
CWnd *parent_wnd = CWnd::FromHandle (parent);
ColorPickerDialogClass *dialog = new ColorPickerDialogClass (red, green, blue, parent_wnd, IDD_COLOR_FORM);
dialog->Create_Form (parent_wnd);
//HINSTANCE old_handle = ::AfxGetResourceHandle ();
//::AfxSetResourceHandle (_hinstance);
return dialog->m_hWnd;
}
BOOL
Get_Form_Color (HWND form_wnd, int *red, int *green, int *blue)
{
//MY_MANAGE_STATE ()
BOOL retval = FALSE;
ColorPickerDialogClass *dialog = (ColorPickerDialogClass *)::GetProp (form_wnd, "COLORPICKERDLGCLASS");
if (dialog != NULL) {
(*red) = dialog->Get_Red ();
(*green) = dialog->Get_Green ();
(*blue) = dialog->Get_Blue ();
retval = TRUE;
}
return retval;
}
BOOL
Set_Form_Color (HWND form_wnd, int red, int green, int blue)
{
//MY_MANAGE_STATE ()
BOOL retval = FALSE;
ColorPickerDialogClass *dialog = (ColorPickerDialogClass *)::GetProp (form_wnd, "COLORPICKERDLGCLASS");
if (dialog != NULL) {
dialog->Set_Color (red, green, blue);
retval = TRUE;
}
return retval;
}
BOOL
Set_Form_Original_Color (HWND form_wnd, int red, int green, int blue)
{
//MY_MANAGE_STATE ()
BOOL retval = FALSE;
ColorPickerDialogClass *dialog = (ColorPickerDialogClass *)::GetProp (form_wnd, "COLORPICKERDLGCLASS");
if (dialog != NULL) {
dialog->Set_Original_Color (red, green, blue);
retval = TRUE;
}
return retval;
}
BOOL
Show_Color_Picker (int *red, int *green, int *blue)
{
//MY_MANAGE_STATE ()
BOOL retval = FALSE;
ColorPickerDialogClass dialog (*red, *green, *blue);
if (dialog.DoModal () == IDOK) {
(*red) = dialog.Get_Red ();
(*green) = dialog.Get_Green ();
(*blue) = dialog.Get_Blue ();
retval = TRUE;
}
return retval;
}
BOOL
Set_Update_Callback (HWND form_wnd, WWCTRL_COLORCALLBACK callback, void *arg)
{
//MY_MANAGE_STATE()
BOOL retval = FALSE;
ColorPickerDialogClass *dialog = (ColorPickerDialogClass *)::GetProp (form_wnd, "COLORPICKERDLGCLASS");
if (dialog != NULL) {
dialog->Set_Update_Callback(callback, arg);
retval = TRUE;
}
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// ColorPickerDialogClass
//
/////////////////////////////////////////////////////////////////////////////
ColorPickerDialogClass::ColorPickerDialogClass
(
int red,
int green,
int blue,
CWnd *pParent,
UINT res_id
)
: m_OrigRed ((float)red),
m_OrigGreen ((float)green),
m_OrigBlue ((float)blue),
m_CurrentRed ((float)red),
m_CurrentGreen ((float)green),
m_CurrentBlue ((float)blue),
m_CurrentColorBar (NULL),
m_OrigColorBar (NULL),
m_RedColorBar (NULL),
m_GreenColorBar (NULL),
m_BlueColorBar (NULL),
m_WhitenessColorBar (NULL),
m_HuePicker (NULL),
m_bDeleteOnClose (false),
m_UpdateCallback(NULL),
CDialog(res_id, pParent)
{
//{{AFX_DATA_INIT(ColorPickerDialogClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Create_Form
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerDialogClass::Create_Form (CWnd *parent)
{
Create (IDD_COLOR_FORM, parent);
SetProp (m_hWnd, "COLORPICKERDLGCLASS", (HANDLE)this);
m_bDeleteOnClose = true;
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerDialogClass::DoDataExchange (CDataExchange *pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(ColorPickerDialogClass)
DDX_Control(pDX, IDC_BLUE_SPIN, m_BlueSpin);
DDX_Control(pDX, IDC_GREEN_SPIN, m_GreenSpin);
DDX_Control(pDX, IDC_RED_SPIN, m_RedSpin);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(ColorPickerDialogClass, CDialog)
//{{AFX_MSG_MAP(ColorPickerDialogClass)
ON_BN_CLICKED(IDC_RESET, OnReset)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL
ColorPickerDialogClass::OnInitDialog (void)
{
CDialog::OnInitDialog ();
//
// Setup the spin controls
//
m_BlueSpin.SetRange (0, 255);
m_GreenSpin.SetRange (0, 255);
m_RedSpin.SetRange (0, 255);
m_BlueSpin.SetPos ((int)m_CurrentBlue);
m_GreenSpin.SetPos ((int)m_CurrentGreen);
m_RedSpin.SetPos ((int)m_CurrentRed);
//
// Get control of all the color bars on the dialog
//
m_CurrentColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_CURRENT_COLOR_BAR));
m_OrigColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_ORIG_COLOR_BAR));
m_RedColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_RED_BAR));
m_GreenColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_GREEN_BAR));
m_BlueColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_BLUE_BAR));
m_WhitenessColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_WHITENESS_BAR));
m_HuePicker = ColorPickerClass::Get_Color_Picker (::GetDlgItem (m_hWnd, IDC_HUE_PICKER));
// Setup the original color bar
m_OrigColorBar->Modify_Point (0, 0, m_OrigRed, m_OrigGreen, m_OrigBlue);
m_HuePicker->Select_Color ((int)m_OrigRed, (int)m_OrigGreen, (int)m_OrigBlue);
//m_WhitenessColorBar->Modify_Point (0, 0, m_OrigRed, m_OrigGreen, m_OrigBlue);
m_RedColorBar->Set_Range (0, 255);
m_GreenColorBar->Set_Range (0, 255);
m_BlueColorBar->Set_Range (0, 255);
m_WhitenessColorBar->Set_Range (0, 255);
m_WhitenessColorBar->Insert_Point (1, 255, 255, 255, 255);
//
// Setup the red/green/blue color bars
//
//m_RedColorBar->Insert_Point (1, 1, 255, 0, 0);
//m_GreenColorBar->Insert_Point (1, 1, 0, 255, 0);
//m_BlueColorBar->Insert_Point (1, 1, 0, 0, 255);
//
// Update the remaining color bars to reflect the initial color
//
Update_Red_Bar ();
Update_Green_Bar ();
Update_Blue_Bar ();
Update_Current_Color_Bar ();
Update_Whiteness_Bar ();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// Update_Red_Bar
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerDialogClass::Update_Red_Bar (void)
{
m_RedColorBar->Set_Selection_Pos (m_CurrentRed);
m_RedColorBar->Modify_Point (0, 0, 0, (float)m_CurrentGreen, (float)m_CurrentBlue);
m_RedColorBar->Modify_Point (1, 255, 255, (float)m_CurrentGreen, (float)m_CurrentBlue);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Update_Green_Bar
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerDialogClass::Update_Green_Bar (void)
{
m_GreenColorBar->Set_Selection_Pos (m_CurrentGreen);
m_GreenColorBar->Modify_Point (0, 0, m_CurrentRed, 0, m_CurrentBlue);
m_GreenColorBar->Modify_Point (1, 255, m_CurrentRed, 255, m_CurrentBlue);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Update_Blue_Bar
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerDialogClass::Update_Blue_Bar (void)
{
m_BlueColorBar->Set_Selection_Pos (m_CurrentBlue);
m_BlueColorBar->Modify_Point (0, 0, m_CurrentRed, m_CurrentGreen, 0);
m_BlueColorBar->Modify_Point (1, 255, m_CurrentRed, m_CurrentGreen, 255);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Update_Current_Color_Bar
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerDialogClass::Update_Current_Color_Bar (void)
{
m_CurrentColorBar->Modify_Point (0, 0, m_CurrentRed, m_CurrentGreen, m_CurrentBlue);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Update_Whiteness_Bar
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerDialogClass::Update_Whiteness_Bar (void)
{
int red = 0;
int green = 0;
int blue = 0;
m_HuePicker->Get_Current_Color (&red, &green, &blue);
//
// Given the current color, determine the 'whiteness' and update
//
float whiteness = min (m_CurrentRed, m_CurrentGreen);
whiteness = min (whiteness, m_CurrentBlue);
float percent = whiteness / 255;
m_WhitenessColorBar->Set_Selection_Pos (whiteness);
m_WhitenessColorBar->Modify_Point (0, 0, (float)red, (float)green, (float)blue);
// Can we extrapolate the starting color from the whiteness factor?
/*if (percent == 1) {
m_WhitenessColorBar->Modify_Point (0, 0, 0, 0, 0);
} else {
//
// Extrapolate the starting color
//
float start_red = (m_CurrentRed - whiteness) / (1 - percent);
float start_green = (m_CurrentGreen - whiteness) / (1 - percent);
float start_blue = (m_CurrentBlue - whiteness) / (1 - percent);
m_WhitenessColorBar->Modify_Point (0, 0, start_red, start_green, start_blue);
}*/
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnNotify
//
/////////////////////////////////////////////////////////////////////////////
BOOL
ColorPickerDialogClass::OnNotify
(
WPARAM wParam,
LPARAM lParam,
LRESULT *pResult
)
{
CBR_NMHDR *color_bar_hdr = (CBR_NMHDR *)lParam;
switch (color_bar_hdr->hdr.idFrom)
{
case IDC_RED_BAR:
{
if (color_bar_hdr->hdr.code == CBRN_SEL_CHANGED) {
float red = color_bar_hdr->red;
float green = m_CurrentGreen;
float blue = m_CurrentBlue;
Update_Color (red, green, blue);
}
}
break;
case IDC_GREEN_BAR:
{
if (color_bar_hdr->hdr.code == CBRN_SEL_CHANGED) {
float red = m_CurrentRed;
float green = color_bar_hdr->green;
float blue = m_CurrentBlue;
Update_Color (red, green, blue);
}
}
break;
case IDC_BLUE_BAR:
{
if (color_bar_hdr->hdr.code == CBRN_SEL_CHANGED) {
float red = m_CurrentRed;
float green = m_CurrentGreen;
float blue = color_bar_hdr->blue;
Update_Color (red, green, blue);
}
}
break;
case IDC_WHITENESS_BAR:
{
if (color_bar_hdr->hdr.code == CBRN_SEL_CHANGED) {
float red = color_bar_hdr->red;
float green = color_bar_hdr->green;
float blue = color_bar_hdr->blue;
Update_Color (red, green, blue, UPDATE_COLOR_BARS);
}
}
break;
case IDC_HUE_PICKER:
{
CP_NMHDR *picker_hdr = (CP_NMHDR *)lParam;
if (picker_hdr->hdr.code == CPN_COLORCHANGE) {
float red = picker_hdr->red;
float green = picker_hdr->green;
float blue = picker_hdr->blue;
float whiteness = m_WhitenessColorBar->Get_Selection_Pos () / 255;
red = red + ((255 - red) * whiteness);
green = green + ((255 - green) * whiteness);
blue = blue + ((255 - blue) * whiteness);
Update_Color (red, green, blue, UPDATE_COLOR_BARS | UPDATE_WHITENESS);
}
}
break;
case IDC_RED_SPIN:
case IDC_GREEN_SPIN:
case IDC_BLUE_SPIN:
{
if (color_bar_hdr->hdr.code == UDN_DELTAPOS) {
float red = (float)m_RedSpin.GetPos ();
float green = (float)m_GreenSpin.GetPos ();
float blue = (float)m_BlueSpin.GetPos ();
Update_Color (red, green, blue, UPDATE_COLOR_BARS | UPDATE_WHITENESS | UPDATE_HUE_PICKER);
}
}
break;
}
return CDialog::OnNotify (wParam, lParam, pResult);
}
/////////////////////////////////////////////////////////////////////////////
//
// Update_Color
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerDialogClass::Update_Color
(
float red,
float green,
float blue,
DWORD flags
)
{
/*bool update_red = m_CurrentRed != red;
bool update_green = m_CurrentGreen != green;
bool update_blue = m_CurrentBlue != blue;*/
m_CurrentRed = red;
m_CurrentGreen = green;
m_CurrentBlue = blue;
int int_blue = (int)blue;
int int_green = (int)green;
int int_red = (int)red;
if (int_blue != m_BlueSpin.GetPos ()) {
m_BlueSpin.SetPos (int_blue);
}
if (int_green != m_GreenSpin.GetPos ()) {
m_GreenSpin.SetPos (int_green);
}
if (int_red != m_RedSpin.GetPos ()) {
m_RedSpin.SetPos (int_red);
}
// Hack to get the edit controls to update in a timely fashion
::UpdateWindow (::GetDlgItem (m_hWnd, IDC_RED_EDIT));
::UpdateWindow (::GetDlgItem (m_hWnd, IDC_GREEN_EDIT));
::UpdateWindow (::GetDlgItem (m_hWnd, IDC_BLUE_EDIT));
//
// Update the red, green and blue color bars
//
if (flags & UPDATE_COLOR_BARS) {
Update_Red_Bar ();
Update_Green_Bar ();
Update_Blue_Bar ();
}
//
// Update the hue picker
//
if (flags & UPDATE_HUE_PICKER) {
m_HuePicker->Select_Color ((int)red, (int)green, (int)blue);
}
//
// Update the whiteness color bar
//
if (flags & UPDATE_WHITENESS) {
Update_Whiteness_Bar ();
}
Update_Current_Color_Bar ();
// If a callback is registered, call it.
if (m_UpdateCallback)
m_UpdateCallback((int)red, (int)green, (int)blue, m_CallArg);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Set_Original_Color
//
/////////////////////////////////////////////////////////////////////////////
void ColorPickerDialogClass::Set_Original_Color (int r, int g, int b)
{
m_OrigRed = (float)r;
m_OrigGreen = (float)g;
m_OrigBlue = (float)b;
m_OrigColorBar->Modify_Point (0, 0, m_OrigRed, m_OrigGreen, m_OrigBlue);
}
/////////////////////////////////////////////////////////////////////////////
//
// OnReset
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerDialogClass::OnReset (void)
{
Update_Color (m_OrigRed,
m_OrigGreen,
m_OrigBlue,
UPDATE_COLOR_BARS| UPDATE_WHITENESS | UPDATE_HUE_PICKER);
return ;
}
LRESULT ColorPickerDialogClass::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
return CDialog::WindowProc(message, wParam, lParam);
}
/////////////////////////////////////////////////////////////////////////////
//
// OnCommand
//
/////////////////////////////////////////////////////////////////////////////
BOOL
ColorPickerDialogClass::OnCommand
(
WPARAM wParam,
LPARAM lParam
)
{
switch (LOWORD (wParam))
{
case IDC_RED_EDIT:
case IDC_GREEN_EDIT:
case IDC_BLUE_EDIT:
{
if (HIWORD (wParam) == EN_KILLFOCUS) {
float red = (float)GetDlgItemInt (IDC_RED_EDIT);
float green = (float)GetDlgItemInt (IDC_GREEN_EDIT);
float blue = (float)GetDlgItemInt (IDC_BLUE_EDIT);
Update_Color (red, green, blue, UPDATE_COLOR_BARS| UPDATE_WHITENESS | UPDATE_HUE_PICKER);
}
}
break;
}
return CDialog::OnCommand(wParam, lParam);
}
/////////////////////////////////////////////////////////////////////////////
//
// PostNcDestroy
//
/////////////////////////////////////////////////////////////////////////////
void
ColorPickerDialogClass::PostNcDestroy (void)
{
CDialog::PostNcDestroy();
if (m_bDeleteOnClose) {
delete this;
}
return ;
}

View File

@@ -0,0 +1,136 @@
/*
** 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/>.
*/
#if !defined(AFX_COLORPICKERDIALOGCLASS_H__C943A7F1_CAA3_11D2_8DDF_00104B6FD9E3__INCLUDED_)
#define AFX_COLORPICKERDIALOGCLASS_H__C943A7F1_CAA3_11D2_8DDF_00104B6FD9E3__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// ColorPickerDialogClass.h : header file
//
#include "resource.h"
#include "colorutils.h"
/////////////////////////////////////////////////////////////////////////////
// Forward declarations
/////////////////////////////////////////////////////////////////////////////
class ColorBarClass;
class ColorPickerClass;
/////////////////////////////////////////////////////////////////////////////
//
// ColorPickerDialogClass dialog
//
class ColorPickerDialogClass : public CDialog
{
// Construction
public:
ColorPickerDialogClass (int red, int green, int blue, CWnd* pParent = NULL, UINT res_id = ColorPickerDialogClass::IDD);
// Dialog Data
//{{AFX_DATA(ColorPickerDialogClass)
enum { IDD = IDD_COLOR_PICKER };
CSpinButtonCtrl m_BlueSpin;
CSpinButtonCtrl m_GreenSpin;
CSpinButtonCtrl m_RedSpin;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(ColorPickerDialogClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
virtual void PostNcDestroy();
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(ColorPickerDialogClass)
virtual BOOL OnInitDialog();
afx_msg void OnReset();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////////
// Public methods
/////////////////////////////////////////////////////////////
int Get_Red (void) const { return (int)m_CurrentRed; }
int Get_Green (void) const { return (int)m_CurrentGreen; }
int Get_Blue (void) const { return (int)m_CurrentBlue; }
void Set_Color (int r, int g, int b)
{ Update_Color((float)r, (float)g, (float)b); }
void Set_Original_Color (int r, int g, int b);
void Create_Form (CWnd *parent);
void Set_Update_Callback (WWCTRL_COLORCALLBACK callme, void *arg)
{ m_UpdateCallback = callme; m_CallArg = arg; }
protected:
/////////////////////////////////////////////////////////////
// Protected methods
/////////////////////////////////////////////////////////////
void Update_Red_Bar (void);
void Update_Green_Bar (void);
void Update_Blue_Bar (void);
void Update_Current_Color_Bar (void);
void Update_Whiteness_Bar (void);
void Update_Color (float red, float green, float blue, DWORD flags = 0xFFFFFFFF);
private:
/////////////////////////////////////////////////////////////
// Private member data
/////////////////////////////////////////////////////////////
float m_OrigRed;
float m_OrigGreen;
float m_OrigBlue;
float m_CurrentRed;
float m_CurrentGreen;
float m_CurrentBlue;
ColorBarClass * m_CurrentColorBar;
ColorBarClass * m_OrigColorBar;
ColorBarClass * m_RedColorBar;
ColorBarClass * m_GreenColorBar;
ColorBarClass * m_BlueColorBar;
ColorBarClass * m_WhitenessColorBar;
ColorPickerClass *m_HuePicker;
bool m_bDeleteOnClose;
// Callback function when color is updated.
WWCTRL_COLORCALLBACK m_UpdateCallback;
void * m_CallArg;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_COLORPICKERDIALOGCLASS_H__C943A7F1_CAA3_11D2_8DDF_00104B6FD9E3__INCLUDED_)

View File

@@ -0,0 +1,345 @@
/*
** 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/>.
*/
// ColorSelectionDialog.cpp : implementation file
//
#include "StdAfx.H"
#include "W3DView.H"
#include "ColorSelectionDialog.H"
#include "Utils.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////
//
// ColorSelectionDialogClass
//
ColorSelectionDialogClass::ColorSelectionDialogClass
(
const Vector3 &def_color,
CWnd *pParent
)
: m_Color (def_color),
m_PaintColor (def_color),
CDialog(ColorSelectionDialogClass::IDD, pParent)
{
//{{AFX_DATA_INIT(ColorSelectionDialogClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
/////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
ColorSelectionDialogClass::DoDataExchange (CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(ColorSelectionDialogClass)
DDX_Control(pDX, IDC_BLUE_SPIN, m_BlueSpin);
DDX_Control(pDX, IDC_GREEN_SPIN, m_GreenSpin);
DDX_Control(pDX, IDC_RED_SPIN, m_RedSpin);
DDX_Control(pDX, IDC_COLOR_WINDOW, m_ColorWindow);
DDX_Control(pDX, IDC_SLIDER_BLUE, m_BlueSlider);
DDX_Control(pDX, IDC_SLIDER_GREEN, m_GreenSlider);
DDX_Control(pDX, IDC_SLIDER_RED, m_RedSlider);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(ColorSelectionDialogClass, CDialog)
//{{AFX_MSG_MAP(ColorSelectionDialogClass)
ON_WM_HSCROLL()
ON_WM_PAINT()
ON_BN_CLICKED(IDC_GRAYSCALE_CHECK, OnGrayscaleCheck)
ON_EN_CHANGE(IDC_BLUE_EDIT, OnChangeBlueEdit)
ON_EN_CHANGE(IDC_GREEN_EDIT, OnChangeGreenEdit)
ON_EN_CHANGE(IDC_RED_EDIT, OnChangeRedEdit)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////
//
// ColorSelectionDialogClass
//
BOOL
ColorSelectionDialogClass::OnInitDialog (void)
{
// Allow the base class to process this message
CDialog::OnInitDialog ();
// Set the ranges of the slider and spin controls
m_RedSlider.SetRange (0, 255);
m_GreenSlider.SetRange (0, 255);
m_BlueSlider.SetRange (0, 255);
m_RedSpin.SetRange (0, 255);
m_GreenSpin.SetRange (0, 255);
m_BlueSpin.SetRange (0, 255);
// Determine the initial settings (in integers)
int red_value = int(m_Color.X * 255.00F);
int green_value = int(m_Color.Y * 255.00F);
int blue_value = int(m_Color.Z * 255.00F);
if ((red_value == green_value) &&
(red_value == blue_value)) {
// Check the grayscale checkbox
SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_SETCHECK, (WPARAM)TRUE);
}
// Set the initial slider positions
m_RedSlider.SetPos (red_value);
m_GreenSlider.SetPos (green_value);
m_BlueSlider.SetPos (blue_value);
m_RedSpin.SetPos (red_value);
m_GreenSpin.SetPos (green_value);
m_BlueSpin.SetPos (blue_value);
return TRUE;
}
/////////////////////////////////////////////////////////////////
//
// ColorSelectionDialogClass
//
void
ColorSelectionDialogClass::OnOK (void)
{
// Record the color
m_Color = m_PaintColor;
// Allow the base class to process this message
CDialog::OnOK ();
return ;
}
/////////////////////////////////////////////////////////////////
//
// OnHScroll
//
void
ColorSelectionDialogClass::OnHScroll
(
UINT nSBCode,
UINT nPos,
CScrollBar *pScrollBar
)
{
// Update the slider positions and the color window
Update_Sliders (::GetWindowLong (*pScrollBar, GWL_ID));
// Allow the base class to process this message
CDialog::OnHScroll (nSBCode, nPos, pScrollBar);
return ;
}
/////////////////////////////////////////////////////////////////
//
// OnPaint
//
void
ColorSelectionDialogClass::OnPaint (void)
{
CPaintDC dc (this);
// Paint the gradients for each color
::Paint_Gradient (::GetDlgItem (m_hWnd, IDC_RED_GRADIENT), 1, 0, 0);
::Paint_Gradient (::GetDlgItem (m_hWnd, IDC_GREEN_GRADIENT), 0, 1, 0);
::Paint_Gradient (::GetDlgItem (m_hWnd, IDC_BLUE_GRADIENT), 0, 0, 1);
// Update the window that displays the color the user has selected
Paint_Color_Window ();
return ;
}
/////////////////////////////////////////////////////////////////
//
// Paint_Color_Window
//
void
ColorSelectionDialogClass::Paint_Color_Window (void)
{
// Get the client coords of the 'color' window
CRect rect;
m_ColorWindow.GetClientRect (&rect);
// Fill the window with the selected color
CDC *pdc = m_ColorWindow.GetDC ();
::FrameRect (*pdc, &rect, (HBRUSH)::GetStockObject (BLACK_BRUSH));
rect.DeflateRect (1, 1);
pdc->FillSolidRect (&rect, RGB (int(m_PaintColor.X * 255), int(m_PaintColor.Y * 255), int(m_PaintColor.Z * 255)));
m_ColorWindow.ReleaseDC (pdc);
// Let the window know it doesn't need to be repainted
m_ColorWindow.ValidateRect (NULL);
return;
}
/////////////////////////////////////////////////////////////////
//
// OnGrayscaleCheck
//
void
ColorSelectionDialogClass::OnGrayscaleCheck (void)
{
// Is the checkbox checked?
if (SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_GETCHECK)) {
// Make the green and blue sliders the same as red
m_GreenSlider.SetPos (m_RedSlider.GetPos ());
m_BlueSlider.SetPos (m_RedSlider.GetPos ());
m_PaintColor.X = float(m_RedSlider.GetPos ()) / 255.00F;
m_PaintColor.Y = float(m_GreenSlider.GetPos ()) / 255.00F;
m_PaintColor.Z = float(m_BlueSlider.GetPos ()) / 255.00F;
// Update the window that displays the color the user has selected
Paint_Color_Window ();
}
return ;
}
/////////////////////////////////////////////////////////////////
//
// OnChangeBlueEdit
//
void
ColorSelectionDialogClass::OnChangeBlueEdit (void)
{
if (::IsWindow (m_BlueSlider)) {
int value = GetDlgItemInt (IDC_BLUE_EDIT);
m_BlueSlider.SetPos (value);
// Update the slider positions and the color window
Update_Sliders (IDC_SLIDER_BLUE);
// Reset the cursor to the end of the edit box
SendDlgItemMessage (IDC_BLUE_EDIT, EM_SETSEL, (WPARAM)(int)10, (LPARAM)(int)20);
}
return ;
}
/////////////////////////////////////////////////////////////////
//
// OnChangeGreenEdit
//
void
ColorSelectionDialogClass::OnChangeGreenEdit (void)
{
if (::IsWindow (m_GreenSlider)) {
int value = GetDlgItemInt (IDC_GREEN_EDIT);
m_GreenSlider.SetPos (value);
// Update the slider positions and the color window
Update_Sliders (IDC_SLIDER_GREEN);
// Reset the cursor to the end of the edit box
SendDlgItemMessage (IDC_GREEN_EDIT, EM_SETSEL, (WPARAM)(int)10, (LPARAM)(int)20);
}
return ;
}
/////////////////////////////////////////////////////////////////
//
// OnChangeRedEdit
//
void
ColorSelectionDialogClass::OnChangeRedEdit (void)
{
if (::IsWindow (m_RedSlider)) {
int value = GetDlgItemInt (IDC_RED_EDIT);
m_RedSlider.SetPos (value);
// Update the slider positions and the color window
Update_Sliders (IDC_SLIDER_RED);
// Reset the cursor to the end of the edit box
SendDlgItemMessage (IDC_RED_EDIT, EM_SETSEL, (WPARAM)(int)10, (LPARAM)(int)20);
}
return ;
}
/////////////////////////////////////////////////////////////////
//
// Update_Sliders
//
void
ColorSelectionDialogClass::Update_Sliders (int slider_id)
{
// Are the sliders moving together?
if (SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_GETCHECK)) {
int position = 0;
// Determine which slider sent this message and
// use its current position
if (slider_id == IDC_SLIDER_RED) {
position = m_RedSlider.GetPos ();
} else if (slider_id == IDC_SLIDER_GREEN) {
position = m_GreenSlider.GetPos ();
} else {
position = m_BlueSlider.GetPos ();
}
// Make all the sliders the same pos
m_RedSlider.SetPos (position);
m_GreenSlider.SetPos (position);
m_BlueSlider.SetPos (position);
}
// Update the edit controls (and their spin controls)
float red_val = m_RedSlider.GetPos ();
float green_val = m_GreenSlider.GetPos ();
float blue_val = m_BlueSlider.GetPos ();
m_RedSpin.SetPos (red_val);
m_GreenSpin.SetPos (green_val);
m_BlueSpin.SetPos (blue_val);
// Record the selected color for later use
m_PaintColor.X = red_val / 255.00F;
m_PaintColor.Y = green_val / 255.00F;
m_PaintColor.Z = blue_val / 255.00F;
// Update the window that displays the color the user has selected
Paint_Color_Window ();
return ;
}

View File

@@ -0,0 +1,109 @@
/*
** 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/>.
*/
#if !defined(AFX_OLORSELECTIONDIALOG_H__C0BCECAE_B6EA_11D2_9FF8_00104B791122__INCLUDED_)
#define AFX_OLORSELECTIONDIALOG_H__C0BCECAE_B6EA_11D2_9FF8_00104B791122__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ColorSelectionDialog.h : header file
//
#include "Resource.H"
#include "Vector3.H"
/////////////////////////////////////////////////////////////////////////////
//
// ColorSelectionDialogClass dialog
//
class ColorSelectionDialogClass : public CDialog
{
// Construction
public:
ColorSelectionDialogClass (const Vector3 &def_color, CWnd *pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(ColorSelectionDialogClass)
enum { IDD = IDD_COLOR_SEL };
CSpinButtonCtrl m_BlueSpin;
CSpinButtonCtrl m_GreenSpin;
CSpinButtonCtrl m_RedSpin;
CStatic m_ColorWindow;
CSliderCtrl m_BlueSlider;
CSliderCtrl m_GreenSlider;
CSliderCtrl m_RedSlider;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(ColorSelectionDialogClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(ColorSelectionDialogClass)
virtual BOOL OnInitDialog();
virtual void OnOK();
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnPaint();
afx_msg void OnGrayscaleCheck();
afx_msg void OnChangeBlueEdit();
afx_msg void OnChangeGreenEdit();
afx_msg void OnChangeRedEdit();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
///////////////////////////////////////////////////////
//
// Public methods
//
const Vector3 & Get_Color (void) const { return m_Color; }
void Set_Color (const Vector3 &color) { m_Color = color; }
protected:
///////////////////////////////////////////////////////
//
// Inline accessors
//
void Paint_Color_Window (void);
void Update_Sliders (int slider_id);
private:
///////////////////////////////////////////////////////
//
// Private member data
//
Vector3 m_Color;
Vector3 m_PaintColor;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_OLORSELECTIONDIALOG_H__C0BCECAE_B6EA_11D2_9FF8_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,188 @@
/*
** 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
//
//
#include "StdAfx.H"
#include "ColorUtils.H"
/////////////////////////////////////////////////////////////////////////////
//
// Draw_Sunken_Rect
//
void
Draw_Sunken_Rect
(
UCHAR *pbits,
const RECT &rect,
int scanline_size
)
{
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
// Draw the 4 lines that compose the rectangle
::Draw_Vert_Line (pbits, rect.left, rect.top, height, ::GetSysColor (COLOR_3DSHADOW), scanline_size);
::Draw_Vert_Line (pbits, rect.right-1, rect.top, height, ::GetSysColor (COLOR_3DHIGHLIGHT), scanline_size);
::Draw_Horz_Line (pbits, rect.left, rect.top, width, ::GetSysColor (COLOR_3DSHADOW), scanline_size);
::Draw_Horz_Line (pbits, rect.left, rect.bottom-1, width, ::GetSysColor (COLOR_3DHIGHLIGHT), scanline_size);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Draw_Raised_Rect
//
void
Draw_Raised_Rect
(
UCHAR *pbits,
const RECT &rect,
int scanline_size
)
{
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
// Draw the 4 lines that compose the rectangle
::Draw_Vert_Line (pbits, rect.left, rect.top, height, ::GetSysColor (COLOR_3DHIGHLIGHT), scanline_size);
::Draw_Vert_Line (pbits, rect.right-1, rect.top, height, ::GetSysColor (COLOR_3DSHADOW), scanline_size);
::Draw_Horz_Line (pbits, rect.left, rect.top, width, ::GetSysColor (COLOR_3DHIGHLIGHT), scanline_size);
::Draw_Horz_Line (pbits, rect.left, rect.bottom-1, width, ::GetSysColor (COLOR_3DSHADOW), scanline_size);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Frame_Rect
//
void
Frame_Rect
(
UCHAR *pbits,
const RECT &rect,
COLORREF color,
int scanline_size
)
{
UCHAR red = GetRValue (color);
UCHAR green = GetRValue (color);
UCHAR blue = GetRValue (color);
int index = (rect.top * scanline_size) + (rect.left * 3);
for (int col = rect.left; col < rect.right; col ++) {
pbits[index++] = blue;
pbits[index++] = green;
pbits[index++] = red;
}
index = ((rect.bottom-1) * scanline_size) + (rect.left * 3);
for (col = rect.left; col < rect.right; col ++) {
pbits[index++] = blue;
pbits[index++] = green;
pbits[index++] = red;
}
index = (rect.top * scanline_size) + (rect.left * 3);
for (int row = rect.top; row < rect.bottom; row ++) {
pbits[index] = blue;
pbits[index + 1] = green;
pbits[index + 2] = red;
index += scanline_size;
}
index = (rect.top * scanline_size) + ((rect.right-1) * 3);
for (row = rect.top; row < rect.bottom; row ++) {
pbits[index] = blue;
pbits[index + 1] = green;
pbits[index + 2] = red;
index += scanline_size;
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Draw_Vert_Line
//
void
Draw_Vert_Line
(
UCHAR *pbits,
int x,
int y,
int len,
COLORREF color,
int scanline_size
)
{
UCHAR red = GetRValue (color);
UCHAR green = GetRValue (color);
UCHAR blue = GetRValue (color);
int index = (y * scanline_size) + (x * 3);
for (int row = y; row < len; row ++) {
pbits[index] = blue;
pbits[index + 1] = green;
pbits[index + 2] = red;
index += scanline_size;
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Draw_Horz_Line
//
void
Draw_Horz_Line
(
UCHAR *pbits,
int x,
int y,
int len,
COLORREF color,
int scanline_size
)
{
UCHAR red = GetRValue (color);
UCHAR green = GetRValue (color);
UCHAR blue = GetRValue (color);
int index = (y * scanline_size) + (x * 3);
for (int col = x; col < len; col ++) {
pbits[index++] = blue;
pbits[index++] = green;
pbits[index++] = red;
}
return ;
}

View File

@@ -0,0 +1,51 @@
/*
** 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/>.
*/
//////////////////////////////////////////////////////////////////////////////////////////
//
// ColorUtils.H
//
//
#ifndef __COLORUTILS_H
#define __COLORUTILS_H
/////////////////////////////////////////////////////////////////////////////
// Callbacks
/////////////////////////////////////////////////////////////////////////////
typedef void (*WWCTRL_COLORCALLBACK)(int,int,int,void*);
/////////////////////////////////////////////////////////////////////////////
// Prototypes
/////////////////////////////////////////////////////////////////////////////
void Frame_Rect (UCHAR *pbits, const RECT &rect, COLORREF color, int scanline_size);
void Draw_Vert_Line (UCHAR *pbits, int x, int y, int len, COLORREF color, int scanline_size);
void Draw_Horz_Line (UCHAR *pbits, int x, int y, int len, COLORREF color, int scanline_size);
void Draw_Sunken_Rect (UCHAR *pbits, const RECT &rect, int scanline_size);
void Draw_Raised_Rect (UCHAR *pbits, const RECT &rect, int scanline_size);
BOOL Show_Color_Picker (int *red, int *green, int *blue);
HWND Create_Color_Picker_Form (HWND parent, int red, int green, int blue);
BOOL Get_Form_Color (HWND form_wnd, int *red, int *green, int *blue);
BOOL Set_Form_Color (HWND form_wnd, int red, int green, int blue);
BOOL Set_Form_Original_Color (HWND form_wnd, int red, int green, int blue);
BOOL Set_Update_Callback (HWND form_wnd, WWCTRL_COLORCALLBACK callback, void *arg=NULL);
void RegisterColorPicker (HINSTANCE hinst);
void RegisterColorBar (HINSTANCE hinst);
#endif //__COLORUTILS_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,180 @@
/*
** 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/>.
*/
#if !defined(AFX_DATATREEVIEW_H__2BB39E40_5D3A_11D2_9FC6_00104B791122__INCLUDED_)
#define AFX_DATATREEVIEW_H__2BB39E40_5D3A_11D2_9FC6_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// DataTreeView.h : header file
//
#include "AfxCView.H"
#include "AssetTypes.H"
#include "Vector.H"
// Forward declarations
class RenderObjClass;
class AssetInfoClass;
/////////////////////////////////////////////////////////////////////////////
//
// CDataTreeView view
//
class CDataTreeView : public CTreeView
{
protected:
CDataTreeView(); // protected constructor used by dynamic creation
DECLARE_DYNCREATE(CDataTreeView)
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDataTreeView)
public:
virtual void OnInitialUpdate();
protected:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
//}}AFX_VIRTUAL
// Implementation
protected:
virtual ~CDataTreeView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
// Generated message map functions
protected:
//{{AFX_MSG(CDataTreeView)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSelChanged(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnDeleteItem(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnDblclk(NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////////////////
// Public methods
/////////////////////////////////////////////////////////////////////
//
// Asset insertion methods
//
bool Add_Asset_To_Tree (LPCTSTR name, ASSET_TYPE type, bool bselect);
void LoadAssetsIntoTree (void);
void Refresh_Asset (LPCTSTR new_name, LPCTSTR old_name, ASSET_TYPE type);
//
// Animation insertion methods
//
void LoadAnimationsIntoTree (void);
void LoadAnimationsIntoTree (HTREEITEM hItem);
bool Are_Anims_Restricted (void) const { return m_RestrictAnims; }
void Restrict_Anims (bool onoff);
//
// Texture insertion methods
//
void Load_Materials_Into_Tree (void);
//
// Display methods
//
void Display_Asset (HTREEITEM htree_item = NULL);
void Select_Next (void);
void Select_Prev (void);
void Reload_Lightmap_Models (void);
//
// Information methods
//
RenderObjClass * Get_Current_Render_Obj (void) const;
AssetInfoClass * Get_Current_Asset_Info (void) const;
LPCTSTR GetCurrentSelectionName (void);
ASSET_TYPE GetCurrentSelectionType (void);
HTREEITEM FindChildItem (HTREEITEM hParentItem, LPCTSTR pszChildItemName);
HTREEITEM FindChildItem (HTREEITEM hParentItem, RenderObjClass *prender_obj);
HTREEITEM FindFirstChildItemBasedOnHierarchyName (HTREEITEM hParentItem, LPCTSTR pszHierarchyName);
HTREEITEM FindSiblingItemBasedOnHierarchyName (HTREEITEM hCurrentItem, LPCTSTR pszHierarchyName);
void Build_Render_Object_List (DynamicVectorClass <CString> &asset_list, HTREEITEM hparent = TVI_ROOT);
//
// Initialization methods
//
void CreateRootNodes (void);
protected:
///////////////////////////////////////////////////////////////////////
// Protected methods
///////////////////////////////////////////////////////////////////////
ASSET_TYPE Determine_Tree_Location (RenderObjClass &render_obj, HTREEITEM &hroot, int &icon_index);
void Determine_Tree_Location (ASSET_TYPE type, HTREEITEM &hroot, int &icon_index);
RenderObjClass * Create_Render_Obj_To_Display (HTREEITEM htree_item);
void Add_Emitters_To_Menu (HMENU hmenu, RenderObjClass &render_obj);
void Free_Child_Models (HTREEITEM parent_item);
private:
///////////////////////////////////////////////////////
//
// Private member data
//
HTREEITEM m_hMaterialsRoot;
HTREEITEM m_hMeshRoot;
HTREEITEM m_hAggregateRoot;
HTREEITEM m_hLODRoot;
HTREEITEM m_hMeshCollectionRoot;
HTREEITEM m_hEmitterRoot;
HTREEITEM m_hPrimitivesRoot;
HTREEITEM m_hHierarchyRoot;
HTREEITEM m_hSoundRoot;
int m_iAnimationIcon;
int m_iTCAnimationIcon;
int m_iADAnimationIcon;
int m_iMeshIcon;
int m_iMaterialIcon;
int m_iLODIcon;
int m_iEmitterIcon;
int m_iPrimitivesIcon;
int m_iAggregateIcon;
int m_iHierarchyIcon;
int m_iSoundIcon;
bool m_RestrictAnims;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_DATATREEVIEW_H__2BB39E40_5D3A_11D2_9FC6_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,248 @@
/*
** 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/>.
*/
// DeviceSelectionDialog.cpp : implementation file
//
#include "StdAfx.H"
#include "W3DView.h"
#include "DeviceSelectionDialog.h"
#include "WW3D.H"
#include "Resource.H"
#include "Globals.h"
#include "W3DView.H"
#include "Utils.H"
#include "rddesc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDeviceSelectionDialog dialog
////////////////////////////////////////////////////////////////////
//
// CDeviceSelectionDialog
//
CDeviceSelectionDialog::CDeviceSelectionDialog
(
BOOL bLookupCachedInfo,
CWnd* pParent /*=NULL*/
)
: m_iDeviceIndex (1),
m_iBitsPerPixel (16),
m_bLookupCachedInfo (bLookupCachedInfo),
CDialog(CDeviceSelectionDialog::IDD, pParent)
{
//{{AFX_DATA_INIT(CDeviceSelectionDialog)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
////////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
CDeviceSelectionDialog::DoDataExchange (CDataExchange* pDX)
{
// Allow the base class to process this message
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDeviceSelectionDialog)
DDX_Control(pDX, IDC_RENDER_DEVICE_COMBO, m_deviceListComboBox);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(CDeviceSelectionDialog, CDialog)
//{{AFX_MSG_MAP(CDeviceSelectionDialog)
ON_CBN_SELCHANGE(IDC_RENDER_DEVICE_COMBO, OnSelchangeRenderDeviceCombo)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDeviceSelectionDialog message handlers
////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
CDeviceSelectionDialog::OnInitDialog (void)
{
CDialog::OnInitDialog();
//
// Loop through all the devices and add them to the combobox
//
int device_count = WW3D::Get_Render_Device_Count ();
int selected_index = 0;
for (int index = 0; index < device_count; index ++) {
//
// Add this device to the combobox
//
const char *name = WW3D::Get_Render_Device_Name(index);
int combo_index = m_deviceListComboBox.InsertString (index, name);
if (m_DriverName.CompareNoCase (name) == 0) {
selected_index = combo_index;
}
// Associate the index of this device with the item we just inserted
m_deviceListComboBox.SetItemData (combo_index, index);
}
// Check the '16bpp' radio by default
SendDlgItemMessage (IDC_COLORDEPTH_16, BM_SETCHECK, (WPARAM)TRUE);
// Force the first entry in the combobox to be selected.
//m_deviceListComboBox.SetCurSel (0);
m_deviceListComboBox.SetCurSel (selected_index);
// Update the static controls on the dialog to reflect the device
UpdateDeviceDescription ();
return TRUE;
}
////////////////////////////////////////////////////////////////////
//
// OnSelchangeRenderDeviceCombo
//
void
CDeviceSelectionDialog::OnSelchangeRenderDeviceCombo (void)
{
int index = m_deviceListComboBox.GetCurSel ();
if (index != CB_ERR) {
//WW3D::Set_Render_Device ();
// Update the static controls with the information from the device
UpdateDeviceDescription ();
}
return ;
}
////////////////////////////////////////////////////////////////////
//
// UpdateDeviceDescription
//
void
CDeviceSelectionDialog::UpdateDeviceDescription (void)
{
const RenderDeviceDescClass &device_desc = WW3D::Get_Render_Device_Desc ();
//
// Reload the static text controls on the dialog
//
SetDlgItemText (IDC_DRIVER_NAME, m_DriverName);
SetDlgItemText (IDC_DEVICE_NAME_STATIC, device_desc.Get_Device_Name());
SetDlgItemText (IDC_DEVICE_VENDOR_STATIC, device_desc.Get_Device_Vendor());
SetDlgItemText (IDC_DEVICE_PLATFORM_STATIC, device_desc.Get_Device_Platform());
SetDlgItemText (IDC_DRIVER_NAME_STATIC, device_desc.Get_Driver_Name());
SetDlgItemText (IDC_DRIVER_VENDOR_STATIC, device_desc.Get_Driver_Vendor());
SetDlgItemText (IDC_DRIVER_VERSION_STATIC, device_desc.Get_Driver_Version());
SetDlgItemText (IDC_HARDWARE_NAME_STATIC, device_desc.Get_Hardware_Name());
SetDlgItemText (IDC_HARDWARE_VENDOR_STATIC, device_desc.Get_Hardware_Vendor());
SetDlgItemText (IDC_HARDWARE_CHIPSET_STATIC, device_desc.Get_Hardware_Chipset());
return ;
}
////////////////////////////////////////////////////////////////////
//
// OnOK
//
void
CDeviceSelectionDialog::OnOK (void)
{
// Ask the combobox for its current selection
m_iDeviceIndex = m_deviceListComboBox.GetItemData (m_deviceListComboBox.GetCurSel ());
m_iBitsPerPixel = (SendDlgItemMessage (IDC_COLORDEPTH_16, BM_GETCHECK) == TRUE) ? 16 : 24;
// Get the device name of the currently selected device
CString stringDeviceName;
m_deviceListComboBox.GetLBText (m_deviceListComboBox.GetCurSel (), stringDeviceName);
m_DriverName = stringDeviceName;
// Cache this information in the registry
theApp.WriteProfileString ("Config", "DeviceName", stringDeviceName);
theApp.WriteProfileInt ("Config", "DeviceBitsPerPix", m_iBitsPerPixel);
// Allow the base class to process this message
CDialog::OnOK();
return ;
}
////////////////////////////////////////////////////////////////////
//
// DoModal
//
int
CDeviceSelectionDialog::DoModal (void)
{
BOOL bFoundDevice = FALSE;
int iReturn = IDOK;
// Get the name of the last used device driver from the registry
m_DriverName = theApp.GetProfileString ("Config", "DeviceName");
if (m_bLookupCachedInfo &&
(m_DriverName.GetLength () > 0) &&
!(::GetKeyState (VK_SHIFT) & 0xF000)) {
//
// Loop through all the devices and see if we can find the right one
//
int device_count = WW3D::Get_Render_Device_Count ();
for (int index = 0; (index < device_count) && !bFoundDevice; index ++) {
//
// Is this the device we are looking for?
//
const char *name = WW3D::Get_Render_Device_Name (index);
if (m_DriverName.CompareNoCase (name) == 0) {
//
// Set the internal device information to simulate 'showing' the dialog
//
m_iDeviceIndex = index;
m_iBitsPerPixel = theApp.GetProfileInt ("Config", "DeviceBitsPerPix", 16);
// Found it!
bFoundDevice = TRUE;
}
}
}
// Show the dialog and allow the user to select the device
if (bFoundDevice == FALSE) {
iReturn = CDialog::DoModal ();
}
// Return the integer return code
return iReturn;
}

View File

@@ -0,0 +1,90 @@
/*
** 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/>.
*/
#if !defined(AFX_DEVICESELECTIONDIALOG_H__49E2DFF9_5D3F_11D2_9FC6_00104B791122__INCLUDED_)
#define AFX_DEVICESELECTIONDIALOG_H__49E2DFF9_5D3F_11D2_9FC6_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// DeviceSelectionDialog.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CDeviceSelectionDialog dialog
class CDeviceSelectionDialog : public CDialog
{
// Construction
public:
CDeviceSelectionDialog(BOOL bLookupCachedInfo = TRUE, CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CDeviceSelectionDialog)
enum { IDD = IDD_RENDER_DEVICE_SELECTOR };
CComboBox m_deviceListComboBox;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDeviceSelectionDialog)
public:
virtual int DoModal();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CDeviceSelectionDialog)
virtual BOOL OnInitDialog();
afx_msg void OnSelchangeRenderDeviceCombo();
virtual void OnOK();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
// Return the selected device index
int GetDeviceIndex () const
{ return m_iDeviceIndex; }
// Return the selected bits per pixel
int GetBitsPerPixel () const
{ return m_iBitsPerPixel; }
const CString &GetDriverName () const
{ return m_DriverName; }
protected:
void UpdateDeviceDescription (void);
private:
BOOL m_bLookupCachedInfo;
int m_iDeviceIndex;
int m_iBitsPerPixel;
CString m_DriverName;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_DEVICESELECTIONDIALOG_H__49E2DFF9_5D3F_11D2_9FC6_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,147 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : LevelEdit *
* *
* $Archive:: /Commando/Code/Tools/W3DView/DialogToolbar.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 2/23/99 10:58a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "StdAfx.H"
#include "DialogToolbar.H"
#include "AfxPriv.H"
BEGIN_MESSAGE_MAP(DialogToolbarClass, CToolBar)
//{{AFX_MSG_MAP(DialogToolbarClass)
ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
ON_MESSAGE_VOID(WM_INITIALUPDATE, OnInitialUpdate)
ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnNeedToolTipText)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
DialogToolbarClass::DialogToolbarClass (void)
: CToolBar ()
{
//{{AFX_DATA_INIT(DialogToolbarClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
#ifdef _DEBUG
void DialogToolbarClass::AssertValid() const
{
CToolBar::AssertValid();
}
void DialogToolbarClass::Dump(CDumpContext& dc) const
{
CToolBar::Dump(dc);
}
#endif //_DEBUG
///////////////////////////////////////////////////////////////////
//
// Enable_Button
//
void
DialogToolbarClass::Enable_Button
(
int id,
bool benable
)
{
// Get the button's style (we enable by using a style bit)
int index = CommandToIndex (id);
UINT style = GetButtonStyle (index) & (~TBBS_DISABLED);
// If we are disabling the button, set the
// disabled style bit.
if (benable == false) {
style |= TBBS_DISABLED;
style &= ~TBBS_PRESSED;
}
// If the button isn't a separator, then modify its style
if (!(style & TBBS_SEPARATOR)) {
SetButtonStyle (index, style);
}
return ;
}
///////////////////////////////////////////////////////////////////
//
// OnIdleUpdateCmdUI
//
LRESULT
DialogToolbarClass::OnIdleUpdateCmdUI (WPARAM, LPARAM)
{
return 0L;
}
///////////////////////////////////////////////////////////////////
//
// OnInitialUpdate
//
void
DialogToolbarClass::OnInitialUpdate (void)
{
return ;
}
///////////////////////////////////////////////////////////////////
//
// OnNotify
//
BOOL
DialogToolbarClass::OnNeedToolTipText
(
UINT id,
NMHDR *pTTTStruct,
LRESULT *pResult
)
{
if (pTTTStruct->code == TTN_NEEDTEXTA) {
TOOLTIPTEXTA *ptooltip_info = (TOOLTIPTEXTA*)pTTTStruct;
::lstrcpy (ptooltip_info->szText, "test");
}
(*pResult) = 0L;
return TRUE;
}

View File

@@ -0,0 +1,105 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : LevelEdit *
* *
* $Archive:: /Commando/Code/Tools/W3DView/DialogToolbar.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 2/23/99 10:58a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __DIALOGTOOLBAR_H
#define __DIALOGTOOLBAR_H
#include "Resource.H"
/////////////////////////////////////////////////////////////////
//
// DialogToolbarClass
//
class DialogToolbarClass : public CToolBar
{
public:
DialogToolbarClass (void);
virtual ~DialogToolbarClass (void) {}
// Form Data
public:
//{{AFX_DATA(DialogToolbarClass)
//}}AFX_DATA
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(DialogToolbarClass)
protected:
//}}AFX_VIRTUAL
// Implementation
protected:
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
// Generated message map functions
//{{AFX_MSG(DialogToolbarClass)
afx_msg LRESULT OnIdleUpdateCmdUI(WPARAM wParam, LPARAM lParam);
afx_msg void OnInitialUpdate();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
//virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
BOOL OnNeedToolTipText (UINT id, NMHDR *pTTTStruct, LRESULT *pResult);
public:
///////////////////////////////////////////////////////
//
// Public methods
//
void Enable_Button (int id, bool benable = true);
};
#endif //__DIALOGTOOLBAR_H

View File

@@ -0,0 +1,104 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : W3DView *
* *
* $Archive:: /Commando/Code/Tools/W3DView/DirectoryDialog.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/25/00 2:56p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "stdafx.h"
#include "directorydialog.h"
#include "utils.h"
////////////////////////////////////////////////////////////////////////////
//
// Browse_For_Folder_Hook_Proc
//
////////////////////////////////////////////////////////////////////////////
UINT CALLBACK Browse_For_Folder_Hook_Proc
(
HWND hdlg,
UINT message,
WPARAM wparam,
LPARAM lparam
)
{
//
// If the user clicked OK, then stuff a dummy filename
// into the control so the dialog will close...
//
if ( message == WM_COMMAND &&
LOWORD (wparam) == IDOK &&
HIWORD (wparam) == BN_CLICKED)
{
::SetDlgItemText (hdlg, 1152, "xxx.xxx");
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////
//
// Browse_For_Folder
//
////////////////////////////////////////////////////////////////////////////
bool
Browse_For_Folder (HWND parent_wnd, LPCTSTR initial_path, CString &path)
{
bool retval = false;
OPENFILENAME openfilename = { sizeof (OPENFILENAME), 0 };
TCHAR filename[MAX_PATH] = { 0 };
openfilename.lpstrInitialDir = initial_path;
openfilename.hwndOwner = parent_wnd;
openfilename.hInstance = ::AfxGetResourceHandle ();
openfilename.lpstrFilter = _T("\0\0");
openfilename.lpstrFile = filename;
openfilename.nMaxFile = sizeof (filename);
openfilename.lpstrTitle = _T("Choose Directory");
openfilename.lpfnHook = Browse_For_Folder_Hook_Proc;
openfilename.lpTemplateName = MAKEINTRESOURCE (1536);
openfilename.Flags = OFN_HIDEREADONLY | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_LONGNAMES;
//
// Display the modified 'file-open' dialog.
//
if (::GetOpenFileName (&openfilename) == IDOK) {
path = ::Strip_Filename_From_Path (filename);
retval = true;
}
return retval;
}

View File

@@ -0,0 +1,55 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : W3DView *
* *
* $Archive:: /Commando/Code/Tools/W3DView/DirectoryDialog.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/25/00 2:52p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __DIRECTORY_DIALOG_H
#define __DIRECTORY_DIALOG_H
/////////////////////////////////////////////////////////////////////////
//
// Prototypes
//
/////////////////////////////////////////////////////////////////////////
bool Browse_For_Folder (HWND parent_wnd, LPCTSTR initial_path, CString &path);
#endif //__DIRECTORY_DIALOG_H

View File

@@ -0,0 +1,504 @@
/*
** 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/>.
*/
// EditLODDialog.cpp : implementation file
//
#include "stdafx.h"
#include "W3DView.h"
#include "EditLODDialog.h"
#include "DistLod.H"
#include "Utils.H"
#include "RendObj.H"
#include "W3DViewDoc.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////
//
// Local Constants
//
const int COL_NAME = 0;
const int COL_SWITCH_UP = 1;
const int COL_SWITCH_DN = 2;
/////////////////////////////////////////////////////////////
//
// CEditLODDialog
//
CEditLODDialog::CEditLODDialog(CWnd* pParent /*=NULL*/)
: m_spinIncrement (0.5F),
CDialog(CEditLODDialog::IDD, pParent)
{
//{{AFX_DATA_INIT(CEditLODDialog)
//}}AFX_DATA_INIT
return ;
}
/////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
CEditLODDialog::DoDataExchange (CDataExchange* pDX)
{
// Allow the base class to process this message
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CEditLODDialog)
DDX_Control(pDX, IDC_SWITCH_UP_SPIN, m_switchUpSpin);
DDX_Control(pDX, IDC_SWITCH_DN_SPIN, m_switchDownSpin);
DDX_Control(pDX, IDC_HIERARCHY_LIST, m_hierarchyListCtrl);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(CEditLODDialog, CDialog)
//{{AFX_MSG_MAP(CEditLODDialog)
ON_NOTIFY(UDN_DELTAPOS, IDC_SWITCH_UP_SPIN, OnDeltaposSwitchUpSpin)
ON_NOTIFY(UDN_DELTAPOS, IDC_SWITCH_DN_SPIN, OnDeltaposSwitchDnSpin)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_HIERARCHY_LIST, OnItemChangedHierarchyList)
ON_EN_UPDATE(IDC_SWITCH_DN_EDIT, OnUpdateSwitchDnEdit)
ON_EN_UPDATE(IDC_SWITCH_UP_EDIT, OnUpdateSwitchUpEdit)
ON_BN_CLICKED(IDC_RECALC, OnRecalc)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
CEditLODDialog::OnInitDialog (void)
{
// Allow the base class to process this message
CDialog::OnInitDialog ();
// Center the dialog around the data tree view instead
// of the direct center of the screen
::CenterDialogAroundTreeView (m_hWnd);
// Get a pointer to the doc
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
// Get the current LOD from the doc
DistLODClass *pLOD = (DistLODClass *)pCDoc->GetDisplayedObject ();
ASSERT (pLOD);
if (pLOD)
{
int iSubObjects = pLOD->Get_Num_Sub_Objects ();
// Add the columns to the list control
m_hierarchyListCtrl.InsertColumn (COL_NAME, "Name");
m_hierarchyListCtrl.InsertColumn (COL_SWITCH_UP, "Switch Up");
m_hierarchyListCtrl.InsertColumn (COL_SWITCH_DN, "Switch Down");
RenderObjClass *pfirst_subobj = pLOD->Get_Sub_Object (0);
if (pfirst_subobj != NULL) {
m_spinIncrement = pfirst_subobj->Get_Bounding_Sphere ().Radius / 5.0F;
MEMBER_RELEASE (pfirst_subobj);
}
// Loop through all the subobjects
for (int iObject = 0;
(iObject < iSubObjects);
iObject ++)
{
// Get this subobject
RenderObjClass *pCSubObject = pLOD->Get_Sub_Object (iObject);
if (pCSubObject)
{
// Add this object to the list
int iIndex = m_hierarchyListCtrl.InsertItem (COL_NAME, pCSubObject->Get_Name ());
CString stringTemp;
stringTemp.Format ("%.2f", pLOD->Get_Switch_Up_Dist (iObject));
m_hierarchyListCtrl.SetItemText (iIndex, COL_SWITCH_UP, stringTemp);
stringTemp.Format ("%.2f", pLOD->Get_Switch_Down_Dist (iObject));
m_hierarchyListCtrl.SetItemText (iIndex, COL_SWITCH_DN, stringTemp);
// Free this object
MEMBER_RELEASE (pCSubObject);
}
}
m_switchUpSpin.SetRange (-20, UD_MAXVAL-20);
m_switchDownSpin.SetRange (-20, UD_MAXVAL-20);
// Resize the columns so they are wide enough to display the largest string
m_hierarchyListCtrl.SetColumnWidth (COL_NAME, LVSCW_AUTOSIZE);
m_hierarchyListCtrl.SetColumnWidth (COL_SWITCH_UP, LVSCW_AUTOSIZE_USEHEADER);
m_hierarchyListCtrl.SetColumnWidth (COL_SWITCH_DN, LVSCW_AUTOSIZE_USEHEADER);
// Select the first item in the list
m_hierarchyListCtrl.SetItemState (0, LVIS_SELECTED, LVIS_SELECTED);
}
}
return TRUE;
}
/////////////////////////////////////////////////////////////
//
// OnOK
//
void
CEditLODDialog::OnOK (void)
{
// Get a pointer to the doc
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
// Get the current LOD from the doc
DistLODClass *pLOD = (DistLODClass *)pCDoc->GetDisplayedObject ();
ASSERT (pLOD);
if (pLOD)
{
int iSubObjects = pLOD->Get_Num_Sub_Objects ();
// Loop through all the subobjects and add them to the list control
for (int iObject = 0;
(iObject < iSubObjects);
iObject ++)
{
// Get the switch up distance from the list control
CString stringTemp = m_hierarchyListCtrl.GetItemText (iObject, COL_SWITCH_UP);
// Convert the string to a float and pass this value
// onto the LOD manager
float switchDistance = ::atof (stringTemp);
pLOD->Set_Switch_Up_Dist (iObject, switchDistance);
// Get the switch down distance from the list control
stringTemp = m_hierarchyListCtrl.GetItemText (iObject, COL_SWITCH_DN);
// Convert the string to a float and pass this value
// onto the LOD manager
switchDistance = ::atof (stringTemp);
pLOD->Set_Switch_Down_Dist (iObject, switchDistance);
}
}
}
// Allow the base class to process this message
CDialog::OnOK ();
return ;
}
/////////////////////////////////////////////////////////////
//
// OnCancel
//
void
CEditLODDialog::OnCancel (void)
{
// Allow the base class to process this message
CDialog::OnCancel ();
return ;
}
/////////////////////////////////////////////////////////////
//
// OnDeltaposSwitchUpSpin
//
void
CEditLODDialog::OnDeltaposSwitchUpSpin
(
NMHDR* pNMHDR,
LRESULT* pResult
)
{
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
if (pNMUpDown)
{
float newVal = float(pNMUpDown->iPos) / 10.00F;
// Change the switching distance in the edit control
CString stringTemp;
stringTemp.Format ("%.2f", newVal);
SetDlgItemText (IDC_SWITCH_UP_EDIT, stringTemp);
// Find the selected item in the list control
int iIndex = m_hierarchyListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
if (iIndex != -1)
{
// Change the switching distance in the list control
m_hierarchyListCtrl.SetItemText (iIndex, COL_SWITCH_UP, stringTemp);
}
}
*pResult = 0;
return ;
}
/////////////////////////////////////////////////////////////
//
// OnDeltaposSwitchDnSpin
//
void
CEditLODDialog::OnDeltaposSwitchDnSpin
(
NMHDR* pNMHDR,
LRESULT* pResult
)
{
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
if (pNMUpDown)
{
float newVal = float(pNMUpDown->iPos) / 10.00F;
// Change the switching distance in the edit control
CString stringTemp;
stringTemp.Format ("%.2f", newVal);
SetDlgItemText (IDC_SWITCH_DN_EDIT, stringTemp);
// Find the selected item in the list control
int iIndex = m_hierarchyListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
if (iIndex != -1)
{
// Change the switching distance in the list control
m_hierarchyListCtrl.SetItemText (iIndex, COL_SWITCH_DN, stringTemp);
}
}
*pResult = 0;
return ;
}
/////////////////////////////////////////////////////////////
//
// OnItemChangedHierarchyList
//
void
CEditLODDialog::OnItemChangedHierarchyList
(
NMHDR* pNMHDR,
LRESULT* pResult
)
{
// Did the 'state' of the entry change?
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if (pNMListView &&
(pNMListView->uChanged & LVIF_STATE) == LVIF_STATE)
{
if ((pNMListView->uNewState & LVIS_SELECTED) != LVIS_SELECTED)
{
// Is there a selected item in the list control?
if (m_hierarchyListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED) == -1)
{
// Disabled the edit and spin controls
EnableControls (FALSE);
}
}
else
{
// Enable the edit and spin controls
EnableControls (TRUE);
// Load the control with data for the selected item.
ResetControls (pNMListView->iItem);
}
}
*pResult = 0;
return ;
}
/////////////////////////////////////////////////////////////
//
// ResetControls
//
void
CEditLODDialog::ResetControls (int iIndex)
{
//
// Set the text of the group box
//
CString stringTemp = m_hierarchyListCtrl.GetItemText (iIndex, COL_NAME);
// Set the text of the group box
CString stringTitle;
stringTitle.Format ("Settings (%s)", (LPCTSTR)stringTemp);
SetDlgItemText (IDC_SETTINGS_GROUP, stringTitle);
//
// Reset the switch up controls
//
// Get the switch up distance from the list control
stringTemp = m_hierarchyListCtrl.GetItemText (iIndex, COL_SWITCH_UP);
// Set the text of the edit control to reflect the switching distance
SetDlgItemText (IDC_SWITCH_UP_EDIT, stringTemp);
// Set the current position of the spin control
float switchDistance = ::atof (stringTemp);
m_switchUpSpin.SetPos (int(switchDistance * 10.00F));
//
// Reset the switch down controls
//
// Get the switch down distance from the list control
stringTemp = m_hierarchyListCtrl.GetItemText (iIndex, COL_SWITCH_DN);
// Set the text of the edit control to reflect the switching distance
SetDlgItemText (IDC_SWITCH_DN_EDIT, stringTemp);
// Set the current position of the spin control
switchDistance = ::atof (stringTemp);
m_switchDownSpin.SetPos (int(switchDistance * 10.00F));
return ;
}
/////////////////////////////////////////////////////////////
//
// EnableControls
//
void
CEditLODDialog::EnableControls (BOOL bEnable)
{
// Enable or disable the windows
::EnableWindow (::GetDlgItem (m_hWnd, IDC_SETTINGS_GROUP), bEnable);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_SWITCH_UP_SPIN), bEnable);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_SWITCH_UP_EDIT), bEnable);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_SWITCH_DN_SPIN), bEnable);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_SWITCH_DN_EDIT), bEnable);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_RECALC), bEnable);
return ;
}
/////////////////////////////////////////////////////////////
//
// OnUpdateSwitchDnEdit
//
void
CEditLODDialog::OnUpdateSwitchDnEdit (void)
{
// Get the switching distance from the edit control
CString stringTemp;
GetDlgItemText (IDC_SWITCH_DN_EDIT, stringTemp);
float newVal = ::atof (stringTemp);
// Change the switching distance in the spin control
m_switchDownSpin.SetPos (int(newVal * 10.00F));
// Find the selected item in the list control
int iIndex = m_hierarchyListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
if (iIndex != -1)
{
// Change the switching distance in the list control
m_hierarchyListCtrl.SetItemText (iIndex, COL_SWITCH_DN, stringTemp);
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnUpdateSwitchUpEdit
//
void CEditLODDialog::OnUpdateSwitchUpEdit (void)
{
// Get the switching distance from the edit control
CString stringTemp;
GetDlgItemText (IDC_SWITCH_UP_EDIT, stringTemp);
float newVal = ::atof (stringTemp);
// Change the switching distance in the spin control
m_switchUpSpin.SetPos (int(newVal * 10.00F));
// Find the selected item in the list control
int iIndex = m_hierarchyListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
if (iIndex != -1)
{
// Change the switching distance in the list control
m_hierarchyListCtrl.SetItemText (iIndex, COL_SWITCH_UP, stringTemp);
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnRecalc
//
void CEditLODDialog::OnRecalc (void)
{
// Get the up switching distance from the edit control
CString stringTemp;
GetDlgItemText (IDC_SWITCH_UP_EDIT, stringTemp);
float switchUp = ::atof (stringTemp);
// Get the down switching distance from the edit control
stringTemp;
GetDlgItemText (IDC_SWITCH_DN_EDIT, stringTemp);
float switchDown = ::atof (stringTemp);
if (switchUp < switchDown)
{
// Calculate the current range
float switchDelta = switchDown - switchUp;
float switchOverlap = switchDelta * 0.1F;
// Get a pointer to the doc
CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
if (pCDoc)
{
// Get the current LOD from the doc
DistLODClass *pLOD = (DistLODClass *)pCDoc->GetDisplayedObject ();
ASSERT (pLOD);
if (pLOD)
{
int iSubObjects = pLOD->Get_Num_Sub_Objects ();
switchUp = switchDown - switchOverlap;
// Loop through all the subobjects (following the highlighted one)
for (int iObject = m_hierarchyListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED) + 1;
(iObject < iSubObjects);
iObject ++)
{
// Set the text of the switch up column
CString stringTemp;
stringTemp.Format ("%.2f", switchUp);
m_hierarchyListCtrl.SetItemText (iObject, COL_SWITCH_UP, stringTemp);
// Set the text of the switch dn column
stringTemp.Format ("%.2f", switchUp+switchDelta);
m_hierarchyListCtrl.SetItemText (iObject, COL_SWITCH_DN, stringTemp);
// Add the range to the switch up distance
switchUp += switchDelta-switchOverlap;
}
}
}
}
return ;
}

View File

@@ -0,0 +1,82 @@
/*
** 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/>.
*/
#if !defined(AFX_EDITLODDIALOG_H__AF3CDE8E_61EC_11D2_9FC7_00104B791122__INCLUDED_)
#define AFX_EDITLODDIALOG_H__AF3CDE8E_61EC_11D2_9FC7_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// EditLODDialog.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CEditLODDialog dialog
class CEditLODDialog : public CDialog
{
// Construction
public:
CEditLODDialog(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CEditLODDialog)
enum { IDD = IDD_EDIT_LOD };
CSpinButtonCtrl m_switchUpSpin;
CSpinButtonCtrl m_switchDownSpin;
CListCtrl m_hierarchyListCtrl;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CEditLODDialog)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CEditLODDialog)
virtual BOOL OnInitDialog();
virtual void OnOK();
virtual void OnCancel();
afx_msg void OnDeltaposSwitchUpSpin(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnDeltaposSwitchDnSpin(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnItemChangedHierarchyList(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnUpdateSwitchDnEdit();
afx_msg void OnUpdateSwitchUpEdit();
afx_msg void OnRecalc();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
protected:
void ResetControls (int iIndex);
void EnableControls (BOOL bEnable);
private:
float m_spinIncrement;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EDITLODDIALOG_H__AF3CDE8E_61EC_11D2_9FC7_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,672 @@
/*
** 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/>.
*/
// EmitterColorPropPage.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "emittercolorproppage.h"
#include "part_emt.h"
#include "utils.h"
#include "opacitysettingsdialog.h"
#include "colorutils.h"
#include "emitterinstancelist.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// EmitterColorPropPageClass property page
IMPLEMENT_DYNCREATE(EmitterColorPropPageClass, CPropertyPage)
/////////////////////////////////////////////////////////////
//
// EmitterColorPropPageClass
//
/////////////////////////////////////////////////////////////
EmitterColorPropPageClass::EmitterColorPropPageClass (EmitterInstanceListClass *pemitter)
: m_pEmitterList (NULL),
m_bValid (true),
m_ColorBar (NULL),
m_OpacityBar (NULL),
m_Lifetime (0),
CPropertyPage (EmitterColorPropPageClass::IDD)
{
::memset (&m_OrigColors, 0, sizeof (m_OrigColors));
::memset (&m_OrigOpacities, 0, sizeof (m_OrigOpacities));
::memset (&m_CurrentColors, 0, sizeof (m_CurrentColors));
::memset (&m_CurrentOpacities, 0, sizeof (m_CurrentOpacities));
//{{AFX_DATA_INIT(EmitterColorPropPageClass)
//}}AFX_DATA_INIT
Initialize ();
return ;
}
/////////////////////////////////////////////////////////////
//
// ~EmitterColorPropPageClass
//
/////////////////////////////////////////////////////////////
EmitterColorPropPageClass::~EmitterColorPropPageClass (void)
{
// Free the original setting arrays
SAFE_DELETE_ARRAY (m_OrigColors.KeyTimes);
SAFE_DELETE_ARRAY (m_OrigColors.Values);
SAFE_DELETE_ARRAY (m_OrigOpacities.KeyTimes);
SAFE_DELETE_ARRAY (m_OrigOpacities.Values);
// Free the current setting arrays
SAFE_DELETE_ARRAY (m_CurrentColors.KeyTimes);
SAFE_DELETE_ARRAY (m_CurrentColors.Values);
SAFE_DELETE_ARRAY (m_CurrentOpacities.KeyTimes);
SAFE_DELETE_ARRAY (m_CurrentOpacities.Values);
return;
}
/////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////
void
EmitterColorPropPageClass::DoDataExchange (CDataExchange* pDX)
{
// Allow the base class to process this message
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(EmitterColorPropPageClass)
DDX_Control(pDX, IDC_OPACITY_RANDOM_SPIN, m_OpacityRandomSpin);
DDX_Control(pDX, IDC_RED_RANDOM_SPIN, m_RedRandomSpin);
DDX_Control(pDX, IDC_GREEN_RANDOM_SPIN, m_GreenRandomSpin);
DDX_Control(pDX, IDC_BLUE_RANDOM_SPIN, m_BlueRandomSpin);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(EmitterColorPropPageClass, CPropertyPage)
//{{AFX_MSG_MAP(EmitterColorPropPageClass)
ON_WM_DESTROY()
ON_NOTIFY(UDN_DELTAPOS, IDC_RED_RANDOM_SPIN, OnDeltaposRedRandomSpin)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////
//
// Initialize
//
/////////////////////////////////////////////////////////////
void
EmitterColorPropPageClass::Initialize (void)
{
SAFE_DELETE_ARRAY (m_OrigColors.KeyTimes);
SAFE_DELETE_ARRAY (m_OrigColors.Values);
SAFE_DELETE_ARRAY (m_OrigOpacities.KeyTimes);
SAFE_DELETE_ARRAY (m_OrigOpacities.Values);
SAFE_DELETE_ARRAY (m_CurrentColors.KeyTimes);
SAFE_DELETE_ARRAY (m_CurrentColors.Values);
SAFE_DELETE_ARRAY (m_CurrentOpacities.KeyTimes);
SAFE_DELETE_ARRAY (m_CurrentOpacities.Values);
if (m_pEmitterList != NULL) {
m_Lifetime = m_pEmitterList->Get_Lifetime ();
//
// Get the initial values from the emitter
//
m_pEmitterList->Get_Color_Keyframes (m_OrigColors);
m_pEmitterList->Get_Color_Keyframes (m_CurrentColors);
m_pEmitterList->Get_Opacity_Keyframes (m_OrigOpacities);
m_pEmitterList->Get_Opacity_Keyframes (m_CurrentOpacities);
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////
BOOL
EmitterColorPropPageClass::OnInitDialog (void)
{
// Allow the base class to process this message
CPropertyPage::OnInitDialog ();
m_ColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_COLOR_BAR));
m_OpacityBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_OPACITY_BAR));
//
// Setup the color bars
//
m_ColorBar->Set_Range (0, 1);
m_OpacityBar->Set_Range (0, 1);
m_OpacityBar->Modify_Point (0, 0, 255, 255, 255);
//
// Setup the spinners
//
m_OpacityRandomSpin.SetRange (0, 100);
m_RedRandomSpin.SetRange (0, 255);
m_GreenRandomSpin.SetRange (0, 255);
m_BlueRandomSpin.SetRange (0, 255);
m_OpacityRandomSpin.SetPos (m_OrigOpacities.Rand * 100);
m_RedRandomSpin.SetPos (m_OrigColors.Rand.X * 255);
m_GreenRandomSpin.SetPos (m_OrigColors.Rand.Y * 255);
m_BlueRandomSpin.SetPos (m_OrigColors.Rand.Z * 255);
//
// Reset the color bars
//
m_ColorBar->Clear_Points ();
m_OpacityBar->Clear_Points ();
m_ColorBar->Modify_Point (0, 0, m_OrigColors.Start.X * 255, m_OrigColors.Start.Y * 255, m_OrigColors.Start.Z * 255);
m_OpacityBar->Modify_Point (0, 0, m_OrigOpacities.Start * 255, m_OrigOpacities.Start * 255, m_OrigOpacities.Start * 255);
//
// Setup the ranges
//
m_ColorBar->Set_Range (0, 1);
m_OpacityBar->Set_Range (0, 1);
//
// Set-up the color bar
//
for (UINT index = 0; index < m_OrigColors.NumKeyFrames; index ++) {
m_ColorBar->Modify_Point (index + 1,
m_OrigColors.KeyTimes[index] / m_Lifetime,
m_OrigColors.Values[index].X * 255,
m_OrigColors.Values[index].Y * 255,
m_OrigColors.Values[index].Z * 255);
}
//
// Set-up the opacity bar
//
for (index = 0; index < m_OrigOpacities.NumKeyFrames; index ++) {
m_OpacityBar->Modify_Point (index + 1,
m_OrigOpacities.KeyTimes[index] / m_Lifetime,
m_OrigOpacities.Values[index] * 255,
m_OrigOpacities.Values[index] * 255,
m_OrigOpacities.Values[index] * 255);
}
//
// Ensure our initial 'current' values are up-to-date
//
m_CurrentColors.Rand = m_OrigColors.Rand;
m_CurrentOpacities.Rand = m_OrigOpacities.Rand;
Update_Colors ();
Update_Opacities ();
return TRUE;
}
/////////////////////////////////////////////////////////////
//
// OnApply
//
/////////////////////////////////////////////////////////////
BOOL
EmitterColorPropPageClass::OnApply (void)
{
/*SAFE_DELETE_ARRAY (m_OrigColors.KeyTimes);
SAFE_DELETE_ARRAY (m_OrigColors.Values);
SAFE_DELETE_ARRAY (m_OrigOpacities.KeyTimes);
SAFE_DELETE_ARRAY (m_OrigOpacities.Values);
//
// Make the current values from the emitter the default values.
//
m_pEmitter->Get_Color_Key_Frames (m_OrigColors);
m_pEmitter->Get_Opacity_Key_Frames (m_OrigOpacities);*/
// Allow the base class to process this message
return CPropertyPage::OnApply ();
}
/////////////////////////////////////////////////////////////
//
// OnDestroy
//
/////////////////////////////////////////////////////////////
void
EmitterColorPropPageClass::OnDestroy (void)
{
CPropertyPage::OnDestroy();
return ;
}
/////////////////////////////////////////////////////////////
//
// OnNotify
//
/////////////////////////////////////////////////////////////
BOOL
EmitterColorPropPageClass::OnNotify
(
WPARAM wParam,
LPARAM lParam,
LRESULT *pResult
)
{
CBR_NMHDR *color_bar_hdr = (CBR_NMHDR *)lParam;
//
// Which control sent the notification?
//
switch (color_bar_hdr->hdr.idFrom)
{
case IDC_OPACITY_BAR:
{
if (color_bar_hdr->hdr.code == CBRN_DBLCLK_POINT) {
//
// Allow the user to edit the keyframe
//
OpacitySettingsDialogClass dialog (color_bar_hdr->red / 255, this);
if (dialog.DoModal () == IDOK) {
m_OpacityBar->Modify_Point (color_bar_hdr->key_index,
color_bar_hdr->position,
dialog.Get_Opacity () * 255,
dialog.Get_Opacity () * 255,
dialog.Get_Opacity () * 255);
// Update the emitter
Update_Opacities ();
m_pEmitterList->Set_Opacity_Keyframes (m_CurrentOpacities);
SetModified ();
}
} else if ((color_bar_hdr->hdr.code == CBRN_MOVING_POINT) ||
(color_bar_hdr->hdr.code == CBRN_DELETED_POINT)) {
// Update the emitter
Update_Opacities ();
m_pEmitterList->Set_Opacity_Keyframes (m_CurrentOpacities);
SetModified ();
}
}
break;
case IDC_COLOR_BAR:
{
if (color_bar_hdr->hdr.code == CBRN_DBLCLK_POINT) {
//
// Allow the user to edit the keyframe
//
int red = (int)color_bar_hdr->red;
int green = (int)color_bar_hdr->green;
int blue = (int)color_bar_hdr->blue;
if (Show_Color_Picker (&red, &green, &blue)) {
m_ColorBar->Modify_Point (color_bar_hdr->key_index,
color_bar_hdr->position,
red,
green,
blue);
// Update the emitter
Update_Colors ();
m_pEmitterList->Set_Color_Keyframes (m_CurrentColors);
SetModified ();
}
} else if ((color_bar_hdr->hdr.code == CBRN_MOVING_POINT) ||
(color_bar_hdr->hdr.code == CBRN_DELETED_POINT)) {
// Update the emitter
Update_Colors ();
m_pEmitterList->Set_Color_Keyframes (m_CurrentColors);
SetModified ();
}
}
break;
case IDC_RED_RANDOM_SPIN:
{
// Update the emitter
NMUPDOWN *pudnotif = (NMUPDOWN *)lParam;
if (pudnotif->hdr.code == UDN_DELTAPOS) {
float pos = (pudnotif->iPos + pudnotif->iDelta);
m_CurrentColors.Rand.X = pos / 255.0F;
m_pEmitterList->Set_Color_Keyframes (m_CurrentColors);
SetModified ();
}
}
break;
case IDC_GREEN_RANDOM_SPIN:
{
// Update the emitter
NMUPDOWN *pudnotif = (NMUPDOWN *)lParam;
if (pudnotif->hdr.code == UDN_DELTAPOS) {
float pos = (pudnotif->iPos + pudnotif->iDelta);
m_CurrentColors.Rand.Y = pos / 255.0F;
m_pEmitterList->Set_Color_Keyframes (m_CurrentColors);
SetModified ();
}
}
break;
case IDC_BLUE_RANDOM_SPIN:
{
// Update the emitter
NMUPDOWN *pudnotif = (NMUPDOWN *)lParam;
if (pudnotif->hdr.code == UDN_DELTAPOS) {
float pos = (pudnotif->iPos + pudnotif->iDelta);
m_CurrentColors.Rand.Z = pos / 255.0F;
m_pEmitterList->Set_Color_Keyframes (m_CurrentColors);
SetModified ();
}
}
break;
case IDC_OPACITY_RANDOM_SPIN:
{
// Update the emitter
NMUPDOWN *pudnotif = (NMUPDOWN *)lParam;
if (pudnotif->hdr.code == UDN_DELTAPOS) {
float pos = (pudnotif->iPos + pudnotif->iDelta);
m_CurrentOpacities.Rand = pos / 100.0F;
m_pEmitterList->Set_Opacity_Keyframes (m_CurrentOpacities);
SetModified ();
}
}
break;
}
return CPropertyPage::OnNotify(wParam, lParam, pResult);
}
/////////////////////////////////////////////////////////////
//
// OnCancel
//
/////////////////////////////////////////////////////////////
void
EmitterColorPropPageClass::OnCancel (void)
{
//
// Reset the emitter to its original state
//
m_pEmitterList->Set_Color_Keyframes (m_OrigColors);
m_pEmitterList->Set_Opacity_Keyframes (m_OrigOpacities);
CPropertyPage::OnCancel ();
return ;
}
/////////////////////////////////////////////////////////////
//
// Update_Opacities
//
/////////////////////////////////////////////////////////////
void
EmitterColorPropPageClass::Update_Opacities (void)
{
float position = 0;
float red = 0;
float green = 0;
float blue = 0;
m_OpacityBar->Get_Point (0, &position, &red, &green, &blue);
//
// Setup the initial or 'starting' opacity
//
m_CurrentOpacities.Start = red / 255;
//
// Free the current setting arrays
//
SAFE_DELETE_ARRAY (m_CurrentOpacities.KeyTimes);
SAFE_DELETE_ARRAY (m_CurrentOpacities.Values);
//
// Determine if we need to build the array of key frames or not
//
int count = m_OpacityBar->Get_Point_Count ();
m_CurrentOpacities.NumKeyFrames = count - 1;
if (count > 1) {
m_CurrentOpacities.KeyTimes = new float[count - 1];
m_CurrentOpacities.Values = new float[count - 1];
//
// Get all the opacity key frames and add them to our structure
//
for (int index = 1; index < count; index ++) {
m_OpacityBar->Get_Point (index, &position, &red, &green, &blue);
m_CurrentOpacities.KeyTimes[index - 1] = position * m_Lifetime;
m_CurrentOpacities.Values[index - 1] = red / 255;
}
}
return ;
}
/////////////////////////////////////////////////////////////
//
// Update_Colors
//
/////////////////////////////////////////////////////////////
void
EmitterColorPropPageClass::Update_Colors (void)
{
float position = 0;
float red = 0;
float green = 0;
float blue = 0;
m_ColorBar->Get_Point (0, &position, &red, &green, &blue);
//
// Setup the initial or 'starting' color
//
m_CurrentColors.Start.X = red / 255;
m_CurrentColors.Start.Y = green / 255;
m_CurrentColors.Start.Z = blue / 255;
//
// Free the current setting arrays
//
SAFE_DELETE_ARRAY (m_CurrentColors.KeyTimes);
SAFE_DELETE_ARRAY (m_CurrentColors.Values);
//
// Determine if we need to build the array of key frames or not
//
int count = m_ColorBar->Get_Point_Count ();
m_CurrentColors.NumKeyFrames = count - 1;
if (count > 1) {
m_CurrentColors.KeyTimes = new float[count - 1];
m_CurrentColors.Values = new Vector3[count - 1];
//
// Get all the color points and add them to our structure
//
for (int index = 1; index < count; index ++) {
m_ColorBar->Get_Point (index, &position, &red, &green, &blue);
m_CurrentColors.KeyTimes[index-1] = position * m_Lifetime;
m_CurrentColors.Values[index-1].X = red / 255;
m_CurrentColors.Values[index-1].Y = green / 255;
m_CurrentColors.Values[index-1].Z = blue / 255;
}
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnCommand
//
/////////////////////////////////////////////////////////////
BOOL
EmitterColorPropPageClass::OnCommand
(
WPARAM wParam,
LPARAM lParam
)
{
switch (LOWORD (wParam))
{
case IDC_RED_RANDOM_EDIT:
{
if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
// Update the emitter
if ((HIWORD (wParam) == EN_KILLFOCUS) &&
SendDlgItemMessage (LOWORD (wParam), EM_GETMODIFY)) {
SendDlgItemMessage (LOWORD (wParam), EM_SETMODIFY, (WPARAM)0);
m_CurrentColors.Rand.X = ((float)GetDlgItemInt (IDC_RED_RANDOM_EDIT)) / 255;
m_pEmitterList->Set_Color_Keyframes (m_CurrentColors);
SetModified ();
}
}
break;
case IDC_GREEN_RANDOM_EDIT:
{
if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
// Update the emitter
if ((HIWORD (wParam) == EN_KILLFOCUS) &&
SendDlgItemMessage (LOWORD (wParam), EM_GETMODIFY)) {
SendDlgItemMessage (LOWORD (wParam), EM_SETMODIFY, (WPARAM)0);
m_CurrentColors.Rand.Y = ((float)GetDlgItemInt (IDC_GREEN_RANDOM_EDIT)) / 255;
m_pEmitterList->Set_Color_Keyframes (m_CurrentColors);
SetModified ();
}
}
break;
case IDC_BLUE_RANDOM_EDIT:
{
if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
// Update the emitter
if ((HIWORD (wParam) == EN_KILLFOCUS) &&
SendDlgItemMessage (LOWORD (wParam), EM_GETMODIFY)) {
SendDlgItemMessage (LOWORD (wParam), EM_SETMODIFY, (WPARAM)0);
m_CurrentColors.Rand.Z = ((float)GetDlgItemInt (IDC_BLUE_RANDOM_EDIT)) / 255;
m_pEmitterList->Set_Color_Keyframes (m_CurrentColors);
SetModified ();
}
}
break;
case IDC_OPACITY_RANDOM_EDIT:
{
if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
// Update the emitter
if ((HIWORD (wParam) == EN_KILLFOCUS) &&
SendDlgItemMessage (LOWORD (wParam), EM_GETMODIFY)) {
SendDlgItemMessage (LOWORD (wParam), EM_SETMODIFY, (WPARAM)0);
m_CurrentOpacities.Rand = ((float)GetDlgItemInt (IDC_OPACITY_RANDOM_EDIT)) / 100;
m_pEmitterList->Set_Opacity_Keyframes (m_CurrentOpacities);
SetModified ();
}
}
break;
}
return CPropertyPage::OnCommand (wParam, lParam);
}
void EmitterColorPropPageClass::OnDeltaposRedRandomSpin(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
// TODO: Add your control notification handler code here
int test = 0;
*pResult = 0;
return ;
}
/////////////////////////////////////////////////////////////
//
// On_Lifetime_Changed
//
/////////////////////////////////////////////////////////////
void
EmitterColorPropPageClass::On_Lifetime_Changed (float lifetime)
{
if (m_Lifetime != lifetime) {
float conversion = lifetime / m_Lifetime;
//
// Rescale the colors
//
for (UINT index = 0; index < m_CurrentColors.NumKeyFrames; index ++) {
m_CurrentColors.KeyTimes[index] *= conversion;
}
//
// Rescale the opacities
//
for (index = 0; index < m_CurrentOpacities.NumKeyFrames; index ++) {
m_CurrentOpacities.KeyTimes[index] *= conversion;
}
//
// Update the emitter
//
m_pEmitterList->Set_Color_Keyframes (m_CurrentColors);
m_pEmitterList->Set_Opacity_Keyframes (m_CurrentOpacities);
m_Lifetime = lifetime;
/*if (m_hWnd != NULL) {
Update_Colors ();
Update_Opacities ();
}*/
}
return ;
}

View File

@@ -0,0 +1,134 @@
/*
** 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/>.
*/
#if !defined(AFX_EMITTERCOLORPROPPAGE_H__83A8B83F_BA3B_11D2_9FFA_00104B791122__INCLUDED_)
#define AFX_EMITTERCOLORPROPPAGE_H__83A8B83F_BA3B_11D2_9FFA_00104B791122__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EmitterColorPropPage.h : header file
//
#include "Resource.H"
#include "Vector3.H"
#include "ColorBar.H"
#include "Part_Emt.H"
// Forward declarations
class EmitterInstanceListClass;
/////////////////////////////////////////////////////////////////////////////
// EmitterColorPropPageClass dialog
class EmitterColorPropPageClass : public CPropertyPage
{
DECLARE_DYNCREATE(EmitterColorPropPageClass)
// Construction
public:
EmitterColorPropPageClass (EmitterInstanceListClass *pemitter_list = NULL);
~EmitterColorPropPageClass ();
// Dialog Data
//{{AFX_DATA(EmitterColorPropPageClass)
enum { IDD = IDD_PROP_PAGE_EMITTER_COLOR };
CSpinButtonCtrl m_OpacityRandomSpin;
CSpinButtonCtrl m_RedRandomSpin;
CSpinButtonCtrl m_GreenRandomSpin;
CSpinButtonCtrl m_BlueRandomSpin;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(EmitterColorPropPageClass)
public:
virtual BOOL OnApply();
virtual void OnCancel();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(EmitterColorPropPageClass)
virtual BOOL OnInitDialog();
afx_msg void OnDestroy();
afx_msg void OnDeltaposRedRandomSpin(NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////
//
// Public methods
//
//
// Inline accessors
//
EmitterInstanceListClass * Get_Emitter (void) const { return m_pEmitterList; }
void Set_Emitter (EmitterInstanceListClass *pemitter_list) { m_pEmitterList = pemitter_list; Initialize (); }
bool Is_Data_Valid (void) const { return m_bValid; }
void Get_Color_Keyframes (ParticlePropertyStruct<Vector3> &colors) { colors = m_CurrentColors; }
void Get_Opacity_Keyframes (ParticlePropertyStruct<float> &opacity) { opacity = m_CurrentOpacities; }
/*const Vector3 & Get_Start_Color (void) const { return m_StartColor; }
const Vector3 & Get_End_Color (void) const { return m_EndColor; }
float Get_Start_Opacity (void) const { return m_StartOpacity; }
float Get_End_Opacity (void) const { return m_EndOpacity; }
float Get_Fade_Time (void) const { return m_FadeTime; }*/
void On_Lifetime_Changed (float lifetime);
protected:
/////////////////////////////////////////////////////////
//
// Protected methods
//
void Initialize (void);
void Update_Colors (void);
void Update_Opacities (void);
private:
/////////////////////////////////////////////////////////
//
// Private member data
//
EmitterInstanceListClass * m_pEmitterList;
bool m_bValid;
ColorBarClass * m_ColorBar;
ColorBarClass * m_OpacityBar;
ParticlePropertyStruct<Vector3> m_OrigColors;
ParticlePropertyStruct<float> m_OrigOpacities;
ParticlePropertyStruct<Vector3> m_CurrentColors;
ParticlePropertyStruct<float> m_CurrentOpacities;
float m_Lifetime;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EMITTERCOLORPROPPAGE_H__83A8B83F_BA3B_11D2_9FFA_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,420 @@
/*
** 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/>.
*/
// EmitterFramePropPage.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "EmitterFramePropPage.h"
#include "Utils.H"
#include "ParticleFrameKeyDialog.H"
#include "EmitterInstanceList.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// EmitterFramePropPageClass property page
IMPLEMENT_DYNCREATE(EmitterFramePropPageClass, CPropertyPage)
/////////////////////////////////////////////////////////////
//
// EmitterFramePropPageClass - constructor
//
/////////////////////////////////////////////////////////////
EmitterFramePropPageClass::EmitterFramePropPageClass() :
CPropertyPage(EmitterFramePropPageClass::IDD),
m_pEmitterList(NULL),
m_bValid(true),
m_FrameBar(NULL),
m_Lifetime(0),
m_MinFrame(0),
m_MaxFrame(1)
{
::memset (&m_Frames, 0, sizeof (m_Frames));
//{{AFX_DATA_INIT(EmitterFramePropPageClass)
//}}AFX_DATA_INIT
Initialize();
}
/////////////////////////////////////////////////////////////
//
// ~EmitterFramePropPageClass - destructor
//
/////////////////////////////////////////////////////////////
EmitterFramePropPageClass::~EmitterFramePropPageClass()
{
// Free the frame arrays
SAFE_DELETE_ARRAY (m_Frames.KeyTimes);
SAFE_DELETE_ARRAY (m_Frames.Values);
}
/////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////
void EmitterFramePropPageClass::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(EmitterFramePropPageClass)
DDX_Control(pDX, IDC_FRAME_LAYOUT_COMBO, m_FrameLayoutCombo);
DDX_Control(pDX, IDC_FRAME_RANDOM_SPIN, m_FrameRandomSpin);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(EmitterFramePropPageClass, CPropertyPage)
//{{AFX_MSG_MAP(EmitterFramePropPageClass)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////
//
// Initialize
//
/////////////////////////////////////////////////////////////
void
EmitterFramePropPageClass::Initialize (void)
{
SAFE_DELETE_ARRAY (m_Frames.KeyTimes);
SAFE_DELETE_ARRAY (m_Frames.Values);
if (m_pEmitterList != NULL) {
m_Lifetime = m_pEmitterList->Get_Lifetime ();
m_pEmitterList->Get_Frame_Keyframes (m_Frames);
//
// Determine what the min and max rotations are
//
m_MaxFrame = WWMath::Max(m_Frames.Start,1.0f);
m_MinFrame = WWMath::Min(m_Frames.Start,0.0f);
for (UINT index = 0; index < m_Frames.NumKeyFrames; index ++) {
if (m_Frames.Values[index] > m_MaxFrame) {
m_MaxFrame = m_Frames.Values[index];
}
if (m_Frames.Values[index] < m_MinFrame) {
m_MinFrame = m_Frames.Values[index];
}
}
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////
BOOL
EmitterFramePropPageClass::OnInitDialog()
{
CPropertyPage::OnInitDialog();
//
// Set the frame layout combo box
//
int mode = m_pEmitterList->Get_Frame_Mode();
switch (mode) {
case W3D_EMITTER_FRAME_MODE_1x1: m_FrameLayoutCombo.SetCurSel(0); break;
case W3D_EMITTER_FRAME_MODE_2x2: m_FrameLayoutCombo.SetCurSel(1); break;
case W3D_EMITTER_FRAME_MODE_4x4: m_FrameLayoutCombo.SetCurSel(2); break;
case W3D_EMITTER_FRAME_MODE_8x8: m_FrameLayoutCombo.SetCurSel(3); break;
case W3D_EMITTER_FRAME_MODE_16x16: m_FrameLayoutCombo.SetCurSel(4); break;
default:
m_FrameLayoutCombo.SetCurSel(4);
break;
}
//
// Create the keyframe control
//
m_FrameBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_FRAME_BAR));
//
// Setup the spinners
//
Initialize_Spinner (m_FrameRandomSpin, m_Frames.Rand, 0, 10000);
//
// Reset the keyframe control
//
m_FrameBar->Set_Range (0, 1);
m_FrameBar->Clear_Points ();
m_FrameBar->Modify_Point (0, 0, 0, 0, 0);
m_FrameBar->Set_Graph_Percent (0, Normalize_Frame(m_Frames.Start));
//
// Load the current set of frame keyframes into the control
//
for (UINT index = 0; index < m_Frames.NumKeyFrames; index ++) {
m_FrameBar->Modify_Point (index + 1,
m_Frames.KeyTimes[index] / m_Lifetime,
0,
0,
0);
m_FrameBar->Set_Graph_Percent (index + 1, Normalize_Frame(m_Frames.Values[index]));
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
/////////////////////////////////////////////////////////////
//
// OnApply
//
/////////////////////////////////////////////////////////////
BOOL EmitterFramePropPageClass::OnApply()
{
return CPropertyPage::OnApply();
}
/////////////////////////////////////////////////////////////
//
// OnNotify
//
/////////////////////////////////////////////////////////////
BOOL EmitterFramePropPageClass::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
CBR_NMHDR *color_bar_hdr = (CBR_NMHDR *)lParam;
//
// Update the spinner controls if necessary
//
NMHDR *pheader = (NMHDR *)lParam;
if ((pheader != NULL) && (pheader->code == UDN_DELTAPOS)) {
LPNMUPDOWN pupdown = (LPNMUPDOWN)lParam;
::Update_Spinner_Buddy (pheader->hwndFrom, pupdown->iDelta);
}
//
// Which control sent the notification?
//
switch (color_bar_hdr->hdr.idFrom)
{
case IDC_FRAME_BAR:
{
if (color_bar_hdr->hdr.code == CBRN_DBLCLK_POINT) {
//
// Allow the user to edit the keyframe
//
float frame = Denormalize_Frame(m_FrameBar->Get_Graph_Percent (color_bar_hdr->key_index));
ParticleFrameKeyDialogClass dialog (frame, this);
if (dialog.DoModal () == IDOK) {
frame = dialog.Get_Frame ();
float norm_val = Normalize_Frame(frame);
m_FrameBar->Set_Redraw (false);
m_FrameBar->Set_Graph_Percent (color_bar_hdr->key_index, norm_val);
//
// Determine if the user changed the 'max' or 'min' frame
//
float new_max = WWMath::Max(frame,1.0f);
float new_min = WWMath::Min(frame,0.0f);
int count = m_FrameBar->Get_Point_Count ();
for (int index = 0; index < count; index ++) {
float tmp = Denormalize_Frame(m_FrameBar->Get_Graph_Percent (index) );
if (tmp > new_max) {
new_max = tmp;
}
if (tmp < new_min) {
new_min = tmp;
}
}
//
// Renormalize the FrameBar key frame points if necessary
//
if ((new_max != m_MaxFrame) || (new_min != m_MinFrame)) {
int count = m_FrameBar->Get_Point_Count ();
for (int index = 0; index < count; index ++) {
float frame = Denormalize_Frame(m_FrameBar->Get_Graph_Percent (index));
float new_norm = Normalize_Frame(frame,new_min,new_max);
m_FrameBar->Set_Graph_Percent (index, new_norm);
}
// Remember the new min and max
m_MinFrame = new_min;
m_MaxFrame = new_max;
}
m_FrameBar->Set_Redraw (true);
//
// Update the emitter
//
Update_Frames ();
m_pEmitterList->Set_Frame_Keyframes (m_Frames);
SetModified ();
}
} else if ((color_bar_hdr->hdr.code == CBRN_MOVING_POINT) ||
(color_bar_hdr->hdr.code == CBRN_DELETED_POINT)) {
//
// Update the emitter
//
Update_Frames ();
m_pEmitterList->Set_Frame_Keyframes (m_Frames);
SetModified ();
}
}
break;
case IDC_FRAME_RANDOM_SPIN:
{
// Update the emitter
m_Frames.Rand = ::GetDlgItemFloat (m_hWnd, IDC_FRAME_RANDOM_EDIT);
m_pEmitterList->Set_Frame_Keyframes (m_Frames);
SetModified ();
}
break;
}
return CPropertyPage::OnNotify(wParam, lParam, pResult);
}
/////////////////////////////////////////////////////////////
//
// Update_Rotations
//
/////////////////////////////////////////////////////////////
void
EmitterFramePropPageClass::Update_Frames (void)
{
float position = 0;
float red = 0;
float green = 0;
float blue = 0;
//
// Setup the initial or 'starting' size
//
m_Frames.Start = Denormalize_Frame(m_FrameBar->Get_Graph_Percent (0));
//
// Free the current setting arrays
//
SAFE_DELETE_ARRAY (m_Frames.KeyTimes);
SAFE_DELETE_ARRAY (m_Frames.Values);
//
// Determine if we need to build the array of key frames or not
//
int count = m_FrameBar->Get_Point_Count ();
m_Frames.NumKeyFrames = count - 1;
if (count > 1) {
m_Frames.KeyTimes = new float[count - 1];
m_Frames.Values = new float[count - 1];
//
// Get all the key frames and add them to our structure
//
for (int index = 1; index < count; index ++) {
m_FrameBar->Get_Point (index, &position, &red, &green, &blue);
m_Frames.KeyTimes[index - 1] = position * m_Lifetime;
m_Frames.Values[index - 1] = Denormalize_Frame(m_FrameBar->Get_Graph_Percent (index) );
}
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnCommand
//
/////////////////////////////////////////////////////////////
BOOL
EmitterFramePropPageClass::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch (LOWORD (wParam))
{
case IDC_FRAME_RANDOM_EDIT:
{
// Update the emitter
if ((HIWORD (wParam) == EN_KILLFOCUS) &&
SendDlgItemMessage (LOWORD (wParam), EM_GETMODIFY))
{
SendDlgItemMessage (LOWORD (wParam), EM_SETMODIFY, (WPARAM)0);
m_Frames.Rand = ::GetDlgItemFloat (m_hWnd, IDC_FRAME_RANDOM_EDIT);
m_pEmitterList->Set_Frame_Keyframes (m_Frames);
SetModified ();
} else if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
}
case IDC_FRAME_LAYOUT_COMBO:
if (HIWORD(wParam) == CBN_SELCHANGE) {
m_pEmitterList->Set_Frame_Mode(m_FrameLayoutCombo.GetCurSel());
SetModified();
}
break;
}
return CPropertyPage::OnCommand(wParam, lParam);
}
/////////////////////////////////////////////////////////////
//
// On_Lifetime_Changed
//
/////////////////////////////////////////////////////////////
void
EmitterFramePropPageClass::On_Lifetime_Changed (float lifetime)
{
if (m_Lifetime != lifetime) {
float conversion = lifetime / m_Lifetime;
//
// Rescale the sizes
//
for (UINT index = 0; index < m_Frames.NumKeyFrames; index ++) {
m_Frames.KeyTimes[index] *= conversion;
}
//
// Update the emitter
//
m_pEmitterList->Set_Frame_Keyframes (m_Frames);
m_Lifetime = lifetime;
}
return ;
}

View File

@@ -0,0 +1,134 @@
/*
** 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/>.
*/
#if !defined(AFX_EMITTERFRAMEPROPPAGE_H__6F068804_EAD5_4A19_BE03_C9C7B534E6E8__INCLUDED_)
#define AFX_EMITTERFRAMEPROPPAGE_H__6F068804_EAD5_4A19_BE03_C9C7B534E6E8__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EmitterFramePropPage.h : header file
//
#include "ColorBar.H"
#include "Part_Emt.H"
class EmitterInstanceListClass;
/////////////////////////////////////////////////////////////////////////////
// EmitterFramePropPageClass dialog
class EmitterFramePropPageClass : public CPropertyPage
{
DECLARE_DYNCREATE(EmitterFramePropPageClass)
// Construction
public:
EmitterFramePropPageClass();
~EmitterFramePropPageClass();
// Dialog Data
//{{AFX_DATA(EmitterFramePropPageClass)
enum { IDD = IDD_PROP_PAGE_EMITTER_FRAME };
CComboBox m_FrameLayoutCombo;
CSpinButtonCtrl m_FrameRandomSpin;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(EmitterFramePropPageClass)
public:
virtual BOOL OnApply();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(EmitterFramePropPageClass)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////
//
// Public methods
//
//
// Inline accessors
//
EmitterInstanceListClass * Get_Emitter (void) const { return m_pEmitterList; }
void Set_Emitter (EmitterInstanceListClass *pemitter_list) { m_pEmitterList = pemitter_list; Initialize (); }
bool Is_Data_Valid (void) const { return m_bValid; }
void Get_Frame_Keyframes (ParticlePropertyStruct<float> &frames) { frames = m_Frames; }
void On_Lifetime_Changed (float lifetime);
void Initialize (void);
void Update_Frames (void);
private:
float Normalize_Frame(float frame);
float Normalize_Frame(float frame,float min,float max);
float Denormalize_Frame(float normalized_val);
/////////////////////////////////////////////////////////
//
// Private member data
//
EmitterInstanceListClass * m_pEmitterList;
bool m_bValid;
ColorBarClass * m_FrameBar;
ParticlePropertyStruct<float> m_Frames;
float m_Lifetime;
float m_MinFrame;
float m_MaxFrame;
};
inline float EmitterFramePropPageClass::Normalize_Frame(float frame)
{
return (frame - m_MinFrame) / (m_MaxFrame - m_MinFrame);
}
inline float EmitterFramePropPageClass::Normalize_Frame(float frame,float min,float max)
{
return (frame - min) / (max - min);
}
inline float EmitterFramePropPageClass::Denormalize_Frame(float normalized_val)
{
return normalized_val * (m_MaxFrame - m_MinFrame) + m_MinFrame;
}
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EMITTERFRAMEPROPPAGE_H__6F068804_EAD5_4A19_BE03_C9C7B534E6E8__INCLUDED_)

View File

@@ -0,0 +1,413 @@
/*
** 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/>.
*/
// EmitterGeneralPropPage.cpp : implementation file
//
#include "StdAfx.H"
#include "W3DView.H"
#include "EmitterGeneralPropPage.H"
#include "EmitterPropertySheet.H"
#include "Part_Emt.H"
#include "Utils.H"
#include "texture.h"
#include "Shader.H"
#include "EmitterInstanceList.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// EmitterGeneralPropPageClass property page
IMPLEMENT_DYNCREATE(EmitterGeneralPropPageClass, CPropertyPage)
/////////////////////////////////////////////////////////////
//
// EmitterGeneralPropPageClass
//
EmitterGeneralPropPageClass::EmitterGeneralPropPageClass (EmitterInstanceListClass *pemitter)
: m_pEmitterList (NULL),
m_Parent (NULL),
m_bValid (true),
m_Lifetime (0),
CPropertyPage(EmitterGeneralPropPageClass::IDD)
{
//{{AFX_DATA_INIT(EmitterGeneralPropPageClass)
//}}AFX_DATA_INIT
Initialize ();
return ;
}
/////////////////////////////////////////////////////////////
//
// ~EmitterGeneralPropPageClass
//
EmitterGeneralPropPageClass::~EmitterGeneralPropPageClass (void)
{
return;
}
/////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
EmitterGeneralPropPageClass::DoDataExchange (CDataExchange* pDX)
{
// Allow the base class to process this message
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(EmitterGeneralPropPageClass)
DDX_Control(pDX, IDC_RENDER_MODE_COMBO, m_RenderModeCombo);
DDX_Control(pDX, IDC_PARTICLE_LIFETIME_SPIN, m_LifetimeSpin);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(EmitterGeneralPropPageClass, CPropertyPage)
//{{AFX_MSG_MAP(EmitterGeneralPropPageClass)
ON_BN_CLICKED(IDC_BROWSE_BUTTON, OnBrowseButton)
ON_EN_CHANGE(IDC_FILENAME_EDIT, OnChangeFilenameEdit)
ON_EN_CHANGE(IDC_NAME_EDIT, OnChangeNameEdit)
ON_EN_CHANGE(IDC_PARTICLE_LIFETIME_EDIT, OnChangeParticleLifetimeEdit)
ON_CBN_SELCHANGE(IDC_SHADER_COMBO, OnSelchangeShaderCombo)
ON_BN_CLICKED(IDC_PARTICLE_LIFETIME_CHECK, OnParticleLifetimeCheck)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////
//
// Initialize
//
void
EmitterGeneralPropPageClass::Initialize (void)
{
if (m_pEmitterList != NULL) {
//
// Get the emitter's texture
//
m_TextureFilename = m_pEmitterList->Get_Texture_Filename ();
m_Lifetime = m_pEmitterList->Get_Lifetime ();
m_EmitterName = m_pEmitterList->Get_Name ();
m_pEmitterList->Get_Shader (m_Shader);
}
return ;
}
/////////////////////////////////////////////////////////////
//
// Add_Shader_To_Combo
//
void
EmitterGeneralPropPageClass::Add_Shader_To_Combo
(
ShaderClass &shader,
LPCTSTR name
)
{
int index = SendDlgItemMessage (IDC_SHADER_COMBO, CB_ADDSTRING, 0, (LPARAM)name);
if (index != CB_ERR) {
SendDlgItemMessage (IDC_SHADER_COMBO, CB_SETITEMDATA, (WPARAM)index, (LPARAM)&shader);
//
// Is the blend mode of this shader the same as that of the
// particle emitter's shader.
//
if ((shader.Get_Alpha_Test () == m_Shader.Get_Alpha_Test ()) &&
(shader.Get_Dst_Blend_Func () == m_Shader.Get_Dst_Blend_Func ()) &&
(shader.Get_Src_Blend_Func () == m_Shader.Get_Src_Blend_Func ())) {
SendDlgItemMessage (IDC_SHADER_COMBO, CB_SETCURSEL, (WPARAM)index);
}
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
EmitterGeneralPropPageClass::OnInitDialog (void)
{
// Allow the base class to process this message
CPropertyPage::OnInitDialog ();
//
// Add the known shaders to the combobox
//
Add_Shader_To_Combo (ShaderClass::_PresetAdditiveSpriteShader, "Additive");
Add_Shader_To_Combo (ShaderClass::_PresetAlphaSpriteShader, "Alpha");
Add_Shader_To_Combo (ShaderClass::_PresetATestSpriteShader, "Alpha-Test");
Add_Shader_To_Combo (ShaderClass::_PresetATestBlendSpriteShader, "Alpha-Test-Blend");
Add_Shader_To_Combo (ShaderClass::_PresetScreenSpriteShader, "Screen");
Add_Shader_To_Combo (ShaderClass::_PresetMultiplicativeSpriteShader, "Multiplicative");
Add_Shader_To_Combo (ShaderClass::_PresetOpaqueSpriteShader, "Opaque");
//
// Fill the edit controls with the default values
//
SetDlgItemText (IDC_NAME_EDIT, m_EmitterName);
SetDlgItemText (IDC_FILENAME_EDIT, m_TextureFilename);
//
// Initialize the lifetime control
//
SendDlgItemMessage (IDC_PARTICLE_LIFETIME_CHECK, BM_SETCHECK, (WPARAM)(m_Lifetime < 100));
if (m_Lifetime > 100) {
m_Lifetime = 0;
}
::Initialize_Spinner (m_LifetimeSpin, m_Lifetime, 0, 1000);
OnParticleLifetimeCheck ();
//
// Initialize the render mode combo
//
m_RenderModeCombo.SetCurSel(m_pEmitterList->Get_Render_Mode());
return TRUE;
}
/////////////////////////////////////////////////////////////
//
// OnApply
//
BOOL
EmitterGeneralPropPageClass::OnApply (void)
{
// Get the data from the dialog controls
GetDlgItemText (IDC_NAME_EDIT, m_EmitterName);
GetDlgItemText (IDC_FILENAME_EDIT, m_TextureFilename);
m_Lifetime = ::GetDlgItemFloat (m_hWnd, IDC_PARTICLE_LIFETIME_EDIT);
if (SendDlgItemMessage (IDC_PARTICLE_LIFETIME_CHECK, BM_GETCHECK) == 0) {
m_Lifetime = 5000000.0F;
}
//
// Get the shader from the combobox
//
int index = SendDlgItemMessage (IDC_SHADER_COMBO, CB_GETCURSEL);
if (index != CB_ERR) {
ShaderClass *shader = (ShaderClass *)SendDlgItemMessage (IDC_SHADER_COMBO, CB_GETITEMDATA, (WPARAM)index);
if (shader != NULL) {
m_Shader = (*shader);
}
}
// Check to make sure the user entered a valid name for the emitter.
BOOL retval = FALSE;
if (m_EmitterName.GetLength () == 0) {
::MessageBox (m_hWnd, "Invalid emitter name. Please enter a new name.", "Invalid settings", MB_ICONEXCLAMATION | MB_OK);
m_bValid = false;
} else {
//
// Apply the changes to the emitter
//
m_pEmitterList->Set_Lifetime (m_Lifetime);
m_pEmitterList->Set_Texture_Filename (m_TextureFilename);
m_pEmitterList->Set_Name (m_EmitterName);
m_pEmitterList->Set_Shader (m_Shader);
m_pEmitterList->Set_Render_Mode (m_RenderModeCombo.GetCurSel());
// Allow the base class to process this message
retval = CPropertyPage::OnApply ();
m_bValid = true;
}
// Return the TRUE/FALSE result code
return retval;
}
/////////////////////////////////////////////////////////////
//
// OnBrowseButton
//
void
EmitterGeneralPropPageClass::OnBrowseButton (void)
{
CFileDialog openFileDialog (TRUE,
".tga",
NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
"Textures files (*.tga)|*.tga||",
::AfxGetMainWnd ());
// Ask the user what texture file they wish to load
if (openFileDialog.DoModal () == IDOK) {
SetDlgItemText (IDC_FILENAME_EDIT, openFileDialog.GetPathName ());
SetModified ();
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnChangeFilenameEdit
//
void
EmitterGeneralPropPageClass::OnChangeFilenameEdit (void)
{
SetModified ();
return ;
}
/////////////////////////////////////////////////////////////
//
// OnChangeNameEdit
//
void
EmitterGeneralPropPageClass::OnChangeNameEdit (void)
{
SetModified ();
return ;
}
/////////////////////////////////////////////////////////////
//
// OnNotify
//
BOOL
EmitterGeneralPropPageClass::OnNotify
(
WPARAM wParam,
LPARAM lParam,
LRESULT *pResult
)
{
//
// Update the spinner control if necessary
//
NMHDR *pheader = (NMHDR *)lParam;
if ((pheader != NULL) && (pheader->code == UDN_DELTAPOS)) {
LPNMUPDOWN pupdown = (LPNMUPDOWN)lParam;
::Update_Spinner_Buddy (pheader->hwndFrom, pupdown->iDelta);
}
// Allow the base class to process this message
return CPropertyPage::OnNotify (wParam, lParam, pResult);
}
/////////////////////////////////////////////////////////////
//
// OnChangeParticleLifetimeEdit
//
void
EmitterGeneralPropPageClass::OnChangeParticleLifetimeEdit (void)
{
SetModified ();
return ;
}
/////////////////////////////////////////////////////////////
//
// OnSelchangeShaderCombo
//
void
EmitterGeneralPropPageClass::OnSelchangeShaderCombo (void)
{
SetModified ();
return ;
}
/////////////////////////////////////////////////////////////
//
// OnCommand
//
BOOL
EmitterGeneralPropPageClass::OnCommand
(
WPARAM wParam,
LPARAM lParam
)
{
switch (LOWORD (wParam)) {
case IDC_FILENAME_EDIT:
case IDC_NAME_EDIT:
case IDC_PARTICLE_LIFETIME_EDIT:
if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
break;
case IDC_PARTICLE_LIFETIME_CHECK:
if (HIWORD (wParam) == BN_CLICKED) {
SetModified ();
}
break;
case IDC_RENDER_MODE_COMBO:
if (HIWORD (wParam) == CBN_SELCHANGE) {
SetModified ();
if (m_Parent != NULL) {
int cur_mode = ::SendMessage ((HWND)lParam, CB_GETCURSEL, 0, 0);
m_Parent->Notify_Render_Mode_Changed(cur_mode);
}
}
break;
}
return CPropertyPage::OnCommand(wParam, lParam);
}
/////////////////////////////////////////////////////////////
//
// OnParticleLifetimeCheck
//
/////////////////////////////////////////////////////////////
void
EmitterGeneralPropPageClass::OnParticleLifetimeCheck (void)
{
bool enable = (SendDlgItemMessage (IDC_PARTICLE_LIFETIME_CHECK, BM_GETCHECK) == 1);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_PARTICLE_LIFETIME_EDIT), enable);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_PARTICLE_LIFETIME_SPIN), enable);
if (enable == false) {
m_Lifetime = 0;
::SetDlgItemFloat (m_hWnd, IDC_PARTICLE_LIFETIME_EDIT, 0);
}
SetModified ();
return ;
}

View File

@@ -0,0 +1,134 @@
/*
** 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/>.
*/
#if !defined(AFX_EMITTERGENERALPROPPAGE_H__83A8B83C_BA3B_11D2_9FFA_00104B791122__INCLUDED_)
#define AFX_EMITTERGENERALPROPPAGE_H__83A8B83C_BA3B_11D2_9FFA_00104B791122__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EmitterGeneralPropPage.h : header file
//
#include "Resource.H"
#include "Shader.H"
// Forward delcarations
class EmitterInstanceListClass;
class EmitterPropertySheetClass;
/////////////////////////////////////////////////////////////////////////////
//
// EmitterGeneralPropPageClass dialog
//
class EmitterGeneralPropPageClass : public CPropertyPage
{
DECLARE_DYNCREATE(EmitterGeneralPropPageClass)
// Construction
public:
EmitterGeneralPropPageClass (EmitterInstanceListClass *pemitter_list = NULL);
~EmitterGeneralPropPageClass ();
// Dialog Data
//{{AFX_DATA(EmitterGeneralPropPageClass)
enum { IDD = IDD_PROP_PAGE_EMITTER_GEN };
CComboBox m_RenderModeCombo;
CSpinButtonCtrl m_LifetimeSpin;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(EmitterGeneralPropPageClass)
public:
virtual BOOL OnApply();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(EmitterGeneralPropPageClass)
virtual BOOL OnInitDialog();
afx_msg void OnBrowseButton();
afx_msg void OnChangeFilenameEdit();
afx_msg void OnChangeNameEdit();
afx_msg void OnChangeParticleLifetimeEdit();
afx_msg void OnSelchangeShaderCombo();
afx_msg void OnParticleLifetimeCheck();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////
//
// Public methods
//
//
// Inline accessors
//
EmitterInstanceListClass * Get_Emitter (void) const { return m_pEmitterList; }
void Set_Emitter (EmitterInstanceListClass *pemitter_list) { m_pEmitterList = pemitter_list; Initialize (); }
EmitterPropertySheetClass *Get_Parent (void) const { return m_Parent; }
void Set_Parent (EmitterPropertySheetClass * parent) { m_Parent = parent; }
bool Is_Data_Valid (void) const { return m_bValid; }
const CString & Get_Name (void) const { return m_EmitterName; }
const CString & Get_Texture_Filename (void) const { return m_TextureFilename; }
float Get_Lifetime (void) const { return m_Lifetime; }
const ShaderClass & Get_Shader (void) const { return m_Shader; }
//void Get_Shader (ShaderClass &shader);
protected:
/////////////////////////////////////////////////////////
//
// Protected methods
//
void Initialize (void);
void Add_Shader_To_Combo (ShaderClass &shader, LPCTSTR name);
private:
/////////////////////////////////////////////////////////
//
// Private member data
//
EmitterInstanceListClass * m_pEmitterList;
EmitterPropertySheetClass *m_Parent;
CString m_EmitterName;
CString m_TextureFilename;
ShaderClass m_Shader;
//int m_ShaderType;
float m_Lifetime;
bool m_bValid;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EMITTERGENERALPROPPAGE_H__83A8B83C_BA3B_11D2_9FFA_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,470 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : W3DView *
* *
* $Archive:: /VSS_Sync/W3DView/EmitterInstanceList.cpp $Modtime:: $*
* *
* $Revision:: 7 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "StdAfx.H"
#include "EmitterInstanceList.H"
#include "Utils.H"
/////////////////////////////////////////////////////////////////////
//
// ~EmitterInstanceListClass
//
/////////////////////////////////////////////////////////////////////
EmitterInstanceListClass::~EmitterInstanceListClass (void)
{
Free_List ();
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Free_List
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Free_List (void)
{
//
// Release our hold on each of the emitter pointers
//
for (int index = 0; index < m_List.Count (); index ++) {
MEMBER_RELEASE (m_List[index]);
}
m_List.Delete_All ();
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Add_Emitter
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Add_Emitter (ParticleEmitterClass *emitter)
{
ASSERT (emitter != NULL);
if (emitter != NULL) {
//
// If this is the first emitter in the list, then initialize
// the definition to it's state
//
if (m_List.Count () == 0) {
ParticleEmitterDefClass *def = emitter->Build_Definition ();
if (def != NULL) {
ParticleEmitterDefClass::operator= (*def);
SAFE_DELETE (def);
}
}
//
// Add this emitter to the list and put a hold on its reference
//
SAFE_ADD_REF (emitter);
m_List.Add (emitter);
}
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Set_Velocity
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Set_Velocity (const Vector3 &value)
{
ParticleEmitterDefClass::Set_Velocity (value);
//
// Pass this setting onto the emitters immediately
//
for (int index = 0; index < m_List.Count (); index ++) {
m_List[index]->Set_Base_Velocity (value);
}
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Set_Acceleration
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Set_Acceleration (const Vector3 &value)
{
ParticleEmitterDefClass::Set_Acceleration (value);
//
// Pass this setting onto the emitters immediately
//
for (int index = 0; index < m_List.Count (); index ++) {
m_List[index]->Set_Acceleration (value);
}
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Set_Burst_Size
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Set_Burst_Size (unsigned int count)
{
ParticleEmitterDefClass::Set_Burst_Size (count);
//
// Pass this setting onto the emitters immediately
//
for (int index = 0; index < m_List.Count (); index ++) {
m_List[index]->Set_Burst_Size (count);
}
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Set_Outward_Vel
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Set_Outward_Vel (float value)
{
ParticleEmitterDefClass::Set_Outward_Vel (value);
//
// Pass this setting onto the emitters immediately
//
for (int index = 0; index < m_List.Count (); index ++) {
m_List[index]->Set_Outwards_Velocity (value);
}
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Set_Vel_Inherit
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Set_Vel_Inherit (float value)
{
ParticleEmitterDefClass::Set_Vel_Inherit (value);
//
// Pass this setting onto the emitters immediately
//
for (int index = 0; index < m_List.Count (); index ++) {
m_List[index]->Set_Velocity_Inheritance_Factor (value);
}
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Set_Velocity_Random
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Set_Velocity_Random (Vector3Randomizer *randomizer)
{
ParticleEmitterDefClass::Set_Velocity_Random (randomizer);
if (randomizer != NULL) {
//
// Pass this setting onto the emitters immediately
//
for (int index = 0; index < m_List.Count (); index ++) {
m_List[index]->Set_Velocity_Randomizer (randomizer->Clone ());
}
}
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Set_Color_Keyframes
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Set_Color_Keyframes (ParticlePropertyStruct<Vector3> &keyframes)
{
//
// Make sure tha any value that is supposed to go to zero, really
// does even if its got a randomizer.
//
if ( (keyframes.Rand.X != 0) ||
(keyframes.Rand.Y != 0) ||
(keyframes.Rand.Z != 0))
{
for (UINT index = 0; index < keyframes.NumKeyFrames; index ++) {
if ((keyframes.Values[index].X <= 0.000001F) &&
(keyframes.Values[index].Y <= 0.000001F) &&
(keyframes.Values[index].Z <= 0.000001F)) {
keyframes.Values[index].X = -keyframes.Rand.X;
keyframes.Values[index].Y = -keyframes.Rand.Y;
keyframes.Values[index].Z = -keyframes.Rand.Z;
}
}
}
ParticleEmitterDefClass::Set_Color_Keyframes (keyframes);
//
// Pass this setting onto the emitters immediately
//
for (int index = 0; index < m_List.Count (); index ++) {
m_List[index]->Reset_Colors (keyframes);
}
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Set_Opacity_Keyframes
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Set_Opacity_Keyframes (ParticlePropertyStruct<float> &keyframes)
{
//
// Make sure tha any value that is supposed to go to zero, really
// does even if its got a randomizer.
//
if (keyframes.Rand != 0)
{
for (UINT index = 0; index < keyframes.NumKeyFrames; index ++) {
if (keyframes.Values[index] <= 0.000001F) {
keyframes.Values[index] = -keyframes.Rand;
}
}
}
ParticleEmitterDefClass::Set_Opacity_Keyframes (keyframes);
//
// Pass this setting onto the emitters immediately
//
for (int index = 0; index < m_List.Count (); index ++) {
m_List[index]->Reset_Opacity (keyframes);
}
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Set_Size_Keyframes
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Set_Size_Keyframes (ParticlePropertyStruct<float> &keyframes)
{
//
// Make sure tha any value that is supposed to go to zero, really
// does even if its got a randomizer.
//
if (keyframes.Rand != 0)
{
for (UINT index = 0; index < keyframes.NumKeyFrames; index ++) {
if (keyframes.Values[index] <= 0.000001F) {
keyframes.Values[index] = -keyframes.Rand;
}
}
}
ParticleEmitterDefClass::Set_Size_Keyframes (keyframes);
//
// Pass this setting onto the emitters immediately
//
for (int index = 0; index < m_List.Count (); index ++) {
m_List[index]->Reset_Size (keyframes);
}
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Set_Rotation_Keyframes
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Set_Rotation_Keyframes (ParticlePropertyStruct<float> &keyframes, float orient_rnd)
{
ParticleEmitterDefClass::Set_Rotation_Keyframes (keyframes, orient_rnd);
//
// Pass this setting onto the emitters immediately
//
for (int index = 0; index < m_List.Count (); index ++) {
m_List[index]->Reset_Rotations (keyframes, orient_rnd);
}
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Set_Frame_Keyframes
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Set_Frame_Keyframes (ParticlePropertyStruct<float> &keyframes)
{
ParticleEmitterDefClass::Set_Frame_Keyframes (keyframes);
//
// Pass this setting onto the emitters immediately
//
for (int index = 0; index < m_List.Count (); index ++) {
m_List[index]->Reset_Frames (keyframes);
}
return ;
}
/////////////////////////////////////////////////////////////////////
//
// Set_Blur_Time_Keyframes
//
/////////////////////////////////////////////////////////////////////
void
EmitterInstanceListClass::Set_Blur_Time_Keyframes (ParticlePropertyStruct<float> &keyframes)
{
ParticleEmitterDefClass::Set_Blur_Time_Keyframes (keyframes);
//
// Pass this setting onto the emitters immediately
//
for (int index = 0; index < m_List.Count (); index ++) {
m_List[index]->Reset_Blur_Times (keyframes);
}
return ;
}
///////////////////////////////////////////////////////////////////////////////////
//
// Get_Color_Keyframes
//
void
EmitterInstanceListClass::Get_Color_Keyframes (ParticlePropertyStruct<Vector3> &keyframes) const
{
ParticleEmitterDefClass::Get_Color_Keyframes (keyframes);
//
// Normalize the data
//
for (UINT index = 0; index < keyframes.NumKeyFrames; index ++) {
if (keyframes.Values[index].X <= 0.000001F) {
keyframes.Values[index].X = 0;
}
if (keyframes.Values[index].Y <= 0.000001F) {
keyframes.Values[index].Y = 0;
}
if (keyframes.Values[index].Z <= 0.000001F) {
keyframes.Values[index].Z = 0;
}
}
return ;
}
///////////////////////////////////////////////////////////////////////////////////
//
// Get_Opacity_Keyframes
//
void
EmitterInstanceListClass::Get_Opacity_Keyframes (ParticlePropertyStruct<float> &keyframes) const
{
ParticleEmitterDefClass::Get_Opacity_Keyframes (keyframes);
//
// Normalize the data
//
for (UINT index = 0; index < keyframes.NumKeyFrames; index ++) {
if (keyframes.Values[index] <= 0.000001F) {
keyframes.Values[index] = 0;
}
}
return ;
}
///////////////////////////////////////////////////////////////////////////////////
//
// Get_Size_Keyframes
//
void
EmitterInstanceListClass::Get_Size_Keyframes (ParticlePropertyStruct<float> &keyframes) const
{
ParticleEmitterDefClass::Get_Size_Keyframes (keyframes);
//
// Normalize the data
//
for (UINT index = 0; index < keyframes.NumKeyFrames; index ++) {
if (keyframes.Values[index] <= 0.000001F) {
keyframes.Values[index] = 0;
}
}
return ;
}

View File

@@ -0,0 +1,114 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : W3DView *
* *
* $Archive:: /VSS_Sync/W3DView/EmitterInstanceList.h $Modtime:: $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __EMITTER_INSTANCE_LIST_H
#define __EMITTER_INSTANCE_LIST_H
#include "Vector.H"
#include "Part_Ldr.H"
#include "Part_Emt.H"
/////////////////////////////////////////////////////////////////////
//
// EmitterInstanceListClass
//
/////////////////////////////////////////////////////////////////////
class EmitterInstanceListClass : public ParticleEmitterDefClass
{
public:
///////////////////////////////////////////////////////
// Public constructors/destructors
///////////////////////////////////////////////////////
EmitterInstanceListClass (void) { }
EmitterInstanceListClass (const EmitterInstanceListClass &src)
: ParticleEmitterDefClass (src) { }
virtual ~EmitterInstanceListClass (void);
///////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////
virtual void Add_Emitter (ParticleEmitterClass *emitter);
virtual void Free_List (void);
///////////////////////////////////////////////////////
// Derived overrides
///////////////////////////////////////////////////////
//
// Note: The following are settings that can be changed on
// the fly. All other settings are simply cached in the
// definition and can be used to create a new prototype loader.
//
virtual void Set_Velocity (const Vector3 &value);
virtual void Set_Acceleration (const Vector3 &value);
virtual void Set_Burst_Size (unsigned int count);
virtual void Set_Outward_Vel (float value);
virtual void Set_Vel_Inherit (float value);
//
// Randomizer accessors
//
virtual void Set_Velocity_Random (Vector3Randomizer *randomizer);
//
// Keyframe accessors
//
virtual void Set_Color_Keyframes (ParticlePropertyStruct<Vector3> &keyframes);
virtual void Set_Opacity_Keyframes (ParticlePropertyStruct<float> &keyframes);
virtual void Set_Size_Keyframes (ParticlePropertyStruct<float> &keyframes);
virtual void Set_Rotation_Keyframes (ParticlePropertyStruct<float> &keyframes, float orient_rnd);
virtual void Set_Frame_Keyframes (ParticlePropertyStruct<float> &keyframes);
virtual void Set_Blur_Time_Keyframes (ParticlePropertyStruct<float> &keyframes);
virtual void Get_Color_Keyframes (ParticlePropertyStruct<Vector3> &keyframes) const;
virtual void Get_Opacity_Keyframes (ParticlePropertyStruct<float> &keyframes) const;
virtual void Get_Size_Keyframes (ParticlePropertyStruct<float> &keyframes) const;
private:
///////////////////////////////////////////////////////
// Private member data
///////////////////////////////////////////////////////
DynamicVectorClass<ParticleEmitterClass *> m_List;
};
#endif //__EMITTER_INSTANCE_LIST_H

View File

@@ -0,0 +1,372 @@
/*
** 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/>.
*/
// EmitterLineGroupPropPage.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "EmitterLineGroupPropPage.h"
#include "w3d_file.h"
#include "EmitterInstanceList.h"
#include "Utils.h"
#include "ColorBar.H"
#include "ParticleBlurTimeKeyDialog.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// EmitterLineGroupPropPageClass property page
IMPLEMENT_DYNCREATE(EmitterLineGroupPropPageClass, CPropertyPage)
EmitterLineGroupPropPageClass::EmitterLineGroupPropPageClass() :
CPropertyPage(EmitterLineGroupPropPageClass::IDD),
m_pEmitterList(NULL),
m_bValid(true),
m_BlurTimeBar(NULL),
m_Lifetime(0),
m_MinBlurTime(0),
m_MaxBlurTime(1)
{
::memset (&m_BlurTimes, 0, sizeof (m_BlurTimes));
//{{AFX_DATA_INIT(EmitterLineGroupPropPageClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
Initialize();
}
EmitterLineGroupPropPageClass::~EmitterLineGroupPropPageClass()
{
// Free the blur time arrays
SAFE_DELETE_ARRAY (m_BlurTimes.KeyTimes);
SAFE_DELETE_ARRAY (m_BlurTimes.Values);
}
void EmitterLineGroupPropPageClass::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(EmitterLineGroupPropPageClass)
DDX_Control(pDX, IDC_BLUR_TIME_RANDOM_SPIN, m_BlurTimeRandomSpin);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(EmitterLineGroupPropPageClass, CPropertyPage)
//{{AFX_MSG_MAP(EmitterLineGroupPropPageClass)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////
//
// Initialize
//
/////////////////////////////////////////////////////////////
void
EmitterLineGroupPropPageClass::Initialize (void)
{
SAFE_DELETE_ARRAY (m_BlurTimes.KeyTimes);
SAFE_DELETE_ARRAY (m_BlurTimes.Values);
if (m_pEmitterList != NULL) {
m_Lifetime = m_pEmitterList->Get_Lifetime ();
m_pEmitterList->Get_Blur_Time_Keyframes (m_BlurTimes);
//
// Determine what the min and max blur times are
//
m_MaxBlurTime = WWMath::Max(m_BlurTimes.Start,1.0f);
m_MinBlurTime = WWMath::Min(m_BlurTimes.Start,0.0f);
for (UINT index = 0; index < m_BlurTimes.NumKeyFrames; index ++) {
if (m_BlurTimes.Values[index] > m_MaxBlurTime) {
m_MaxBlurTime = m_BlurTimes.Values[index];
}
if (m_BlurTimes.Values[index] < m_MinBlurTime) {
m_MinBlurTime = m_BlurTimes.Values[index];
}
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
// EmitterLineGroupPropPageClass message handlers
BOOL EmitterLineGroupPropPageClass::OnInitDialog()
{
CPropertyPage::OnInitDialog();
//
// Create the keyframe control
//
m_BlurTimeBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_BLUR_TIME_BAR));
//
// Setup the spinners
//
Initialize_Spinner (m_BlurTimeRandomSpin, m_BlurTimes.Rand, 0, 10000);
//
// Reset the keyframe control
//
m_BlurTimeBar->Set_Range (0, 1);
m_BlurTimeBar->Clear_Points ();
m_BlurTimeBar->Modify_Point (0, 0, 0, 0, 0);
m_BlurTimeBar->Set_Graph_Percent (0, Normalize_Blur_Time(m_BlurTimes.Start));
//
// Load the current set of frame keyframes into the control
//
for (UINT index = 0; index < m_BlurTimes.NumKeyFrames; index ++) {
m_BlurTimeBar->Modify_Point (index + 1,
m_BlurTimes.KeyTimes[index] / m_Lifetime,
0,
0,
0);
m_BlurTimeBar->Set_Graph_Percent (index + 1, Normalize_Blur_Time(m_BlurTimes.Values[index]));
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
/////////////////////////////////////////////////////////////
//
// Update_Blur_Times
//
/////////////////////////////////////////////////////////////
void
EmitterLineGroupPropPageClass::Update_Blur_Times (void)
{
float position = 0;
float red = 0;
float green = 0;
float blue = 0;
//
// Setup the initial or 'starting' size
//
m_BlurTimes.Start = Denormalize_Blur_Time(m_BlurTimeBar->Get_Graph_Percent (0));
//
// Free the current setting arrays
//
SAFE_DELETE_ARRAY (m_BlurTimes.KeyTimes);
SAFE_DELETE_ARRAY (m_BlurTimes.Values);
//
// Determine if we need to build the array of key frames or not
//
int count = m_BlurTimeBar->Get_Point_Count ();
m_BlurTimes.NumKeyFrames = count - 1;
if (count > 1) {
m_BlurTimes.KeyTimes = new float[count - 1];
m_BlurTimes.Values = new float[count - 1];
//
// Get all the key frames and add them to our structure
//
for (int index = 1; index < count; index ++) {
m_BlurTimeBar->Get_Point (index, &position, &red, &green, &blue);
m_BlurTimes.KeyTimes[index - 1] = position * m_Lifetime;
m_BlurTimes.Values[index - 1] = Denormalize_Blur_Time(m_BlurTimeBar->Get_Graph_Percent (index) );
}
}
return ;
}
/////////////////////////////////////////////////////////////
//
// On_Lifetime_Changed
//
/////////////////////////////////////////////////////////////
void
EmitterLineGroupPropPageClass::On_Lifetime_Changed (float lifetime)
{
if (m_Lifetime != lifetime) {
float conversion = lifetime / m_Lifetime;
//
// Rescale the sizes
//
for (UINT index = 0; index < m_BlurTimes.NumKeyFrames; index ++) {
m_BlurTimes.KeyTimes[index] *= conversion;
}
//
// Update the emitter
//
m_pEmitterList->Set_Blur_Time_Keyframes (m_BlurTimes);
m_Lifetime = lifetime;
}
return ;
}
BOOL EmitterLineGroupPropPageClass::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch (LOWORD (wParam))
{
case IDC_BLUR_TIME_RANDOM_EDIT:
{
// Update the emitter
if ((HIWORD (wParam) == EN_KILLFOCUS) &&
SendDlgItemMessage (LOWORD (wParam), EM_GETMODIFY))
{
SendDlgItemMessage (LOWORD (wParam), EM_SETMODIFY, (WPARAM)0);
m_BlurTimes.Rand = ::GetDlgItemFloat (m_hWnd, IDC_BLUR_TIME_RANDOM_EDIT);
m_pEmitterList->Set_Blur_Time_Keyframes (m_BlurTimes);
SetModified ();
} else if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
}
break;
}
return CPropertyPage::OnCommand(wParam, lParam);
}
BOOL EmitterLineGroupPropPageClass::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
CBR_NMHDR *color_bar_hdr = (CBR_NMHDR *)lParam;
//
// Update the spinner controls if necessary
//
NMHDR *pheader = (NMHDR *)lParam;
if ((pheader != NULL) && (pheader->code == UDN_DELTAPOS)) {
LPNMUPDOWN pupdown = (LPNMUPDOWN)lParam;
::Update_Spinner_Buddy (pheader->hwndFrom, pupdown->iDelta);
}
//
// Which control sent the notification?
//
switch (color_bar_hdr->hdr.idFrom)
{
case IDC_BLUR_TIME_BAR:
{
if (color_bar_hdr->hdr.code == CBRN_DBLCLK_POINT) {
//
// Allow the user to edit the keyframe
//
float blur_time = Denormalize_Blur_Time(m_BlurTimeBar->Get_Graph_Percent (color_bar_hdr->key_index));
ParticleBlurTimeKeyDialogClass dialog (blur_time, this);
if (dialog.DoModal () == IDOK) {
blur_time = dialog.Get_Blur_Time ();
float norm_val = Normalize_Blur_Time(blur_time);
m_BlurTimeBar->Set_Redraw (false);
m_BlurTimeBar->Set_Graph_Percent (color_bar_hdr->key_index, norm_val);
//
// Determine if the user changed the 'max' or 'min' frame
//
float new_max = WWMath::Max(blur_time,1.0f);
float new_min = WWMath::Min(blur_time,0.0f);
int count = m_BlurTimeBar->Get_Point_Count ();
for (int index = 0; index < count; index ++) {
float tmp = Denormalize_Blur_Time(m_BlurTimeBar->Get_Graph_Percent (index) );
if (tmp > new_max) {
new_max = tmp;
}
if (tmp < new_min) {
new_min = tmp;
}
}
//
// Renormalize the BlurTimeBar key frame points if necessary
//
if ((new_max != m_MaxBlurTime) || (new_min != m_MinBlurTime)) {
int count = m_BlurTimeBar->Get_Point_Count ();
for (int index = 0; index < count; index ++) {
float frame = Denormalize_Blur_Time(m_BlurTimeBar->Get_Graph_Percent (index));
float new_norm = Normalize_Blur_Time(frame,new_min,new_max);
m_BlurTimeBar->Set_Graph_Percent (index, new_norm);
}
// Remember the new min and max
m_MinBlurTime = new_min;
m_MaxBlurTime = new_max;
}
m_BlurTimeBar->Set_Redraw (true);
//
// Update the emitter
//
Update_Blur_Times ();
m_pEmitterList->Set_Blur_Time_Keyframes (m_BlurTimes);
SetModified ();
}
} else if ((color_bar_hdr->hdr.code == CBRN_MOVING_POINT) ||
(color_bar_hdr->hdr.code == CBRN_DELETED_POINT)) {
//
// Update the emitter
//
Update_Blur_Times ();
m_pEmitterList->Set_Blur_Time_Keyframes (m_BlurTimes);
SetModified ();
}
}
break;
case IDC_BLUR_TIME_RANDOM_SPIN:
{
// Update the emitter
m_BlurTimes.Rand = ::GetDlgItemFloat (m_hWnd, IDC_BLUR_TIME_RANDOM_EDIT);
m_pEmitterList->Set_Blur_Time_Keyframes (m_BlurTimes);
SetModified ();
}
break;
}
return CPropertyPage::OnNotify(wParam, lParam, pResult);
}
float EmitterLineGroupPropPageClass::Normalize_Blur_Time(float blur)
{
return (blur - m_MinBlurTime) / (m_MaxBlurTime - m_MinBlurTime);
}
float EmitterLineGroupPropPageClass::Normalize_Blur_Time(float blur,float min,float max)
{
return (blur - min) / (max - min);
}
float EmitterLineGroupPropPageClass::Denormalize_Blur_Time(float normalized_val)
{
return normalized_val * (m_MaxBlurTime - m_MinBlurTime) + m_MinBlurTime;
}

View File

@@ -0,0 +1,116 @@
/*
** 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/>.
*/
#if !defined(AFX_EMITTERLINEGROUPPROPPAGE_H__51E7B2D1_1943_454E_B188_5F7D508D7203__INCLUDED_)
#define AFX_EMITTERLINEGROUPPROPPAGE_H__51E7B2D1_1943_454E_B188_5F7D508D7203__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EmitterLineGroupPropPage.h : header file
//
#include "part_emt.h"
// Forward declarations
class EmitterInstanceListClass;
class ColorBarClass;
/////////////////////////////////////////////////////////////////////////////
// EmitterLineGroupPropPageClass dialog
class EmitterLineGroupPropPageClass : public CPropertyPage
{
DECLARE_DYNCREATE(EmitterLineGroupPropPageClass)
// Construction
public:
EmitterLineGroupPropPageClass();
~EmitterLineGroupPropPageClass();
// Dialog Data
//{{AFX_DATA(EmitterLineGroupPropPageClass)
enum { IDD = IDD_PROP_PAGE_EMITTER_LINEGROUP };
CSpinButtonCtrl m_BlurTimeRandomSpin;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(EmitterLineGroupPropPageClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(EmitterLineGroupPropPageClass)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////
//
// Public methods
//
//
// Inline accessors
//
EmitterInstanceListClass * Get_Emitter (void) const { return m_pEmitterList; }
void Set_Emitter (EmitterInstanceListClass *pemitter_list) { m_pEmitterList = pemitter_list; Initialize (); }
bool Is_Data_Valid (void) const { return m_bValid; }
void Get_Blur_Time_Keyframes (ParticlePropertyStruct<float> &blurtimes) { blurtimes = m_BlurTimes; }
void On_Lifetime_Changed (float lifetime);
void Initialize (void);
void Update_Blur_Times (void);
private:
float Normalize_Blur_Time(float blur);
float Normalize_Blur_Time(float blur,float min,float max);
float Denormalize_Blur_Time(float normalized_val);
/////////////////////////////////////////////////////////
//
// Private member data
//
EmitterInstanceListClass * m_pEmitterList;
bool m_bValid;
ColorBarClass * m_BlurTimeBar;
ParticlePropertyStruct<float> m_BlurTimes;
float m_Lifetime;
float m_MinBlurTime;
float m_MaxBlurTime;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EMITTERLINEGROUPPROPPAGE_H__51E7B2D1_1943_454E_B188_5F7D508D7203__INCLUDED_)

View File

@@ -0,0 +1,231 @@
/*
** 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/>.
*/
// EmitterLinePropPage.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "EmitterLinePropPage.h"
#include "w3d_file.h"
#include "EmitterInstanceList.h"
#include "Utils.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// EmitterLinePropPageClass property page
IMPLEMENT_DYNCREATE(EmitterLinePropPageClass, CPropertyPage)
EmitterLinePropPageClass::EmitterLinePropPageClass() :
CPropertyPage(EmitterLinePropPageClass::IDD),
m_pEmitterList(NULL),
m_bValid(true),
m_MappingMode(W3D_EMITTER_RENDER_MODE_TRI_PARTICLES),
m_MergeIntersections(false),
m_EndCaps(false),
m_DisableSorting(false),
m_SubdivisionLevel(0),
m_NoiseAmplitude(0.0f),
m_MergeAbortFactor(0.0f),
m_TextureTileFactor(0.0f),
m_UPerSec(0.0f),
m_VPerSec(0.0f)
{
//{{AFX_DATA_INIT(EmitterLinePropPageClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
EmitterLinePropPageClass::~EmitterLinePropPageClass()
{
}
void EmitterLinePropPageClass::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(EmitterLinePropPageClass)
DDX_Control(pDX, IDC_MAPMODE_COMBO, m_MapModeCombo);
DDX_Control(pDX, IDC_MERGE_ABORT_FACTOR_SPIN, m_MergeAbortFactorSpin);
DDX_Control(pDX, IDC_VPERSEC_SPIN, m_VPerSecSpin);
DDX_Control(pDX, IDC_UVTILING_SPIN, m_UVTilingSpin);
DDX_Control(pDX, IDC_UPERSEC_SPIN, m_UPerSecSpin);
DDX_Control(pDX, IDC_NOISE_AMPLITUDE_SPIN, m_NoiseAmplitudeSpin);
DDX_Control(pDX, IDC_SUBDIVISION_LEVEL_SPIN, m_SubdivisionLevelSpin);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(EmitterLinePropPageClass, CPropertyPage)
//{{AFX_MSG_MAP(EmitterLinePropPageClass)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// EmitterLinePropPageClass message handlers
/////////////////////////////////////////////////////////////
//
// Initialize
//
void
EmitterLinePropPageClass::Initialize (void)
{
if (m_pEmitterList != NULL) {
//
// Read the settings from the emitter
//
m_MappingMode = m_pEmitterList->Get_Line_Texture_Mapping_Mode();
m_MergeIntersections = !!m_pEmitterList->Is_Merge_Intersections();
m_DisableSorting = !!m_pEmitterList->Is_Sorting_Disabled();
m_EndCaps = !!m_pEmitterList->Are_End_Caps_Enabled();
m_SubdivisionLevel = m_pEmitterList->Get_Subdivision_Level();
m_NoiseAmplitude = m_pEmitterList->Get_Noise_Amplitude();
m_MergeAbortFactor = m_pEmitterList->Get_Merge_Abort_Factor();
m_TextureTileFactor = m_pEmitterList->Get_Texture_Tile_Factor();
Vector2 uvrate = m_pEmitterList->Get_UV_Offset_Rate();
m_UPerSec = uvrate.X;
m_VPerSec = uvrate.Y;
}
return ;
}
BOOL EmitterLinePropPageClass::OnInitDialog()
{
CPropertyPage::OnInitDialog();
// Set up the spinner ranges
m_SubdivisionLevelSpin.SetRange(0,8);
m_SubdivisionLevelSpin.SetPos(m_SubdivisionLevel);
::Initialize_Spinner (m_NoiseAmplitudeSpin, m_NoiseAmplitude, -10000, 10000);
::Initialize_Spinner (m_MergeAbortFactorSpin, m_MergeAbortFactor, -10000, 10000);
::Initialize_Spinner (m_UVTilingSpin, m_TextureTileFactor, 0.0f,8.0f);
::Initialize_Spinner (m_UPerSecSpin, m_UPerSec, 0.0f,32.0f);
::Initialize_Spinner (m_VPerSecSpin, m_VPerSec, 0.0f,32.0f);
// Set the combo box
m_MapModeCombo.SetCurSel(m_MappingMode);
// Set the checkboxes
SendDlgItemMessage (IDC_MERGE_INTERSECTIONS_CHECK, BM_SETCHECK, (WPARAM)(m_MergeIntersections != 0));
SendDlgItemMessage (IDC_END_CAPS_CHECK, BM_SETCHECK, (WPARAM)(m_EndCaps != 0));
SendDlgItemMessage (IDC_DISABLE_SORTING_CHECK, BM_SETCHECK, (WPARAM)(m_DisableSorting != 0));
bool enable = (m_pEmitterList->Get_Render_Mode() == W3D_EMITTER_RENDER_MODE_LINE);
::Enable_Dialog_Controls(m_hWnd,enable);
return TRUE;
}
BOOL EmitterLinePropPageClass::OnApply()
{
//
// Get the data from the controls
//
m_SubdivisionLevel = GetDlgItemInt (IDC_SUBDIVISION_LEVEL_EDIT);
m_NoiseAmplitude = ::GetDlgItemFloat (m_hWnd, IDC_NOISE_AMPLITUDE_EDIT);
m_MergeAbortFactor = ::GetDlgItemFloat (m_hWnd, IDC_MERGE_ABORT_FACTOR_EDIT);
m_TextureTileFactor = ::GetDlgItemFloat (m_hWnd, IDC_UVTILING_EDIT);
m_UPerSec = ::GetDlgItemFloat (m_hWnd, IDC_UPERSEC_EDIT);
m_VPerSec = ::GetDlgItemFloat (m_hWnd, IDC_VPERSEC_EDIT);
m_MappingMode = SendDlgItemMessage (IDC_MAPMODE_COMBO, CB_GETCURSEL);
m_MergeIntersections = !!SendDlgItemMessage (IDC_MERGE_INTERSECTIONS_CHECK, BM_GETCHECK);
m_EndCaps = !!SendDlgItemMessage (IDC_END_CAPS_CHECK, BM_GETCHECK);
m_DisableSorting = !!SendDlgItemMessage (IDC_DISABLE_SORTING_CHECK, BM_GETCHECK);
//
// Apply the changes to the emitter
//
m_pEmitterList->Set_Subdivision_Level (m_SubdivisionLevel);
m_pEmitterList->Set_Noise_Amplitude (m_NoiseAmplitude);
m_pEmitterList->Set_Merge_Abort_Factor (m_MergeAbortFactor);
m_pEmitterList->Set_Texture_Tile_Factor (m_TextureTileFactor);
m_pEmitterList->Set_UV_Offset_Rate (Vector2(m_UPerSec,m_VPerSec));
m_pEmitterList->Set_Line_Texture_Mapping_Mode (m_MappingMode);
m_pEmitterList->Set_Merge_Intersections (m_MergeIntersections);
m_pEmitterList->Set_Disable_Sorting(m_DisableSorting);
m_pEmitterList->Set_End_Caps(m_EndCaps);
// Allow the base class to process this message
return CPropertyPage::OnApply();
}
BOOL EmitterLinePropPageClass::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch (LOWORD (wParam))
{
// Check if any of the edit boxes were modified,
case IDC_SUBDIVISION_LEVEL_EDIT:
case IDC_NOISE_AMPLITUDE_EDIT:
case IDC_MERGE_ABORT_FACTOR_EDIT:
case IDC_UVTILING_EDIT:
case IDC_UPERSEC_EDIT:
case IDC_VPERSEC_EDIT:
if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
break;
case IDC_MERGE_INTERSECTIONS_CHECK:
case IDC_END_CAPS_CHECK:
case IDC_DISABLE_SORTING_CHECK:
if (HIWORD (wParam) == BN_CLICKED) {
SetModified ();
}
break;
case IDC_MAPMODE_COMBO:
if (HIWORD (wParam) == CBN_SELCHANGE) {
SetModified ();
}
break;
}
return CPropertyPage::OnCommand(wParam, lParam);
}
BOOL EmitterLinePropPageClass::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
//
// Update the spinner control if necessary
//
NMHDR *pheader = (NMHDR *)lParam;
if ((pheader != NULL) && (pheader->code == UDN_DELTAPOS)) {
LPNMUPDOWN pupdown = (LPNMUPDOWN)lParam;
::Update_Spinner_Buddy (pheader->hwndFrom, pupdown->iDelta);
SetModified ();
}
// Allow the base class to process this message
return CPropertyPage::OnNotify (wParam, lParam, pResult);
}

View File

@@ -0,0 +1,135 @@
/*
** 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/>.
*/
#if !defined(AFX_EMITTERLINEPROPPAGE_H__BBD9ED4C_E752_439A_81D5_A4FA9A6F6FC8__INCLUDED_)
#define AFX_EMITTERLINEPROPPAGE_H__BBD9ED4C_E752_439A_81D5_A4FA9A6F6FC8__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EmitterLinePropPage.h : header file
//
// Forward delcarations
class EmitterInstanceListClass;
/////////////////////////////////////////////////////////////////////////////
// EmitterLinePropPageClass dialog
class EmitterLinePropPageClass : public CPropertyPage
{
DECLARE_DYNCREATE(EmitterLinePropPageClass)
// Construction
public:
EmitterLinePropPageClass();
~EmitterLinePropPageClass();
// Dialog Data
//{{AFX_DATA(EmitterLinePropPageClass)
enum { IDD = IDD_PROP_PAGE_EMITTER_LINEPROPS };
CComboBox m_MapModeCombo;
CSpinButtonCtrl m_MergeAbortFactorSpin;
CSpinButtonCtrl m_VPerSecSpin;
CSpinButtonCtrl m_UVTilingSpin;
CSpinButtonCtrl m_UPerSecSpin;
CSpinButtonCtrl m_NoiseAmplitudeSpin;
CSpinButtonCtrl m_SubdivisionLevelSpin;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(EmitterLinePropPageClass)
public:
virtual BOOL OnApply();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(EmitterLinePropPageClass)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////
//
// Public methods
//
EmitterInstanceListClass * Get_Emitter (void) const { return m_pEmitterList; }
void Set_Emitter (EmitterInstanceListClass *pemitter_list) { m_pEmitterList = pemitter_list; Initialize (); }
bool Is_Data_Valid (void) const { return m_bValid; }
int Get_Mapping_Mode (void) const { return m_MappingMode; }
bool Get_Merge_Intersections (void) const { return m_MergeIntersections; }
bool Get_End_Caps (void) const { return m_EndCaps; }
bool Get_Disable_Sorting (void) const { return m_DisableSorting; }
int Get_Subdivision_Level (void) const { return m_SubdivisionLevel; }
float Get_Noise_Amplitude (void) const { return m_NoiseAmplitude; }
float Get_Merge_Abort_Factor (void) const { return m_MergeAbortFactor; }
float Get_Texture_Tile_Factor (void) const { return m_TextureTileFactor; }
float Get_U_Per_Sec(void) const { return m_UPerSec; }
float Get_V_Per_Sed(void) const { return m_VPerSec; }
protected:
/////////////////////////////////////////////////////////
//
// Protected methods
//
void Initialize (void);
private:
/////////////////////////////////////////////////////////
//
// Private member data
//
EmitterInstanceListClass * m_pEmitterList;
bool m_bValid;
int m_MappingMode;
bool m_MergeIntersections;
bool m_EndCaps;
bool m_DisableSorting;
int m_SubdivisionLevel;
float m_NoiseAmplitude;
float m_MergeAbortFactor;
float m_TextureTileFactor;
float m_UPerSec;
float m_VPerSec;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EMITTERLINEPROPPAGE_H__BBD9ED4C_E752_439A_81D5_A4FA9A6F6FC8__INCLUDED_)

View File

@@ -0,0 +1,298 @@
/*
** 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/>.
*/
// EmitterParticlePropPage.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "EmitterParticlePropPage.h"
#include "Part_Emt.H"
#include "Utils.H"
#include "Vector3RndCombo.H"
#include "VolumeRandomDialog.H"
#include "EmitterInstanceList.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// EmitterParticlePropPageClass property page
IMPLEMENT_DYNCREATE(EmitterParticlePropPageClass, CPropertyPage)
/////////////////////////////////////////////////////////////
//
// EmitterParticlePropPageClass
//
EmitterParticlePropPageClass::EmitterParticlePropPageClass (EmitterInstanceListClass *pemitter)
: m_pEmitterList (pemitter),
m_bValid (true),
m_Rate (0),
m_BurstSize (0),
m_MaxParticles (0),
m_Randomizer (NULL),
CPropertyPage(EmitterParticlePropPageClass::IDD)
{
//{{AFX_DATA_INIT(EmitterParticlePropPageClass)
//}}AFX_DATA_INIT
Initialize ();
return ;
}
/////////////////////////////////////////////////////////////
//
// ~EmitterParticlePropPageClass
//
EmitterParticlePropPageClass::~EmitterParticlePropPageClass (void)
{
SAFE_DELETE (m_Randomizer);
return;
}
/////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
EmitterParticlePropPageClass::DoDataExchange (CDataExchange* pDX)
{
// Allow the base class to process this message
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(EmitterParticlePropPageClass)
DDX_Control(pDX, IDC_BURST_SIZE_SPIN, m_BurstSizeSpin);
DDX_Control(pDX, IDC_EMISSION_RATE_SPIN, m_EmitionRateSpin);
DDX_Control(pDX, IDC_MAX_PARTICLES_SPIN, m_MaxParticlesSpin);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(EmitterParticlePropPageClass, CPropertyPage)
//{{AFX_MSG_MAP(EmitterParticlePropPageClass)
ON_BN_CLICKED(IDC_SPECIFY_CREATION_VOLUME, OnSpecifyCreationVolume)
ON_BN_CLICKED(IDC_MAX_PARTICLES_CHECK, OnMaxParticlesCheck)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////
//
// Initialize
//
void
EmitterParticlePropPageClass::Initialize (void)
{
SAFE_DELETE (m_Randomizer);
if (m_pEmitterList != NULL) {
//
// Read the settings from the emitter
//
m_Rate = m_pEmitterList->Get_Emission_Rate ();
m_BurstSize = m_pEmitterList->Get_Burst_Size ();
m_MaxParticles = m_pEmitterList->Get_Max_Emissions ();
m_Randomizer = m_pEmitterList->Get_Creation_Volume ();
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
EmitterParticlePropPageClass::OnInitDialog (void)
{
// Allow the base class to process this message
CPropertyPage::OnInitDialog ();
//
// Setup the burst controls
//
m_BurstSizeSpin.SetRange (0, 10000);
m_BurstSizeSpin.SetPos (m_BurstSize);
::Initialize_Spinner (m_EmitionRateSpin, m_Rate, -10000, 10000);
//
// Setup the max particles spin
//
m_MaxParticlesSpin.SetRange (0, 10000);
m_MaxParticlesSpin.SetPos (m_MaxParticles);
SendDlgItemMessage (IDC_MAX_PARTICLES_CHECK, BM_SETCHECK, WPARAM(m_MaxParticles != 0));
::EnableWindow (::GetDlgItem (m_hWnd, IDC_MAX_PARTICLES_EDIT), m_MaxParticles != 0);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_MAX_PARTICLES_SPIN), m_MaxParticles != 0);
return TRUE;
}
/////////////////////////////////////////////////////////////
//
// OnApply
//
BOOL
EmitterParticlePropPageClass::OnApply (void)
{
//
// Get the data from the controls
//
m_Rate = ::GetDlgItemFloat (m_hWnd, IDC_EMISSION_RATE_EDIT);
m_BurstSize = GetDlgItemInt (IDC_BURST_SIZE_EDIT);
//
// Determine if we need to cap the particles or not
//
m_MaxParticles = 0;
if (SendDlgItemMessage (IDC_MAX_PARTICLES_CHECK, BM_GETCHECK)) {
m_MaxParticles = GetDlgItemInt (IDC_MAX_PARTICLES_EDIT);
}
//
// Apply the changes to the emitter
//
m_pEmitterList->Set_Emission_Rate (m_Rate);
m_pEmitterList->Set_Burst_Size (m_BurstSize);
m_pEmitterList->Set_Max_Emissions (m_MaxParticles);
m_pEmitterList->Set_Creation_Volume (m_Randomizer->Clone ());
// Allow the base class to process this message
return CPropertyPage::OnApply ();
}
/////////////////////////////////////////////////////////////
//
// WindowProc
//
LRESULT
EmitterParticlePropPageClass::WindowProc
(
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
/*switch (message)
{
}*/
// Allow the base class to process this message
return CPropertyPage::WindowProc(message, wParam, lParam);
}
/////////////////////////////////////////////////////////////
//
// OnNotify
//
BOOL
EmitterParticlePropPageClass::OnNotify
(
WPARAM wParam,
LPARAM lParam,
LRESULT *pResult
)
{
//
// Update the spinner control if necessary
//
NMHDR *pheader = (NMHDR *)lParam;
if ((pheader != NULL) && (pheader->code == UDN_DELTAPOS)) {
LPNMUPDOWN pupdown = (LPNMUPDOWN)lParam;
::Update_Spinner_Buddy (pheader->hwndFrom, pupdown->iDelta);
SetModified ();
}
// Allow the base class to process this message
return CPropertyPage::OnNotify (wParam, lParam, pResult);
}
/////////////////////////////////////////////////////////////
//
// OnSpecifyCreationVolume
//
/////////////////////////////////////////////////////////////
void
EmitterParticlePropPageClass::OnSpecifyCreationVolume (void)
{
VolumeRandomDialogClass dialog (m_Randomizer, this);
if (dialog.DoModal () == IDOK) {
//
// Get the new randomizer from the dialog
//
SAFE_DELETE (m_Randomizer);
m_Randomizer = dialog.Get_Randomizer ();
SetModified ();
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnCommand
//
/////////////////////////////////////////////////////////////
BOOL
EmitterParticlePropPageClass::OnCommand
(
WPARAM wParam,
LPARAM lParam
)
{
switch (LOWORD (wParam))
{
case IDC_BURST_SIZE_EDIT:
case IDC_EMISSION_RATE_EDIT:
case IDC_MAX_PARTICLES_EDIT:
if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
break;
}
return CPropertyPage::OnCommand(wParam, lParam);
}
/////////////////////////////////////////////////////////////
//
// OnMaxParticlesCheck
//
/////////////////////////////////////////////////////////////
void
EmitterParticlePropPageClass::OnMaxParticlesCheck (void)
{
BOOL enable = SendDlgItemMessage (IDC_MAX_PARTICLES_CHECK, BM_GETCHECK);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_MAX_PARTICLES_EDIT), enable);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_MAX_PARTICLES_SPIN), enable);
SetModified ();
return ;
}

View File

@@ -0,0 +1,124 @@
/*
** 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/>.
*/
#if !defined(AFX_EMITTERPARTICLEPROPPAGE_H__83A8B83D_BA3B_11D2_9FFA_00104B791122__INCLUDED_)
#define AFX_EMITTERPARTICLEPROPPAGE_H__83A8B83D_BA3B_11D2_9FFA_00104B791122__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EmitterParticlePropPage.h : header file
//
#include "Resource.H"
#include "Vector3.H"
#include "V3_Rnd.H"
// Forward delcarations
class EmitterInstanceListClass;
//class Vector3Randomizer;
/////////////////////////////////////////////////////////////////////////////
// EmitterParticlePropPageClass dialog
class EmitterParticlePropPageClass : public CPropertyPage
{
DECLARE_DYNCREATE(EmitterParticlePropPageClass)
// Construction
public:
EmitterParticlePropPageClass (EmitterInstanceListClass *pemitter_list = NULL);
~EmitterParticlePropPageClass ();
// Dialog Data
//{{AFX_DATA(EmitterParticlePropPageClass)
enum { IDD = IDD_PROP_PAGE_EMITTER_PARTICLE };
CSpinButtonCtrl m_BurstSizeSpin;
CSpinButtonCtrl m_EmitionRateSpin;
CSpinButtonCtrl m_MaxParticlesSpin;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(EmitterParticlePropPageClass)
public:
virtual BOOL OnApply();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(EmitterParticlePropPageClass)
virtual BOOL OnInitDialog();
afx_msg void OnSpecifyCreationVolume();
afx_msg void OnMaxParticlesCheck();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////
//
// Public methods
//
//
// Inline accessors
//
EmitterInstanceListClass * Get_Emitter (void) const { return m_pEmitterList; }
void Set_Emitter (EmitterInstanceListClass *pemitter_list) { m_pEmitterList = pemitter_list; Initialize (); }
bool Is_Data_Valid (void) const { return m_bValid; }
float Get_Rate (void) const { return m_Rate; }
int Get_Burst_Size (void) const { return m_BurstSize; }
int Get_Max_Particles (void) const { return m_MaxParticles; }
Vector3Randomizer * Get_Creation_Volume (void) const { return m_Randomizer->Clone (); }
protected:
/////////////////////////////////////////////////////////
//
// Protected methods
//
void Initialize (void);
private:
/////////////////////////////////////////////////////////
//
// Private member data
//
EmitterInstanceListClass * m_pEmitterList;
bool m_bValid;
float m_Rate;
int m_BurstSize;
int m_MaxParticles;
Vector3Randomizer * m_Randomizer;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EMITTERPARTICLEPROPPAGE_H__83A8B83D_BA3B_11D2_9FFA_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,382 @@
/*
** 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/>.
*/
// EmitterPhysicsPropPage.cpp : implementation file
//
#include "StdAfx.H"
#include "W3DView.H"
#include "EmitterPhysicsPropPage.H"
#include "Utils.H"
#include "Part_Emt.H"
#include "VolumeRandomDialog.H"
#include "EmitterInstanceList.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// EmitterPhysicsPropPageClass property page
IMPLEMENT_DYNCREATE(EmitterPhysicsPropPageClass, CPropertyPage)
/////////////////////////////////////////////////////////////
//
// EmitterPhysicsPropPageClass
//
/////////////////////////////////////////////////////////////
EmitterPhysicsPropPageClass::EmitterPhysicsPropPageClass (EmitterInstanceListClass *pemitter)
: m_pEmitterList (NULL),
m_bValid (true),
m_Velocity (0, 0, 1),
m_Acceleration (0, 0, 0),
m_OutFactor (0),
m_InheritanceFactor (0),
m_Randomizer (NULL),
CPropertyPage(EmitterPhysicsPropPageClass::IDD)
{
//{{AFX_DATA_INIT(EmitterPhysicsPropPageClass)
//}}AFX_DATA_INIT
Initialize ();
return ;
}
/////////////////////////////////////////////////////////////
//
// ~EmitterPhysicsPropPageClass
//
/////////////////////////////////////////////////////////////
EmitterPhysicsPropPageClass::~EmitterPhysicsPropPageClass (void)
{
SAFE_DELETE (m_Randomizer);
return;
}
/////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////
void
EmitterPhysicsPropPageClass::DoDataExchange (CDataExchange* pDX)
{
// Allow the base class to process this message
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(EmitterPhysicsPropPageClass)
DDX_Control(pDX, IDC_OUT_FACTOR_SPIN, m_OutSpin);
DDX_Control(pDX, IDC_INHERITANCE_FACTOR_SPIN, m_InheritanceSpin);
DDX_Control(pDX, IDC_VELOCITY_Z_SPIN, m_VelocityZSpin);
DDX_Control(pDX, IDC_VELOCITY_Y_SPIN, m_VelocityYSpin);
DDX_Control(pDX, IDC_VELOCITY_X_SPIN, m_VelocityXSpin);
DDX_Control(pDX, IDC_ACCELERATION_Z_SPIN, m_AccelZSpin);
DDX_Control(pDX, IDC_ACCELERATION_Y_SPIN, m_AccelYSpin);
DDX_Control(pDX, IDC_ACCELERATION_X_SPIN, m_AccelXSpin);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(EmitterPhysicsPropPageClass, CPropertyPage)
//{{AFX_MSG_MAP(EmitterPhysicsPropPageClass)
ON_BN_CLICKED(IDC_SPECIFY_VELOCITY_RANDOM, OnSpecifyVelocityRandom)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////
//
// Initialize
//
/////////////////////////////////////////////////////////////
void
EmitterPhysicsPropPageClass::Initialize (void)
{
SAFE_DELETE (m_Randomizer);
if (m_pEmitterList != NULL) {
//
// Get the emitter's settings
//
m_Velocity = m_pEmitterList->Get_Velocity ();
m_Acceleration = m_pEmitterList->Get_Acceleration ();
m_OutFactor = m_pEmitterList->Get_Outward_Vel ();
m_InheritanceFactor = m_pEmitterList->Get_Vel_Inherit ();
m_Randomizer = m_pEmitterList->Get_Velocity_Random ();
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////
BOOL
EmitterPhysicsPropPageClass::OnInitDialog (void)
{
// Allow the base class to process this message
CPropertyPage::OnInitDialog ();
//
// Setup the velocity controls
//
::Initialize_Spinner (m_OutSpin, m_OutFactor, -10000, 10000);
::Initialize_Spinner (m_InheritanceSpin, m_InheritanceFactor, -10000, 10000);
::Initialize_Spinner (m_VelocityXSpin, m_Velocity.X, -10000, 10000);
::Initialize_Spinner (m_VelocityYSpin, m_Velocity.Y, -10000, 10000);
::Initialize_Spinner (m_VelocityZSpin, m_Velocity.Z, -10000, 10000);
//
// Setup the acceleration controls
//
::Initialize_Spinner (m_AccelXSpin, m_Acceleration.X, -10000, 10000);
::Initialize_Spinner (m_AccelYSpin, m_Acceleration.Y, -10000, 10000);
::Initialize_Spinner (m_AccelZSpin, m_Acceleration.Z, -10000, 10000);
return TRUE;
}
/////////////////////////////////////////////////////////////
//
// OnApply
//
/////////////////////////////////////////////////////////////
BOOL
EmitterPhysicsPropPageClass::OnApply (void)
{
//
// Read the velocity settings
//
m_Velocity.X = ::GetDlgItemFloat (m_hWnd, IDC_VELOCITY_X_EDIT);
m_Velocity.Y = ::GetDlgItemFloat (m_hWnd, IDC_VELOCITY_Y_EDIT);
m_Velocity.Z = ::GetDlgItemFloat (m_hWnd, IDC_VELOCITY_Z_EDIT);
m_OutFactor = ::GetDlgItemFloat (m_hWnd, IDC_OUT_FACTOR_SPIN);
m_InheritanceFactor = ::GetDlgItemFloat (m_hWnd, IDC_INHERITANCE_FACTOR_SPIN);
//
// Read the acceleration settings
//
m_Acceleration.X = ::GetDlgItemFloat (m_hWnd, IDC_ACCELERATION_X_EDIT);
m_Acceleration.Y = ::GetDlgItemFloat (m_hWnd, IDC_ACCELERATION_Y_EDIT);
m_Acceleration.Z = ::GetDlgItemFloat (m_hWnd, IDC_ACCELERATION_Z_EDIT);
// Allow the base class to process this message
return CPropertyPage::OnApply ();
}
/////////////////////////////////////////////////////////////
//
// OnNotify
//
/////////////////////////////////////////////////////////////
BOOL
EmitterPhysicsPropPageClass::OnNotify
(
WPARAM wParam,
LPARAM lParam,
LRESULT *pResult
)
{
//
// Update the spinner control if necessary
//
NMHDR *pheader = (NMHDR *)lParam;
if ((pheader != NULL) && (pheader->code == UDN_DELTAPOS)) {
LPNMUPDOWN pupdown = (LPNMUPDOWN)lParam;
::Update_Spinner_Buddy (pheader->hwndFrom, pupdown->iDelta);
On_Setting_Changed (wParam);
}
// Allow the base class to process this message
return CPropertyPage::OnNotify (wParam, lParam, pResult);
}
/////////////////////////////////////////////////////////////
//
// OnSpecifyCreationVolume
//
/////////////////////////////////////////////////////////////
void
EmitterPhysicsPropPageClass::OnSpecifyVelocityRandom (void)
{
VolumeRandomDialogClass dialog (m_Randomizer, this);
if (dialog.DoModal () == IDOK) {
//
// Get the new randomizer from the dialog
//
SAFE_DELETE (m_Randomizer);
m_Randomizer = dialog.Get_Randomizer ();
if (m_Randomizer != NULL) {
m_pEmitterList->Set_Velocity_Random (m_Randomizer->Clone ());
SetModified ();
}
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnCommand
//
/////////////////////////////////////////////////////////////
BOOL
EmitterPhysicsPropPageClass::OnCommand
(
WPARAM wParam,
LPARAM lParam
)
{
switch (LOWORD (wParam))
{
case IDC_VELOCITY_X_EDIT:
case IDC_VELOCITY_Y_EDIT:
case IDC_VELOCITY_Z_EDIT:
{
// Update the emitter
if ((HIWORD (wParam) == EN_KILLFOCUS) &&
SendDlgItemMessage (LOWORD (wParam), EM_GETMODIFY)) {
SendDlgItemMessage (LOWORD (wParam), EM_SETMODIFY, (WPARAM)0);
On_Setting_Changed (LOWORD (wParam));
} else if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
}
break;
case IDC_ACCELERATION_X_EDIT:
case IDC_ACCELERATION_Y_EDIT:
case IDC_ACCELERATION_Z_EDIT:
{
// Update the emitter
if ((HIWORD (wParam) == EN_KILLFOCUS) &&
SendDlgItemMessage (LOWORD (wParam), EM_GETMODIFY)) {
SendDlgItemMessage (LOWORD (wParam), EM_SETMODIFY, (WPARAM)0);
On_Setting_Changed (LOWORD (wParam));
} else if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
}
break;
case IDC_INHERITANCE_FACTOR_EDIT:
{
// Update the emitter
if ((HIWORD (wParam) == EN_KILLFOCUS) &&
SendDlgItemMessage (LOWORD (wParam), EM_GETMODIFY)) {
SendDlgItemMessage (LOWORD (wParam), EM_SETMODIFY, (WPARAM)0);
On_Setting_Changed (LOWORD (wParam));
} else if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
}
break;
case IDC_OUT_FACTOR_EDIT:
{
// Update the emitter
if ((HIWORD (wParam) == EN_KILLFOCUS) &&
SendDlgItemMessage (LOWORD (wParam), EM_GETMODIFY)) {
SendDlgItemMessage (LOWORD (wParam), EM_SETMODIFY, (WPARAM)0);
On_Setting_Changed (LOWORD (wParam));
} else if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
}
break;
}
return CPropertyPage::OnCommand (wParam, lParam);
}
/////////////////////////////////////////////////////////////
//
// On_Setting_Changed
//
/////////////////////////////////////////////////////////////
void
EmitterPhysicsPropPageClass::On_Setting_Changed (UINT ctrl_id)
{
switch (ctrl_id)
{
case IDC_VELOCITY_X_EDIT:
case IDC_VELOCITY_Y_EDIT:
case IDC_VELOCITY_Z_EDIT:
case IDC_VELOCITY_X_SPIN:
case IDC_VELOCITY_Y_SPIN:
case IDC_VELOCITY_Z_SPIN:
{
Vector3 velocity;
velocity.X = ::GetDlgItemFloat (m_hWnd, IDC_VELOCITY_X_EDIT);
velocity.Y = ::GetDlgItemFloat (m_hWnd, IDC_VELOCITY_Y_EDIT);
velocity.Z = ::GetDlgItemFloat (m_hWnd, IDC_VELOCITY_Z_EDIT);
m_pEmitterList->Set_Velocity (velocity);
SetModified ();
}
break;
case IDC_ACCELERATION_X_EDIT:
case IDC_ACCELERATION_Y_EDIT:
case IDC_ACCELERATION_Z_EDIT:
case IDC_ACCELERATION_X_SPIN:
case IDC_ACCELERATION_Y_SPIN:
case IDC_ACCELERATION_Z_SPIN:
{
Vector3 acceleration;
acceleration.X = ::GetDlgItemFloat (m_hWnd, IDC_ACCELERATION_X_EDIT);
acceleration.Y = ::GetDlgItemFloat (m_hWnd, IDC_ACCELERATION_Y_EDIT);
acceleration.Z = ::GetDlgItemFloat (m_hWnd, IDC_ACCELERATION_Z_EDIT);
m_pEmitterList->Set_Acceleration (acceleration);
SetModified ();
}
break;
case IDC_INHERITANCE_FACTOR_EDIT:
case IDC_INHERITANCE_FACTOR_SPIN:
{
float value = ::GetDlgItemFloat (m_hWnd, IDC_INHERITANCE_FACTOR_EDIT);
m_pEmitterList->Set_Vel_Inherit (value);
SetModified ();
}
break;
case IDC_OUT_FACTOR_EDIT:
case IDC_OUT_FACTOR_SPIN:
{
float value = ::GetDlgItemFloat (m_hWnd, IDC_OUT_FACTOR_EDIT);
m_pEmitterList->Set_Outward_Vel (value);
SetModified ();
}
break;
}
return ;
}

View File

@@ -0,0 +1,129 @@
/*
** 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/>.
*/
#if !defined(AFX_EMITTERPHYSICSPROPPAGE_H__83A8B83E_BA3B_11D2_9FFA_00104B791122__INCLUDED_)
#define AFX_EMITTERPHYSICSPROPPAGE_H__83A8B83E_BA3B_11D2_9FFA_00104B791122__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EmitterPhysicsPropPage.h : header file
//
#include "Resource.H"
#include "Vector3.H"
// Forward delcarations
class EmitterInstanceListClass;
class Vector3Randomizer;
/////////////////////////////////////////////////////////////////////////////
// EmitterPhysicsPropPageClass dialog
class EmitterPhysicsPropPageClass : public CPropertyPage
{
DECLARE_DYNCREATE(EmitterPhysicsPropPageClass)
// Construction
public:
EmitterPhysicsPropPageClass (EmitterInstanceListClass *pemitter_list = NULL);
~EmitterPhysicsPropPageClass ();
// Dialog Data
//{{AFX_DATA(EmitterPhysicsPropPageClass)
enum { IDD = IDD_PROP_PAGE_EMITTER_PHYSICS };
CSpinButtonCtrl m_OutSpin;
CSpinButtonCtrl m_InheritanceSpin;
CSpinButtonCtrl m_VelocityZSpin;
CSpinButtonCtrl m_VelocityYSpin;
CSpinButtonCtrl m_VelocityXSpin;
CSpinButtonCtrl m_AccelZSpin;
CSpinButtonCtrl m_AccelYSpin;
CSpinButtonCtrl m_AccelXSpin;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(EmitterPhysicsPropPageClass)
public:
virtual BOOL OnApply();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(EmitterPhysicsPropPageClass)
virtual BOOL OnInitDialog();
afx_msg void OnSpecifyVelocityRandom();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////
//
// Public methods
//
//
// Inline accessors
//
EmitterInstanceListClass * Get_Emitter (void) const { return m_pEmitterList; }
void Set_Emitter (EmitterInstanceListClass *pemitter_list) { m_pEmitterList = pemitter_list; Initialize (); }
bool Is_Data_Valid (void) const { return m_bValid; }
Vector3Randomizer * Get_Velocity_Random (void) const { return m_Randomizer; }
const Vector3 & Get_Velocity (void) const { return m_Velocity; }
const Vector3 & Get_Acceleration (void) const { return m_Acceleration; }
float Get_Out_Factor (void) const { return m_OutFactor; }
float Get_Inheritance_Factor (void) const { return m_InheritanceFactor; }
protected:
/////////////////////////////////////////////////////////
//
// Protected methods
//
void Initialize (void);
void On_Setting_Changed (UINT ctrl_id);
private:
/////////////////////////////////////////////////////////
//
// Private member data
//
EmitterInstanceListClass * m_pEmitterList;
bool m_bValid;
Vector3 m_Velocity;
Vector3 m_Acceleration;
float m_OutFactor;
float m_InheritanceFactor;
Vector3Randomizer * m_Randomizer;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EMITTERPHYSICSPROPPAGE_H__83A8B83E_BA3B_11D2_9FFA_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,521 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : W3DView *
* *
* $Archive:: /VSS_Sync/W3DView/EmitterPropertySheet.cpp $Modtime:: $*
* *
* $Revision:: 12 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "StdAfx.H"
#include "W3DView.H"
#include "EmitterPropertySheet.H"
#include "Part_Emt.H"
#include "Part_Ldr.H"
#include "AssetMgr.H"
#include "W3DViewDoc.H"
#include "Utils.H"
#include "DataTreeView.H"
#include "AssetInfo.H"
#include "texture.h"
#include "EmitterInstanceList.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// EmitterPropertySheetClass
IMPLEMENT_DYNAMIC(EmitterPropertySheetClass, CPropertySheet)
/////////////////////////////////////////////////////////////
//
// EmitterPropertySheetClass
//
EmitterPropertySheetClass::EmitterPropertySheetClass
(
EmitterInstanceListClass *emitter_list,
UINT nIDCaption,
CWnd *pParentWnd
)
: m_pEmitterList (NULL),
CPropertySheet (nIDCaption, pParentWnd, 0)
{
m_pEmitterList = emitter_list;
Initialize ();
return ;
}
/////////////////////////////////////////////////////////////
//
// EmitterPropertySheetClass
//
EmitterPropertySheetClass::EmitterPropertySheetClass
(
EmitterInstanceListClass *emitter_list,
LPCTSTR pszCaption,
CWnd *pParentWnd
)
: m_pEmitterList (NULL),
CPropertySheet (pszCaption, pParentWnd, 0)
{
m_pEmitterList = emitter_list;
Initialize ();
return ;
}
/////////////////////////////////////////////////////////////
//
// EmitterPropertySheetClass
//
EmitterPropertySheetClass::~EmitterPropertySheetClass (void)
{
SAFE_DELETE (m_pEmitterList);
return ;
}
BEGIN_MESSAGE_MAP(EmitterPropertySheetClass, CPropertySheet)
//{{AFX_MSG_MAP(EmitterPropertySheetClass)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// EmitterPropertySheetClass message handlers
/////////////////////////////////////////////////////////////
//
// EmitterPropertySheetClass
//
LRESULT
EmitterPropertySheetClass::WindowProc
(
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
switch (message)
{
// Is a control sending us an oldstyle notification?
case WM_COMMAND:
{
// What control sent the notification?
switch (LOWORD (wParam))
{
case IDCANCEL:
{
::GetCurrentDocument ()->Reload_Displayed_Object ();
}
break;
case IDOK:
{
// If the apply button isn't enabled, then don't do the apply operation.
if (::IsWindowEnabled (::GetDlgItem (m_hWnd, ID_APPLY_NOW)) == FALSE) {
break;
}
}
case ID_APPLY_NOW:
{
// Did the user click the button?
if (HIWORD (wParam) == BN_CLICKED) {
LRESULT lresult = CPropertySheet::WindowProc (message, wParam, lParam);
// If all the pages contain valid data, then update the emitter
if (m_GeneralPage.Is_Data_Valid () &&
m_ParticlePage.Is_Data_Valid () &&
m_PhysicsPage.Is_Data_Valid () &&
m_ColorPage.Is_Data_Valid () &&
m_UserPage.Is_Data_Valid () &&
m_SizePage.Is_Data_Valid () &&
m_LinePage.Is_Data_Valid () &&
m_RotationPage.Is_Data_Valid () &&
m_FramePage.Is_Data_Valid () &&
m_LineGroupPage.Is_Data_Valid () )
{
// Update the current emitter to match the data
Update_Emitter ();
}
return lresult;
}
}
break;
}
break;
}
break;
}
// Allow the base class to process this message
return CPropertySheet::WindowProc (message, wParam, lParam);
}
/////////////////////////////////////////////////////////////
//
// Add_Emitter_To_Viewer
//
void
EmitterPropertySheetClass::Add_Emitter_To_Viewer (void)
{
CW3DViewDoc *pdoc = ::GetCurrentDocument ();
if ((pdoc != NULL) && (m_pEmitterList != NULL)) {
//
// Create a new prototype for this emitter and add it to the asset manager
//
ParticleEmitterDefClass *pdefinition = new ParticleEmitterDefClass (*m_pEmitterList);
ParticleEmitterPrototypeClass *pprototype = new ParticleEmitterPrototypeClass (pdefinition);
//
// Update the asset manager with the new prototype
//
if (m_LastSavedName.GetLength () > 0) {
WW3DAssetManager::Get_Instance()->Remove_Prototype (m_LastSavedName);
}
WW3DAssetManager::Get_Instance()->Add_Prototype (pprototype);
//
// Add this emitter to the data tree
//
CDataTreeView *pdata_tree = pdoc->GetDataTreeView ();
pdata_tree->Refresh_Asset (m_pEmitterList->Get_Name (), m_LastSavedName, TypeEmitter);
/*if (m_LastSavedName.GetLength () > 0) {
pdata_tree->Refresh_Asset (m_pEmitterList->Get_Name (), m_LastSavedName, TypeEmitter);
} else {
pdata_tree->Add_Asset_To_Tree (m_pEmitterList->Get_Name (), TypeEmitter, true);
}*/
//
// Display the emitter
//
pdoc->Reload_Displayed_Object ();
m_LastSavedName = m_pEmitterList->Get_Name ();
//
// Regenerate the emitter pointer list
//
m_pEmitterList->Free_List ();
pdoc->Build_Emitter_List (m_pEmitterList, m_pEmitterList->Get_Name ());
}
return ;
}
/////////////////////////////////////////////////////////////
//
// Update_Emitter
//
void
EmitterPropertySheetClass::Update_Emitter (void)
{
//
// Update those pages that are dependant on the particle's
// lifetime.
//
float lifetime = m_GeneralPage.Get_Lifetime ();
m_ColorPage.On_Lifetime_Changed (lifetime);
m_SizePage.On_Lifetime_Changed (lifetime);
m_RotationPage.On_Lifetime_Changed (lifetime);
m_FramePage.On_Lifetime_Changed (lifetime);
m_LineGroupPage.On_Lifetime_Changed (lifetime);
Add_Emitter_To_Viewer ();
//
// Create a new emitter
//
/*ParticleEmitterClass *pemitter = Create_Emitter ();
Add_Emitter_To_Viewer (pemitter);
//
// Use this emitter as the edited emitter from here on out
//
MEMBER_RELEASE (m_pEmitter);
m_pEmitter = pemitter;*/
// Pass the emitter along to the pages
/*m_GeneralPage.Set_Emitter (m_pEmitterList);
m_ParticlePage.Set_Emitter (m_pEmitterList);
m_PhysicsPage.Set_Emitter (m_pEmitterList);
m_ColorPage.Set_Emitter (m_pEmitterList);
m_UserPage.Set_Emitter (m_pEmitterList);
m_SizePage.Set_Emitter (m_pEmitterList);*/
return ;
}
/////////////////////////////////////////////////////////////
//
// Initialize
//
void
EmitterPropertySheetClass::Initialize (void)
{
if (m_pEmitterList == NULL) {
Create_New_Emitter ();
} else {
m_LastSavedName = m_pEmitterList->Get_Name ();
}
// Pass the emitter along to the pages
m_GeneralPage.Set_Emitter (m_pEmitterList);
m_ParticlePage.Set_Emitter (m_pEmitterList);
m_PhysicsPage.Set_Emitter (m_pEmitterList);
m_ColorPage.Set_Emitter (m_pEmitterList);
m_UserPage.Set_Emitter (m_pEmitterList);
m_SizePage.Set_Emitter (m_pEmitterList);
m_LinePage.Set_Emitter (m_pEmitterList);
m_RotationPage.Set_Emitter (m_pEmitterList);
m_FramePage.Set_Emitter (m_pEmitterList);
m_LineGroupPage.Set_Emitter (m_pEmitterList);
// Initialize the user page with data from the prototype
/*if (m_pEmitter != NULL) {
ParticleEmitterPrototypeClass *proto = NULL;
proto = (ParticleEmitterPrototypeClass *)WW3DAssetManager::Get_Instance ()->Find_Prototype (m_pEmitter->Get_Name ());
if (proto != NULL) {
ParticleEmitterDefClass *definition = proto->Get_Definition ();
m_UserPage.Set_Type (definition->Get_User_Type ());
m_UserPage.Set_String (definition->Get_User_String ());
}
}*/
// Add the pages to the sheet
AddPage (&m_GeneralPage);
AddPage (&m_ParticlePage);
AddPage (&m_PhysicsPage);
AddPage (&m_ColorPage);
AddPage (&m_SizePage);
AddPage (&m_UserPage);
AddPage (&m_LinePage);
AddPage (&m_RotationPage);
AddPage (&m_FramePage);
AddPage (&m_LineGroupPage);
m_GeneralPage.Set_Parent(this);
return ;
}
/////////////////////////////////////////////////////////////
//
// Create_Emitter
//
/*ParticleEmitterClass *
EmitterPropertySheetClass::Create_Emitter (void)
{
//
// Read the particle settings
//
float rate = m_ParticlePage.Get_Rate ();
int burst = m_ParticlePage.Get_Burst_Size ();
float max_particles = m_ParticlePage.Get_Max_Particles ();
//
// Read the physics settings
//
Vector3 velocity = m_PhysicsPage.Get_Velocity ();
Vector3 acceleration = m_PhysicsPage.Get_Acceleration ();
float out_factor = m_PhysicsPage.Get_Out_Factor ();
float inherit_factor = m_PhysicsPage.Get_Inheritance_Factor ();
//
// Read the general settings
//
CString name = m_GeneralPage.Get_Name ();
CString texture_name = m_GeneralPage.Get_Texture_Filename ();
float lifetime = m_GeneralPage.Get_Lifetime ();
ShaderClass shader = m_GeneralPage.Get_Shader ();
//
// Read the keyframe settings
//
ParticlePropertyStruct<Vector3> colors;
ParticlePropertyStruct<float> opacity;
ParticlePropertyStruct<float> size;
m_ColorPage.Get_Color_Keyframes (colors);
m_ColorPage.Get_Opacity_Keyframes (opacity);
m_SizePage.Get_Size_Keyframes (size);
//
// Read the randomizers
//
Vector3Randomizer *creation_vol = m_ParticlePage.Get_Creation_Volume ();
Vector3Randomizer *vel_random = m_PhysicsPage.Get_Velocity_Random ();
//
// Load the texture
//
TextureClass *ptexture = NULL;
if (texture_name.GetLength () > 0) {
ptexture = WW3DAssetManager::Get_Instance()->Get_Texture (texture_name);
}
//
// Create the new particle emitter
//
ParticleEmitterClass *pemitter = new ParticleEmitterClass (rate,
burst,
creation_vol,
velocity,
vel_random,
out_factor,
inherit_factor,
colors,
opacity,
size,
acceleration,
lifetime,
ptexture,
shader,
max_particles);
//
// Pass the name onto the emitter
//
pemitter->Set_Name (name);
// Return the emitter
return pemitter;
}*/
/////////////////////////////////////////////////////////////
//
// Create_New_Emitter
//
void
EmitterPropertySheetClass::Create_New_Emitter (void)
{
ParticlePropertyStruct<Vector3> color;
color.Start = Vector3 (1, 1, 1);
color.Rand.Set (0,0,0);
color.NumKeyFrames = 0;
color.KeyTimes = NULL;
color.Values = NULL;
ParticlePropertyStruct<float> opacity;
opacity.Start = 1.0F;
opacity.Rand = 0.0F;
opacity.NumKeyFrames = 0;
opacity.KeyTimes = NULL;
opacity.Values = NULL;
ParticlePropertyStruct<float> size;
size.Start = 0.1F;
size.Rand = 0.0F;
size.NumKeyFrames = 0;
size.KeyTimes = NULL;
size.Values = NULL;
ParticlePropertyStruct<float> rotation;
rotation.Start = 0.0f;
rotation.Rand = 0.0f;
rotation.NumKeyFrames = 0;
rotation.KeyTimes = NULL;
rotation.Values = NULL;
ParticlePropertyStruct<float> frames;
frames.Start = 0.0f;
frames.Rand = 0.0f;
frames.NumKeyFrames = 0;
frames.KeyTimes = NULL;
frames.Values = NULL;
ParticlePropertyStruct<float> blurtimes;
blurtimes.Start = 0.0f;
blurtimes.Rand = 0.0f;
blurtimes.NumKeyFrames = 0;
blurtimes.KeyTimes = NULL;
blurtimes.Values = NULL;
//
// Create the new emitter
//
ParticleEmitterClass *emitter = NULL;
emitter = new ParticleEmitterClass (10,
1,
new Vector3SolidBoxRandomizer(Vector3(0.1F, 0.1F, 0.1F)),
Vector3 (0, 0, 1),
new Vector3SolidBoxRandomizer(Vector3(0, 0, 0.1F)),
0,
0,
color,
opacity,
size,
rotation,
0.0f,
frames,
blurtimes,
Vector3 (0, 0, 0),
1.0F,
NULL,
ShaderClass::_PresetAdditiveSpriteShader,
0);
//
// Create the new emitter list
//
m_pEmitterList = new EmitterInstanceListClass;
m_pEmitterList->Add_Emitter (emitter);
//
// Display the new emitter
//
::GetCurrentDocument ()->Display_Emitter (emitter);
MEMBER_RELEASE (emitter);
/*SAFE_DELETE_ARRAY (color.Values);
SAFE_DELETE_ARRAY (color.KeyTimes);
SAFE_DELETE_ARRAY (opacity.Values);
SAFE_DELETE_ARRAY (opacity.KeyTimes);
SAFE_DELETE_ARRAY (size.Values);
SAFE_DELETE_ARRAY (size.KeyTimes);*/
return ;
}
void
EmitterPropertySheetClass::Notify_Render_Mode_Changed(int new_mode)
{
bool enable_line_page = (new_mode == W3D_EMITTER_RENDER_MODE_LINE);
::Enable_Dialog_Controls(m_LinePage,enable_line_page);
}

View File

@@ -0,0 +1,128 @@
/*
** 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/>.
*/
#if !defined(AFX_EMITTERPROPERTYSHEET_H__83A8B844_BA3B_11D2_9FFA_00104B791122__INCLUDED_)
#define AFX_EMITTERPROPERTYSHEET_H__83A8B844_BA3B_11D2_9FFA_00104B791122__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EmitterPropertySheet.h : header file
//
#include "EmitterColorPropPage.H"
#include "EmitterGeneralPropPage.H"
#include "EmitterParticlePropPage.H"
#include "EmitterPhysicsPropPage.H"
#include "EmitterSizePropPage.H"
#include "EmitterUserPropPage.H"
#include "EmitterLinePropPage.H"
#include "EmitterRotationPropPage.H"
#include "EmitterFramePropPage.H"
#include "EmitterLineGroupPropPage.H"
// Forward declarations
class ParticleEmitterClass;
class EmitterInstanceListClass;
class AssetInfoClass;
/////////////////////////////////////////////////////////////////////////////
//
// EmitterPropertySheetClass
//
class EmitterPropertySheetClass : public CPropertySheet
{
DECLARE_DYNAMIC(EmitterPropertySheetClass)
// Construction
public:
EmitterPropertySheetClass (EmitterInstanceListClass *emitter_list, UINT nIDCaption, CWnd* pParentWnd = NULL);
EmitterPropertySheetClass (EmitterInstanceListClass *emitter_list, LPCTSTR pszCaption, CWnd* pParentWnd = NULL);
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(EmitterPropertySheetClass)
protected:
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~EmitterPropertySheetClass();
// Generated message map functions
protected:
//{{AFX_MSG(EmitterPropertySheetClass)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
//////////////////////////////////////////////////////////////////////
//
// Public methods
//
void Notify_Render_Mode_Changed(int new_mode);
protected:
//////////////////////////////////////////////////////////////////////
//
// Protected methods
//
void Initialize (void);
ParticleEmitterClass * Create_Emitter (void);
void Update_Emitter (void);
void Add_Emitter_To_Viewer (void);
void Create_New_Emitter (void);
private:
//////////////////////////////////////////////////////////////////////
//
// Private member data
//
EmitterGeneralPropPageClass m_GeneralPage;
EmitterParticlePropPageClass m_ParticlePage;
EmitterPhysicsPropPageClass m_PhysicsPage;
EmitterColorPropPageClass m_ColorPage;
EmitterUserPropPageClass m_UserPage;
EmitterSizePropPageClass m_SizePage;
EmitterLinePropPageClass m_LinePage;
EmitterRotationPropPageClass m_RotationPage;
EmitterFramePropPageClass m_FramePage;
EmitterLineGroupPropPageClass m_LineGroupPage;
EmitterInstanceListClass * m_pEmitterList;
CString m_LastSavedName;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EMITTERPROPERTYSHEET_H__83A8B844_BA3B_11D2_9FFA_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,420 @@
/*
** 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/>.
*/
// EmitterRotationPropPage.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "EmitterRotationPropPage.h"
#include "Utils.H"
#include "ParticleRotationKeyDialog.H"
#include "EmitterInstanceList.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// EmitterRotationPropPageClass property page
IMPLEMENT_DYNCREATE(EmitterRotationPropPageClass, CPropertyPage)
/////////////////////////////////////////////////////////////
//
// EmitterRotationPropPageClass - constructor
//
/////////////////////////////////////////////////////////////
EmitterRotationPropPageClass::EmitterRotationPropPageClass() :
CPropertyPage(EmitterRotationPropPageClass::IDD),
m_pEmitterList(NULL),
m_bValid(true),
m_RotationBar(NULL),
m_Lifetime(0),
m_MinRotation(0),
m_MaxRotation(1),
m_InitialOrientationRandom(0)
{
::memset (&m_Rotations, 0, sizeof (m_Rotations));
//{{AFX_DATA_INIT(EmitterRotationPropPageClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
Initialize();
}
/////////////////////////////////////////////////////////////
//
// ~EmitterRotationPropPageClass - destructor
//
/////////////////////////////////////////////////////////////
EmitterRotationPropPageClass::~EmitterRotationPropPageClass()
{
// Free the rotation arrays
SAFE_DELETE_ARRAY (m_Rotations.KeyTimes);
SAFE_DELETE_ARRAY (m_Rotations.Values);
}
/////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////
void EmitterRotationPropPageClass::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(EmitterRotationPropPageClass)
DDX_Control(pDX, IDC_INITIAL_ORIENTATION_RANDOM_SPIN, m_InitialOrientationRandomSpin);
DDX_Control(pDX, IDC_ROTATION_RANDOM_SPIN, m_RotationRandomSpin);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(EmitterRotationPropPageClass, CPropertyPage)
//{{AFX_MSG_MAP(EmitterRotationPropPageClass)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// EmitterRotationPropPageClass message handlers
/////////////////////////////////////////////////////////////
//
// Initialize
//
/////////////////////////////////////////////////////////////
void EmitterRotationPropPageClass::Initialize (void)
{
SAFE_DELETE_ARRAY (m_Rotations.KeyTimes);
SAFE_DELETE_ARRAY (m_Rotations.Values);
if (m_pEmitterList != NULL) {
m_Lifetime = m_pEmitterList->Get_Lifetime ();
m_pEmitterList->Get_Rotation_Keyframes (m_Rotations);
m_InitialOrientationRandom = m_pEmitterList->Get_Initial_Orientation_Random();
//
// Determine what the min and max rotations are
//
m_MaxRotation = WWMath::Max(m_Rotations.Start,1.0f);
m_MinRotation = WWMath::Min(m_Rotations.Start,0.0f);
for (UINT index = 0; index < m_Rotations.NumKeyFrames; index ++) {
if (m_Rotations.Values[index] > m_MaxRotation) {
m_MaxRotation = m_Rotations.Values[index];
}
if (m_Rotations.Values[index] < m_MinRotation) {
m_MinRotation = m_Rotations.Values[index];
}
}
}
}
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////
BOOL
EmitterRotationPropPageClass::OnInitDialog()
{
CPropertyPage::OnInitDialog();
//
// Create the keyframe control
//
m_RotationBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_ROTATION_BAR));
//
// Setup the spinners
//
Initialize_Spinner (m_RotationRandomSpin, m_Rotations.Rand, 0, 10000);
Initialize_Spinner (m_InitialOrientationRandomSpin, m_InitialOrientationRandom, 0, 10000);
//
// Reset the color bars
//
m_RotationBar->Set_Range (0, 1);
m_RotationBar->Clear_Points ();
m_RotationBar->Modify_Point (0, 0, 0, 0, 0);
m_RotationBar->Set_Graph_Percent (0, Normalize_Rotation(m_Rotations.Start));
//
// Load the current set of frame keyframes into the control
//
for (UINT index = 0; index < m_Rotations.NumKeyFrames; index ++) {
m_RotationBar->Modify_Point (index + 1,
m_Rotations.KeyTimes[index] / m_Lifetime,
0,
0,
0);
m_RotationBar->Set_Graph_Percent (index + 1, Normalize_Rotation(m_Rotations.Values[index]));
}
return TRUE;
}
/////////////////////////////////////////////////////////////
//
// OnNotify
//
/////////////////////////////////////////////////////////////
BOOL EmitterRotationPropPageClass::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
CBR_NMHDR *color_bar_hdr = (CBR_NMHDR *)lParam;
//
// Update the spinner controls if necessary
//
NMHDR *pheader = (NMHDR *)lParam;
if ((pheader != NULL) && (pheader->code == UDN_DELTAPOS)) {
LPNMUPDOWN pupdown = (LPNMUPDOWN)lParam;
::Update_Spinner_Buddy (pheader->hwndFrom, pupdown->iDelta);
}
//
// Which control sent the notification?
//
switch (color_bar_hdr->hdr.idFrom)
{
case IDC_ROTATION_BAR:
{
if (color_bar_hdr->hdr.code == CBRN_DBLCLK_POINT) {
//
// Allow the user to edit the keyframe
//
float rotation = Denormalize_Rotation(m_RotationBar->Get_Graph_Percent (color_bar_hdr->key_index));
ParticleRotationKeyDialogClass dialog (rotation, this);
if (dialog.DoModal () == IDOK) {
rotation = dialog.Get_Rotation ();
float norm_val = Normalize_Rotation(rotation);
m_RotationBar->Set_Redraw (false);
m_RotationBar->Set_Graph_Percent (color_bar_hdr->key_index, norm_val);
//
// Determine if the user changed the 'max' or 'min' rotation
//
float new_max = WWMath::Max(rotation,1.0f);
float new_min = WWMath::Min(rotation,0.0f);
int count = m_RotationBar->Get_Point_Count ();
for (int index = 0; index < count; index ++) {
float tmp = Denormalize_Rotation(m_RotationBar->Get_Graph_Percent (index) );
if (tmp > new_max) {
new_max = tmp;
}
if (tmp < new_min) {
new_min = tmp;
}
}
//
// Renormalize the RotationBar key frame points if necessary
//
if ((new_max != m_MaxRotation) || (new_min != m_MinRotation)) {
int count = m_RotationBar->Get_Point_Count ();
for (int index = 0; index < count; index ++) {
float rotation = Denormalize_Rotation(m_RotationBar->Get_Graph_Percent (index));
float new_norm = Normalize_Rotation(rotation,new_min,new_max);
m_RotationBar->Set_Graph_Percent (index, new_norm);
}
// Remember the new min and max
m_MinRotation = new_min;
m_MaxRotation = new_max;
}
m_RotationBar->Set_Redraw (true);
//
// Update the emitter
//
Update_Rotations ();
m_pEmitterList->Set_Rotation_Keyframes (m_Rotations, m_InitialOrientationRandom);
SetModified ();
}
} else if ((color_bar_hdr->hdr.code == CBRN_MOVING_POINT) ||
(color_bar_hdr->hdr.code == CBRN_DELETED_POINT)) {
//
// Update the emitter
//
Update_Rotations ();
m_pEmitterList->Set_Rotation_Keyframes (m_Rotations, m_InitialOrientationRandom);
SetModified ();
}
}
break;
case IDC_ROTATION_RANDOM_SPIN:
{
// Update the emitter
m_Rotations.Rand = ::GetDlgItemFloat (m_hWnd, IDC_ROTATION_RANDOM_EDIT);
m_pEmitterList->Set_Rotation_Keyframes (m_Rotations, m_InitialOrientationRandom);
SetModified ();
}
break;
case IDC_INITIAL_ORIENTATION_RANDOM_SPIN:
{
// Update the emitter
m_InitialOrientationRandom = ::GetDlgItemFloat (m_hWnd, IDC_INITIAL_ORIENTATION_RANDOM_EDIT);
m_pEmitterList->Set_Rotation_Keyframes (m_Rotations, m_InitialOrientationRandom);
SetModified ();
}
break;
}
return CPropertyPage::OnNotify (wParam, lParam, pResult);
}
/////////////////////////////////////////////////////////////
//
// Update_Rotations
//
/////////////////////////////////////////////////////////////
void
EmitterRotationPropPageClass::Update_Rotations (void)
{
float position = 0;
float red = 0;
float green = 0;
float blue = 0;
//
// Setup the initial or 'starting' size
//
m_Rotations.Start = Denormalize_Rotation(m_RotationBar->Get_Graph_Percent (0));
//
// Free the current setting arrays
//
SAFE_DELETE_ARRAY (m_Rotations.KeyTimes);
SAFE_DELETE_ARRAY (m_Rotations.Values);
//
// Determine if we need to build the array of key frames or not
//
int count = m_RotationBar->Get_Point_Count ();
m_Rotations.NumKeyFrames = count - 1;
if (count > 1) {
m_Rotations.KeyTimes = new float[count - 1];
m_Rotations.Values = new float[count - 1];
//
// Get all the rotation key frames and add them to our structure
//
for (int index = 1; index < count; index ++) {
m_RotationBar->Get_Point (index, &position, &red, &green, &blue);
m_Rotations.KeyTimes[index - 1] = position * m_Lifetime;
m_Rotations.Values[index - 1] = Denormalize_Rotation(m_RotationBar->Get_Graph_Percent (index) );
}
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnCommand
//
/////////////////////////////////////////////////////////////
BOOL
EmitterRotationPropPageClass::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch (LOWORD (wParam))
{
case IDC_ROTATION_RANDOM_EDIT:
{
// Update the emitter
if ((HIWORD (wParam) == EN_KILLFOCUS) &&
SendDlgItemMessage (LOWORD (wParam), EM_GETMODIFY)) {
SendDlgItemMessage (LOWORD (wParam), EM_SETMODIFY, (WPARAM)0);
m_Rotations.Rand = ::GetDlgItemFloat (m_hWnd, IDC_ROTATION_RANDOM_EDIT);
m_pEmitterList->Set_Rotation_Keyframes (m_Rotations, m_InitialOrientationRandom);
SetModified ();
} else if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
}
break;
case IDC_INITIAL_ORIENTATION_RANDOM_EDIT:
{
// Update the emitter
if ((HIWORD (wParam) == EN_KILLFOCUS) &&
SendDlgItemMessage (LOWORD (wParam), EM_GETMODIFY)) {
SendDlgItemMessage (LOWORD (wParam), EM_SETMODIFY, (WPARAM)0);
m_InitialOrientationRandom = ::GetDlgItemFloat (m_hWnd, IDC_INITIAL_ORIENTATION_RANDOM_EDIT);
m_pEmitterList->Set_Rotation_Keyframes (m_Rotations, m_InitialOrientationRandom);
SetModified ();
} else if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
}
break;
}
return CPropertyPage::OnCommand(wParam, lParam);
}
/////////////////////////////////////////////////////////////
//
// On_Lifetime_Changed
//
/////////////////////////////////////////////////////////////
void
EmitterRotationPropPageClass::On_Lifetime_Changed (float lifetime)
{
if (m_Lifetime != lifetime) {
float conversion = lifetime / m_Lifetime;
//
// Rescale the sizes
//
for (UINT index = 0; index < m_Rotations.NumKeyFrames; index ++) {
m_Rotations.KeyTimes[index] *= conversion;
}
//
// Update the emitter
//
m_pEmitterList->Set_Rotation_Keyframes (m_Rotations, m_InitialOrientationRandom);
m_Lifetime = lifetime;
}
return ;
}

View File

@@ -0,0 +1,143 @@
/*
** 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/>.
*/
#if !defined(AFX_EMITTERROTATIONPROPPAGE_H__35F8A2F6_C91C_4750_BF06_100433C1ECBB__INCLUDED_)
#define AFX_EMITTERROTATIONPROPPAGE_H__35F8A2F6_C91C_4750_BF06_100433C1ECBB__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EmitterRotationPropPage.h : header file
//
#include "ColorBar.H"
#include "Part_Emt.H"
// Forward delcarations
class EmitterInstanceListClass;
/////////////////////////////////////////////////////////////////////////////
// EmitterRotationPropPageClass dialog
class EmitterRotationPropPageClass : public CPropertyPage
{
DECLARE_DYNCREATE(EmitterRotationPropPageClass)
// Construction
public:
EmitterRotationPropPageClass();
~EmitterRotationPropPageClass();
// Dialog Data
//{{AFX_DATA(EmitterRotationPropPageClass)
enum { IDD = IDD_PROP_PAGE_EMITTER_ROTATION };
CSpinButtonCtrl m_InitialOrientationRandomSpin;
CSpinButtonCtrl m_RotationRandomSpin;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(EmitterRotationPropPageClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(EmitterRotationPropPageClass)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////
//
// Public methods
//
//
// Inline accessors
//
EmitterInstanceListClass * Get_Emitter (void) const { return m_pEmitterList; }
void Set_Emitter (EmitterInstanceListClass *pemitter_list) { m_pEmitterList = pemitter_list; Initialize (); }
bool Is_Data_Valid (void) const { return m_bValid; }
void Get_Rotation_Keyframes (ParticlePropertyStruct<float> &rotations) { rotations = m_Rotations; }
void On_Lifetime_Changed (float lifetime);
protected:
/////////////////////////////////////////////////////////
//
// Protected methods
//
void Initialize (void);
void Update_Rotations (void);
private:
float Normalize_Rotation(float rot);
float Normalize_Rotation(float rot,float min,float max);
float Denormalize_Rotation(float normalized_val);
/////////////////////////////////////////////////////////
//
// Private member data
//
EmitterInstanceListClass * m_pEmitterList;
bool m_bValid;
ColorBarClass * m_RotationBar;
ParticlePropertyStruct<float> m_Rotations;
float m_Lifetime;
float m_MinRotation;
float m_MaxRotation;
float m_InitialOrientationRandom;
};
inline float EmitterRotationPropPageClass::Normalize_Rotation(float rot)
{
return (rot - m_MinRotation) / (m_MaxRotation - m_MinRotation);
}
inline float EmitterRotationPropPageClass::Normalize_Rotation(float rot,float min,float max)
{
return (rot - min) / (max - min);
}
inline float EmitterRotationPropPageClass::Denormalize_Rotation(float normalized_val)
{
return normalized_val * (m_MaxRotation - m_MinRotation) + m_MinRotation;
}
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EMITTERROTATIONPROPPAGE_H__35F8A2F6_C91C_4750_BF06_100433C1ECBB__INCLUDED_)

View File

@@ -0,0 +1,416 @@
/*
** 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/>.
*/
// EmitterSizePropPage.cpp : implementation file
//
#include "Stdafx.H"
#include "W3dview.H"
#include "EmitterSizePropPage.H"
#include "Utils.H"
#include "ParticleSizeDialog.H"
#include "EmitterInstanceList.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// EmitterSizePropPageClass property page
IMPLEMENT_DYNCREATE(EmitterSizePropPageClass, CPropertyPage)
/////////////////////////////////////////////////////////////
//
// EmitterSizePropPageClass
//
/////////////////////////////////////////////////////////////
EmitterSizePropPageClass::EmitterSizePropPageClass (EmitterInstanceListClass *pemitter)
: m_pEmitterList (NULL),
m_bValid (true),
m_SizeBar (NULL),
m_Lifetime (0),
CPropertyPage(EmitterSizePropPageClass::IDD)
{
::memset (&m_OrigSizes, 0, sizeof (m_OrigSizes));
::memset (&m_CurrentSizes, 0, sizeof (m_CurrentSizes));
//{{AFX_DATA_INIT(EmitterSizePropPageClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
Initialize ();
return ;
}
/////////////////////////////////////////////////////////////
//
// ~EmitterSizePropPageClass
//
/////////////////////////////////////////////////////////////
EmitterSizePropPageClass::~EmitterSizePropPageClass (void)
{
// Free the original setting arrays
SAFE_DELETE_ARRAY (m_OrigSizes.KeyTimes);
SAFE_DELETE_ARRAY (m_OrigSizes.Values);
// Free the current setting arrays
SAFE_DELETE_ARRAY (m_CurrentSizes.KeyTimes);
SAFE_DELETE_ARRAY (m_CurrentSizes.Values);
return ;
}
/////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////
void
EmitterSizePropPageClass::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(EmitterSizePropPageClass)
DDX_Control(pDX, IDC_SIZE_RANDOM_SPIN, m_SizeRandomSpin);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(EmitterSizePropPageClass, CPropertyPage)
//{{AFX_MSG_MAP(EmitterSizePropPageClass)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////
//
// Initialize
//
/////////////////////////////////////////////////////////////
void
EmitterSizePropPageClass::Initialize (void)
{
SAFE_DELETE_ARRAY (m_OrigSizes.KeyTimes);
SAFE_DELETE_ARRAY (m_OrigSizes.Values);
SAFE_DELETE_ARRAY (m_CurrentSizes.KeyTimes);
SAFE_DELETE_ARRAY (m_CurrentSizes.Values);
if (m_pEmitterList != NULL) {
m_Lifetime = m_pEmitterList->Get_Lifetime ();
m_pEmitterList->Get_Size_Keyframes (m_OrigSizes);
m_pEmitterList->Get_Size_Keyframes (m_CurrentSizes);
//
// Determine what the largest size is
//
m_MaxSize = m_OrigSizes.Start;
for (UINT index = 0; index < m_OrigSizes.NumKeyFrames; index ++) {
if (m_OrigSizes.Values[index] > m_MaxSize) {
m_MaxSize = m_OrigSizes.Values[index];
}
}
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////
BOOL
EmitterSizePropPageClass::OnInitDialog (void)
{
// Allow the base class to process this message
CPropertyPage::OnInitDialog ();
m_SizeBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_SIZE_BAR));
m_SizeBar->Set_Range (0, 1);
//
// Setup the spinners
//
Initialize_Spinner (m_SizeRandomSpin, m_OrigSizes.Rand, 0, 10000);
//
// Reset the color bars
//
m_SizeBar->Set_Range (0, 1);
m_SizeBar->Clear_Points ();
m_SizeBar->Modify_Point (0, 0, 0, 0, 0);
m_SizeBar->Set_Graph_Percent (0, m_OrigSizes.Start / m_MaxSize);
//
// Set-up the color bar
//
for (UINT index = 0; index < m_OrigSizes.NumKeyFrames; index ++) {
m_SizeBar->Modify_Point (index + 1,
m_OrigSizes.KeyTimes[index] / m_Lifetime,
0,
0,
0);
m_SizeBar->Set_Graph_Percent (index + 1, m_OrigSizes.Values[index] / m_MaxSize);
}
return TRUE;
}
/////////////////////////////////////////////////////////////
//
// OnApply
//
/////////////////////////////////////////////////////////////
BOOL
EmitterSizePropPageClass::OnApply (void)
{
/*SAFE_DELETE_ARRAY (m_OrigSizes.KeyTimes);
SAFE_DELETE_ARRAY (m_OrigSizes.Values);
//
// Make the current values from the emitter the default values.
//
m_pEmitterList->Get_Size_Key_Frames (m_OrigSizes);*/
// Allow the base class to process this message
return CPropertyPage::OnApply ();
}
/////////////////////////////////////////////////////////////
//
// OnNotify
//
/////////////////////////////////////////////////////////////
BOOL
EmitterSizePropPageClass::OnNotify
(
WPARAM wParam,
LPARAM lParam,
LRESULT *pResult
)
{
CBR_NMHDR *color_bar_hdr = (CBR_NMHDR *)lParam;
//
// Update the spinner controls if necessary
//
NMHDR *pheader = (NMHDR *)lParam;
if ((pheader != NULL) && (pheader->code == UDN_DELTAPOS)) {
LPNMUPDOWN pupdown = (LPNMUPDOWN)lParam;
::Update_Spinner_Buddy (pheader->hwndFrom, pupdown->iDelta);
}
//
// Which control sent the notification?
//
switch (color_bar_hdr->hdr.idFrom)
{
case IDC_SIZE_BAR:
{
if (color_bar_hdr->hdr.code == CBRN_DBLCLK_POINT) {
//
// Allow the user to edit the keyframe
//
float size = m_SizeBar->Get_Graph_Percent (color_bar_hdr->key_index) * m_MaxSize;
ParticleSizeDialogClass dialog (size, this);
if (dialog.DoModal () == IDOK) {
size = dialog.Get_Size ();
m_SizeBar->Set_Redraw (false);
m_SizeBar->Set_Graph_Percent (color_bar_hdr->key_index, size / m_MaxSize);
//
// Determine if the user changed the 'max' size
//
float new_max = size;
int count = m_SizeBar->Get_Point_Count ();
for (int index = 0; index < count; index ++) {
float size = m_SizeBar->Get_Graph_Percent (index) * m_MaxSize;
if (size > new_max) {
new_max = size;
}
}
//
// Rescale the key frame points if necessary
//
if (new_max != m_MaxSize) {
int count = m_SizeBar->Get_Point_Count ();
for (int index = 0; index < count; index ++) {
float percent = m_SizeBar->Get_Graph_Percent (index);
m_SizeBar->Set_Graph_Percent (index, (percent * m_MaxSize) / new_max);
}
// Remember the new size maximum
m_MaxSize = new_max;
}
m_SizeBar->Set_Redraw (true);
//
// Update the emitter
//
Update_Sizes ();
m_pEmitterList->Set_Size_Keyframes (m_CurrentSizes);
SetModified ();
}
} else if ((color_bar_hdr->hdr.code == CBRN_MOVING_POINT) ||
(color_bar_hdr->hdr.code == CBRN_DELETED_POINT)) {
//
// Update the emitter
//
Update_Sizes ();
m_pEmitterList->Set_Size_Keyframes (m_CurrentSizes);
SetModified ();
}
}
break;
case IDC_SIZE_RANDOM_SPIN:
{
// Update the emitter
m_CurrentSizes.Rand = ::GetDlgItemFloat (m_hWnd, IDC_SIZE_RANDOM_EDIT);
m_pEmitterList->Set_Size_Keyframes (m_CurrentSizes);
SetModified ();
}
break;
}
return CPropertyPage::OnNotify (wParam, lParam, pResult);
}
/////////////////////////////////////////////////////////////
//
// Update_Sizes
//
/////////////////////////////////////////////////////////////
void
EmitterSizePropPageClass::Update_Sizes (void)
{
float position = 0;
float red = 0;
float green = 0;
float blue = 0;
//
// Setup the initial or 'starting' size
//
m_CurrentSizes.Start = m_SizeBar->Get_Graph_Percent (0) * m_MaxSize;
//
// Free the current setting arrays
//
SAFE_DELETE_ARRAY (m_CurrentSizes.KeyTimes);
SAFE_DELETE_ARRAY (m_CurrentSizes.Values);
//
// Determine if we need to build the array of key frames or not
//
int count = m_SizeBar->Get_Point_Count ();
m_CurrentSizes.NumKeyFrames = count - 1;
if (count > 1) {
m_CurrentSizes.KeyTimes = new float[count - 1];
m_CurrentSizes.Values = new float[count - 1];
//
// Get all the size key frames and add them to our structure
//
for (int index = 1; index < count; index ++) {
m_SizeBar->Get_Point (index, &position, &red, &green, &blue);
m_CurrentSizes.KeyTimes[index - 1] = position * m_Lifetime;
m_CurrentSizes.Values[index - 1] = m_SizeBar->Get_Graph_Percent (index) * m_MaxSize;
}
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnCommand
//
/////////////////////////////////////////////////////////////
BOOL
EmitterSizePropPageClass::OnCommand
(
WPARAM wParam,
LPARAM lParam
)
{
switch (LOWORD (wParam))
{
case IDC_SIZE_RANDOM_EDIT:
{
// Update the emitter
if ((HIWORD (wParam) == EN_KILLFOCUS) &&
SendDlgItemMessage (LOWORD (wParam), EM_GETMODIFY)) {
SendDlgItemMessage (LOWORD (wParam), EM_SETMODIFY, (WPARAM)0);
m_CurrentSizes.Rand = ::GetDlgItemFloat (m_hWnd, IDC_SIZE_RANDOM_EDIT);
m_pEmitterList->Set_Size_Keyframes (m_CurrentSizes);
SetModified ();
} else if (HIWORD (wParam) == EN_CHANGE) {
SetModified ();
}
}
break;
}
return CPropertyPage::OnCommand (wParam, lParam);
}
/////////////////////////////////////////////////////////////
//
// On_Lifetime_Changed
//
/////////////////////////////////////////////////////////////
void
EmitterSizePropPageClass::On_Lifetime_Changed (float lifetime)
{
if (m_Lifetime != lifetime) {
float conversion = lifetime / m_Lifetime;
//
// Rescale the sizes
//
for (UINT index = 0; index < m_CurrentSizes.NumKeyFrames; index ++) {
m_CurrentSizes.KeyTimes[index] *= conversion;
}
//
// Update the emitter
//
m_pEmitterList->Set_Size_Keyframes (m_CurrentSizes);
m_Lifetime = lifetime;
}
return ;
}

View File

@@ -0,0 +1,119 @@
/*
** 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/>.
*/
#if !defined(AFX_EMITTERSIZEPROPPAGE_H__0CD2CBA3_1219_11D3_A034_00104B791122__INCLUDED_)
#define AFX_EMITTERSIZEPROPPAGE_H__0CD2CBA3_1219_11D3_A034_00104B791122__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EmitterSizePropPage.h : header file
//
#include "ColorBar.H"
#include "Part_Emt.H"
// Forward delcarations
class EmitterInstanceListClass;
/////////////////////////////////////////////////////////////////////////////
//
// EmitterSizePropPageClass dialog
//
/////////////////////////////////////////////////////////////////////////////
class EmitterSizePropPageClass : public CPropertyPage
{
DECLARE_DYNCREATE(EmitterSizePropPageClass)
// Construction
public:
EmitterSizePropPageClass(EmitterInstanceListClass *pemitter = NULL);
~EmitterSizePropPageClass();
// Dialog Data
//{{AFX_DATA(EmitterSizePropPageClass)
enum { IDD = IDD_PROP_PAGE_EMITTER_SIZE };
CSpinButtonCtrl m_SizeRandomSpin;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(EmitterSizePropPageClass)
public:
virtual BOOL OnApply();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(EmitterSizePropPageClass)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////
//
// Public methods
//
//
// Inline accessors
//
EmitterInstanceListClass * Get_Emitter (void) const { return m_pEmitterList; }
void Set_Emitter (EmitterInstanceListClass *pemitter_list) { m_pEmitterList = pemitter_list; Initialize (); }
bool Is_Data_Valid (void) const { return m_bValid; }
void Get_Size_Keyframes (ParticlePropertyStruct<float> &sizes) { sizes = m_CurrentSizes; }
void On_Lifetime_Changed (float lifetime);
protected:
/////////////////////////////////////////////////////////
//
// Protected methods
//
void Initialize (void);
void Update_Sizes (void);
private:
/////////////////////////////////////////////////////////
//
// Private member data
//
EmitterInstanceListClass * m_pEmitterList;
bool m_bValid;
ColorBarClass * m_SizeBar;
ParticlePropertyStruct<float> m_OrigSizes;
ParticlePropertyStruct<float> m_CurrentSizes;
float m_Lifetime;
float m_MaxSize;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EMITTERSIZEPROPPAGE_H__0CD2CBA3_1219_11D3_A034_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,177 @@
/*
** 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/>.
*/
// EmitterUserPropPage.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "EmitterUserPropPage.h"
#include "W3D_File.H"
#include "Part_Emt.H"
#include "EmitterInstanceList.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// EmitterUserPropPageClass property page
IMPLEMENT_DYNCREATE(EmitterUserPropPageClass, CPropertyPage)
/////////////////////////////////////////////////////////////
//
// EmitterUserPropPageClass
//
EmitterUserPropPageClass::EmitterUserPropPageClass (EmitterInstanceListClass *pemitter)
: m_pEmitterList (NULL),
m_bValid (true),
m_iType (EMITTER_TYPEID_DEFAULT),
CPropertyPage(EmitterUserPropPageClass::IDD)
{
//{{AFX_DATA_INIT(EmitterUserPropPageClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
Initialize ();
return ;
}
/////////////////////////////////////////////////////////////
//
// ~EmitterUserPropPageClass
//
EmitterUserPropPageClass::~EmitterUserPropPageClass (void)
{
return;
}
/////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
EmitterUserPropPageClass::DoDataExchange (CDataExchange* pDX)
{
// Allow the base class to process this message
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(EmitterUserPropPageClass)
DDX_Control(pDX, IDC_TYPE_COMBO, m_TypeCombo);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(EmitterUserPropPageClass, CPropertyPage)
//{{AFX_MSG_MAP(EmitterUserPropPageClass)
ON_EN_CHANGE(IDC_PROGRAMMER_SETTINGS_EDIT, OnChangeProgrammerSettingsEdit)
ON_CBN_SELCHANGE(IDC_TYPE_COMBO, OnSelchangeTypeCombo)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////
//
// Initialize
//
void
EmitterUserPropPageClass::Initialize (void)
{
if (m_pEmitterList != NULL) {
// Record the user information from the emitter (if it exists)
m_iType = m_pEmitterList->Get_User_Type ();
m_UserString = m_pEmitterList->Get_User_String ();
}
return ;
}
/////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
EmitterUserPropPageClass::OnInitDialog (void)
{
// Allow the base class to process this message
CPropertyPage::OnInitDialog ();
// Add the list of user-types to the combobox
for (int index = 0; index < EMITTER_TYPEID_COUNT; index ++) {
m_TypeCombo.AddString (EMITTER_TYPE_NAMES[index]);
}
// Select the correct entry in the combobox
m_TypeCombo.SetCurSel (m_iType);
// Fill in the user-box
SetDlgItemText (IDC_PROGRAMMER_SETTINGS_EDIT, m_UserString);
return TRUE;
}
/////////////////////////////////////////////////////////////
//
// OnApply
//
BOOL
EmitterUserPropPageClass::OnApply (void)
{
// Get the settings from the controls
m_iType = m_TypeCombo.GetCurSel ();
GetDlgItemText (IDC_PROGRAMMER_SETTINGS_EDIT, m_UserString);
//
// Pass the new settings onto the emitter
//
m_pEmitterList->Set_User_Type (m_iType);
m_pEmitterList->Set_User_String (m_UserString);
// Allow the base class to process this message
return CPropertyPage::OnApply ();
}
/////////////////////////////////////////////////////////////
//
// OnChangeProgrammerSettingsEdit
//
void
EmitterUserPropPageClass::OnChangeProgrammerSettingsEdit (void)
{
SetModified ();
return ;
}
/////////////////////////////////////////////////////////////
//
// OnSelchangeTypeCombo
//
void
EmitterUserPropPageClass::OnSelchangeTypeCombo (void)
{
SetModified ();
return ;
}

View File

@@ -0,0 +1,115 @@
/*
** 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/>.
*/
#if !defined(AFX_EMITTERUSERPROPPAGE_H__83A8B840_BA3B_11D2_9FFA_00104B791122__INCLUDED_)
#define AFX_EMITTERUSERPROPPAGE_H__83A8B840_BA3B_11D2_9FFA_00104B791122__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EmitterUserPropPage.h : header file
//
#include "Resource.H"
// Forward delcarations
class EmitterInstanceListClass;
/////////////////////////////////////////////////////////////////////////////
// EmitterUserPropPageClass dialog
class EmitterUserPropPageClass : public CPropertyPage
{
DECLARE_DYNCREATE(EmitterUserPropPageClass)
// Construction
public:
EmitterUserPropPageClass (EmitterInstanceListClass *pemitter_list = NULL);
~EmitterUserPropPageClass ();
// Dialog Data
//{{AFX_DATA(EmitterUserPropPageClass)
enum { IDD = IDD_PROP_PAGE_EMITTER_USER };
CComboBox m_TypeCombo;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(EmitterUserPropPageClass)
public:
virtual BOOL OnApply();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(EmitterUserPropPageClass)
virtual BOOL OnInitDialog();
afx_msg void OnChangeProgrammerSettingsEdit();
afx_msg void OnSelchangeTypeCombo();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////
//
// Public methods
//
//
// Inline accessors
//
EmitterInstanceListClass * Get_Emitter (void) const { return m_pEmitterList; }
void Set_Emitter (EmitterInstanceListClass *pemitter_list) { m_pEmitterList = pemitter_list; Initialize (); }
bool Is_Data_Valid (void) const { return m_bValid; }
int Get_Type (void) const { return m_iType; }
const CString & Get_String (void) const { return m_UserString; }
void Set_Type (int type) { m_iType = type; }
void Set_String (LPCTSTR string) { m_UserString = string; }
protected:
/////////////////////////////////////////////////////////
//
// Protected methods
//
void Initialize (void);
private:
/////////////////////////////////////////////////////////
//
// Private member data
//
EmitterInstanceListClass * m_pEmitterList;
bool m_bValid;
int m_iType;
CString m_UserString;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EMITTERUSERPROPPAGE_H__83A8B840_BA3B_11D2_9FFA_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,112 @@
/*
** 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/>.
*/
// GammaDialog.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "GammaDialog.h"
#include "dx8wrapper.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// GammaDialogClass dialog
GammaDialogClass::GammaDialogClass(CWnd* pParent /*=NULL*/)
: CDialog(GammaDialogClass::IDD, pParent)
{
//{{AFX_DATA_INIT(GammaDialogClass)
m_gamma = 0;
//}}AFX_DATA_INIT
}
void GammaDialogClass::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(GammaDialogClass)
DDX_Control(pDX, IDC_GAMMA_SLIDER, m_gammaslider);
DDX_Slider(pDX, IDC_GAMMA_SLIDER, m_gamma);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(GammaDialogClass, CDialog)
//{{AFX_MSG_MAP(GammaDialogClass)
ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_GAMMA_SLIDER, OnReleasedcaptureGammaSlider)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// GammaDialogClass message handlers
BOOL GammaDialogClass::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
m_gamma=AfxGetApp()->GetProfileInt("Config","Gamma",10);
if (m_gamma<10) m_gamma=10;
if (m_gamma>30) m_gamma=30;
m_gammaslider.SetRange(10,30);
m_gammaslider.SetPos(m_gamma);
CString string;
string.Format("%3.2f",m_gamma/10.0f);
SetDlgItemText(IDC_GAMMA_DISPLAY,string);
string.Format("Calibration instructions\n");
string+="A. Set Gamma to 1.0 and Monitor Contrast and Brightness to maximum\n";
string+="B. Adjust Monitor Brightness down so Bar 3 is barely visible\n";
string+="C. Adjust Monitor Contrast as preferred but Bars 1,2,3,4 must be distinguishable from each other\n";
string+="D. Set the Gamma using the Slider below so the gray box on the left matches it's checkered surroundings\n";
string+="E. Press OK to save settings";
SetDlgItemText(IDC_INSTRUCTIONS,string);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void GammaDialogClass::OnOK()
{
// TODO: Add extra validation here
m_gamma=m_gammaslider.GetPos();
if (m_gamma<10) m_gamma=10;
if (m_gamma>30) m_gamma=30;
::AfxGetApp()->WriteProfileInt("Config","Gamma",m_gamma);
DX8Wrapper::Set_Gamma(m_gamma/10.0f,0.0f,1.0f);
CDialog::OnOK();
}
void GammaDialogClass::OnReleasedcaptureGammaSlider(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
m_gamma=m_gammaslider.GetPos();
DX8Wrapper::Set_Gamma(m_gamma/10.0f,0.0f,1.0f);
CString string;
string.Format("%3.2f",m_gamma/10.0f);
SetDlgItemText(IDC_GAMMA_DISPLAY,string);
*pResult = 0;
}

View File

@@ -0,0 +1,67 @@
/*
** 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/>.
*/
#if !defined(AFX_GAMMADIALOG_H__DA25161A_E783_44DE_8398_B311C20C3BE9__INCLUDED_)
#define AFX_GAMMADIALOG_H__DA25161A_E783_44DE_8398_B311C20C3BE9__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// GammaDialog.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// GammaDialogClass dialog
class GammaDialogClass : public CDialog
{
// Construction
public:
GammaDialogClass(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(GammaDialogClass)
enum { IDD = IDD_GAMMA_DIALOG };
CSliderCtrl m_gammaslider;
int m_gamma;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(GammaDialogClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(GammaDialogClass)
virtual BOOL OnInitDialog();
virtual void OnOK();
afx_msg void OnReleasedcaptureGammaSlider(NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GAMMADIALOG_H__DA25161A_E783_44DE_8398_B311C20C3BE9__INCLUDED_)

View File

@@ -0,0 +1,40 @@
/*
** 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/>.
*/
/////////////////////////////////////////////////////////////////////
//
// Globals.CPP
//
// Module containing global variable initialization.
//
//
#include "stdafx.h"
#include "globals.h"
#include "assetmgr.h"
#include "viewerassetmgr.h"
// Main asset manager for the application.
ViewerAssetMgrClass *_TheAssetMgr = NULL;
int g_iDeviceIndex = -1;//DEFAULT_DEVICEINDEX;
int g_iBitsPerPixel = -1;//DEFAULT_BITSPERPIX;
int g_iWidth = 640;
int g_iHeight = 480;

View File

@@ -0,0 +1,50 @@
/*
** 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/>.
*/
/////////////////////////////////////////////////////////////////////
//
// Globals.H
//
// Module containing global variable definitions.
//
//
/////////////////////////////////////////////////////////////////////
#ifndef __GLOBALS_H
#define __GLOBALS_H
//////////////////////////////////////////////////////
// Externs
//////////////////////////////////////////////////////
extern class ViewerAssetMgrClass *_TheAssetMgr;
extern class CW3DViewApp theApp;
extern int g_iDeviceIndex;
extern int g_iBitsPerPixel;
extern int g_iWidth;
extern int g_iHeight;
//////////////////////////////////////////////////////
// Contants
//////////////////////////////////////////////////////
const int DEFAULT_DEVICEINDEX = 1;
const int DEFAULT_BITSPERPIX = 16;
#endif //__GLOBALS_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,263 @@
/*
** 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/>.
*/
#if !defined(AFX_GRAPHICVIEW_H__2BB39E41_5D3A_11D2_9FC6_00104B791122__INCLUDED_)
#define AFX_GRAPHICVIEW_H__2BB39E41_5D3A_11D2_9FC6_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// GraphicView.h : header file
//
/////////////////////////////////////////////////////////////////
//
// Constants
//
#define ROTATION_X 0x01
#define ROTATION_Y 0x02
#define ROTATION_Z 0x04
#define ROTATION_X_BACK 0x08
#define ROTATION_Y_BACK 0x10
#define ROTATION_Z_BACK 0x20
// Forward declarations
class ParticleEmitterClass;
/////////////////////////////////////////////////////////////////////////////
// CGraphicView view
#include "Camera.H"
class CGraphicView : public CView
{
protected:
CGraphicView(); // protected constructor used by dynamic creation
DECLARE_DYNCREATE(CGraphicView)
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CGraphicView)
public:
virtual void OnInitialUpdate();
protected:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
//}}AFX_VIRTUAL
// Implementation
protected:
virtual ~CGraphicView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
// Generated message map functions
protected:
//{{AFX_MSG(CGraphicView)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnDestroy();
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////
//
// Public Data Types
//
typedef enum
{
AnimInvalid = -1,
AnimPlaying = 0,
AnimStopped = 1,
AnimPaused = 2
} ANIMATION_STATE;
typedef enum
{
CameraFront = -1,
CameraBack = 0,
CameraTop = 1,
CameraBottom = 2,
CameraLeft = 3,
CameraRight = 4
} CAMERA_POS;
typedef enum
{
NoRotation = 0,
RotateX = ROTATION_X,
RotateY = ROTATION_Y,
RotateZ = ROTATION_Z,
RotateXBack = ROTATION_X_BACK,
RotateYBack = ROTATION_Y_BACK,
RotateZBack = ROTATION_Z_BACK
} OBJECT_ROTATION;
typedef enum
{
FreeRotation = 0,
OnlyRotateX = ROTATION_X,
OnlyRotateY = ROTATION_Y,
OnlyRotateZ = ROTATION_Z
} CAMERA_ROTATION;
/////////////////////////////////////////////////
//
// Public Methods
//
BOOL InitializeGraphicView (void);
//
// Initial display methods
//
void Reset_Camera_To_Display_Sphere (SphereClass &sphere);
void Reset_Camera_To_Display_Object (RenderObjClass &physObject);
void Reset_Camera_To_Display_Emitter (ParticleEmitterClass &emitter);
void Load_Default_Dat (void);
void UpdateDisplay (void);
void RepaintView (BOOL bUpdateAnimation = TRUE, DWORD ticks_to_use = 0);
void SetActiveUpdate (BOOL bActive)
{ m_bActive = bActive;
if (!m_bActive) { ::SetProp (m_hWnd, "Inactive", (HANDLE)1); }
else { RemoveProp (m_hWnd, "Inactive"); m_dwLastFrameUpdate = ::GetTickCount (); }
}
void Allow_Update (bool onoff);
//
// Animation methods
//
float GetAnimationSpeed (void) const { return m_animationSpeed; }
void SetAnimationSpeed (float animationSpeed) { m_animationSpeed = animationSpeed; }
ANIMATION_STATE GetAnimationState (void) const { return m_animationState; }
void SetAnimationState (ANIMATION_STATE animationState);
//
// Camera Methods
//
void SetAllowedCameraRotation (CAMERA_ROTATION cameraRotation);
CAMERA_ROTATION GetAllowedCameraRotation () const { return m_allowedCameraRotation; }
void SetCameraPos (CAMERA_POS cameraPos);
class CameraClass *GetCamera (void) const { return m_pCamera; }
float Get_Camera_Distance (void) const { return m_CameraDistance; }
void Set_Camera_Distance (float dist);
void Set_Camera_Bone_Pos_X (bool onoff) { m_CameraBonePosX = onoff; }
BOOL Is_Camera_Bone_Pos_X (void) const { return m_CameraBonePosX; }
//
// Object rotation methods
//
void ResetObject (void);
void RotateObject (OBJECT_ROTATION rotation);
OBJECT_ROTATION GetObjectRotation (void) const { return m_objectRotation; }
//
// Light rotation methods
//
void Rotate_Light (OBJECT_ROTATION rotation) { m_LightRotation = rotation; }
OBJECT_ROTATION Get_Light_Rotation (void) const { return m_LightRotation; }
//
// Fullscreen mode
//
BOOL Is_Fullscreen (void) const { return !(BOOL)m_iWindowed; }
void Set_Fullscreen (bool fullscreen) { m_iWindowed = fullscreen ? 0 : 1; InitializeGraphicView (); }
//
// Misc
//
RenderObjClass * Get_Light_Mesh (void) const { return m_pLightMesh; }
Vector3 & Get_Object_Center (void) { return m_ObjectCenter; }
//
// FOV methods
//
void Set_FOV (double hfov, double vfov, bool force = false);
void Reset_FOV (void);
protected:
/////////////////////////////////////////////////
//
// Protected methods
//
void Rotate_Object (void);
void Rotate_Light (void);
private:
/////////////////////////////////////////////////
//
// Private Member Data
//
BOOL m_bInitialized;
BOOL m_bActive;
UINT m_TimerID;
CameraClass * m_pCamera;
RenderObjClass * m_pLightMesh;
bool m_bLightMeshInScene;
Vector3 m_ObjectCenter;
SphereClass m_ViewedSphere;
BOOL m_bMouseDown;
BOOL m_bRMouseDown;
POINT m_lastPoint;
int m_iWindowed;
int m_UpdateCounter;
float m_CameraDistance;
DWORD m_ParticleCountUpdate;
BOOL m_CameraBonePosX;
// Animation data
DWORD m_dwLastFrameUpdate;
float m_animationSpeed;
ANIMATION_STATE m_animationState;
OBJECT_ROTATION m_objectRotation;
OBJECT_ROTATION m_LightRotation;
CAMERA_ROTATION m_allowedCameraRotation;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GRAPHICVIEW_H__2BB39E41_5D3A_11D2_9FC6_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,182 @@
/*
** 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/>.
*/
// HierarchyPropPage.cpp : implementation file
//
#include "stdafx.h"
#include "W3DView.h"
#include "HierarchyPropPage.h"
#include "AssetMgr.H"
#include "RendObj.H"
#include "AssetPropertySheet.H"
#include "MeshPropPage.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CHierarchyPropPage property page
IMPLEMENT_DYNCREATE(CHierarchyPropPage, CPropertyPage)
////////////////////////////////////////////////////////////////
//
// CHierarchyPropPage
//
CHierarchyPropPage::CHierarchyPropPage (const CString &stringHierarchyName)
: CPropertyPage(CHierarchyPropPage::IDD)
{
//{{AFX_DATA_INIT(CHierarchyPropPage)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_stringHierarchyName = stringHierarchyName;
return ;
}
////////////////////////////////////////////////////////////////
//
// CHierarchyPropPage
//
CHierarchyPropPage::~CHierarchyPropPage (void)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
CHierarchyPropPage::DoDataExchange (CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CHierarchyPropPage)
DDX_Control(pDX, IDC_SUBOBJECT_LIST, m_subObjectListCtrl);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(CHierarchyPropPage, CPropertyPage)
//{{AFX_MSG_MAP(CHierarchyPropPage)
ON_NOTIFY(NM_DBLCLK, IDC_SUBOBJECT_LIST, OnDblclkSubObjectList)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CHierarchyPropPage message handlers
////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
CHierarchyPropPage::OnInitDialog (void)
{
// Allow the base class to process this message
CPropertyPage::OnInitDialog();
if (m_stringHierarchyName.GetLength () > 0)
{
// Get a pointer to the hierarchy object from the asset manager
RenderObjClass *pCHierarchy = WW3DAssetManager::Get_Instance()->Create_Render_Obj (m_stringHierarchyName);
ASSERT (pCHierarchy);
if (pCHierarchy)
{
CString stringDesc;
stringDesc.Format (IDS_HIERARCHY_PROP_DESC, m_stringHierarchyName);
// Put the description onto the dialog
SetDlgItemText (IDC_DESCRIPTION, stringDesc);
// Put the polygon count onto the dialog
SetDlgItemInt (IDC_TOTAL_POLYGONS, pCHierarchy->Get_Num_Polys ());
// Put the subobject count onto the dialog
int iSubObjects = pCHierarchy->Get_Num_Sub_Objects ();
SetDlgItemInt (IDC_SUBOBJECTS, iSubObjects);
// Add the name column to the list control
m_subObjectListCtrl.InsertColumn (0, "Name");
// Loop through all the subobjects and add them to the list control
for (int iObject = 0;
iObject < iSubObjects;
iObject ++)
{
// Get this subobject
RenderObjClass *pCSubObject = pCHierarchy->Get_Sub_Object (iObject);
if (pCSubObject)
{
// Add this object to the list
m_subObjectListCtrl.InsertItem (0, pCSubObject->Get_Name ());
// Free this object
pCSubObject->Release_Ref ();
pCSubObject = NULL;
}
}
// Resize the column so it is wide enough to display the largest string
m_subObjectListCtrl.SetColumnWidth (0, LVSCW_AUTOSIZE);
// Free the object
pCHierarchy->Release_Ref ();
pCHierarchy = NULL;
}
}
GetParent ()->GetDlgItem (IDOK)->ShowWindow (SW_HIDE);
GetParent ()->GetDlgItem (IDCANCEL)->SetWindowText ("Close");
return TRUE;
}
////////////////////////////////////////////////////////////////
//
// OnDblclkSubObjectList
//
void
CHierarchyPropPage::OnDblclkSubObjectList
(
NMHDR* pNMHDR,
LRESULT* pResult
)
{
// Get the currently selected item
int iIndex = m_subObjectListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
if (iIndex != -1)
{
// Create a one-page property sheet that will display property information
// for the mesh
CMeshPropPage meshPropPage (m_subObjectListCtrl.GetItemText (iIndex, 0));
CAssetPropertySheet propertySheet (IDS_MESH_PROP_TITLE, &meshPropPage, this);
// Show the property sheet
propertySheet.DoModal ();
}
(*pResult) = 0;
return ;
}

View File

@@ -0,0 +1,74 @@
/*
** 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/>.
*/
#if !defined(AFX_HIERARCHYPROPPAGE_H__FB40246E_5DFB_11D2_9FC7_00104B791122__INCLUDED_)
#define AFX_HIERARCHYPROPPAGE_H__FB40246E_5DFB_11D2_9FC7_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// HierarchyPropPage.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CHierarchyPropPage dialog
class CHierarchyPropPage : public CPropertyPage
{
DECLARE_DYNCREATE(CHierarchyPropPage)
// Construction
public:
CHierarchyPropPage (const CString &stringHierarchyName);
~CHierarchyPropPage ();
// Dialog Data
//{{AFX_DATA(CHierarchyPropPage)
enum { IDD = IDD_PROP_PAGE_HIERARCHY };
CListCtrl m_subObjectListCtrl;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(CHierarchyPropPage)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CHierarchyPropPage)
virtual BOOL OnInitDialog();
afx_msg void OnDblclkSubObjectList(NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
// Private constructor that shouldn't be called
CHierarchyPropPage () {};
CString m_stringHierarchyName;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_HIERARCHYPROPPAGE_H__FB40246E_5DFB_11D2_9FC7_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,108 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : W3DView *
* *
* $Archive:: /Commando/Code/Tools/W3DView/LODDefs.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 3/03/99 7:26p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __LODDEFS_H
#define __LODDEFS_H
////////////////////////////////////////////////////////////////////////////
//
// Data types
//
typedef enum
{
TYPE_COMMANDO = 0,
TYPE_G,
TYPE_COUNT
} LOD_NAMING_TYPE;
////////////////////////////////////////////////////////////////////////////
//
// Inline functions
//
__inline bool Is_LOD_Name_Valid (LPCTSTR name, LOD_NAMING_TYPE &type)
{
bool retval = false;
// Does this name fit with the format expected?
LPCTSTR last_2_chars = name + (::lstrlen (name)-2);
if (((last_2_chars[0] == 'L') || (last_2_chars[0] == 'l')) &&
((last_2_chars[1] >= '0') && (last_2_chars[1] <= '9'))) {
type = TYPE_COMMANDO;
retval = true;
} else if ((last_2_chars[1] >= 'a' && last_2_chars[1] <= 'z') ||
(last_2_chars[1] >= 'A' && last_2_chars[1] <= 'Z')) {
type = TYPE_G;
retval = true;
}
return retval;
}
__inline bool Is_Model_Part_of_LOD (LPCTSTR name, LPCTSTR base, LOD_NAMING_TYPE &type)
{
// Assume failure
bool retval = false;
// Does the name start with the base?
if (::strstr (name, base) == name) {
// Get the remaining characters in the name (after the base)
LPCTSTR extension = name + ::lstrlen (base);
// What naming convention are we using?
if (type == TYPE_COMMANDO) {
if (((extension[0] == 'L') || (extension[0] == 'l')) &&
((extension[1] >= '0') && (extension[1] <= '9'))) {
retval = (extension[2] == 0);
}
} else if (type == TYPE_G) {
if ((extension[0] >= 'a' && extension[0] <= 'z') ||
(extension[0] >= 'A' && extension[0] <= 'Z')) {
retval = (extension[1] == 0);
}
}
}
// Return the true/false result ccde
return retval;
}
#endif //__LODDEFS_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,292 @@
/*
** 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/>.
*/
// MainFrm.h : interface of the CMainFrame class
//
/////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_MAINFRM_H__2BB39E2F_5D3A_11D2_9FC6_00104B791122__INCLUDED_)
#define AFX_MAINFRM_H__2BB39E2F_5D3A_11D2_9FC6_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#include "DataTreeView.H"
#include "Toolbar.H"
class CMainFrame : public CFrameWnd
{
protected: // create from serialization only
CMainFrame();
DECLARE_DYNCREATE(CMainFrame)
// Attributes
protected:
CSplitterWnd m_wndSplitter;
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMainFrame)
public:
virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo);
protected:
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
// Generated message map functions
protected:
//{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnObjectProperties();
afx_msg void OnUpdateObjectProperties(CCmdUI* pCmdUI);
afx_msg void OnLodGenerate();
afx_msg void OnActivateApp(BOOL bActive, HTASK hTask);
afx_msg void OnFileOpen();
afx_msg void OnAniSpeed();
afx_msg void OnAniStop();
afx_msg void OnAniStart();
afx_msg void OnAniPause();
afx_msg void OnCameraBack();
afx_msg void OnCameraBottom();
afx_msg void OnCameraFront();
afx_msg void OnCameraLeft();
afx_msg void OnCameraReset();
afx_msg void OnCameraRight();
afx_msg void OnCameraTop();
afx_msg void OnObjectRotateZ();
afx_msg void OnObjectRotateY();
afx_msg void OnObjectRotateX();
afx_msg void OnLightAmbient();
afx_msg void OnLightScene();
afx_msg void OnBackgroundColor();
afx_msg void OnBackgroundBMP();
afx_msg void OnSaveSettings();
afx_msg void OnLoadSettings();
afx_msg void OnLODSetSwitch();
afx_msg void OnLODSave();
afx_msg void OnLODSaveAll();
afx_msg void OnBackgroundObject();
afx_msg void OnUpdateViewAnimationBar(CCmdUI* pCmdUI);
afx_msg void OnUpdateViewObjectBar(CCmdUI* pCmdUI);
afx_msg void OnViewAnimationBar();
afx_msg void OnViewObjectBar();
afx_msg void OnAniStepFwd();
afx_msg void OnAniStepBkwd();
afx_msg void OnObjectReset();
afx_msg void OnCameraAllowRotateX();
afx_msg void OnCameraAllowRotateY();
afx_msg void OnCameraAllowRotateZ();
afx_msg void OnUpdateCameraAllowRotateX(CCmdUI* pCmdUI);
afx_msg void OnUpdateCameraAllowRotateY(CCmdUI* pCmdUI);
afx_msg void OnUpdateCameraAllowRotateZ(CCmdUI* pCmdUI);
afx_msg void OnUpdateObjectRotateX(CCmdUI* pCmdUI);
afx_msg void OnUpdateObjectRotateY(CCmdUI* pCmdUI);
afx_msg void OnUpdateObjectRotateZ(CCmdUI* pCmdUI);
afx_msg void OnDeviceChange();
afx_msg void OnViewFullscreen();
afx_msg void OnUpdateViewFullscreen(CCmdUI* pCmdUI);
afx_msg void OnWindowPosChanging(WINDOWPOS FAR* lpwndpos);
afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);
afx_msg void OnCreateEmitter();
afx_msg void OnEditEmitter();
afx_msg void OnUpdateEditEmitter(CCmdUI* pCmdUI);
afx_msg void OnSaveEmitter();
afx_msg void OnUpdateSaveEmitter(CCmdUI* pCmdUI);
afx_msg void OnBoneAutoAssign();
afx_msg void OnBoneManagement();
afx_msg void OnSaveAggregate();
afx_msg void OnCameraAnimate();
afx_msg void OnUpdateCameraAnimate(CCmdUI* pCmdUI);
afx_msg void OnUpdateLodSave(CCmdUI* pCmdUI);
afx_msg void OnUpdateSaveAggregate(CCmdUI* pCmdUI);
afx_msg void OnCameraResetOnLoad();
afx_msg void OnUpdateCameraResetOnLoad(CCmdUI* pCmdUI);
afx_msg void OnObjectRotateYBack();
afx_msg void OnObjectRotateZBack();
afx_msg void OnLightRotateY();
afx_msg void OnLightRotateYBack();
afx_msg void OnLightRotateZ();
afx_msg void OnLightRotateZBack();
afx_msg void OnDestroy();
afx_msg void OnDecLight();
afx_msg void OnIncLight();
afx_msg void OnDecAmbientLight();
afx_msg void OnIncAmbientLight();
afx_msg void OnMakeAggregate();
afx_msg void OnRenameAggregate();
afx_msg void OnCrashApp();
afx_msg void OnLODRecordScreenArea();
afx_msg void OnLODIncludeNull();
afx_msg void OnUpdateLODIncludeNull(CCmdUI* pCmdUI);
afx_msg void OnLodPrevLevel();
afx_msg void OnUpdateLodPrevLevel(CCmdUI* pCmdUI);
afx_msg void OnLodNextLevel();
afx_msg void OnUpdateLodNextLevel(CCmdUI* pCmdUI);
afx_msg void OnLodAutoswitch();
afx_msg void OnUpdateLodAutoswitch(CCmdUI* pCmdUI);
afx_msg void OnUpdateMakeMovie(CCmdUI* pCmdUI);
afx_msg void OnMakeMovie();
afx_msg void OnSaveScreenshot();
afx_msg void OnSlideshowDown();
afx_msg void OnSlideshowUp();
afx_msg void OnAdvancedAnim();
afx_msg void OnUpdateAdvancedAnim(CCmdUI* pCmdUI);
afx_msg void OnCameraSettings();
afx_msg void OnCopyScreenSize();
afx_msg void OnListMissingTextures();
afx_msg void OnCopyAssets();
afx_msg void OnUpdateCopyAssets(CCmdUI* pCmdUI);
afx_msg void OnLightingExpose();
afx_msg void OnUpdateLightingExpose(CCmdUI* pCmdUI);
afx_msg void OnTexturePath();
afx_msg void OnChangeResolution();
afx_msg void OnCreateSphere();
afx_msg void OnCreateRing();
afx_msg void OnUpdateEditPrimitive(CCmdUI* pCmdUI);
afx_msg void OnEditPrimitive();
afx_msg void OnExportPrimitive();
afx_msg void OnUpdateExportPrimitive(CCmdUI* pCmdUI);
afx_msg void OnKillSceneLight();
afx_msg void OnPrelitMultipass();
afx_msg void OnUpdatePrelitMultipass(CCmdUI* pCmdUI);
afx_msg void OnPrelitMultitex();
afx_msg void OnUpdatePrelitMultitex(CCmdUI* pCmdUI);
afx_msg void OnPrelitVertex();
afx_msg void OnUpdatePrelitVertex(CCmdUI* pCmdUI);
afx_msg void OnAddToLineup();
afx_msg void OnUpdateAddToLineup(CCmdUI* pCmdUI);
afx_msg void OnImportFacialAnims();
afx_msg void OnUpdateImportFacialAnims(CCmdUI* pCmdUI);
afx_msg void OnRestrictAnims();
afx_msg void OnUpdateRestrictAnims(CCmdUI* pCmdUI);
afx_msg void OnBindSubobjectLod();
afx_msg void OnUpdateBindSubobjectLod(CCmdUI* pCmdUI);
afx_msg void OnSetCameraDistance();
afx_msg void OnObjectAlternateMaterials();
afx_msg void OnCreateSoundObject();
afx_msg void OnEditSoundObject();
afx_msg void OnUpdateEditSoundObject(CCmdUI* pCmdUI);
afx_msg void OnExportSoundObj();
afx_msg void OnUpdateExportSoundObj(CCmdUI* pCmdUI);
afx_msg void OnWireframeMode();
afx_msg void OnUpdateWireframeMode(CCmdUI* pCmdUI);
afx_msg void OnUpdateBackgroundFog(CCmdUI* pCmdUI);
afx_msg void OnBackgroundFog();
afx_msg void OnUpdateScaleEmitter(CCmdUI* pCmdUI);
afx_msg void OnScaleEmitter();
afx_msg void OnUpdateToggleSorting(CCmdUI* pCmdUI);
afx_msg void OnToggleSorting();
afx_msg void OnCameraBonePosX();
afx_msg void OnUpdateCameraBonePosX(CCmdUI* pCmdUI);
afx_msg void OnViewPatchGapFill();
afx_msg void OnUpdateViewPatchGapFill(CCmdUI* pCmdUI);
afx_msg void OnViewSubdivision1();
afx_msg void OnUpdateViewSubdivision1(CCmdUI* pCmdUI);
afx_msg void OnViewSubdivision2();
afx_msg void OnUpdateViewSubdivision2(CCmdUI* pCmdUI);
afx_msg void OnViewSubdivision3();
afx_msg void OnUpdateViewSubdivision3(CCmdUI* pCmdUI);
afx_msg void OnViewSubdivision4();
afx_msg void OnUpdateViewSubdivision4(CCmdUI* pCmdUI);
afx_msg void OnViewSubdivision5();
afx_msg void OnUpdateViewSubdivision5(CCmdUI* pCmdUI);
afx_msg void OnViewSubdivision6();
afx_msg void OnUpdateViewSubdivision6(CCmdUI* pCmdUI);
afx_msg void OnViewSubdivision7();
afx_msg void OnUpdateViewSubdivision7(CCmdUI* pCmdUI);
afx_msg void OnViewSubdivision8();
afx_msg void OnUpdateViewSubdivision8(CCmdUI* pCmdUI);
afx_msg void OnMungeSortOnLoad();
afx_msg void OnUpdateMungeSortOnLoad(CCmdUI* pCmdUI);
afx_msg void OnEnableGammaCorrection();
afx_msg void OnUpdateEnableGammaCorrection(CCmdUI* pCmdUI);
afx_msg void OnSetGamma();
afx_msg void OnEditAnimatedSoundsOptions();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
//////////////////////////////////////////////////////////////////////
// Public methods
//////////////////////////////////////////////////////////////////////
CView *GetPane (int iRow, int iCol) const
{ return (CView *)m_wndSplitter.GetPane (iRow, iCol); }
void ShowObjectProperties (void);
void OnSelectionChanged (ASSET_TYPE newAssetType);
void Update_Frame_Time (DWORD milliseconds);
void UpdatePolygonCount (int iPolygons);
void Update_Particle_Count (int particles);
void UpdateCameraDistance (float cameraDistance);
void UpdateFrameCount (int iCurrentFrame, int iTotalFrames, float frame_rate);
void RestoreOriginalSize (void);
void Select_Device (bool show_dlg = true);
HMENU Get_Emitters_List_Menu (void) const { return m_hEmittersSubMenu; }
void Update_Emitters_List (void);
protected:
//////////////////////////////////////////////////////////////////////
// Protected methods
//////////////////////////////////////////////////////////////////////
void Restore_Window_State (void);
private:
//////////////////////////////////////////////////////////////////////
// Private member data
//////////////////////////////////////////////////////////////////////
ASSET_TYPE m_currentAssetType;
CFancyToolbar m_objectToolbar;
CFancyToolbar m_animationToolbar;
BOOL m_bShowAnimationBar;
RECT m_OrigRect;
HMENU m_hEmittersSubMenu;
BOOL m_bInitialized;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_MAINFRM_H__2BB39E2F_5D3A_11D2_9FC6_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,188 @@
/*
** 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/>.
*/
// MeshPropPage.cpp : implementation file
//
#include "stdafx.h"
#include "W3DView.h"
#include "MeshPropPage.h"
#include "RendObj.H"
#include "AssetMgr.H"
#include "Mesh.H"
#include "MeshMdl.H"
#include "w3d_file.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMeshPropPage property page
IMPLEMENT_DYNCREATE(CMeshPropPage, CPropertyPage)
////////////////////////////////////////////////////////////////
//
// CMeshPropPage
//
CMeshPropPage::CMeshPropPage (const CString &stringMeshName)
: CPropertyPage(CMeshPropPage::IDD)
{
//{{AFX_DATA_INIT(CMeshPropPage)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_stringMeshName = stringMeshName;
return ;
}
////////////////////////////////////////////////////////////////
//
// ~CMeshPropPage
//
CMeshPropPage::~CMeshPropPage (void)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
CMeshPropPage::DoDataExchange (CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMeshPropPage)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(CMeshPropPage, CPropertyPage)
//{{AFX_MSG_MAP(CMeshPropPage)
ON_WM_CLOSE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMeshPropPage message handlers
////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
CMeshPropPage::OnInitDialog (void)
{
// Allow the base class to process this message
CPropertyPage::OnInitDialog();
if (m_stringMeshName.GetLength () > 0)
{
// Get a pointer to the mesh object from the asset manager
MeshClass *pCMesh = (MeshClass *)WW3DAssetManager::Get_Instance()->Create_Render_Obj (m_stringMeshName);
ASSERT (pCMesh);
if (pCMesh)
{
CString stringDesc;
stringDesc.Format (IDS_MESH_PROP_DESC, m_stringMeshName);
// Put the description onto the dialog
SetDlgItemText (IDC_DESCRIPTION, stringDesc);
// Put the polygon count onto the dialog
SetDlgItemInt (IDC_POLYGON_COUNT, pCMesh->Get_Num_Polys ());
MeshModelClass *pmeshmodel = pCMesh->Get_Model ();
ASSERT (pmeshmodel);
if (pmeshmodel)
{
// Put the vertex count onto the dialog
SetDlgItemInt (IDC_VERTEX_COUNT, pmeshmodel->Get_Vertex_Count ());
}
// Put the user text onto the dialog
SetDlgItemText (IDC_USER_TEXT, pCMesh->Get_User_Text ());
// Get the flags for the mesh
DWORD dwFlags = pCMesh->Get_W3D_Flags ();
// Determine what type of mesh this is
if ((dwFlags & W3D_MESH_FLAG_COLLISION_BOX) == W3D_MESH_FLAG_COLLISION_BOX)
{
SendDlgItemMessage (IDC_MESH_TYPE_COLLISION_BOX, BM_SETCHECK, (WPARAM)TRUE);
}
else if ((dwFlags & W3D_MESH_FLAG_SKIN) == W3D_MESH_FLAG_SKIN)
{
SendDlgItemMessage (IDC_MESH_TYPE_SKIN, BM_SETCHECK, (WPARAM)TRUE);
}
else if ((dwFlags & W3D_MESH_FLAG_SHADOW) == W3D_MESH_FLAG_SHADOW)
{
SendDlgItemMessage (IDC_MESH_TYPE_SHADOW, BM_SETCHECK, (WPARAM)TRUE);
}
else
{
SendDlgItemMessage (IDC_MESH_TYPE_NORMAL, BM_SETCHECK, (WPARAM)TRUE);
}
// Is this collision type physical?
DWORD dwCollisionFlags = dwFlags & W3D_MESH_FLAG_COLLISION_TYPE_MASK;
if ((dwCollisionFlags & W3D_MESH_FLAG_COLLISION_TYPE_PHYSICAL) == W3D_MESH_FLAG_COLLISION_TYPE_PHYSICAL)
{
SendDlgItemMessage (IDC_COLLISION_TYPE_PHYSICAL, BM_SETCHECK, (WPARAM)TRUE);
}
// Is this collision type projectile?
if ((dwCollisionFlags & W3D_MESH_FLAG_COLLISION_TYPE_PROJECTILE) == W3D_MESH_FLAG_COLLISION_TYPE_PROJECTILE)
{
SendDlgItemMessage (IDC_COLLISION_TYPE_PROJECTILE, BM_SETCHECK, (WPARAM)TRUE);
}
// Is this a hidden mesh?
if ((dwFlags & W3D_MESH_FLAG_HIDDEN) == W3D_MESH_FLAG_HIDDEN)
{
SendDlgItemMessage (IDC_HIDDEN, BM_SETCHECK, (WPARAM)TRUE);
}
// Free the object
pCMesh->Release_Ref ();
pCMesh = NULL;
}
}
GetParent ()->GetDlgItem (IDOK)->ShowWindow (SW_HIDE);
GetParent ()->GetDlgItem (IDCANCEL)->SetWindowText ("Close");
return TRUE;
}
void CMeshPropPage::OnClose()
{
// TODO: Add your message handler code here and/or call default
CPropertyPage::OnClose();
return ;
}

View File

@@ -0,0 +1,74 @@
/*
** 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/>.
*/
#if !defined(AFX_MESHPROPPAGE_H__FB40246F_5DFB_11D2_9FC7_00104B791122__INCLUDED_)
#define AFX_MESHPROPPAGE_H__FB40246F_5DFB_11D2_9FC7_00104B791122__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// MeshPropPage.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CMeshPropPage dialog
class CMeshPropPage : public CPropertyPage
{
DECLARE_DYNCREATE(CMeshPropPage)
// Construction
public:
CMeshPropPage (const CString &stringMeshName);
~CMeshPropPage ();
// Dialog Data
//{{AFX_DATA(CMeshPropPage)
enum { IDD = IDD_PROP_PAGE_MESH };
// NOTE - ClassWizard will add data members here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(CMeshPropPage)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CMeshPropPage)
virtual BOOL OnInitDialog();
afx_msg void OnClose();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
CMeshPropPage () {};
CString m_stringMeshName;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_MESHPROPPAGE_H__FB40246F_5DFB_11D2_9FC7_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,120 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : W3DView *
* *
* $Archive:: /Commando/Code/Tools/W3DView/OpacitySettingsDialog.cpp $Modtime:: $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "stdafx.h"
#include "w3dview.h"
#include "OpacitySettingsDialog.h"
#include "ColorBar.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//
// OpacitySettingsDialogClass
//
/////////////////////////////////////////////////////////////////////////////
OpacitySettingsDialogClass::OpacitySettingsDialogClass (float opacity, CWnd *pParent)
: m_OpacityBar (NULL),
m_Opacity (opacity),
CDialog(OpacitySettingsDialogClass::IDD, pParent)
{
//{{AFX_DATA_INIT(OpacitySettingsDialogClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////////////////////
void
OpacitySettingsDialogClass::DoDataExchange (CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(OpacitySettingsDialogClass)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(OpacitySettingsDialogClass, CDialog)
//{{AFX_MSG_MAP(OpacitySettingsDialogClass)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL
OpacitySettingsDialogClass::OnInitDialog (void)
{
CDialog::OnInitDialog();
m_OpacityBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_OPACITY_BAR));
ASSERT (m_OpacityBar);
//
// Setup the opacity bar
//
m_OpacityBar->Set_Range (0, 1);
m_OpacityBar->Modify_Point (0, 0, 0, 0, 0);
m_OpacityBar->Insert_Point (1, 1, 255, 255, 255);
m_OpacityBar->Set_Selection_Pos (m_Opacity);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnOK
//
/////////////////////////////////////////////////////////////////////////////
void
OpacitySettingsDialogClass::OnOK (void)
{
m_Opacity = m_OpacityBar->Get_Selection_Pos ();
CDialog::OnOK ();
return ;
}

View File

@@ -0,0 +1,83 @@
/*
** 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/>.
*/
#if !defined(AFX_OPACITYSETTINGSDIALOG_H__52B0C804_0D48_11D3_A031_00104B791122__INCLUDED_)
#define AFX_OPACITYSETTINGSDIALOG_H__52B0C804_0D48_11D3_A031_00104B791122__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// OpacitySettingsDialog.h : header file
//
// Forward declarations
class ColorBarClass;
/////////////////////////////////////////////////////////////////////////////
// OpacitySettingsDialogClass dialog
class OpacitySettingsDialogClass : public CDialog
{
// Construction
public:
OpacitySettingsDialogClass(float opacity, CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(OpacitySettingsDialogClass)
enum { IDD = IDD_OPACITY };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(OpacitySettingsDialogClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(OpacitySettingsDialogClass)
virtual BOOL OnInitDialog();
virtual void OnOK();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////
float Get_Opacity (void) const { return m_Opacity; }
private:
////////////////////////////////////////////////////////////////
// Private member data
////////////////////////////////////////////////////////////////
ColorBarClass * m_OpacityBar;
float m_Opacity;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_OPACITYSETTINGSDIALOG_H__52B0C804_0D48_11D3_A031_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,340 @@
/*
** 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/>.
*/
// OpacityVectorDialog.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "OpacityVectorDialog.h"
#include "wwmath.h"
#include "vector3.h"
#include "sphereobj.h"
#include "ringobj.h"
#include "colorbar.h"
#include "euler.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//
// OpacityVectorDialogClass
//
/////////////////////////////////////////////////////////////////////////////
OpacityVectorDialogClass::OpacityVectorDialogClass(CWnd* pParent /*=NULL*/)
: m_OpacityBar (NULL),
m_RenderObj (NULL),
m_KeyIndex (0),
CDialog(OpacityVectorDialogClass::IDD, pParent)
{
//{{AFX_DATA_INIT(OpacityVectorDialogClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////////////////////
void
OpacityVectorDialogClass::DoDataExchange (CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(OpacityVectorDialogClass)
DDX_Control(pDX, IDC_SLIDER_Z, m_SliderZ);
DDX_Control(pDX, IDC_SLIDER_Y, m_SliderY);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(OpacityVectorDialogClass, CDialog)
//{{AFX_MSG_MAP(OpacityVectorDialogClass)
ON_WM_HSCROLL()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL
OpacityVectorDialogClass::OnInitDialog (void)
{
CDialog::OnInitDialog();
m_OpacityBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_OPACITY_BAR));
ASSERT (m_OpacityBar);
//
// Setup the opacity bar
//
m_OpacityBar->Set_Range (0, 10);
m_OpacityBar->Modify_Point (0, 0, 255, 255, 255);
m_OpacityBar->Insert_Point (1, 10, 0, 0, 0);
float value = ::atan (((m_Value.intensity / 10.0F) * 11.0F)) / DEG_TO_RAD (84.5) * 10.0F;
m_OpacityBar->Set_Selection_Pos (value);
//
// Setup the sliders
//
m_SliderY.SetRange (0, 179);
m_SliderZ.SetRange (0, 179);
float log_test = ::log (8.0F);
float log_test2 = ::_logb (log_test);
float log_test3 = ::exp (log_test);
//
// Convert the normalized vector to Euler angles...
//
/*Vector3 dir_vector (m_Value.X, m_Value.Y, m_Value.Z);
float x_rot = ::acos (dir_vector * Vector3 (1, 0, 0));
float y_rot = ::acos (dir_vector * Vector3 (0, 1, 0));
float z_rot = ::acos (dir_vector * Vector3 (0, 0, 1));
x_rot = RAD_TO_DEG (x_rot);
y_rot = RAD_TO_DEG (y_rot);
z_rot = RAD_TO_DEG (z_rot);
x_rot = WWMath::Wrap (x_rot, -180, 180);
y_rot = WWMath::Wrap (y_rot, -180, 180);
z_rot = WWMath::Wrap (z_rot, -180, 180);*/
/*Matrix3D rot_90 (1);
rot_90.Rotate_Z (DEG_TO_RADF (90));
Vector3 x_axis (m_Value.X, m_Value.Y, m_Value.Z);
x_axis.Normalize ();
Vector3 y_axis = rot_90 * x_axis;
Vector3 z_axis;
Vector3::Cross_Product (x_axis, y_axis, &z_axis);
Matrix3D orientation (x_axis, y_axis, z_axis, Vector3 (0, 0, 0));
EulerAnglesClass euler_angle (orientation, EulerOrderXYZr);
float x_rot = RAD_TO_DEG (euler_angle.Get_Angle (0));
float y_rot = RAD_TO_DEG (euler_angle.Get_Angle (1));
float z_rot = RAD_TO_DEG (euler_angle.Get_Angle (2));
x_rot = WWMath::Wrap (x_rot, 0, 360);
y_rot = WWMath::Wrap (y_rot, 0, 360);
z_rot = WWMath::Wrap (z_rot, 0, 360);*/
Matrix3D rotation = Build_Matrix3D (m_Value.angle);
//Vector3 point = m_Value.angle.Rotate_Vector (Vector3 (1, 0, 0));
EulerAnglesClass euler_angle (rotation, EulerOrderXYZr);
//float x_rot = RAD_TO_DEG (euler_angle.Get_Angle (0));
float y_rot = RAD_TO_DEG (euler_angle.Get_Angle (1));
float z_rot = RAD_TO_DEG (euler_angle.Get_Angle (2));
//float y_rot = RAD_TO_DEG (rotation.Get_Y_Rotation ());
//float z_rot = RAD_TO_DEG (rotation.Get_Z_Rotation ());
y_rot = WWMath::Wrap (y_rot, 0, 360);
z_rot = WWMath::Wrap (z_rot, 0, 360);
m_SliderY.SetPos ((int)y_rot);
m_SliderZ.SetPos ((int)z_rot);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnOK
//
/////////////////////////////////////////////////////////////////////////////
void
OpacityVectorDialogClass::OnOK (void)
{
m_Value = Update_Value ();
CDialog::OnOK ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Update_Object
//
/////////////////////////////////////////////////////////////////////////////
void
OpacityVectorDialogClass::Update_Object (void)
{
Update_Object (Update_Value ());
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Update_Value
//
/////////////////////////////////////////////////////////////////////////////
AlphaVectorStruct
OpacityVectorDialogClass::Update_Value (void)
{
AlphaVectorStruct value;
int y_pos = m_SliderY.GetPos ();
int z_pos = m_SliderZ.GetPos ();
//float x_rot = DEG_TO_RADF ((float)x_pos);
float y_rot = DEG_TO_RADF ((float)y_pos);
float z_rot = DEG_TO_RADF ((float)z_pos);
Matrix3 rot_mat (true);
//rot_mat.Rotate_X (x_rot);
rot_mat.Rotate_Y (y_rot);
rot_mat.Rotate_Z (z_rot);
value.angle = ::Build_Quaternion (rot_mat);
float percent = ::tan ((m_OpacityBar->Get_Selection_Pos () / 10.0F) * DEG_TO_RAD (84.5)) / 11.0F;
percent = min (1.0F, percent);
percent = max (0.0F, percent);
value.intensity = 10.0F * percent;
return value;
}
/////////////////////////////////////////////////////////////////////////////
//
// Update_Object
//
/////////////////////////////////////////////////////////////////////////////
void
OpacityVectorDialogClass::Update_Object (const AlphaVectorStruct &value)
{
if (m_RenderObj != NULL) {
//
// Determine what type of object this is
//
switch (m_RenderObj->Class_ID ())
{
case RenderObjClass::CLASSID_SPHERE:
{
//
// Update the key with the new vector
//
SphereVectorChannelClass &vector_channel = ((SphereRenderObjClass *)m_RenderObj)->Get_Vector_Channel ();
vector_channel.Set_Key_Value (m_KeyIndex, value);
//
// Force the animation to restart
//
((SphereRenderObjClass *)m_RenderObj)->Restart_Animation ();
}
break;
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnCancel
//
/////////////////////////////////////////////////////////////////////////////
void
OpacityVectorDialogClass::OnCancel (void)
{
Update_Object (m_Value);
CDialog::OnCancel ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnHScroll
//
/////////////////////////////////////////////////////////////////////////////
void
OpacityVectorDialogClass::OnHScroll
(
UINT nSBCode,
UINT nPos,
CScrollBar * pScrollBar
)
{
//
// Update the object
//
Update_Object ();
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
return ;
}
/////////////////////////////////////////////////////////////
//
// OnNotify
//
/////////////////////////////////////////////////////////////
BOOL
OpacityVectorDialogClass::OnNotify
(
WPARAM wParam,
LPARAM lParam,
LRESULT *pResult
)
{
CBR_NMHDR *color_bar_hdr = (CBR_NMHDR *)lParam;
//
// Which control sent the notification?
//
switch (color_bar_hdr->hdr.idFrom)
{
case IDC_OPACITY_BAR:
{
//
// Update the object
//
if (color_bar_hdr->hdr.code == CBRN_SEL_CHANGED) {
Update_Object ();
}
}
break;
}
return CDialog::OnNotify (wParam, lParam, pResult);
}

View File

@@ -0,0 +1,105 @@
/*
** 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/>.
*/
#if !defined(AFX_OPACITYVECTORDIALOG_H__E86BBE8C_F527_11D3_A08F_00104B791122__INCLUDED_)
#define AFX_OPACITYVECTORDIALOG_H__E86BBE8C_F527_11D3_A08F_00104B791122__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "resource.h"
#include "sphereobj.h"
// Forward declarations
class ColorBarClass;
class RenderObjClass;
/////////////////////////////////////////////////////////////////////////////
//
// OpacityVectorDialogClass
//
/////////////////////////////////////////////////////////////////////////////
class OpacityVectorDialogClass : public CDialog
{
// Construction
public:
OpacityVectorDialogClass(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(OpacityVectorDialogClass)
enum { IDD = IDD_OPACITY_VECTOR };
CSliderCtrl m_SliderZ;
CSliderCtrl m_SliderY;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(OpacityVectorDialogClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(OpacityVectorDialogClass)
virtual BOOL OnInitDialog();
virtual void OnOK();
virtual void OnCancel();
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////
void Set_Render_Obj (RenderObjClass *render_obj) { m_RenderObj = render_obj; }
void Set_Vector (const AlphaVectorStruct &def_vector) { m_Value = def_vector; }
const AlphaVectorStruct & Get_Vector (void) const { return m_Value; }
void Set_Key_Index (int index) { m_KeyIndex = index; }
private:
////////////////////////////////////////////////////////////////
// Protected methods
////////////////////////////////////////////////////////////////
void Update_Object (const AlphaVectorStruct &value);
void Update_Object (void);
AlphaVectorStruct Update_Value (void);
private:
////////////////////////////////////////////////////////////////
// Private member data
////////////////////////////////////////////////////////////////
ColorBarClass * m_OpacityBar;
RenderObjClass * m_RenderObj;
AlphaVectorStruct m_Value;
int m_KeyIndex;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_OPACITYVECTORDIALOG_H__E86BBE8C_F527_11D3_A08F_00104B791122__INCLUDED_)

View File

@@ -0,0 +1,93 @@
/*
** 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/>.
*/
// ParticleBlurTimeKeyDialog.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "ParticleBlurTimeKeyDialog.h"
#include "Utils.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// ParticleBlurTimeKeyDialogClass dialog
ParticleBlurTimeKeyDialogClass::ParticleBlurTimeKeyDialogClass(float blur_time, CWnd* pParent) :
CDialog(ParticleBlurTimeKeyDialogClass::IDD, pParent),
m_BlurTime(blur_time)
{
//{{AFX_DATA_INIT(ParticleBlurTimeKeyDialogClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void ParticleBlurTimeKeyDialogClass::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(ParticleBlurTimeKeyDialogClass)
DDX_Control(pDX, IDC_BLUR_TIME_SPIN, m_BlurTimeSpin);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(ParticleBlurTimeKeyDialogClass, CDialog)
//{{AFX_MSG_MAP(ParticleBlurTimeKeyDialogClass)
ON_BN_CLICKED(IDOK2, OnOk2)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// ParticleBlurTimeKeyDialogClass message handlers
BOOL ParticleBlurTimeKeyDialogClass::OnInitDialog()
{
CDialog::OnInitDialog();
Initialize_Spinner (m_BlurTimeSpin, m_BlurTime, -1024, 1024);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
BOOL ParticleBlurTimeKeyDialogClass::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
//
// Update the spinner control if necessary
//
NMHDR *pheader = (NMHDR *)lParam;
if ((pheader != NULL) && (pheader->code == UDN_DELTAPOS)) {
LPNMUPDOWN pupdown = (LPNMUPDOWN)lParam;
::Update_Spinner_Buddy (pheader->hwndFrom, pupdown->iDelta);
}
return CDialog::OnNotify(wParam, lParam, pResult);
}
void ParticleBlurTimeKeyDialogClass::OnOk2()
{
m_BlurTime = GetDlgItemFloat(m_hWnd,IDC_BLUR_TIME_EDIT);
CDialog::OnOK();
}

View File

@@ -0,0 +1,80 @@
/*
** 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/>.
*/
#if !defined(AFX_PARTICLEBLURTIMEKEYDIALOG_H__FCCD7E5F_E09A_450E_A1A4_0E401CC00C3B__INCLUDED_)
#define AFX_PARTICLEBLURTIMEKEYDIALOG_H__FCCD7E5F_E09A_450E_A1A4_0E401CC00C3B__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ParticleBlurTimeKeyDialog.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// ParticleBlurTimeKeyDialogClass dialog
class ParticleBlurTimeKeyDialogClass : public CDialog
{
// Construction
public:
ParticleBlurTimeKeyDialogClass(float blur_time, CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(ParticleBlurTimeKeyDialogClass)
enum { IDD = IDD_PARTICLE_BLUR_TIME_KEY };
CSpinButtonCtrl m_BlurTimeSpin;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(ParticleBlurTimeKeyDialogClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(ParticleBlurTimeKeyDialogClass)
virtual BOOL OnInitDialog();
afx_msg void OnOk2();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////////
// Public methods
/////////////////////////////////////////////////////////////
float Get_Blur_Time (void) const { return m_BlurTime; }
private:
/////////////////////////////////////////////////////////////
// Private member data
/////////////////////////////////////////////////////////////
float m_BlurTime;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_PARTICLEBLURTIMEKEYDIALOG_H__FCCD7E5F_E09A_450E_A1A4_0E401CC00C3B__INCLUDED_)

View File

@@ -0,0 +1,94 @@
/*
** 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/>.
*/
// ParticleFrameKeyDialog.cpp : implementation file
//
#include "stdafx.h"
#include "w3dview.h"
#include "ParticleFrameKeyDialog.h"
#include "Utils.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// ParticleFrameKeyDialogClass dialog
ParticleFrameKeyDialogClass::ParticleFrameKeyDialogClass(float frame,CWnd* pParent /*=NULL*/) :
CDialog(ParticleFrameKeyDialogClass::IDD, pParent),
m_Frame(frame)
{
//{{AFX_DATA_INIT(ParticleFrameKeyDialogClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void ParticleFrameKeyDialogClass::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(ParticleFrameKeyDialogClass)
DDX_Control(pDX, IDC_FRAME_SPIN, m_FrameSpin);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(ParticleFrameKeyDialogClass, CDialog)
//{{AFX_MSG_MAP(ParticleFrameKeyDialogClass)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// ParticleFrameKeyDialogClass message handlers
BOOL ParticleFrameKeyDialogClass::OnInitDialog()
{
CDialog::OnInitDialog();
Initialize_Spinner (m_FrameSpin, m_Frame, -1024, 1024);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void ParticleFrameKeyDialogClass::OnOK()
{
m_Frame = GetDlgItemFloat(m_hWnd,IDC_FRAME_EDIT);
CDialog::OnOK();
}
BOOL ParticleFrameKeyDialogClass::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
//
// Update the spinner control if necessary
//
NMHDR *pheader = (NMHDR *)lParam;
if ((pheader != NULL) && (pheader->code == UDN_DELTAPOS)) {
LPNMUPDOWN pupdown = (LPNMUPDOWN)lParam;
::Update_Spinner_Buddy (pheader->hwndFrom, pupdown->iDelta);
}
return CDialog::OnNotify(wParam, lParam, pResult);
}

View File

@@ -0,0 +1,81 @@
/*
** 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/>.
*/
#if !defined(AFX_PARTICLEFRAMEKEYDIALOG_H__43470F6A_86E2_44CF_8ED9_EE9B74D35908__INCLUDED_)
#define AFX_PARTICLEFRAMEKEYDIALOG_H__43470F6A_86E2_44CF_8ED9_EE9B74D35908__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ParticleFrameKeyDialog.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// ParticleFrameKeyDialogClass dialog
class ParticleFrameKeyDialogClass : public CDialog
{
// Construction
public:
ParticleFrameKeyDialogClass(float frame,CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(ParticleFrameKeyDialogClass)
enum { IDD = IDD_PARTICLE_FRAME_KEY };
CSpinButtonCtrl m_FrameSpin;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(ParticleFrameKeyDialogClass)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(ParticleFrameKeyDialogClass)
virtual BOOL OnInitDialog();
virtual void OnOK();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
/////////////////////////////////////////////////////////////
// Public methods
/////////////////////////////////////////////////////////////
float Get_Frame (void) const { return m_Frame; }
private:
/////////////////////////////////////////////////////////////
// Private member data
/////////////////////////////////////////////////////////////
float m_Frame;
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_PARTICLEFRAMEKEYDIALOG_H__43470F6A_86E2_44CF_8ED9_EE9B74D35908__INCLUDED_)

Some files were not shown because too many files have changed in this diff Show More