| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563 |
- /*
- ** 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/>.
- */
- // SceneLightDialog.cpp : implementation file
- //
- #include "stdafx.h"
- #include "W3DView.h"
- #include "SceneLightDialog.h"
- #include "Utils.H"
- #include "MainFrm.H"
- #include "W3DViewDoc.H"
- #include "Scene.H"
- #include "Light.H"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- //////////////////////////////////////////////////////////////
- //
- // CSceneLightDialog
- //
- CSceneLightDialog::CSceneLightDialog(CWnd* pParent /*=NULL*/)
- : m_CurrentChannel (DIFFUSE),
- m_InitialStartAtten (0),
- m_InitialEndAtten (0),
- m_InitialDistance (0),
- m_InitialIntensity (0),
- m_InitialAttenOn (TRUE),
- CDialog(CSceneLightDialog::IDD, pParent)
- {
- //{{AFX_DATA_INIT(CSceneLightDialog)
- //}}AFX_DATA_INIT
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // DoDataExchange
- //
- void
- CSceneLightDialog::DoDataExchange (CDataExchange* pDX)
- {
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CSceneLightDialog)
- DDX_Control(pDX, IDC_START_ATTENUATION_SPIN, m_StartAttenSpin);
- DDX_Control(pDX, IDC_END_ATTENUATION_SPIN, m_EndAttenSpin);
- DDX_Control(pDX, IDC_DISTANCE_SPIN, m_DistanceSpin);
- DDX_Control(pDX, IDC_INTENSITY_SLIDER, m_IntensitySlider);
- 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(CSceneLightDialog, CDialog)
- //{{AFX_MSG_MAP(CSceneLightDialog)
- ON_WM_HSCROLL()
- ON_BN_CLICKED(IDC_GRAYSCALE_CHECK, OnGrayscaleCheck)
- ON_BN_CLICKED(IDC_CHANNEL_BOTH_RADIO, OnChannelBothRadio)
- ON_BN_CLICKED(IDC_CHANNEL_DIFFUSE_RADIO, OnChannelDiffuseRadio)
- ON_BN_CLICKED(IDC_CHANNEL_SPECULAR_RADIO, OnChannelSpecularRadio)
- ON_BN_CLICKED(IDC_ATTENUATION_CHECK, OnAttenuationCheck)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- //////////////////////////////////////////////////////////////
- //
- // OnInitDialog
- //
- BOOL
- CSceneLightDialog::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);
- // Set the initial ranges for the color sliders
- 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 diffuse;
- Vector3 specular;
- pCDoc->GetSceneLight ()->Get_Diffuse (&diffuse);
- pCDoc->GetSceneLight ()->Get_Specular (&specular);
- // Remember these initial settings so we can restore them
- // if the user cancels
- m_InitialRedDiffuse = int(diffuse.X * 100.00F);
- m_InitialGreenDiffuse = int(diffuse.Y * 100.00F);
- m_InitialBlueDiffuse = int(diffuse.Z * 100.00F);
- m_InitialRedSpecular = int(specular.X * 100.00F);
- m_InitialGreenSpecular = int(specular.Y * 100.00F);
- m_InitialBlueSpecular = int(specular.Z * 100.00F);
- Set_Color_Control_State (diffuse);
- // Get the light's attenuation
- double start = 0;
- double end = 0;
- pCDoc->GetSceneLight ()->Get_Far_Attenuation_Range (start, end);
- BOOL atten_on = pCDoc->GetSceneLight ()->Get_Flag (LightClass::FAR_ATTENUATION);
- SendDlgItemMessage (IDC_ATTENUATION_CHECK, BM_SETCHECK, (WPARAM)atten_on);
- // Get the light's intensity
- float intensity = pCDoc->GetSceneLight ()->Get_Intensity ();
- // Attempt to calculate the light's distance from the object
- float distance = 0;
- if (pCDoc->GetDisplayedObject () != NULL) {
-
- // Get the position of the light and the displayed object
- Vector3 light_pos = pCDoc->GetSceneLight ()->Get_Position ();
- Vector3 obj_pos = pCDoc->GetDisplayedObject ()->Get_Position ();
- // Compute the distance of the 2 vectors
- distance = (light_pos - obj_pos).Length ();
- }
- // Set-up the edit controls
- ::SetDlgItemFloat (m_hWnd, IDC_START_ATTENUATION_EDIT, start);
- ::SetDlgItemFloat (m_hWnd, IDC_END_ATTENUATION_EDIT, end);
- ::SetDlgItemFloat (m_hWnd, IDC_DISTANCE_EDIT, distance);
-
- // Set-up the spin controls
- m_DistanceSpin.SetRange (0, 1000000L);
- m_DistanceSpin.SetPos ((distance * 100));
- m_StartAttenSpin.SetRange (0, 1000000L);
- m_StartAttenSpin.SetPos ((start * 100));
- m_EndAttenSpin.SetRange (0, 1000000L);
- m_EndAttenSpin.SetPos ((end * 100));
- // Setup the slider control
- m_IntensitySlider.SetRange (0, 100);
- m_IntensitySlider.SetPos (intensity * 100.0F);
- // Record the initial settings so we can restore them on cancel
- m_InitialStartAtten = start;
- m_InitialEndAtten = end;
- m_InitialDistance = distance;
- m_InitialIntensity = intensity;
- m_InitialAttenOn = atten_on;
- }
- // Check the 'Diffuse' channel by default
- SendDlgItemMessage (IDC_CHANNEL_DIFFUSE_RADIO, BM_SETCHECK, (WPARAM)TRUE);
- Update_Attenuation_Controls ();
- return TRUE;
- }
- //////////////////////////////////////////////////////////////
- //
- // OnHScroll
- //
- void
- CSceneLightDialog::OnHScroll
- (
- UINT nSBCode,
- UINT nPos,
- CScrollBar* pScrollBar
- )
- {
- // Did the intensity slider send this message or did the color sliders?
- if (pScrollBar == GetDlgItem (IDC_INTENSITY_SLIDER)) {
-
- // Update the light's intensity settings
- float intensity = ((float)m_IntensitySlider.GetPos ()) / 100.0F;
- ::GetCurrentDocument ()->GetSceneLight ()->Set_Intensity (intensity);
- } else {
- // Are the 3 colors locked together?
- if (SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_GETCHECK)) {
-
- // Which color sent this message?
- int iCurrentPos = 0;
- if (pScrollBar == GetDlgItem (IDC_SLIDER_RED)) {
- // Use this color as default
- iCurrentPos = m_redSlider.GetPos ();
- }
- else if (pScrollBar == GetDlgItem (IDC_SLIDER_GREEN)) {
- // Use this color as default
- iCurrentPos = m_greenSlider.GetPos ();
- }
- else {
- // Use this color as default
- iCurrentPos = m_blueSlider.GetPos ();
- }
- // Make all the sliders the same pos
- m_redSlider.SetPos (iCurrentPos);
- m_greenSlider.SetPos (iCurrentPos);
- m_blueSlider.SetPos (iCurrentPos);
- }
- // Update the light to reflect the new settings
- Vector3 color;
- color.X = float(m_redSlider.GetPos ()) / 100.00F;
- color.Y = float(m_greenSlider.GetPos ()) / 100.00F;
- color.Z = float(m_blueSlider.GetPos ()) / 100.00F;
- Update_Light (color);
- }
- // Allow the base class to process this message
- CDialog::OnHScroll (nSBCode, nPos, pScrollBar);
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // OnCancel
- //
- void
- CSceneLightDialog::OnCancel (void)
- {
- // Get a pointer to the document so we can change the scene light's
- // settings and position
- CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
- if (pCDoc && pCDoc->GetScene ()) {
- Vector3 diffuse;
- diffuse.X = float(m_InitialRedDiffuse) / 100.00F;
- diffuse.Y = float(m_InitialGreenDiffuse) / 100.00F;
- diffuse.Z = float(m_InitialBlueDiffuse) / 100.00F;
- Vector3 specular;
- specular.X = float(m_InitialRedSpecular) / 100.00F;
- specular.Y = float(m_InitialGreenSpecular) / 100.00F;
- specular.Z = float(m_InitialBlueSpecular) / 100.00F;
- // Restore the scene light's color
- pCDoc->GetSceneLight ()->Set_Diffuse (diffuse);
- pCDoc->GetSceneLight ()->Set_Specular (specular);
- // Restore the intensity, attenuation, and distance settings
- pCDoc->GetSceneLight ()->Set_Intensity (m_InitialIntensity);
- pCDoc->GetSceneLight ()->Set_Far_Attenuation_Range (m_InitialStartAtten, m_InitialEndAtten);
- pCDoc->GetSceneLight ()->Set_Flag (LightClass::FAR_ATTENUATION, (m_InitialAttenOn == TRUE));
- Update_Distance (m_InitialDistance);
- }
- // Allow the base class to process this message
- CDialog::OnCancel ();
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // WindowProc
- //
- LRESULT
- CSceneLightDialog::WindowProc
- (
- UINT message,
- WPARAM wParam,
- LPARAM lParam
- )
- {
- switch (message)
- {
- case WM_NOTIFY:
- {
- // Did this notification come from a spin control?
- NMHDR *pheader = (NMHDR *)lParam;
- if ((pheader != NULL) && (pheader->code == UDN_DELTAPOS)) {
- LPNMUPDOWN pupdown = (LPNMUPDOWN)lParam;
-
- // Get the buddy window associated with this spin control
- HWND hbuddy_wnd = (HWND)SendDlgItemMessage ((int)wParam, UDM_GETBUDDY);
- if (::IsWindow (hbuddy_wnd)) {
- // Get the current value, increment it, and put it back into the control
- float value = ::GetWindowFloat (hbuddy_wnd);
- value += (((float)(pupdown->iDelta)) / 100.0F);
- ::SetWindowFloat (hbuddy_wnd, value);
- // Force update the light
- Update_Distance (::GetDlgItemFloat (m_hWnd, IDC_DISTANCE_EDIT));
- Update_Attenuation ();
- }
- }
- }
- break;
- case WM_COMMAND:
- {
- if (HIWORD (wParam) == EN_KILLFOCUS) {
- switch (LOWORD (wParam))
- {
- case IDC_DISTANCE_EDIT:
- {
- Update_Distance (::GetDlgItemFloat (m_hWnd, IDC_DISTANCE_EDIT));
- }
- break;
-
- case IDC_START_ATTENUATION_EDIT:
- case IDC_END_ATTENUATION_EDIT:
- {
- Update_Attenuation ();
- }
- break;
- }
- }
- }
- break;
- case 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);
- }
- break;
- }
-
- // Allow the base class to process this message
- return CDialog::WindowProc (message, wParam, lParam);
- }
- //////////////////////////////////////////////////////////////
- //
- // OnGrayscaleCheck
- //
- void
- CSceneLightDialog::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 color;
- color.X = float(m_redSlider.GetPos ()) / 100.00F;
- color.Y = float(m_greenSlider.GetPos ()) / 100.00F;
- color.Z = float(m_blueSlider.GetPos ()) / 100.00F;
- Update_Light (color);
- }
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // OnChannelBothRadio
- //
- void
- CSceneLightDialog::OnChannelBothRadio (void)
- {
- m_CurrentChannel = BOTH;
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // OnChannelDiffuseRadio
- //
- void
- CSceneLightDialog::OnChannelDiffuseRadio (void)
- {
- // Reset the UI to reflect the current diffuse color
- Vector3 color;
- ::GetCurrentDocument ()->GetSceneLight ()->Get_Diffuse (&color);
- Set_Color_Control_State (color);
- m_CurrentChannel = DIFFUSE;
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // OnChannelSpecularRadio
- //
- void
- CSceneLightDialog::OnChannelSpecularRadio (void)
- {
- // Reset the UI to reflect the current specular color
- Vector3 color;
- ::GetCurrentDocument ()->GetSceneLight ()->Get_Specular (&color);
- Set_Color_Control_State (color);
- m_CurrentChannel = SPECULAR;
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // Update_Light
- //
- void
- CSceneLightDialog::Update_Light (const Vector3 &color)
- {
- // Get a pointer to the document so we can change the scene light's
- // settings
- CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
- if (pCDoc && pCDoc->GetScene ()) {
- // Update the diffuse setting of the scene light if necessary
- if (m_CurrentChannel & DIFFUSE) {
- pCDoc->GetSceneLight ()->Set_Diffuse (color);
- }
- // Update the specular setting of the scene light if necessary
- if (m_CurrentChannel & SPECULAR) {
- pCDoc->GetSceneLight ()->Set_Specular (color);
- }
- }
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // Set_Color_Control_State
- //
- void
- CSceneLightDialog::Set_Color_Control_State (const Vector3 &color)
- {
- // Should we 'lock' the color sliders together?
- if ((color.X == color.Y) &&
- (color.X == color.Z)) {
- SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_SETCHECK, (WPARAM)TRUE);
- } else {
- SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_SETCHECK, (WPARAM)FALSE);
- }
- // Set the color slider positions
- m_redSlider.SetPos (int(color.X * 100.0F));
- m_greenSlider.SetPos (int(color.Y * 100.0F));
- m_blueSlider.SetPos (int(color.Z * 100.0F));
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // Update_Attenuation
- //
- void
- CSceneLightDialog::Update_Attenuation (void)
- {
- // Get a pointer to the document so we can change the scene light's
- // settings
- CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
- if (pCDoc && pCDoc->GetScene ()) {
- // Update the attenuation settings
- float start = ::GetDlgItemFloat (m_hWnd, IDC_START_ATTENUATION_EDIT);
- float end = ::GetDlgItemFloat (m_hWnd, IDC_END_ATTENUATION_EDIT);
- pCDoc->GetSceneLight ()->Set_Far_Attenuation_Range (start, end);
- }
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // Update_Distance
- //
- void
- CSceneLightDialog::Update_Distance (float distance)
- {
- // Get a pointer to the document so we can change the scene light's
- // settings
- CW3DViewDoc *pCDoc = ::GetCurrentDocument ();
- if (pCDoc && pCDoc->GetScene ()) {
- // Get the position of the displayed object
- Vector3 obj_pos (0,0,0);
- if (pCDoc->GetDisplayedObject ()) {
- obj_pos = pCDoc->GetDisplayedObject ()->Get_Position ();
- }
- // Get the position of the light and the displayed object
- Vector3 light_pos = pCDoc->GetSceneLight ()->Get_Position ();
- Vector3 new_pos = (light_pos - obj_pos);
- new_pos.Normalize ();
- new_pos = new_pos * distance;
- // Update the attenuation settings
- pCDoc->GetSceneLight ()->Set_Position (new_pos);
- }
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // Update_Attenuation_Controls
- //
- void
- CSceneLightDialog::Update_Attenuation_Controls (void)
- {
- // Enable or disable the attenuation controls based on the group's checkstate
- BOOL enable = (SendDlgItemMessage (IDC_ATTENUATION_CHECK, BM_GETCHECK) == 1);
- ::EnableWindow (::GetDlgItem (m_hWnd, IDC_START_ATTENUATION_EDIT), enable);
- ::EnableWindow (::GetDlgItem (m_hWnd, IDC_START_ATTENUATION_SPIN), enable);
- ::EnableWindow (::GetDlgItem (m_hWnd, IDC_END_ATTENUATION_EDIT), enable);
- ::EnableWindow (::GetDlgItem (m_hWnd, IDC_END_ATTENUATION_SPIN), enable);
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // OnAttenuationCheck
- //
- void
- CSceneLightDialog::OnAttenuationCheck (void)
- {
- // Update the scene light to reflect the new setting
- bool enable = (SendDlgItemMessage (IDC_ATTENUATION_CHECK, BM_GETCHECK) == 1);
- CW3DViewDoc *pdoc = ::GetCurrentDocument ();
- pdoc->GetSceneLight ()->Set_Flag (LightClass::FAR_ATTENUATION, enable);
- // Update the dialog controls to reflect the new setting
- Update_Attenuation_Controls ();
- return ;
- }
|