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