868 lines
23 KiB
C++
868 lines
23 KiB
C++
/*
|
|
** Command & Conquer Renegade(tm)
|
|
** Copyright 2025 Electronic Arts Inc.
|
|
**
|
|
** This program is free software: you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
// ParameterInheritanceDialog.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "leveledit.h"
|
|
#include "ParameterInheritanceDialog.h"
|
|
#include "definition.h"
|
|
#include "presetmgr.h"
|
|
#include "preset.h"
|
|
#include "parameter.h"
|
|
#include "definitionparameter.h"
|
|
#include "combatchunkid.h"
|
|
#include "soldier.h"
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Local macros
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
#ifndef ListView_SetCheckState
|
|
#define ListView_SetCheckState(hwndLV, i, fCheck) \
|
|
ListView_SetItemState(hwndLV, i, \
|
|
INDEXTOSTATEIMAGEMASK((fCheck)+1), LVIS_STATEIMAGEMASK)
|
|
#endif
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Local constants
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
static const int ICON_GAME_SETTING = 0;
|
|
static const int ICON_PHYS_SETTING = 1;
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Local prototypes
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
static LRESULT CALLBACK CheckBoxSubclassProc (HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
|
|
static BOOL TreeView_SetCheckState (HWND hwndTreeView, HTREEITEM hItem, BOOL fCheck);
|
|
static bool Find_Parameter_In_List (DynamicVectorClass<DefinitionParameterClass *> ¶meter_list, ParameterClass *parameter);
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ParameterInheritanceDialogClass
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ParameterInheritanceDialogClass::ParameterInheritanceDialogClass(CWnd* pParent /*=NULL*/)
|
|
: m_Preset (NULL),
|
|
CDialog(ParameterInheritanceDialogClass::IDD, pParent)
|
|
{
|
|
//{{AFX_DATA_INIT(ParameterInheritanceDialogClass)
|
|
// NOTE: the ClassWizard will add member initialization here
|
|
//}}AFX_DATA_INIT
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DoDataExchange
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ParameterInheritanceDialogClass::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(ParameterInheritanceDialogClass)
|
|
DDX_Control(pDX, IDC_PARAMETER_LIST, m_ListCtrl);
|
|
DDX_Control(pDX, IDC_CHILD_TREE, m_TreeCtrl);
|
|
//}}AFX_DATA_MAP
|
|
return ;
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(ParameterInheritanceDialogClass, CDialog)
|
|
//{{AFX_MSG_MAP(ParameterInheritanceDialogClass)
|
|
ON_WM_DESTROY()
|
|
ON_NOTIFY(LVN_DELETEITEM, IDC_PARAMETER_LIST, OnDeleteitemParameterList)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnInitDialog
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL
|
|
ParameterInheritanceDialogClass::OnInitDialog (void)
|
|
{
|
|
CDialog::OnInitDialog ();
|
|
|
|
//
|
|
// Configure the list control
|
|
//
|
|
CRect rect;
|
|
m_ListCtrl.GetClientRect (&rect);
|
|
m_ListCtrl.InsertColumn (0, "Name");
|
|
m_ListCtrl.SetColumnWidth (0, rect.Width () - ::GetSystemMetrics (SM_CXVSCROLL) - 1);
|
|
|
|
//
|
|
// Create a small imagelist for the list control to use
|
|
//
|
|
CImageList *imagelist = new CImageList;
|
|
imagelist->Create (16, 16, ILC_COLOR | ILC_MASK, 2, 0);
|
|
HICON icon1 = (HICON)::LoadImage (::AfxGetInstanceHandle (), MAKEINTRESOURCE(IDI_PARAM), IMAGE_ICON, 16, 16, LR_SHARED | LR_DEFAULTCOLOR);
|
|
HICON icon2 = (HICON)::LoadImage (::AfxGetInstanceHandle (), MAKEINTRESOURCE(IDI_PHYS), IMAGE_ICON, 16, 16, LR_SHARED | LR_DEFAULTCOLOR);
|
|
imagelist->Add (icon1);
|
|
imagelist->Add (icon2);
|
|
m_ListCtrl.SetImageList (imagelist, LVSIL_SMALL);
|
|
|
|
//
|
|
// Create a state imagelist for the list control to use for checkboxes
|
|
//
|
|
imagelist = new CImageList;
|
|
imagelist->Create (MAKEINTRESOURCE (IDB_CHECKBOX_STATES1), 13, 0, RGB (255, 0, 255));
|
|
m_ListCtrl.SetImageList (imagelist, LVSIL_STATE);
|
|
|
|
//
|
|
// Create a state imagelist for the tree control to use for checkboxes
|
|
//
|
|
imagelist = new CImageList;
|
|
imagelist->Create (MAKEINTRESOURCE (IDB_CHECKBOX_STATES), 13, 0, RGB (255, 0, 255));
|
|
m_TreeCtrl.SetImageList (imagelist, TVSIL_STATE);
|
|
|
|
//
|
|
// Fill in the parameter list and preset list
|
|
//
|
|
Populate_List_Ctrl ();
|
|
Populate_Tree_Ctrl ();
|
|
|
|
//
|
|
// Subclass the list and tree controls so we can handle the checkstates
|
|
//
|
|
LONG oldproc1 = ::SetWindowLong (m_ListCtrl, GWL_WNDPROC, (LONG)CheckBoxSubclassProc);
|
|
LONG oldproc2 = ::SetWindowLong (m_TreeCtrl, GWL_WNDPROC, (LONG)CheckBoxSubclassProc);
|
|
::SetProp (m_ListCtrl, "OLDPROC", (HANDLE)oldproc1);
|
|
::SetProp (m_TreeCtrl, "OLDPROC", (HANDLE)oldproc2);
|
|
::SetProp (m_ListCtrl, "IS_LIST_CTRL", (HANDLE)TRUE);
|
|
::SetProp (m_TreeCtrl, "IS_LIST_CTRL", (HANDLE)FALSE);
|
|
|
|
//
|
|
// Determine whether or not to enable the dialogue propogation controls
|
|
//
|
|
bool enable_dialogue_ctrls = false;
|
|
if (m_Preset != NULL && m_Preset->Is_Soldier_Preset ()) {
|
|
enable_dialogue_ctrls = true;
|
|
}
|
|
::EnableWindow (::GetDlgItem (m_hWnd, IDC_PROPOGATE_DIALOGUE), enable_dialogue_ctrls);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Populate_List_Ctrl
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ParameterInheritanceDialogClass::Populate_List_Ctrl (void)
|
|
{
|
|
ASSERT (m_Preset != NULL);
|
|
|
|
//
|
|
// Get the definition this preset sits on
|
|
//
|
|
DefinitionClass *definition = m_Preset->Get_Definition ();
|
|
ASSERT (definition != NULL);
|
|
if (definition != NULL) {
|
|
|
|
//
|
|
// Recursively add paramters from this definition to the list control
|
|
//
|
|
Add_Parameters_To_List (definition, NULL, ICON_GAME_SETTING);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Add_Parameters_To_List
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ParameterInheritanceDialogClass::Add_Parameters_To_List
|
|
(
|
|
DefinitionClass * definition,
|
|
DefinitionParameterClass * parent,
|
|
int icon
|
|
)
|
|
{
|
|
ASSERT (definition != NULL);
|
|
|
|
//
|
|
// Add these parameters to the list control
|
|
//
|
|
int count = definition->Get_Parameter_Count ();
|
|
for (int index = 0; index < count; index ++) {
|
|
ParameterClass *parameter = definition->Lock_Parameter (index);
|
|
if (parameter != NULL) {
|
|
|
|
//
|
|
// Is this parameter one we need to recurse into?
|
|
//
|
|
if (parameter->Get_Type () == ParameterClass::TYPE_MODELDEFINITIONID) {
|
|
|
|
//
|
|
// Lookup the definition that this parameter points to
|
|
//
|
|
int def_id = ((ModelDefParameterClass *)parameter)->Get_Value ();
|
|
DefinitionClass *model_def = DefinitionMgrClass::Find_Definition (def_id, false);
|
|
if (model_def != NULL) {
|
|
|
|
DefinitionParameterClass *def_param = new DefinitionParameterClass;
|
|
def_param->Set_Definition (definition);
|
|
def_param->Set_Parameter (parameter);
|
|
def_param->Set_Index (index);
|
|
def_param->Set_Parent (parent);
|
|
|
|
//
|
|
// Recurse into this model definition
|
|
//
|
|
Add_Parameters_To_List (model_def, def_param, ICON_PHYS_SETTING);
|
|
MEMBER_RELEASE (def_param);
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Insert this preset into the list control
|
|
//
|
|
int item_index = m_ListCtrl.InsertItem (0xFFFF, parameter->Get_Name (), icon);
|
|
if (item_index >= 0) {
|
|
|
|
DefinitionParameterClass *def_param = new DefinitionParameterClass;
|
|
def_param->Set_Definition (definition);
|
|
def_param->Set_Parameter (parameter);
|
|
def_param->Set_Index (index);
|
|
def_param->Set_Parent (parent);
|
|
|
|
m_ListCtrl.SetItemData (item_index, (LONG)def_param);
|
|
ListView_SetCheckState (m_ListCtrl, item_index, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
definition->Unlock_Parameter (index);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Populate_Tree_Ctrl
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ParameterInheritanceDialogClass::Populate_Tree_Ctrl (void)
|
|
{
|
|
ASSERT (m_Preset != NULL);
|
|
int parent_id = m_Preset->Get_ID ();
|
|
|
|
//
|
|
// Add all the presets that 'inherit' from this preset
|
|
//
|
|
Add_Children_To_Tree (TVI_ROOT, parent_id);
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Add_Children_To_Tree
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ParameterInheritanceDialogClass::Add_Children_To_Tree (HTREEITEM parent_item, int parent_id)
|
|
{
|
|
//
|
|
// Lookup the parent preset
|
|
//
|
|
PresetClass *parent_preset = PresetMgrClass::Find_Preset (parent_id);
|
|
if (parent_preset != NULL) {
|
|
|
|
//
|
|
// Loop over all the children of this preset
|
|
//
|
|
int count = parent_preset->Get_Child_Preset_Count ();
|
|
for (int index = 0; index < count; index ++) {
|
|
PresetClass *child_preset = parent_preset->Get_Child_Preset (index);
|
|
if (child_preset != NULL) {
|
|
|
|
//
|
|
// Add this preset to the tree
|
|
//
|
|
HTREEITEM new_item = m_TreeCtrl.InsertItem (child_preset->Get_Name (), parent_item);
|
|
if (new_item != NULL) {
|
|
|
|
//
|
|
// Associate the preset pointer with this tree item
|
|
//
|
|
m_TreeCtrl.SetItemData (new_item, (LONG)child_preset);
|
|
|
|
//
|
|
// Check this preset by default
|
|
//
|
|
TreeView_SetCheckState (m_TreeCtrl, new_item, true);
|
|
|
|
//
|
|
// Recursively fill in this presets's children
|
|
//
|
|
Add_Children_To_Tree (new_item, child_preset->Get_ID ());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Ensure this leaf is sorted
|
|
//
|
|
m_TreeCtrl.SortChildren (parent_item);
|
|
m_TreeCtrl.Expand (parent_item, TVE_EXPAND);
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnDestroy
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ParameterInheritanceDialogClass::OnDestroy (void)
|
|
{
|
|
//
|
|
// Free the small image list we associated with the list control
|
|
//
|
|
CImageList *imagelist = m_ListCtrl.GetImageList (LVSIL_SMALL);
|
|
m_ListCtrl.SetImageList (NULL, LVSIL_SMALL);
|
|
SAFE_DELETE (imagelist);
|
|
|
|
//
|
|
// Free the state image list we associated with the list control
|
|
//
|
|
imagelist = m_ListCtrl.GetImageList (LVSIL_STATE);
|
|
m_ListCtrl.SetImageList (NULL, LVSIL_STATE);
|
|
SAFE_DELETE (imagelist);
|
|
|
|
//
|
|
// Free the state image list we associated with the tree control
|
|
//
|
|
imagelist = m_TreeCtrl.GetImageList (TVSIL_STATE);
|
|
m_TreeCtrl.SetImageList (NULL, TVSIL_STATE);
|
|
SAFE_DELETE (imagelist);
|
|
|
|
CDialog::OnDestroy ();
|
|
return ;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CheckBoxSubclassProc
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
LRESULT CALLBACK
|
|
CheckBoxSubclassProc
|
|
(
|
|
HWND hwnd,
|
|
UINT message,
|
|
WPARAM wparam,
|
|
LPARAM lparam
|
|
)
|
|
{
|
|
WNDPROC old_proc = (WNDPROC)::GetProp (hwnd, "OLDPROC");
|
|
|
|
if (message == WM_LBUTTONUP) {
|
|
|
|
//
|
|
// Is this the list control or the tree control?
|
|
//
|
|
BOOL is_list_ctrl = (BOOL)::GetProp (hwnd, "IS_LIST_CTRL");
|
|
if (is_list_ctrl) {
|
|
|
|
//
|
|
// Find out where the user clicked
|
|
//
|
|
LVHITTESTINFO hittest = { 0 };
|
|
hittest.pt.x = LOWORD (lparam);
|
|
hittest.pt.y = HIWORD (lparam);
|
|
::SendMessage (hwnd, LVM_HITTEST, 0, (LPARAM)&hittest);
|
|
|
|
//
|
|
// Did the user click one of the checkboxes?
|
|
//
|
|
if (hittest.flags & LVHT_ONITEMSTATEICON) {
|
|
|
|
//
|
|
// Notify the dialog that the user wants to toggle the checkbox
|
|
//
|
|
::PostMessage (::GetParent (hwnd), WM_USER+102, 0, (LPARAM)hittest.iItem);
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Find out where the user clicked
|
|
//
|
|
TVHITTESTINFO hittest = { 0 };
|
|
hittest.pt.x = LOWORD (lparam);
|
|
hittest.pt.y = HIWORD (lparam);
|
|
::SendMessage (hwnd, TVM_HITTEST, 0, (LPARAM)&hittest);
|
|
|
|
//
|
|
// Did the user click one of the checkboxes?
|
|
//
|
|
if (hittest.flags & TVHT_ONITEMSTATEICON) {
|
|
|
|
//
|
|
// Notify the dialog that the user wants to toggle the checkbox
|
|
//
|
|
::PostMessage (::GetParent (hwnd), WM_USER+103, 0, (LPARAM)hittest.hItem);
|
|
}
|
|
}
|
|
|
|
} else if (message == WM_DESTROY) {
|
|
::SetWindowLong (hwnd, GWL_WNDPROC, (LONG)old_proc);
|
|
::RemoveProp (hwnd, "OLDPROC");
|
|
::RemoveProp (hwnd, "IS_LIST_CTRL");
|
|
}
|
|
|
|
//
|
|
// Allow the default message processing to occur
|
|
//
|
|
LRESULT result = 0L;
|
|
if (old_proc != NULL) {
|
|
result = ::CallWindowProc (old_proc, hwnd, message, wparam, lparam);
|
|
} else {
|
|
result = ::DefWindowProc (hwnd, message, wparam, lparam);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// WindowProc
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
LRESULT
|
|
ParameterInheritanceDialogClass::WindowProc
|
|
(
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
if (message == WM_USER + 102) {
|
|
|
|
//
|
|
// Invert the checked state of this entry
|
|
//
|
|
int index = (int)lParam;
|
|
BOOL checked = ListView_GetCheckState (m_ListCtrl, index);
|
|
Update_List_Entry_Check (index, (bool)(checked != 1));
|
|
|
|
} else if (message == WM_USER + 103) {
|
|
|
|
//
|
|
// Invert the checked state of this entry
|
|
//
|
|
HTREEITEM tree_item = (HTREEITEM)lParam;
|
|
BOOL checked = m_TreeCtrl.GetCheck (tree_item);
|
|
Update_Tree_Entry_Check (tree_item, (bool)(checked != 1));
|
|
}
|
|
|
|
return CDialog::WindowProc (message, wParam, lParam);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Update_Tree_Entry_Check
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ParameterInheritanceDialogClass::Update_Tree_Entry_Check (HTREEITEM parent_item, bool checked)
|
|
{
|
|
//
|
|
// Update this entry's check-state
|
|
//
|
|
TreeView_SetCheckState (m_TreeCtrl, parent_item, checked);
|
|
|
|
//
|
|
// Recurse through all the children
|
|
//
|
|
for ( HTREEITEM item = m_TreeCtrl.GetChildItem (parent_item);
|
|
item != NULL;
|
|
item = m_TreeCtrl.GetNextSiblingItem (item))
|
|
{
|
|
Update_Tree_Entry_Check (item, checked);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Update_List_Entry_Check
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ParameterInheritanceDialogClass::Update_List_Entry_Check (int index, bool checked)
|
|
{
|
|
//
|
|
// Is this entry part of a selection?
|
|
//
|
|
if (m_ListCtrl.GetItemState (index, LVIS_SELECTED) == LVIS_SELECTED) {
|
|
|
|
//
|
|
// Apply the new check state to all the selected entries
|
|
//
|
|
int sel_index = -1;
|
|
while ((sel_index = m_ListCtrl.GetNextItem (sel_index, LVNI_ALL | LVNI_SELECTED)) >= 0) {
|
|
ListView_SetCheckState (m_ListCtrl, sel_index, checked);
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Simply change the check state of this entry
|
|
//
|
|
ListView_SetCheckState (m_ListCtrl, index, checked);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// TreeView_SetCheckState
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL
|
|
TreeView_SetCheckState (HWND hwndTreeView, HTREEITEM hItem, BOOL fCheck)
|
|
{
|
|
TVITEM tvItem;
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_STATE;
|
|
tvItem.hItem = hItem;
|
|
tvItem.stateMask = TVIS_STATEIMAGEMASK;
|
|
|
|
/*
|
|
Since state images are one-based, 1 in this macro turns the check off, and
|
|
2 turns it on.
|
|
*/
|
|
tvItem.state = INDEXTOSTATEIMAGEMASK((fCheck ? 2 : 1));
|
|
|
|
return TreeView_SetItem(hwndTreeView, &tvItem);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnOK
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ParameterInheritanceDialogClass::OnOK (void)
|
|
{
|
|
DynamicVectorClass<PresetClass *> preset_list;
|
|
DynamicVectorClass<DefinitionParameterClass *> parameter_list;
|
|
|
|
//
|
|
// Build a list of selected parameters and presets
|
|
//
|
|
Build_Parameter_List (parameter_list);
|
|
Build_Preset_List (TVI_ROOT, preset_list);
|
|
|
|
//
|
|
// Does the user want to propogate the dialogue settings?
|
|
//
|
|
bool propogate_dialogue_settings = false;
|
|
if (SendDlgItemMessage (IDC_PROPOGATE_DIALOGUE, BM_GETCHECK) == 1) {
|
|
propogate_dialogue_settings = true;
|
|
}
|
|
|
|
//
|
|
// Loop over all the selected presets and propagate the changes
|
|
//
|
|
DefinitionClass *base_def = m_Preset->Get_Definition ();
|
|
for (int index = 0; index < preset_list.Count (); index ++) {
|
|
PresetClass *preset = preset_list[index];
|
|
DefinitionClass *derived_def = preset->Get_Definition ();
|
|
|
|
if (base_def != NULL) {
|
|
Propagate_Changes (base_def, derived_def, parameter_list);
|
|
|
|
//
|
|
// Propogate the dialogue settings if necessary
|
|
//
|
|
if ( propogate_dialogue_settings &&
|
|
base_def->Get_Class_ID () == CLASSID_GAME_OBJECT_DEF_SOLDIER &&
|
|
derived_def->Get_Class_ID () == CLASSID_GAME_OBJECT_DEF_SOLDIER)
|
|
{
|
|
SoldierGameObjDef *base_soldier = reinterpret_cast<SoldierGameObjDef *> (base_def);
|
|
SoldierGameObjDef *derived_soldier = reinterpret_cast<SoldierGameObjDef *> (derived_def);
|
|
|
|
DialogueClass *src_list = base_soldier->Get_Dialog_List ();
|
|
DialogueClass *dest_list = derived_soldier->Get_Dialog_List ();
|
|
|
|
//
|
|
// Copy the settings from the base to the derived...
|
|
//
|
|
for (int index = 0; index < DIALOG_MAX; index ++) {
|
|
dest_list[index] = src_list[index];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
CDialog::OnOK ();
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Find_Parameter_In_List
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool
|
|
Find_Parameter_In_List
|
|
(
|
|
DynamicVectorClass<DefinitionParameterClass *> ¶meter_list,
|
|
ParameterClass * parameter
|
|
)
|
|
{
|
|
bool retval = false;
|
|
|
|
//
|
|
// Loop over all the parameters in the list
|
|
//
|
|
for (int index = 0; index < parameter_list.Count (); index ++) {
|
|
DefinitionParameterClass *def_param = parameter_list[index];
|
|
|
|
//
|
|
// Is this the parameter we were looking for?
|
|
//
|
|
if (def_param != NULL && def_param->Get_Parameter () == parameter) {
|
|
retval = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Propagate_Changes
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ParameterInheritanceDialogClass::Propagate_Changes
|
|
(
|
|
DefinitionClass * base_def,
|
|
DefinitionClass * derived_def,
|
|
DynamicVectorClass<DefinitionParameterClass *> ¶meter_list
|
|
)
|
|
{
|
|
bool is_valid = true;
|
|
|
|
//
|
|
// Compare all the parameters with this derived definition to
|
|
// find any that are not overridden.
|
|
//
|
|
int param_count = base_def->Get_Parameter_Count ();
|
|
for (int param_index = 0; is_valid && param_index < param_count; param_index ++) {
|
|
ParameterClass *parameter = base_def->Lock_Parameter (param_index);
|
|
ParameterClass *curr_parameter = derived_def->Lock_Parameter (param_index);
|
|
ASSERT (parameter != NULL);
|
|
ASSERT (curr_parameter != NULL);
|
|
|
|
//
|
|
// Are we comparing the same parameter? (We better be).
|
|
//
|
|
if ( parameter->Get_Type () == curr_parameter->Get_Type () &&
|
|
::lstrcmpi (parameter->Get_Name (), curr_parameter->Get_Name ()) == 0)
|
|
{
|
|
//
|
|
// Do we need to recurse into this parameter?
|
|
//
|
|
if (parameter->Get_Type () == ParameterClass::TYPE_MODELDEFINITIONID) {
|
|
|
|
//
|
|
// Lookup the definitions that these parameters reference
|
|
//
|
|
int base_id = ((ModelDefParameterClass *)parameter)->Get_Value ();
|
|
int derived_id = ((ModelDefParameterClass *)curr_parameter)->Get_Value ();
|
|
DefinitionClass *base_model_def = DefinitionMgrClass::Find_Definition (base_id, false);
|
|
DefinitionClass *derived_model_def = DefinitionMgrClass::Find_Definition (derived_id, false);
|
|
|
|
//
|
|
// Recurse into these definitions
|
|
//
|
|
if ( base_model_def != NULL && derived_model_def != NULL &&
|
|
base_model_def->Get_Class_ID () == derived_model_def->Get_Class_ID ())
|
|
{
|
|
Propagate_Changes (base_model_def, derived_model_def, parameter_list);
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Should we propagate this parameter's value?
|
|
//
|
|
if (::Find_Parameter_In_List (parameter_list, parameter)) {
|
|
|
|
//
|
|
// Copy the parameter value from the parent.
|
|
//
|
|
curr_parameter->Copy_Value (*parameter);
|
|
}
|
|
}
|
|
|
|
} else {
|
|
is_valid = false;
|
|
}
|
|
|
|
//
|
|
// Release the parameter pointers
|
|
//
|
|
base_def->Unlock_Parameter (param_index);
|
|
derived_def->Unlock_Parameter (param_index);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Build_Parameter_List
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ParameterInheritanceDialogClass::Build_Parameter_List (DynamicVectorClass<DefinitionParameterClass *> ¶meter_list)
|
|
{
|
|
//
|
|
// Loop over all the parameters
|
|
//
|
|
for (int index = 0; index < m_ListCtrl.GetItemCount (); index ++) {
|
|
DefinitionParameterClass *parameter = NULL;
|
|
parameter = (DefinitionParameterClass *)m_ListCtrl.GetItemData (index);
|
|
|
|
//
|
|
// Add this parameter to the list if the user checked it
|
|
//
|
|
if (parameter != NULL && ListView_GetCheckState (m_ListCtrl, index)) {
|
|
parameter_list.Add (parameter);
|
|
}
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Build_Preset_List
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ParameterInheritanceDialogClass::Build_Preset_List
|
|
(
|
|
HTREEITEM parent_item,
|
|
DynamicVectorClass<PresetClass *> & preset_list
|
|
)
|
|
{
|
|
//
|
|
// Loop over all the immediate children
|
|
//
|
|
for ( HTREEITEM item = m_TreeCtrl.GetChildItem (parent_item);
|
|
item != NULL;
|
|
item = m_TreeCtrl.GetNextSiblingItem (item))
|
|
{
|
|
PresetClass *preset = (PresetClass *)m_TreeCtrl.GetItemData (item);
|
|
if (preset != NULL) {
|
|
|
|
//
|
|
// Add this preset to the list if necessary
|
|
//
|
|
if (m_TreeCtrl.GetCheck (item)) {
|
|
preset_list.Add (preset);
|
|
}
|
|
|
|
//
|
|
// Recurse down the tree
|
|
//
|
|
Build_Preset_List (item, preset_list);
|
|
}
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnDeleteitemParameterList
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ParameterInheritanceDialogClass::OnDeleteitemParameterList
|
|
(
|
|
NMHDR * pNMHDR,
|
|
LRESULT* pResult
|
|
)
|
|
{
|
|
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
|
|
(*pResult) = 0;
|
|
|
|
//
|
|
// Free the object we associted with this entry
|
|
//
|
|
DefinitionParameterClass *def_param = NULL;
|
|
def_param = (DefinitionParameterClass *)m_ListCtrl.GetItemData (pNMListView->iItem);
|
|
MEMBER_RELEASE (def_param);
|
|
|
|
m_ListCtrl.SetItemData (pNMListView->iItem, 0);
|
|
return ;
|
|
}
|
|
|