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.
2413 lines
91 KiB
C++
2413 lines
91 KiB
C++
// DlgObjectBalance.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "mw4gameed.h"
|
|
#include <stdarg.h>
|
|
#include <stuff\notationfile.hpp>
|
|
#include <stuff\vector3d.hpp>
|
|
#include "DlgObjectBalance.h"
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
const int c_Max_Objects_Supported = 100;
|
|
extern CMW4GameEdApp 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;
|
|
|
|
|
|
}
|
|
|