Files
firestorm/Gameleap/code/mw4/Tools/Balancer/dlgObjectBalance.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

2407 lines
91 KiB
C++

// DlgObjectBalance.cpp : implementation file
//
#include "stdafx.h"
#include "Balancer.h"
#include <stdarg.h>
#include <stuff\stuff.hpp>
#include "DlgObjectBalance.h"
using namespace Stuff;
const int c_Max_Objects_Supported = 100;
extern CBalancerApp theApp;
//
// User passes in an array of data to the dialog at startup.
// this array type is...CDOPPROPERTIES_TO_EDIT_ARRAY
//
extern LPCSTR MyLoadStringTempBuffer(UINT uiID);
extern void EndDirectoryWithBackSlash(CString & strDir);
/////////////////////////////////////////////////////////////////////////////
// CDlgObjectBalance dialog
//
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Rather than have the calling function have to fill in the structure manually they can call this
// function with all the propeties they want to edit. Then they just pass this in to the appropriate
// function to specify what properties to get. They will have to clear up the memory with free though
//
CDOPPROPERTIES_TO_EDIT_ARRAY * CDlgObjectBalance::CreatePropertiesToEditArray(int nCount, ...)
{
va_list marker;
CDOPPROPERTIES_TO_EDIT_ARRAY * pRet = Allocate_CDOPPROPERTIES_TO_EDIT_ARRAY(nCount);
va_start( marker, nCount ); /* Initialize variable arguments. */
pRet->nCount = nCount;
for (int i = 0 ; i < nCount; i++)
{
pRet->ppProperties_To_Edit_Entry[i]->ePropertyType = va_arg(marker, CDOPVARTYPE);
strcpy(pRet->ppProperties_To_Edit_Entry[i]->szPropertyTag, va_arg(marker, char *));
strcpy(pRet->ppProperties_To_Edit_Entry[i]->szPropertyTagForDisplay, va_arg(marker, char *));
pRet->ppProperties_To_Edit_Entry[i]->uiReserved1_CTRLID = 0;
}
va_end( marker ); /* Reset variable arguments. */
return pRet;
}
//
// Since I am using a pointer to represent an array the structure has to be allocated with enough size to
// store the array. In addition the internal pointer variable must be directed to within
// the allocation itself. This way I can use array notation To then on.
//
CDOPPROPERTIES_TO_EDIT_ARRAY * CDlgObjectBalance::Allocate_CDOPPROPERTIES_TO_EDIT_ARRAY(int nPropertyCount, CDOPPROPERTIES_TO_EDIT_ARRAY * * ppCDOPPROPERTIES_TO_EDIT_ARRAY)
{
CDOPPROPERTIES_TO_EDIT_ARRAY * pNew = (CDOPPROPERTIES_TO_EDIT_ARRAY *)
malloc(sizeof(CDOPPROPERTIES_TO_EDIT_ARRAY) + (nPropertyCount) * sizeof(CDOPPROPERTIES_TO_EDIT_ENTRY *) +
(nPropertyCount) * sizeof(CDOPPROPERTIES_TO_EDIT_ENTRY)); // we could - 1 from the count since one is allocated as part of the structure, but
// I'm electing to have the 4 byte buffer instead of worrying about nPropertyCount == 0
for (int i = 0; i < nPropertyCount; i++)
{
pNew->ppProperties_To_Edit_Entry[i] = (CDOPPROPERTIES_TO_EDIT_ENTRY *)(void *)(((DWORD)&(pNew->ppProperties_To_Edit_Entry)) +
sizeof(CDOPPROPERTIES_TO_EDIT_ENTRY *) * (nPropertyCount) + i * sizeof(CDOPPROPERTIES_TO_EDIT_ENTRY));
}
if (ppCDOPPROPERTIES_TO_EDIT_ARRAY)
*ppCDOPPROPERTIES_TO_EDIT_ARRAY = pNew;
return pNew;
}
//
// Since I am using a pointer to represent an array the structure has to be allocated with enough size to
// store the array. In addition the internal pointer variable must be directed to within
// the allocation itself. This way I can use array notation To then on.
//
CDOPPROPERTIES_OBJECT_PROPERTIES * CDlgObjectBalance::Allocate_CDOPPROPERTIES_OBJECT_PROPERTIES(int nPropertyCount, CDOPPROPERTIES_OBJECT_PROPERTIES * * ppCDOPPROPERTIES_OBJECT_PROPERTIES)
{
CDOPPROPERTIES_OBJECT_PROPERTIES * pNew = (CDOPPROPERTIES_OBJECT_PROPERTIES *)
malloc (sizeof(CDOPPROPERTIES_OBJECT_PROPERTIES) + nPropertyCount * sizeof(CDOPPROPERTYVALUE *) +
nPropertyCount * sizeof(CDOPPROPERTYVALUE));
for (int i = 0 ; i < nPropertyCount; i++)
{
pNew->ppObjectProperties[i] = (CDOPPROPERTYVALUE * )(void *)(((DWORD)&(pNew->ppObjectProperties)) +
sizeof(CDOPPROPERTYVALUE *) * nPropertyCount + sizeof(CDOPPROPERTYVALUE) * i);
}
if (ppCDOPPROPERTIES_OBJECT_PROPERTIES)
*ppCDOPPROPERTIES_OBJECT_PROPERTIES = pNew;
return pNew;
}
//
// Since I am using a pointer to represent an array the structure has to be allocated with enough size to
// store the array. In addition the internal pointer variable must be directed to within
// the allocation itself. This way I can use array notation To then on.
//
CDOPPROPERTIES_OBJECT_LIST * CDlgObjectBalance::Allocate_CDOPPROPERTIES_OBJECT_LIST(int nObjectCount, int nPropertyCount, CDOPPROPERTIES_OBJECT_LIST ** ppCDOPPROPERTIES_OBJECT_LIST )
{
// This one is the most complex since it has to allocate enough room for all the objects, to have all the properties and have
// all the data for those properties
CDOPPROPERTIES_OBJECT_LIST * pNew = (CDOPPROPERTIES_OBJECT_LIST *)
malloc(sizeof(CDOPPROPERTIES_OBJECT_LIST) + nObjectCount * sizeof(CDOPPROPERTIES_OBJECT_PROPERTIES *)
+(nObjectCount * (sizeof(CDOPPROPERTIES_OBJECT_PROPERTIES) + nPropertyCount * sizeof(CDOPPROPERTYVALUE *)))
+(nObjectCount * (nPropertyCount * sizeof(CDOPPROPERTYVALUE)))
);
for (int i = 0; i < nObjectCount; i++)
{
// For the object array set up the pointers to each properties array
pNew->ppPropertiesArray[i] = (CDOPPROPERTIES_OBJECT_PROPERTIES * )(void *)(((DWORD)&(pNew->ppPropertiesArray))
+sizeof(CDOPPROPERTIES_OBJECT_PROPERTIES * ) * nObjectCount
+ i * (sizeof(CDOPPROPERTIES_OBJECT_PROPERTIES) + nPropertyCount * (sizeof(CDOPPROPERTYVALUE *))
+nPropertyCount * sizeof(CDOPPROPERTYVALUE)));
// For each object set up the pointer list for the properties array
for (int j = 0; j < nPropertyCount; j++)
{
pNew->ppPropertiesArray[i]->ppObjectProperties[j] = (CDOPPROPERTYVALUE *)(void *)(((DWORD)&(pNew->ppPropertiesArray[i]->ppObjectProperties))
+ nPropertyCount * sizeof(CDOPPROPERTYVALUE *)
+ j * sizeof(CDOPPROPERTYVALUE));
}
}
if (ppCDOPPROPERTIES_OBJECT_LIST)
*ppCDOPPROPERTIES_OBJECT_LIST = pNew;
return pNew;
}
//****************************************************************************************
//
//
//
//****************************************************************************************
BOOL CDlgObjectBalance::Copy_CDOPPROPERTIES_TO_EDIT_ARRAY(CDOPPROPERTIES_TO_EDIT_ARRAY * pCDOPPROPERTIES_TO_EDIT_ARRAY_DEST, CDOPPROPERTIES_TO_EDIT_ARRAY * pCDOPPROPERTIES_TO_EDIT_ARRAY_SRC)
{
pCDOPPROPERTIES_TO_EDIT_ARRAY_DEST->nCount = pCDOPPROPERTIES_TO_EDIT_ARRAY_SRC->nCount;
for (int i = 0; i < pCDOPPROPERTIES_TO_EDIT_ARRAY_SRC->nCount; i++)
{
memcpy(pCDOPPROPERTIES_TO_EDIT_ARRAY_DEST->ppProperties_To_Edit_Entry[i],
pCDOPPROPERTIES_TO_EDIT_ARRAY_SRC->ppProperties_To_Edit_Entry[i],
sizeof(CDOPPROPERTIES_TO_EDIT_ENTRY));
}
return TRUE;
}
//****************************************************************************************
//
//
//
//****************************************************************************************
BOOL CDlgObjectBalance::Copy_CDOPPROPERTIES_OBJECT_PROPERTIES(CDOPPROPERTIES_OBJECT_PROPERTIES * pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST, CDOPPROPERTIES_OBJECT_PROPERTIES * pCDOPPROPERTIES_OBJECT_PROPERTIES_SRC)
{
pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->fDirty = pCDOPPROPERTIES_OBJECT_PROPERTIES_SRC->fDirty;
pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->fReadOnly = pCDOPPROPERTIES_OBJECT_PROPERTIES_SRC->fReadOnly;
pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->nProperties = pCDOPPROPERTIES_OBJECT_PROPERTIES_SRC->nProperties;
memcpy(pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->szObjectName,
pCDOPPROPERTIES_OBJECT_PROPERTIES_SRC->szObjectName,
sizeof(pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->szObjectName));
for (int i = 0 ; i < pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->nProperties; i++)
{
memcpy(pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->ppObjectProperties[i],
pCDOPPROPERTIES_OBJECT_PROPERTIES_SRC->ppObjectProperties[i],
sizeof(CDOPPROPERTYVALUE));
}
return TRUE;
}
//****************************************************************************************
//
//
//
//****************************************************************************************
BOOL CDlgObjectBalance::Copy_CDOPPROPERTIES_OBJECT_LIST(CDOPPROPERTIES_OBJECT_LIST * pCDOPPROPERTIES_OBJECT_LIST_DEST, CDOPPROPERTIES_OBJECT_LIST * pCDOPPROPERTIES_OBJECT_LIST_SRC)
{
pCDOPPROPERTIES_OBJECT_LIST_DEST->nObjectCount = pCDOPPROPERTIES_OBJECT_LIST_SRC->nObjectCount;
for (int i = 0; i < pCDOPPROPERTIES_OBJECT_LIST_DEST->nObjectCount; i++)
{
Copy_CDOPPROPERTIES_OBJECT_PROPERTIES(pCDOPPROPERTIES_OBJECT_LIST_DEST->ppPropertiesArray[i],
pCDOPPROPERTIES_OBJECT_LIST_SRC->ppPropertiesArray[i]);
}
return TRUE;
}
//****************************************************************************************
//
//
//
//****************************************************************************************
BOOL CDlgObjectBalance::IsEqual_CDOPPROPERTIES_TO_EDIT_ARRAY(CDOPPROPERTIES_TO_EDIT_ARRAY * pCDOPPROPERTIES_TO_EDIT_ARRAY1, CDOPPROPERTIES_TO_EDIT_ARRAY * pCDOPPROPERTIES_TO_EDIT_ARRAY2)
{
if (pCDOPPROPERTIES_TO_EDIT_ARRAY1->nCount != pCDOPPROPERTIES_TO_EDIT_ARRAY2->nCount)
return FALSE;
for (int i = 0; i < pCDOPPROPERTIES_TO_EDIT_ARRAY1->nCount; i++)
{
if (memcmp(pCDOPPROPERTIES_TO_EDIT_ARRAY1->ppProperties_To_Edit_Entry[i],
pCDOPPROPERTIES_TO_EDIT_ARRAY2->ppProperties_To_Edit_Entry[i],
sizeof(CDOPPROPERTIES_TO_EDIT_ENTRY)))
return FALSE;
}
return TRUE;
}
//****************************************************************************************
//
//
//
//****************************************************************************************
BOOL CDlgObjectBalance::IsEqual_CDOPPROPERTIES_OBJECT_PROPERTIES(CDOPPROPERTIES_OBJECT_PROPERTIES * pCDOPPROPERTIES_OBJECT_PROPERTIES1, CDOPPROPERTIES_OBJECT_PROPERTIES * pCDOPPROPERTIES_OBJECT_PROPERTIES2)
{
if (pCDOPPROPERTIES_OBJECT_PROPERTIES1->nProperties != pCDOPPROPERTIES_OBJECT_PROPERTIES2->nProperties ||
pCDOPPROPERTIES_OBJECT_PROPERTIES1->fDirty != pCDOPPROPERTIES_OBJECT_PROPERTIES2->fDirty ||
pCDOPPROPERTIES_OBJECT_PROPERTIES1->fReadOnly != pCDOPPROPERTIES_OBJECT_PROPERTIES2->fReadOnly ||
memcmp(pCDOPPROPERTIES_OBJECT_PROPERTIES1->szObjectName,
pCDOPPROPERTIES_OBJECT_PROPERTIES2->szObjectName,
sizeof(pCDOPPROPERTIES_OBJECT_PROPERTIES2->szObjectName)))
return FALSE;
for (int i = 0 ; i < pCDOPPROPERTIES_OBJECT_PROPERTIES2->nProperties; i++)
{
if (memcmp(pCDOPPROPERTIES_OBJECT_PROPERTIES1->ppObjectProperties[i],
pCDOPPROPERTIES_OBJECT_PROPERTIES2->ppObjectProperties[i],
sizeof(CDOPPROPERTYVALUE)))
{
return FALSE;
}
}
return TRUE;
}
//****************************************************************************************
//
//
//
//****************************************************************************************
BOOL CDlgObjectBalance::IsEqual_CDOPPROPERTIES_OBJECT_LIST(CDOPPROPERTIES_OBJECT_LIST * pCDOPPROPERTIES_OBJECT_LIST1, CDOPPROPERTIES_OBJECT_LIST * pCDOPPROPERTIES_OBJECT_LIST2)
{
if (pCDOPPROPERTIES_OBJECT_LIST1->nObjectCount != pCDOPPROPERTIES_OBJECT_LIST2->nObjectCount)
return FALSE;
for (int i = 0 ; i < pCDOPPROPERTIES_OBJECT_LIST2->nObjectCount; i++)
{
if (!IsEqual_CDOPPROPERTIES_OBJECT_PROPERTIES(pCDOPPROPERTIES_OBJECT_LIST1->ppPropertiesArray[i],
pCDOPPROPERTIES_OBJECT_LIST2->ppPropertiesArray[i]))
return FALSE;
}
return TRUE;
}
//****************************************************************************************
//
//
//
//****************************************************************************************
CDlgObjectBalance::~CDlgObjectBalance()
{
if (m_pObjectList)
{
free(m_pObjectList);
}
}
//****************************************************************************************
//
//
//
//****************************************************************************************
CDlgObjectBalance::CDlgObjectBalance(CWnd* pParent /*=NULL*/)
: CDialog(CDlgObjectBalance::IDD, pParent)
{
//{{AFX_DATA_INIT(CDlgObjectBalance)
//}}AFX_DATA_INIT
m_pObjectList = NULL;
ClearObjectDataSet();
// This will be passed in later with a list of properties to edit
m_paPropertiesToEdit = NULL;
m_fnFilterFunction = NULL;
m_fShowFullObjectName = FALSE;
m_fShowFullPropertyName = FALSE;
m_fShowPageOnly = FALSE;
m_eSearchType = eSingleSubdirectory;
m_fDirty = FALSE;
m_fAllowPresentToChange = TRUE;
m_nHorzControlSize = 0;
m_nLastControlID = IDC_VARIABLE_VALUE_PLACEHOLDER;
}
//****************************************************************************************
//
//
//
//****************************************************************************************
int CDlgObjectBalance::DoModal()
{
//
// Check to make sure we have all the data set that we need
//
if (
m_strFileNameToSearchSubdirectoriesFor.IsEmpty() ||
m_strObjectFilesRootDirectory.IsEmpty() ||
m_paPropertiesToEdit == NULL ||
!m_paPropertiesToEdit->nCount // have to have at least one property
)
{
return IDABORT;
}
return CDialog::DoModal();
}
//****************************************************************************************
//
//
//
//****************************************************************************************
void CDlgObjectBalance::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDlgObjectBalance)
DDX_Control(pDX, IDC_DOP_PROPERTIES, m_staticPropertiesGroup);
DDX_Control(pDX, ID_DOB_SCROLLBAR, m_sbScrollBarVert);
DDX_Control(pDX, ID_DOB_SCROLLBAR2, m_sbScrollBarHorz);
//}}AFX_DATA_MAP
}
//****************************************************************************************
//
//
//
//****************************************************************************************
BEGIN_MESSAGE_MAP(CDlgObjectBalance, CDialog)
//{{AFX_MSG_MAP(CDlgObjectBalance)
ON_BN_CLICKED(IDC_VALUE_PLUS, OnValuePlus)
ON_BN_CLICKED(IDC_VALUE_MULTIPLY, OnValueMultiply)
ON_BN_CLICKED(IDC_VALUE_MINUS, OnValueMinus)
ON_BN_CLICKED(IDC_VALUE_DIVIDE, OnValueDivide)
ON_WM_VSCROLL()
ON_WM_HSCROLL()
ON_BN_CLICKED(IDC_FILL_ALL_VALUES, OnFillAllValues)
ON_BN_CLICKED(IDC_CHECKALL_APPLY_BUTTONS, OnCheckallApplyButtons)
//}}AFX_MSG_MAP
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDlgObjectBalance message handlers
BOOL CDlgObjectBalance::OnInitDialog()
{
CDialog::OnInitDialog();
m_fDirty = FALSE;
ClearObjectDataSet();
//
// For now we just have a fixed size data set maximum. Otherwise we would have to
// iterate all the files once or create a link list of objects instead of an array.
// Any of these can be done, the array was simply created to save time getting this
// code up to speed.
//
if (m_pObjectList)
free(m_pObjectList);
m_pObjectList = Allocate_CDOPPROPERTIES_OBJECT_LIST(c_Max_Objects_Supported, m_paPropertiesToEdit->nCount);
m_pObjectList->nObjectCount = 0; // this many being used currently
//
// Search for the weapons subsytem files
//
LoadObjectData(m_strObjectFilesRootDirectory, m_eSearchType);
//
// Create all the sub-controls that represent the data that we are going to be editting in the
// dialog
// Note: We are not allowed to get here if we don't have a properties list since DoModal should kick
// us out, and this dialog is not meant to be modeless.
CreateSubControlsForProperties();
ClearModifierCells();
UpdateControlData(TRUE);
UpdateData(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::CreateSubControlsForProperties()
{
//
// Go through the list of properties we are editting and place all the controls.
// Use the reserved value in the property array passed in to store the starting ID
// of each properties control set. Offsets To there are based on the type of variable
// that is being used.
m_nLastControlID = IDC_VARIABLE_VALUE_PLACEHOLDER;
//
// The following hidden objects have been added to the resource dialog in order to
// make formatting fully adjustable without having to modify constants in the code
// We get the base size, and position for all controls To these
// IDC_DOP_PROPNAME, IDC_DOP_PROPPRESENT, IDC_DOP_PROPEDIT1, IDC_DOP_PROPEDIT2, IDC_DOP_PROPEDIT3
//
// Use the dummy hidden controls to place our new ones, unhide the dummy controls
// for the first property, and then build the rest
CWnd * pControlPlus = GetDlgItem(IDC_VALUE_PLUS);
CWnd * pControlPresentPlaceHolder = GetDlgItem(IDC_VARIABLE_PRESENT_PLACEHOLDER);
CWnd * pControlValuePlaceHolder = GetDlgItem(IDC_VARIABLE_VALUE_PLACEHOLDER);
CWnd * pControlObjectNameHeader = GetDlgItem(IDC_OBJECT_NAME_HEADER);
CWnd * pControlApplyChangesPlaceHolder = GetDlgItem(IDC_APPLYCHANGESPLACEHOLDER);
CWnd * pControlGroupboxArea = GetDlgItem(IDC_DOP_PROPERTIES);
if (!pControlPlus || !pControlPresentPlaceHolder || !pControlValuePlaceHolder)
return; // badness has occurred, but no way out of it at this point
//CFont * pFontControlPlus = pControlPlus ->GetFont();
CFont * pFontControlPresentPlaceHolder = pControlPresentPlaceHolder->GetFont();
CFont * pFontControlValuePlaceHolder = pControlValuePlaceHolder ->GetFont();
CFont * pFontControlObjectNameHeader = pControlObjectNameHeader ->GetFont();
CRect crRectDlg;
CRect crControlPlus;
CRect crControlPresentPlaceHolder;
CRect crControlValuePlaceHolder;
CRect crControlObjectNameHeader;
CRect crControlApplyChangesPlaceHolder;
CRect crControlGroupboxArea;
GetWindowRect(crRectDlg);
pControlPlus->GetWindowRect(crControlPlus);
pControlPresentPlaceHolder->GetWindowRect(crControlPresentPlaceHolder);
pControlValuePlaceHolder->GetWindowRect(crControlValuePlaceHolder);
pControlObjectNameHeader->GetWindowRect(crControlObjectNameHeader);
pControlApplyChangesPlaceHolder->GetWindowRect(crControlApplyChangesPlaceHolder);
pControlGroupboxArea->GetWindowRect(crControlGroupboxArea);
pControlApplyChangesPlaceHolder->GetWindowRect(crControlApplyChangesPlaceHolder);
//
// Offset the rects relative to the dialog
//
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crControlPlus, 2);
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crControlPresentPlaceHolder, 2);
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crControlValuePlaceHolder, 2);
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crControlObjectNameHeader, 2);
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crControlGroupboxArea, 2);
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crControlApplyChangesPlaceHolder, 2);
//
// If the caller wants to override the edit control size then they can.
//
if (m_nHorzControlSize > 0)
{
crControlValuePlaceHolder.right = crControlValuePlaceHolder.left + m_nHorzControlSize;
}
int nCurrentProperty = 0;
// if we didn't have at least one item in the property list DoModal() should have kicked us out
// so it should be safe to reference this without checking here.
// Next root ID is 1 after this set
int nCurrObject = 0;
//
// For the first pass we create a set of controls on the top to allow the multiple adding/multiplying
// factors used for balancing.
//
//
int nCurrX = crControlValuePlaceHolder.left;
int nCurrY = crControlPlus.top;
const int nYBufferSizeAfterRow = 0;
const int nXBufferSizeAfterPresent = 2;
const int nXBufferSizeAfterSmallEdit = 1;
const char * szStaticText = NULL;
//
// The ID's for the controls are based on the total number possible per row to make it easier,
// 1 for the name of the object and 4 for the 1 present checkbox and 3 edit controls
// It starts with the base controls then adds a whole row of values. Then those are applied to the upper row
// so the first row of actual values is two rows after the place holder base value.
int nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (1) );
const int nXBufferSizeAfterFullEdit = 4;
HWND hWndTemp = NULL;
while (nCurrentProperty < m_paPropertiesToEdit->nCount)
{
// Create a property name header
if (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->szPropertyTagForDisplay[0] )
{
szStaticText = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->szPropertyTagForDisplay;
}
else
{
szStaticText =
m_fShowFullPropertyName ?
m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->szPropertyTag
: (m_fShowPageOnly ?
GetPageNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->szPropertyTag )
: GetEntryNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->szPropertyTag ));
}
hWndTemp = ::CreateWindow("STATIC",
szStaticText,
WS_VISIBLE | SS_LEFT | WS_CHILD,
nCurrX, crControlObjectNameHeader.top, crControlValuePlaceHolder.Width(), crControlObjectNameHeader.Height(),
GetSafeHwnd(),
// This is now located on the second row of ID's that I am concerned about
(HMENU)((int) nCurrID + 1 + ((m_paPropertiesToEdit->nCount * 4) + 1)), theApp.m_hInstance, NULL);
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlObjectNameHeader, (LPARAM)FALSE);
CDOPVARTYPE eVarType = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType;
switch (eVarType)
{
case eVector3D:
hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT",
"",
WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD,
nCurrX, nCurrY, crControlValuePlaceHolder.Width()/3, crControlValuePlaceHolder.Height(),
GetSafeHwnd(), (HMENU)(int)(nCurrID+1), theApp.m_hInstance, NULL);
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE);
nCurrX += crControlValuePlaceHolder.Width()/3 + nXBufferSizeAfterSmallEdit;
hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT",
"",
WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD ,
nCurrX, nCurrY, crControlValuePlaceHolder.Width()/3, crControlValuePlaceHolder.Height(),
GetSafeHwnd(), (HMENU)(int)(nCurrID+2), theApp.m_hInstance, NULL);
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE);
nCurrX += crControlValuePlaceHolder.Width()/3 + nXBufferSizeAfterSmallEdit;
hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT",
"",
WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD ,
nCurrX, nCurrY, crControlValuePlaceHolder.Width()/3, crControlValuePlaceHolder.Height(),
GetSafeHwnd(), (HMENU)(int)(nCurrID+3), theApp.m_hInstance, NULL);
nCurrX += crControlValuePlaceHolder.Width()/3 + nXBufferSizeAfterFullEdit
+ crControlPresentPlaceHolder.Width() + nXBufferSizeAfterPresent;
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE);
break;
case efloat:
case eint:
case eLPSTR:
case eBOOL:
hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT",
"",
WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD,
nCurrX, nCurrY, crControlValuePlaceHolder.Width(), crControlValuePlaceHolder.Height(),
GetSafeHwnd(), (HMENU)(int)(nCurrID+1), theApp.m_hInstance, NULL);
nCurrX += crControlValuePlaceHolder.Width() + nXBufferSizeAfterFullEdit
+ crControlPresentPlaceHolder.Width() + nXBufferSizeAfterPresent;
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE);
break;
}
nCurrID += 4;
nCurrentProperty++;
}
m_nMaxVisibleVert = crControlGroupboxArea.Height()/(crControlValuePlaceHolder.Height() + nYBufferSizeAfterRow);
m_nCurScrollPosVert = 0;
m_nScrollIncrementVert = (crControlValuePlaceHolder.Height() + nYBufferSizeAfterRow);
m_sbScrollBarVert.SetScrollPos(0, FALSE);
m_sbScrollBarVert.SetScrollRange(0, max(0, m_pObjectList->nObjectCount - m_nMaxVisibleVert + 2), TRUE);
m_nMaxVisibleHorz = (crControlGroupboxArea.Width() - (crControlPresentPlaceHolder.left))
/(crControlValuePlaceHolder.Width() + nXBufferSizeAfterPresent + nXBufferSizeAfterFullEdit
+ crControlPresentPlaceHolder.Width());
m_nCurScrollPosHorz = 0;
m_nScrollIncrementHorz = (crControlValuePlaceHolder.Width() + nXBufferSizeAfterPresent + nXBufferSizeAfterSmallEdit + crControlPresentPlaceHolder.Width());
m_sbScrollBarHorz.SetScrollPos(0, FALSE);
m_sbScrollBarHorz.SetScrollRange(0, max(0, m_paPropertiesToEdit->nCount - m_nMaxVisibleHorz + 2), TRUE);
//
// Set up the static window's children to work as part of the dialog itself.
//
long wsWindowStyle = ::GetWindowLong(pControlGroupboxArea->GetSafeHwnd(), GWL_EXSTYLE);
wsWindowStyle |= WS_EX_CONTROLPARENT;
::SetWindowLong(pControlGroupboxArea->GetSafeHwnd(), GWL_EXSTYLE, wsWindowStyle);
//
// The ID's for the controls are based on the total number possible per row to make it easier,
// 1 for the name of the object and 4 for the 1 present checkbox and 3 edit controls
// It starts with the base controls then adds a whole row of values. Then those are applied to the upper row
// so the first row of actual values is two rows after the place holder base value.
nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrObject + 3) );
nCurrY = crControlValuePlaceHolder.top;
while (nCurrObject < m_pObjectList->nObjectCount)
{
BOOL fReadOnly = m_pObjectList->ppPropertiesArray[nCurrObject]->fReadOnly;
UINT uiDisabledFlagIfNecessary = fReadOnly ? WS_DISABLED : 0;
nCurrX = crControlPlus.left;
szStaticText =
m_fShowFullObjectName ?
m_pObjectList->ppPropertiesArray[nCurrObject]->szObjectName :
GetShortObjectName(m_pObjectList->ppPropertiesArray[nCurrObject]->szObjectName);
hWndTemp = ::CreateWindow("STATIC",
szStaticText,
WS_VISIBLE | SS_LEFT | WS_CHILD,
crControlObjectNameHeader.left - crControlGroupboxArea.left + 2, nCurrY - crControlGroupboxArea.top, crControlObjectNameHeader.Width(), crControlValuePlaceHolder.Height(),
pControlGroupboxArea->GetSafeHwnd(),
(HMENU)IDC_STATIC, theApp.m_hInstance, NULL);
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlObjectNameHeader, (LPARAM)FALSE);
HWND hWndTemp = NULL;
nCurrentProperty = 0; // reset for use in the next pass
nCurrX = crControlPresentPlaceHolder.left;
//
// Create the check boxes that allow you to control which weapons are effected by a given change.
//
// Since the CurrID is the present button, and represents the beginning of data storage, nCurrID -1 will be the apply checkbox
nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrObject + 3));
hWndTemp = ::CreateWindow("BUTTON",
"",
WS_VISIBLE | BS_CHECKBOX | WS_CHILD | BS_AUTOCHECKBOX | uiDisabledFlagIfNecessary,
crControlApplyChangesPlaceHolder.left - crControlGroupboxArea.left, nCurrY - crControlGroupboxArea.top, crControlApplyChangesPlaceHolder.Width(), crControlApplyChangesPlaceHolder.Height(),
pControlGroupboxArea->GetSafeHwnd(),
(HMENU)(int)(nCurrID-1),
theApp.m_hInstance, NULL);
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPresentPlaceHolder, (LPARAM)FALSE);
if (fReadOnly)
{
::SendMessage(hWndTemp, BM_SETCHECK, BST_UNCHECKED, 0);
}
// Start the ID count for the controls at the set above 0, to skip the place holders
// It could be made tighter than this but isn't necessary.
while (nCurrentProperty < m_paPropertiesToEdit->nCount)
{
nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrObject + 3) + (nCurrentProperty * 4));
hWndTemp = ::CreateWindow("BUTTON",
"",
WS_VISIBLE | BS_CHECKBOX | WS_CHILD | BS_AUTOCHECKBOX | uiDisabledFlagIfNecessary | (m_fAllowPresentToChange ? 0 : WS_DISABLED),
nCurrX - crControlGroupboxArea.left, nCurrY - crControlGroupboxArea.top, crControlPresentPlaceHolder.Width(), crControlPresentPlaceHolder.Height(),
pControlGroupboxArea->GetSafeHwnd(),
(HMENU)(int)(nCurrID+0),
theApp.m_hInstance, NULL);
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPresentPlaceHolder, (LPARAM)FALSE);
nCurrX += crControlPresentPlaceHolder.Width() + nXBufferSizeAfterPresent;
CDOPVARTYPE eVarType = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType;
switch (eVarType)
{
case eVector3D:
hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT",
"",
WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD | uiDisabledFlagIfNecessary,
nCurrX - crControlGroupboxArea.left, nCurrY - crControlGroupboxArea.top, crControlValuePlaceHolder.Width()/3, crControlValuePlaceHolder.Height(),
pControlGroupboxArea->GetSafeHwnd(),
(HMENU)(int)(nCurrID+1),
theApp.m_hInstance, NULL);
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE);
nCurrX += crControlValuePlaceHolder.Width()/3 + nXBufferSizeAfterSmallEdit;
hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT",
"",
WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD | uiDisabledFlagIfNecessary,
nCurrX - crControlGroupboxArea.left, nCurrY - crControlGroupboxArea.top, crControlValuePlaceHolder.Width()/3, crControlValuePlaceHolder.Height(),
pControlGroupboxArea->GetSafeHwnd(),
(HMENU)(int)(nCurrID+2),
theApp.m_hInstance, NULL);
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE);
nCurrX += crControlValuePlaceHolder.Width()/3 + nXBufferSizeAfterSmallEdit;
hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT",
"",
WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD | uiDisabledFlagIfNecessary,
nCurrX - crControlGroupboxArea.left, nCurrY - crControlGroupboxArea.top, crControlValuePlaceHolder.Width()/3, crControlValuePlaceHolder.Height(),
pControlGroupboxArea->GetSafeHwnd(),
(HMENU)(int)(nCurrID+3),
theApp.m_hInstance, NULL);
nCurrX += crControlValuePlaceHolder.Width()/3 + nXBufferSizeAfterFullEdit;
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE);
break;
case efloat:
case eint:
case eLPSTR:
case eBOOL:
hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT",
"",
WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD | uiDisabledFlagIfNecessary,
nCurrX - crControlGroupboxArea.left, nCurrY - crControlGroupboxArea.top, crControlValuePlaceHolder.Width(), crControlValuePlaceHolder.Height(),
pControlGroupboxArea->GetSafeHwnd(),
(HMENU)(int)(nCurrID+1),
theApp.m_hInstance, NULL);
nCurrX += crControlValuePlaceHolder.Width() + nXBufferSizeAfterFullEdit;
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE);
break;
} // switch on property type
nCurrID += 4;
nCurrentProperty++;
} // while currentproperty
nCurrY += crControlValuePlaceHolder.Height() + nYBufferSizeAfterRow;
nCurrObject++;
} // while nCurrentObject
m_nLastControlID = nCurrID;
} // end of CreateSubControlsForProperties()
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::OnOK()
{
//
// Validate the data and save any changes made since the last sel change
//
UpdateControlData(FALSE);
//
// Ask them if they want to commit the changes? Or should pressing OK be enough? Should there be a
// safety net?
//
if (m_fDirty)
{
int ret = MessageBox( MyLoadStringTempBuffer(IDS_SAVE_WEAPONS_CHANGES), MyLoadStringTempBuffer(IDS_SAVE_WEAPONS_CHANGES_CAPTION), MB_YESNO);
if (ret != IDYES)
{
return;
}
//
// save the changes, exit if failed without ending the dialog
//
if (!SaveObjectData())
{
MessageBox(MyLoadStringTempBuffer(IDS_SAVE_WEAPONS_FAILED), MyLoadStringTempBuffer(IDS_ERROR_CAPTION), MB_OK | MB_ICONEXCLAMATION);
}
}
//
// If we got here, everything should be saved
//
CDialog::OnOK();
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::OnCancel()
{
//
// It's safe to exit, as long as all the notation files are closed out, which should be the case
//
CDialog::OnCancel();
}
//****************************************************************************************
//
// Sets the root directory to search under. Only goes one level deep currently
//
//****************************************************************************************
BOOL CDlgObjectBalance::SetObjectFilesDirectory(LPCSTR lpszDirectoryPath)
{
m_strObjectFilesRootDirectory = lpszDirectoryPath;
EndDirectoryWithBackSlash(m_strObjectFilesRootDirectory );
return TRUE;
}
//****************************************************************************************
//
// Sets the root file name type to search for like "*.data"
//
//****************************************************************************************
BOOL CDlgObjectBalance::SetFileNameToSearchSubdirectoriesFor(LPCSTR lpszFileSearchString)
{
m_strFileNameToSearchSubdirectoriesFor = lpszFileSearchString;
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::ClearObjectDataSet()
{
//
// If you didn't allocate this structure as a whole you have to walk the tree and kill the internal
// pointer memory before you do this, but if you used the allocate_... function provided above it was
// all allocated as one huge chunk instead of in parts.
//
if (m_pObjectList)
{
free(m_pObjectList);
m_pObjectList = NULL;
}
}
//****************************************************************************************
//
//
//****************************************************************************************
LPCSTR CDlgObjectBalance::GetPageNameToPropertyName(LPCSTR szPropertyName)
{
static char s_szPageNameBuffer[128];
// get everything up to the first \ in the string
const char * pTempSrc = szPropertyName;
char * pTempDest = s_szPageNameBuffer;
while (*pTempSrc && *pTempSrc != '\\') *(pTempDest++) = *(pTempSrc++);
*pTempDest = '\0';
return s_szPageNameBuffer;
}
//****************************************************************************************
//
//
//****************************************************************************************
LPCSTR CDlgObjectBalance::GetEntryNameToPropertyName(LPCSTR szPropertyName)
{
static char s_szEntryNameBuffer[128];
// get everything after the last \ in the string
const char * pTempSrc = szPropertyName;
const char * pLastBackSlash = szPropertyName;
while (*pTempSrc)
{
if (*pTempSrc == '\\')
pLastBackSlash = pTempSrc;
pTempSrc++;
}
if (*pLastBackSlash == '\\')
pLastBackSlash++;
strcpy(s_szEntryNameBuffer, pLastBackSlash);
return s_szEntryNameBuffer;
}
//****************************************************************************************
//
// Save weapons data will save all the information back to the appropriate notation files. It only saves
// out the weapons that are changed.
//
//****************************************************************************************
BOOL CDlgObjectBalance::SaveObjectData()
{
int nFailures = 0;
for (int i = 0; i< m_pObjectList->nObjectCount;i++)
{
if (!m_pObjectList->ppPropertiesArray[i]->fDirty) // not an error condition, just a shortcut
continue; // don't worry about saving this one if it hasn't changed.
if (!m_pObjectList->ppPropertiesArray[i]->szObjectName[0])
{
nFailures++;
continue;
}
if (m_pObjectList->ppPropertiesArray[i]->fReadOnly) // shouldn't have been allowed to change this
{
nFailures++;
continue;
}
//
// Loop through all the properties and save them
//
Page * page = NULL;
char szCurrentPageName[128] = ""; // used to prevent repetitively searching for the same page
NotationFile outfile((LPCSTR)m_pObjectList->ppPropertiesArray[i]->szObjectName, NotationFile::Raw);
for (int j=0; j < m_pObjectList->ppPropertiesArray[i]->nProperties; j++)
{
const char * szPageName = GetPageNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->szPropertyTag);
if (!page || strcmp(szCurrentPageName, szPageName))
{
strcpy(szCurrentPageName, szPageName);
page = outfile.FindPage(szPageName);
if (!page) // if for some reason we can't find the page, jump out
continue;
}
const char * szEntryName = GetEntryNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->szPropertyTag);
//
// For each item in the data list, if it shouldn't be there, delete it. If it supposed to be there set it
// Assumption is made that there are not two of any particular value key
//
if (!m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->fPresent)
{
page->DeleteNote(szEntryName);
}
else
{
page->DeleteNote(szEntryName); // temporary kludge to force the dirty bit. This can be removed
// after we decide if it is safe to make "SetEntry" set the dirty bit itself
switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->ePropertyType)
{
case efloat:
page->SetEntry(szEntryName, m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.fltValue);
break;
case eint:
page->SetEntry(szEntryName, m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.nValue);
break;
case eLPSTR:
page->SetEntry(szEntryName, m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.szValue);
break;
case eBOOL:
page->SetEntry(szEntryName, m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.fValue);
break;
case eVector3D:
{
Vector3D v3D(m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.v3dValues.x,
m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.v3dValues.y,
m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.v3dValues.z);
page->SetEntry(szEntryName, (Vector3D)v3D);
break;
}
} // switch for property type
} // else, we are setting a property instead of removing one (ie.. fPresent true)
} // for loop iterating properties
outfile.Save();
} // for loop iterating objects
return (!nFailures);
}
//****************************************************************************************
// LoadObjectData()
//
// This routine will search the content\weaponsubsystems directory for subdirectories containing .data files
// It will then open those .data files to read in weapon data. It is a simplistic algorithm that should be replaced
// by either searching through resources.build or some other weapons reference file if they are made to be fully up
// to date with their references to the weapons.
//
// Recursive function so watch what kind of initializations you do, or how you effect
// global variables.
//
// Directory passed in must end in a backslash
//****************************************************************************************
BOOL CDlgObjectBalance::LoadObjectData(LPCSTR szDirectoryToSearchFor, DIRECTORYSEARCHTYPE eSearchType)
{
CString strRootDirSearchString = szDirectoryToSearchFor;
strRootDirSearchString += "*.*";
CString strFullSubdirectoryName ;
BOOL fRet = TRUE;
//
// If we are only supposed to seach in the root directory pass this to the next function that finds
// the actual files
//
if (eSearchType == eRootOnly)
{
fRet = LoadDataFilesFromSubdirectory(szDirectoryToSearchFor);
return fRet; // return so we don't do any more searching
}
//
// If we are doing all directories then we should search in the root as well, then
// proceed down to the next level.
//
if (eSearchType == eAllSubdirectories)
{
fRet = LoadDataFilesFromSubdirectory(szDirectoryToSearchFor);
}
//
// If we got an error, exit now, we don't continue searching the subdirectories
//
if (!fRet)
return fRet;
//
// If we got here we need to search for subdirectories of the current one
// Then call this function recursively on each of those directories
//
//
// Now we iterate through the current directory looking for subdirectories.
//
//
WIN32_FIND_DATA wfdFindFileData;
HANDLE hFileSearch = FindFirstFile((LPCSTR)strRootDirSearchString , &wfdFindFileData);
if (hFileSearch == INVALID_HANDLE_VALUE)
{
// strOutput.Format("\r\nError : Didn't find any files in the source dir to copy.");
// OutputString(strOutput);
return TRUE;
}
if (wfdFindFileData.cFileName[0] == '\0')
{
// strOutput.Format("\r\nError : Didn't find any files in the source dir to copy.");
// OutputString(strOutput);
FindClose(hFileSearch);
return TRUE;
}
while (wfdFindFileData.cFileName[0])
{
if (!stricmp(wfdFindFileData.cFileName, ".") || !stricmp(wfdFindFileData.cFileName, ".."))
{
goto NextFile;
}
if (!(wfdFindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
goto NextFile;
}
strFullSubdirectoryName = szDirectoryToSearchFor;
strFullSubdirectoryName += wfdFindFileData.cFileName;
EndDirectoryWithBackSlash(strFullSubdirectoryName);
if (eSearchType == eAllSubdirectories)
{
LoadObjectData(strFullSubdirectoryName, eAllSubdirectories);
}
else // since eRootOnly was already weeded out above, this means "eSingleSubdirectory"
{
LoadObjectData(strFullSubdirectoryName, eRootOnly);
}
NextFile:
if (!FindNextFile(hFileSearch, &wfdFindFileData))
{
break;
}
} // while
FindClose(hFileSearch);
fRet = TRUE;
//
// Now the list box should be updated. We need a default selection, and then that will trigger the
// the fields to update correctly on the dialog box.
//
return fRet;
}
//****************************************************************************************
//
//****************************************************************************************
LPCSTR CDlgObjectBalance::GetShortObjectName(LPCSTR szObjectName)
{
//
// CString is used to remove the directory info To the weapons name. Find the last \
//
CString strObjectNameOnly(szObjectName);
int nPos = 0;
if (!m_fShowFullObjectName)
{
nPos = strObjectNameOnly.ReverseFind('\\');
nPos ++; // goes to 0 if not found, otherwise the character after the \ or the null terminator if that's last
}
return (szObjectName + nPos);
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::LoadDataFilesFromSubdirectory(CString strSubdirectory)
{
EndDirectoryWithBackSlash(strSubdirectory);
CString strFullFilename ;
CString strRootDirSearchString = strSubdirectory;
strRootDirSearchString += m_strFileNameToSearchSubdirectoriesFor;
//
// Now we iterate through the subdirectory looking for files
//
//
WIN32_FIND_DATA wfdFindFileData;
HANDLE hFileSearch = FindFirstFile((LPCSTR)strRootDirSearchString , &wfdFindFileData);
if (hFileSearch == INVALID_HANDLE_VALUE)
{
// strOutput.Format("\r\nError : Didn't find any files in the source dir to copy.");
// OutputString(strOutput);
return TRUE;
}
if (wfdFindFileData.cFileName[0] == '\0')
{
// strOutput.Format("\r\nError : Didn't find any files in the source dir to copy.");
// OutputString(strOutput);
FindClose(hFileSearch);
return TRUE;
}
while (wfdFindFileData.cFileName[0])
{
if (!stricmp(wfdFindFileData.cFileName, ".") || !stricmp(wfdFindFileData.cFileName, ".."))
{
goto NextFile;
}
if (wfdFindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
goto NextFile;
}
strFullFilename = strSubdirectory;
strFullFilename += wfdFindFileData.cFileName;
//
// See if there is an additional filter function to call, and if so, call it
//
if (m_fnFilterFunction && !m_fnFilterFunction((LPCSTR)strFullFilename))
{
goto NextFile;
}
//
// We have a .data file, so see if it is appropriately setup and load into a data structure and
// add to the list box. We need to know if it is read only so we know whether or not we can
// alter the data
// The data structure will also have to store a variable to know if the data has been altered.
//
if (LoadObjectDataFromFile(strFullFilename , (wfdFindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)))
{
//
// If we successfully loaded the weapon, add it to the list box
//
// Alias some of the data for readability of the code
int nCurrObject = m_pObjectList->nObjectCount;
CDOPPROPERTIES_OBJECT_PROPERTIES * pObjectPropertiesArray = (m_pObjectList->ppPropertiesArray[nCurrObject]);
//
// CString is used to remove the directory info To the weapons name. Find the last \
//
CString strObjectNameOnly(pObjectPropertiesArray->szObjectName);
int nPos = 0;
if (!m_fShowFullObjectName)
{
nPos = strObjectNameOnly.ReverseFind('\\');
nPos ++; // goes to 0 if not found, otherwise the character after the \ or the null terminator if that's last
}
m_pObjectList->nObjectCount++; // only increment on success since we don't want the index off in the list
}
NextFile:
if (!FindNextFile(hFileSearch, &wfdFindFileData))
{
break;
}
} // while
FindClose(hFileSearch);
return TRUE;
}
//****************************************************************************************
//
//
//
//
//
//****************************************************************************************
BOOL CDlgObjectBalance::LoadObjectDataFromFile(CString strFullObjectFilename, BOOL fReadOnly )
{
// CString strOutput;
NotationFile infile(strFullObjectFilename, NotationFile::Raw);
//
// Alias some of the data for readability of the code
int nCurrObject = m_pObjectList->nObjectCount;
CDOPPROPERTIES_OBJECT_PROPERTIES * pObjectPropertiesArray = (m_pObjectList->ppPropertiesArray[nCurrObject]);
int nTotalProperties = m_paPropertiesToEdit->nCount;
//
// allocate the memory for the properties for this object
//
pObjectPropertiesArray->fDirty = FALSE;
pObjectPropertiesArray->fReadOnly = fReadOnly;
pObjectPropertiesArray->nProperties = nTotalProperties;
strcpy(pObjectPropertiesArray->szObjectName, (LPCSTR)strFullObjectFilename);
// already allocated
// pObjectPropertiesArray->ppObjectProperties = Allocate_CDOPPROPERTIES_OBJECT_PROPERTIES(nTotalProperties);
//
// Now go through and for each item in the properties list we need to get the page and entry
// we will cache the page name so we don't keep getting the same one if it repeats
//
Page * page = NULL;
char szCurrentPageName[128] = ""; // used to prevent repetitively searching for the same page
for (int j=0; j < nTotalProperties; j++)
{
pObjectPropertiesArray->ppObjectProperties[j]->fPresent = FALSE; // by default...
// put in default values for each type
switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->ePropertyType)
{
case efloat:
pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.fltValue = 0.0f;
break;
case eint:
pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.nValue = 0;
break;
case eLPSTR:
pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.szValue[0] = 0;
break;
case eBOOL:
pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.fValue = FALSE;
break;
case eVector3D:
pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.v3dValues.x = 0.0f;
pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.v3dValues.y = 0.0f;
pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.v3dValues.z = 0.0f;
break;
} // switch for property type
const char * szPageName = GetPageNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->szPropertyTag);
if (!page || strcmp(szCurrentPageName, szPageName))
{
strcpy(szCurrentPageName, szPageName);
page = infile.FindPage(szPageName);
if (!page) // if for some reason we can't find the page, jump out
continue;
}
const char * szEntryName = GetEntryNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->szPropertyTag);
//
// For each item in the data list, if it shouldn't be there, delete it. If it supposed to be there set it
// Assumption is made that there are not two of any particular value key
//
switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->ePropertyType)
{
case efloat:
if (page->GetEntry(szEntryName, &(pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.fltValue)))
{
pObjectPropertiesArray->ppObjectProperties[j]->fPresent = TRUE;
}
break;
case eint:
if (page->GetEntry(szEntryName, &(pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.nValue)))
{
pObjectPropertiesArray->ppObjectProperties[j]->fPresent = TRUE;
}
break;
case eLPSTR:
{
const char * szTemp;
if (page->GetEntry(szEntryName, &szTemp))
{
strcpy(pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.szValue, szTemp) ;
pObjectPropertiesArray->ppObjectProperties[j]->fPresent = TRUE;
}
}
break;
case eBOOL:
if (page->GetEntry(szEntryName, &(pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.fValue)))
{
pObjectPropertiesArray->ppObjectProperties[j]->fPresent = TRUE;
}
break;
case eVector3D:
{
Vector3D v3D(0.0f, 0.0f, 0.0f);
if (page->GetEntry(szEntryName, (Vector3D *)&v3D))
{
pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.v3dValues.x = v3D.x;
pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.v3dValues.y = v3D.y;
pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.v3dValues.z = v3D.z;
pObjectPropertiesArray->ppObjectProperties[j]->fPresent = TRUE;
}
break;
}
} // switch for property type
} // for loop iterating properties
//
// This is a good place to make any known automated updates to the data. If we have just made them all
// add a new variable, or we removed a line, or we changed the type of data stored, we can do it at load
// time, then mark the dirty flag. Beware to honor the readonly flag here though. We don't want the read only
// and the dirty bit set at the same time.
//
//
// Note that we don't increment the weapon count here as we have to make sure we added to the list box
// since they are kept in sync by the index in the list box.
//
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::DisableAllControls()
{
for (UINT i = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (2) )
; i < m_nLastControlID ; i++)
{
CWnd * pWnd = GetDescendantWindow(i);
if (pWnd)
pWnd->EnableWindow(FALSE);
}
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::GetBOOLFromButton(UINT uiID, BOOL * pfDest)
{
CButton * pWnd = (CButton *)GetDescendantWindow(uiID);
if (!pWnd)
return FALSE;
*pfDest = pWnd->GetCheck();
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::GetBOOLFromControl(UINT uiID, BOOL * pfDest)
{
CWnd * pWnd = GetDescendantWindow(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
pWnd->GetWindowText(szTemp, 255);
*pfDest = FALSE;
if (!stricmp(szTemp, "true") ||
!stricmp(szTemp, "yes") ||
!stricmp(szTemp, "1"))
{
*pfDest = TRUE;
}
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::GetfloatFromControl(UINT uiID, float * pfltDest)
{
CWnd * pWnd = GetDescendantWindow(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
pWnd->GetWindowText(szTemp, 255);
*pfltDest = (float)atof(szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::GetLPSTRFromControl(UINT uiID, LPSTR pszDest)
{
CWnd * pWnd = GetDescendantWindow(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
pWnd->GetWindowText(szTemp, 255);
szTemp[255] = 0;
strcpy(pszDest, szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::GetintFromControl(UINT uiID, int * pnDest)
{
CWnd * pWnd = GetDescendantWindow(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
pWnd->GetWindowText(szTemp, 255);
*pnDest = atoi(szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::GetVector3DFromControl(UINT uiID, float * pfltx, float * pflty, float * pfltz)
{
CWnd * pWnd = GetDescendantWindow(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
pWnd->GetWindowText(szTemp, 255);
*pfltx = (float)atof(szTemp);
pWnd = GetDescendantWindow(uiID +1);
if (!pWnd)
return FALSE;
pWnd->GetWindowText(szTemp, 255);
*pflty = (float)atof(szTemp);
pWnd = GetDescendantWindow(uiID +2);
if (!pWnd)
return FALSE;
pWnd->GetWindowText(szTemp, 255);
*pfltz = (float)atof(szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::SetBOOLToButton(UINT uiID, BOOL fDest)
{
CButton * pWnd = (CButton *)GetDescendantWindow(uiID);
if (!pWnd)
return FALSE;
pWnd->SetCheck(fDest);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::SetBOOLToControl(UINT uiID, BOOL fSrc)
{
CWnd * pWnd = GetDescendantWindow(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
sprintf(szTemp, fSrc ? "true" : "false");
pWnd->SetWindowText(szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::SetfloatToControl(UINT uiID, float fltSrc)
{
CWnd * pWnd = GetDescendantWindow(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
sprintf(szTemp, "%f", (double) fltSrc);
pWnd->SetWindowText(szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::SetLPSTRToControl(UINT uiID, LPSTR pszSrc)
{
CWnd * pWnd = GetDescendantWindow(uiID);
if (!pWnd)
return FALSE;
pWnd->SetWindowText(pszSrc);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::SetintToControl(UINT uiID, int nSrc)
{
CWnd * pWnd = GetDescendantWindow(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
sprintf(szTemp, "%d", nSrc);
pWnd->SetWindowText(szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::SetVector3DToControl(UINT uiID, float fltx, float flty, float fltz)
{
CWnd * pWnd = GetDescendantWindow(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
sprintf(szTemp, "%f", (double) fltx);
pWnd->SetWindowText(szTemp);
sprintf(szTemp, "%f", (double) flty);
pWnd->SetWindowText(szTemp);
sprintf(szTemp, "%f", (double) fltz);
pWnd->SetWindowText(szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::UpdateControlData(BOOL fToControls)
{
CDOPPROPERTIES_OBJECT_PROPERTIES * pObjectProperties = NULL;
if (!fToControls)
{
pObjectProperties =
Allocate_CDOPPROPERTIES_OBJECT_PROPERTIES(m_paPropertiesToEdit->nCount);
}
for (int nCurrentObject = 0; nCurrentObject < m_pObjectList->nObjectCount; nCurrentObject++)
{
//
//
UINT uiFirst = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrentObject+3) );
for (int nCurrentProperty = 0; nCurrentProperty < m_paPropertiesToEdit->nCount; nCurrentProperty++)
{
// First is the first ID of the controls for this property. End is the first control of the next
// property.
UINT uCurrID = uiFirst + (nCurrentProperty*4);
if (!fToControls)
{
Copy_CDOPPROPERTIES_OBJECT_PROPERTIES(pObjectProperties, m_pObjectList->ppPropertiesArray[nCurrentObject]);
GetBOOLFromButton(uCurrID,&(pObjectProperties->ppObjectProperties[nCurrentProperty]->fPresent) );
switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType)
{
case efloat:
GetfloatFromControl(uCurrID + 1,&(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.fltValue));
break;
case eint:
GetintFromControl(uCurrID + 1,&(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.nValue));
break;
case eLPSTR:
GetLPSTRFromControl(uCurrID + 1,(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.szValue));
break;
case eBOOL:
GetBOOLFromControl(uCurrID + 1,&(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.fValue));
break;
case eVector3D:
GetVector3DFromControl(uCurrID + 1,&(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.v3dValues.x),
&(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.v3dValues.y),
&(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.v3dValues.z));
break;
} // switch on property type
BOOL fDirty = !IsEqual_CDOPPROPERTIES_OBJECT_PROPERTIES(m_pObjectList->ppPropertiesArray[nCurrentObject], pObjectProperties);
//
if( fDirty && !m_pObjectList->ppPropertiesArray[nCurrentObject]->fReadOnly)
{
m_fDirty = TRUE;
Copy_CDOPPROPERTIES_OBJECT_PROPERTIES(m_pObjectList->ppPropertiesArray[nCurrentObject], pObjectProperties);
m_pObjectList->ppPropertiesArray[nCurrentObject]->fDirty = TRUE;
}
} // if !fFromControls
else
{
SetBOOLToButton(uCurrID,(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->fPresent) );
switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType)
{
case efloat:
SetfloatToControl(uCurrID + 1,(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.fltValue));
break;
case eint:
SetintToControl(uCurrID + 1,(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.nValue));
break;
case eLPSTR:
SetLPSTRToControl(uCurrID + 1,(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.szValue));
break;
case eBOOL:
SetBOOLToControl(uCurrID + 1,(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.fValue));
break;
case eVector3D:
SetVector3DToControl(uCurrID + 1,(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.v3dValues.x),
(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.v3dValues.y),
(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.v3dValues.z));
break;
} // switch on property type
}
} // for loop for property list
} // nCurrentObject loop
free(pObjectProperties);
return TRUE;
}
#define TooSmall(M_fltTemp) ((M_fltTemp >= -0.00001f) && (M_fltTemp <= 0.00001f))
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::AlterAllProperties(CDOPMATHTYPE eMathType)
{
//
// Run through the list of properties, and read in the value from the controls at the top
// if the control value is non-zero, call the function for altering all the object values
// for that property.
//
float fltTemp;
int nTemp;
float fltTempArray[3];
UINT uiFirst = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (1));
for (int nCurrentProperty = 0; nCurrentProperty < m_paPropertiesToEdit->nCount; nCurrentProperty++)
{
CDOPVARTYPE eVarType = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType;
switch (eVarType)
{
case efloat:
fltTemp = 0.0f;
GetfloatFromControl(uiFirst + (nCurrentProperty*4 + 1), &fltTemp);
if (TooSmall(fltTemp))
{
continue;
}
AlterProperty(nCurrentProperty, (void *)&fltTemp, eMathType);
break;
case eint:
GetintFromControl(uiFirst + (nCurrentProperty*4 + 1), &nTemp);
nTemp = 0;;
if (nTemp == 0)
{
continue;
}
AlterProperty(nCurrentProperty, (void *)&nTemp, eMathType);
break;
case eVector3D:
fltTempArray[0] = 0.0f; fltTempArray[1] = 0.0f; fltTempArray[2] = 0.0f;
if (TooSmall(fltTempArray[0]) && TooSmall(fltTempArray[1]) && TooSmall(fltTempArray[2]))
{
continue;
}
GetVector3DFromControl(uiFirst + (nCurrentProperty*4 + 1), &(fltTempArray[0]), &(fltTempArray[1]), &(fltTempArray[2]));
AlterProperty(nCurrentProperty, (void *)&(fltTempArray[0]), eMathType);
break;
}
}
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::DoTheMath(float * pValue, float * pModifier, CDOPMATHTYPE eMath)
{
if (TooSmall(*pModifier))
{
return;
}
switch (eMath)
{
case ePlus:
*pValue = *pValue + *pModifier;
break;
case eMinus:
*pValue = *pValue - *pModifier;
break;
case eMultiply:
*pValue = *pValue * *pModifier;
break;
case eDivide:
*pValue = *pValue / *pModifier;
break;
}
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::DoTheMath(int * pValue, int * pModifier, CDOPMATHTYPE eMath)
{
if (!*pModifier)
{
return;
}
switch (eMath)
{
case ePlus:
*pValue = *pValue + *pModifier;
break;
case eMinus:
*pValue = *pValue - *pModifier;
break;
case eMultiply:
*pValue = *pValue * *pModifier;
break;
case eDivide:
*pValue = *pValue / *pModifier;
break;
}
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::AlterProperty(int nProperty, void * pValueToAlterWith, CDOPMATHTYPE eMath)
{
//
//
//
for (int nCurrentObject = 0; nCurrentObject < m_pObjectList->nObjectCount; nCurrentObject++)
{
//
//
UINT uiOfControl = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrentObject+3) ) ;
CButton * pWnd = (CButton *)GetDescendantWindow(uiOfControl - 1);
uiOfControl += 1 + (nProperty*4);
//
// If the apply button isn't checked this object should be skipped
//
if (pWnd && !pWnd->GetCheck())
continue;
CDOPVARTYPE eVarType = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nProperty]->ePropertyType;
switch (eVarType)
{
case efloat:
{
float fltValue;
GetfloatFromControl(uiOfControl, &fltValue);
DoTheMath(&fltValue, (float *)pValueToAlterWith, eMath);
SetfloatToControl(uiOfControl, fltValue);
}
break;
case eint:
{
int nValue;
GetintFromControl(uiOfControl, &nValue);
DoTheMath(&nValue, (int *)pValueToAlterWith, eMath);
SetintToControl(uiOfControl, nValue);
}
break;
case eVector3D:
{
for (int i = 0; i<3; i++)
{
float fltValue;
GetfloatFromControl(uiOfControl + i, &fltValue);
DoTheMath(&fltValue, (float *)&(((float *)pValueToAlterWith)[i]), eMath);
SetfloatToControl(uiOfControl + i, fltValue);
}
}
break;
}
}
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::OnValuePlus()
{
AlterAllProperties(ePlus);
ClearModifierCells();
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::OnValueMultiply()
{
AlterAllProperties(eMultiply);
ClearModifierCells();
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::OnValueMinus()
{
AlterAllProperties(eMinus);
ClearModifierCells();
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::OnValueDivide()
{
AlterAllProperties(eDivide);
ClearModifierCells();
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::ClearModifierCells()
{
//
// Since the cells have been used to do math already we want to clear the values to make
// sure we don't do an operation twice when not wanting it.
//
UINT uiFirst = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (1));
for (int nCurrentProperty = 0; nCurrentProperty < m_paPropertiesToEdit->nCount; nCurrentProperty++)
{
CDOPVARTYPE eVarType = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType;
switch (eVarType)
{
case efloat:
SetfloatToControl(uiFirst + (nCurrentProperty*4 + 1), 0.0f);
break;
case eint:
SetintToControl(uiFirst + (nCurrentProperty*4 + 1), 0);
break;
case eVector3D:
SetVector3DToControl(uiFirst + (nCurrentProperty*4 + 1), 0.0f, 0.0f, 0.0f);
break;
} // switch eVarType
} // for properties loop
} // end of ClearModifierCells
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
int nCurPos = m_nCurScrollPosVert;
switch(nSBCode)
{
case SB_BOTTOM:
m_nCurScrollPosVert = m_pObjectList->nObjectCount - m_nMaxVisibleVert + 2;
break;
case SB_ENDSCROLL:
m_nCurScrollPosVert = pScrollBar->GetScrollPos();
break;
case SB_LINEDOWN:
m_nCurScrollPosVert ++;
break;
case SB_LINEUP:
m_nCurScrollPosVert --;
break;
case SB_PAGEDOWN:
m_nCurScrollPosVert += m_nMaxVisibleVert;
break;
case SB_PAGEUP:
m_nCurScrollPosVert -= m_nMaxVisibleVert;
break;
case SB_THUMBPOSITION:
m_nCurScrollPosVert = nPos;
break;
case SB_THUMBTRACK:
m_nCurScrollPosVert = nPos;
break;
case SB_TOP:
m_nCurScrollPosVert = 0;
break;
}
m_nCurScrollPosVert = max(0, m_nCurScrollPosVert);
m_nCurScrollPosVert = min(m_nCurScrollPosVert, m_pObjectList->nObjectCount - m_nMaxVisibleVert + 2);
pScrollBar->SetScrollPos(m_nCurScrollPosVert, TRUE);
CWnd * pControlGroupboxArea = GetDescendantWindow(IDC_DOP_PROPERTIES);
int nMoveAmount = m_nScrollIncrementVert * (nCurPos - m_nCurScrollPosVert);
CWnd * pChildWindow = pControlGroupboxArea->GetWindow(GW_CHILD);
//CRect crControlGroupboxArea;
//pControlGroupboxArea->GetWindowRect(crControlGroupboxArea);
CRect crWindowRect;
while (pChildWindow)
{
pChildWindow->GetWindowRect(crWindowRect);
::MapWindowPoints(NULL, pControlGroupboxArea->GetSafeHwnd(), (LPPOINT) (LPRECT)crWindowRect, 2);
// pControlGroupboxArea->InvalidateRect(crWindowRect, TRUE);
// pChildWindow->InvalidateRect(NULL, TRUE);
crWindowRect.OffsetRect(0, nMoveAmount);
// pControlGroupboxArea->InvalidateRect(crWindowRect, TRUE);
pChildWindow->SetWindowPos(NULL, crWindowRect.left, crWindowRect.top, 0, 0,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSIZE | SWP_NOZORDER );
// pChildWindow->InvalidateRect(NULL, TRUE);
pChildWindow = pChildWindow->GetWindow(GW_HWNDNEXT);
}
/*
pControlGroupboxArea->ScrollWindow(0, m_nScrollIncrementVert * (m_nCurScrollPosVert - nCurPos), NULL, NULL);
*/
CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
CRect crGroupboxRect;
pControlGroupboxArea->GetWindowRect(crGroupboxRect);
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crGroupboxRect, 2);
// InvalidateRect(crGroupboxRect, TRUE);
crGroupboxRect.OffsetRect(-crGroupboxRect.left, -crGroupboxRect.top);
// pControlGroupboxArea->InvalidateRect(crGroupboxRect, TRUE);
pControlGroupboxArea->InvalidateRect(NULL, TRUE);
pControlGroupboxArea->UpdateWindow();
// UpdateWindow();
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
int nCurPos = m_nCurScrollPosHorz;
switch(nSBCode)
{
case SB_BOTTOM:
m_nCurScrollPosHorz = m_paPropertiesToEdit->nCount - m_nMaxVisibleVert + 2;
break;
case SB_ENDSCROLL:
m_nCurScrollPosHorz = pScrollBar->GetScrollPos();
break;
case SB_LINEDOWN:
m_nCurScrollPosHorz ++;
break;
case SB_LINEUP:
m_nCurScrollPosHorz --;
break;
case SB_PAGEDOWN:
m_nCurScrollPosHorz += m_nMaxVisibleHorz;
break;
case SB_PAGEUP:
m_nCurScrollPosHorz -= m_nMaxVisibleHorz;
break;
case SB_THUMBPOSITION:
m_nCurScrollPosHorz = nPos;
break;
case SB_THUMBTRACK:
m_nCurScrollPosHorz = nPos;
break;
case SB_TOP:
m_nCurScrollPosHorz = 0;
break;
}
m_nCurScrollPosHorz = max(0, m_nCurScrollPosHorz);
m_nCurScrollPosHorz = min(m_nCurScrollPosHorz, m_paPropertiesToEdit->nCount - m_nMaxVisibleHorz + 2);
pScrollBar->SetScrollPos(m_nCurScrollPosHorz, TRUE);
CWnd * pControlGroupboxArea = GetDescendantWindow(IDC_DOP_PROPERTIES);
int nMoveAmount = m_nScrollIncrementHorz * (nCurPos - m_nCurScrollPosHorz);
CRect crDisplayableArea;
pControlGroupboxArea->GetClientRect(crDisplayableArea);
CRect crWindowRect;
CWnd * pControlValuePlaceHolder = GetDescendantWindow(IDC_VARIABLE_PRESENT_PLACEHOLDER, FALSE);
pControlValuePlaceHolder->GetWindowRect(crWindowRect);
//
// Set the displayable area to the left of the first "present" check box
//
::MapWindowPoints(NULL, pControlGroupboxArea->GetSafeHwnd(), (LPPOINT) (LPRECT)crWindowRect, 2);
crDisplayableArea.left = crWindowRect.left - 1;
CWnd * pChildWindow = pControlGroupboxArea->GetWindow(GW_CHILD);
while (pChildWindow)
{
if (IsHorizontallyScrollable(pChildWindow))
{
pChildWindow->GetWindowRect(crWindowRect);
::MapWindowPoints(NULL, pControlGroupboxArea->GetSafeHwnd(), (LPPOINT) (LPRECT)crWindowRect, 2);
crWindowRect.OffsetRect(nMoveAmount, 0);
pChildWindow->SetWindowPos(NULL, crWindowRect.left, crWindowRect.top, 0, 0,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSIZE | SWP_NOZORDER );
pChildWindow->ShowWindow(IsRectTotallyWithinHorizontally(crWindowRect, crDisplayableArea) ? SW_SHOW : SW_HIDE);
}
pChildWindow = pChildWindow->GetWindow(GW_HWNDNEXT);
}
//
// Scroll the text headers and property edit windows at the top.
//
int nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * 1;
for (int nCurrProperty = 0; nCurrProperty < m_paPropertiesToEdit->nCount; nCurrProperty++)
{
for (int nCurControl = 1; nCurControl < 4; nCurControl++)
{
for (int nRowMultiplier = 0; nRowMultiplier < 2; nRowMultiplier ++)
{
pChildWindow = GetDescendantWindow(nCurrID + nCurrProperty * 4 + nCurControl +
(((m_paPropertiesToEdit->nCount * 4) + 1) * nRowMultiplier), FALSE);
if (pChildWindow)
{
if (IsHorizontallyScrollable(pChildWindow))
{
CRect crTestRect;
pChildWindow->GetWindowRect(crWindowRect);
crTestRect = crWindowRect;// can't actually move this window relative to a non-parent window
::MapWindowPoints(NULL, pControlGroupboxArea->GetSafeHwnd(), (LPPOINT) (LPRECT)crTestRect, 2);
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crWindowRect, 2);
InvalidateRect(crWindowRect, TRUE);
crWindowRect.OffsetRect(nMoveAmount, 0);
InvalidateRect(crWindowRect, TRUE);
crTestRect.OffsetRect(nMoveAmount, 0);
pChildWindow->SetWindowPos(NULL, crWindowRect.left, crWindowRect.top, 0, 0,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSIZE | SWP_NOZORDER );
pChildWindow->ShowWindow(IsRectTotallyWithinHorizontally(crWindowRect, crDisplayableArea) ? SW_SHOW : SW_HIDE);
}
}
}
}
}
CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
CRect crGroupboxRect;
pControlGroupboxArea->GetWindowRect(crGroupboxRect);
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crGroupboxRect, 2);
crGroupboxRect.OffsetRect(-crGroupboxRect.left, -crGroupboxRect.top);
pControlGroupboxArea->InvalidateRect(NULL, TRUE);
pControlGroupboxArea->UpdateWindow();
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::IsRectTotallyWithinHorizontally(LPRECT pRectToTest, LPRECT pOuterRect) // used for scrolling
{
// we are going to clip the rectangles to a rectangle bordering the first present box on the left, and the
// client area of the static control for the other three sides
// they intersect so lets see if the one rect is totally contained
if ((min(pRectToTest->left, pOuterRect->left) == pOuterRect->left) &&
(max(pRectToTest->right, pOuterRect->right) == pOuterRect->right))
{
return TRUE;
}
return FALSE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::IsHorizontallyScrollable(CWnd * pChildWindow)
{
int nID = pChildWindow->GetDlgCtrlID();
//
// Don't move the name of the object
//
if (nID == IDC_STATIC)
return FALSE;
//
// If the id is an even multiplier of 4 off of the base then it is a present control
//
int nFirstButton = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * 1;
int nRowThisButtonWouldBeOn = (nID - nFirstButton) / ((m_paPropertiesToEdit->nCount * 4) + 1);
if (nID < nFirstButton)
return FALSE;
if (nID > IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * (m_pObjectList->nObjectCount+3))
return FALSE;
//
// Don't move the apply button either
// The apply button cheats and would actually be told it's one row below the current one by the math above
nRowThisButtonWouldBeOn--;
int nFirstButtonOnThisRow = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * (nRowThisButtonWouldBeOn+3);
if ( nID == (nFirstButtonOnThisRow - 1))
return FALSE;
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::OnEraseBkgnd( CDC* pDC )
{
return CDialog::OnEraseBkgnd(pDC);
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
if (IsCreatedControl(wParam))
{
//
//
//
OnNotifyCreatedControl(wParam, lParam, pResult);
}
return CDialog::OnNotify(wParam, lParam, pResult);
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::IsCreatedControl(int uID)
{
int nMinControl = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (2) );
return (uID >= nMinControl && uID <= m_nLastControlID);
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::OnNotifyCreatedControl(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
if (IsCreatedPresentButton(wParam))
{
//
// Figure out the correct items to enable/disable
//
for (int i = wParam + 1; i < wParam + 4; i++)
{
CButton * pButton = (CButton *)GetDescendantWindow(i, FALSE);
BOOL fChecked = pButton->GetCheck() == 1;
CWnd * pWnd = GetDescendantWindow(i, FALSE);
if (pButton && pWnd)
{
pWnd->EnableWindow(fChecked);
}
}
}
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::IsCreatedPresentButton(int uID)
{
//
// If the id is an even multiplier of 4 off of the base then it is a present control
//
int nFirstButton = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * 2;
int nRowThisButtonWouldBeOn = (uID - nFirstButton) / ((m_paPropertiesToEdit->nCount * 4) + 1);
int nFirstButtonOnThisRow = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * (nRowThisButtonWouldBeOn+3);
if ( ((uID - nFirstButtonOnThisRow) % 4 ) == 0)
return TRUE;
return FALSE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::OnCommand(WPARAM wParam, LPARAM lParam)
{
if (IsCreatedControl(LOWORD(wParam)))
{
//
//
//
OnCommandCreatedControl(wParam, lParam);
}
return CDialog::OnCommand(wParam, lParam);
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::OnCommandCreatedControl(WPARAM wParam, LPARAM lParam)
{
if (IsCreatedPresentButton(LOWORD(wParam)) && HIWORD(wParam) == BN_CLICKED)
{
//
// Figure out the correct items to enable/disable
//
CButton * pButton = (CButton *)GetDescendantWindow(LOWORD(wParam), FALSE);
if (pButton)
{
BOOL fChecked = pButton->GetCheck() == 1;
for (int i = LOWORD(wParam) + 1; i < LOWORD(wParam) + 4; i++)
{
CWnd * pWnd = GetDescendantWindow(i, FALSE);
if (pWnd)
{
pWnd->EnableWindow(fChecked);
}
}
}
}
else if (IsCreatedApplyButton(LOWORD(wParam)) && HIWORD(wParam) == BN_CLICKED)
{
//
// Get the state we should set the apply all button to
//
int nStateForAllButton = GetStateForApplyAllButton();
CButton * pButton = (CButton *) GetDescendantWindow(IDC_CHECKALL_APPLY_BUTTONS, FALSE);
if (pButton)
{
pButton->SetCheck(nStateForAllButton);
}
}
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::OnFillAllValues()
{
//
// Run through the row of values and copy the first element into all the rest
//
// All of our current uses for this dialog use floats or vector3d's so I currently
// don't worry about having ints/bools/strings in the row
//
float flt[3] = {0.0f, 0.0f, 0.0f};
//
// Scroll the text headers and property edit windows at the top.
//
int nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * 1;
int nCurrProperty = 0; // has to start at 0 to get our fill values
int nCurControl;
for (nCurControl = 1; nCurControl < 4; nCurControl++)
{
if (!GetfloatFromControl(nCurrID + nCurrProperty * 4 + nCurControl, &(flt[nCurControl -1])))
{
flt[nCurControl - 1] = 0.0f;
}
}
//
// Start loop at one since we got the data from the first one.
//
for (nCurrProperty = 1; nCurrProperty < m_paPropertiesToEdit->nCount; nCurrProperty++)
{
for (nCurControl = 1; nCurControl < 4; nCurControl++)
{
if (!SetfloatToControl(nCurrID + nCurrProperty * 4 + nCurControl, flt[nCurControl -1]))
{
flt[nCurControl - 1] = 0.0f;
}
}
}
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::OnCheckallApplyButtons()
{
//
// If our current state is off, turn all buttons on including this one
// If our current state is on, turn all buttons off including this one
// If our current state is other, turn all buttons off including this one
//
// This button state must be updated whenever any of the apply buttons are checked.
CButton * pButton = (CButton *) GetDescendantWindow(IDC_CHECKALL_APPLY_BUTTONS, FALSE);
if (pButton)
{
int nStateOfCheck = pButton->GetCheck();
if (nStateOfCheck == 2) // don't act it's not set to anything in particular
{
return;
}
SetAllApplyButtons(nStateOfCheck);
}
}
//****************************************************************************************
//
//****************************************************************************************
int CDlgObjectBalance::GetStateForApplyAllButton()
{
// Iterate through all the apply buttons
// Then if we have two that don't match we can return indeterminate. Otherwise we return the state
// of the buttons
int nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (3) );
CButton * pButton = NULL;
pButton = (CButton * ) GetDescendantWindow(nCurrID - 1);
if (!pButton)
{
return 2;
}
int nButtonStates = pButton->GetCheck();
// start at 1 since we already got one
for (int nCurrentObject = 1; nCurrentObject < m_pObjectList->nObjectCount; nCurrentObject++)
{
nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrentObject + 3) );
pButton = (CButton * ) GetDescendantWindow(nCurrID - 1);
if (!pButton)
{
return 2;
}
if (pButton->IsWindowEnabled())
{
if (pButton->GetCheck() != nButtonStates) // something isn't the same
{
return 2;
}
}
}
return nButtonStates;
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectBalance::SetAllApplyButtons(int nState)
{
// Iterate through all the apply buttons
// Then if we have two that don't match we can return indeterminate. Otherwise we return the state
// of the buttons
CButton * pButton = NULL;
int nCurrID = IDC_STATIC;
for (int nCurrentObject = 0; nCurrentObject < m_pObjectList->nObjectCount; nCurrentObject++)
{
nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrentObject + 3) );
pButton = (CButton * ) GetDescendantWindow(nCurrID - 1);
if (!pButton)
{
continue; // shouldn't really hit this though
}
if (pButton->IsWindowEnabled())
pButton->SetCheck(nState);
}
return;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectBalance::IsCreatedApplyButton(int uID)
{
//
// If the id is an even multiplier of 4 off of the base then it is a present control
//
int nFirstButton = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * 2;
int nRowThisButtonWouldBeOn = (uID - nFirstButton) / ((m_paPropertiesToEdit->nCount * 4) + 1);
//
// The apply button actually resides on the row below this one, so these calculations are one off
//
nRowThisButtonWouldBeOn ++;
int nFirstButtonOnThisRow = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * (nRowThisButtonWouldBeOn+3);
if ( uID == (nFirstButtonOnThisRow - 1))
return TRUE;
return FALSE;
}