/* ** 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 . */ // ColorPickerDialogClass.cpp : implementation file // #include "StdAfx.H" #include "ColorPickerDialogClass.H" #include "ColorBar.H" #include "ColorPicker.H" #include "WWCtrl.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; extern "C" { 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; } } extern "C" { 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; } } extern "C" { 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; } } extern "C" { 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; } } extern "C" { 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; } } extern "C" { 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 ; }