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

1659 lines
61 KiB
C++

// DlgObjectProperties.cpp : implementation file
//
#include "stdafx.h"
#include "mw4gameed.h"
#include <stdarg.h>
#include <stuff\notationfile.hpp>
#include <stuff\vector3d.hpp>
#include "DlgObjectProperties.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
//
LPCSTR MyLoadStringTempBuffer(UINT uiID);
//
// This function needs to be moved somewhere more generic
//
//
LPCSTR MyLoadStringTempBuffer(UINT uiID)
{
static TCHAR strings[10][1024];
static nNext = 0;
nNext = (nNext + 1) % 10;
::LoadString(NULL, uiID, strings[nNext], 1023);
return strings[nNext];
}
// puts a backslash as the last char unless it's an empty string, ends in a slash already, or ends with a ':'
void EndDirectoryWithBackSlash(CString & strDir)
{
int nLen = strDir.GetLength();
if (!nLen)
return;
if (strDir.GetAt(nLen-1) == '\\' || strDir.GetAt(nLen -1) == ':')
return;
strDir += '\\';
}
/////////////////////////////////////////////////////////////////////////////
// CDlgObjectProperties 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 * CDlgObjectProperties::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 * CDlgObjectProperties::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 * CDlgObjectProperties::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 * CDlgObjectProperties::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 CDlgObjectProperties::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 CDlgObjectProperties::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 CDlgObjectProperties::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 CDlgObjectProperties::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 CDlgObjectProperties::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 CDlgObjectProperties::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;
}
//****************************************************************************************
//
//
//
//****************************************************************************************
CDlgObjectProperties::~CDlgObjectProperties()
{
if (m_pObjectList)
{
free(m_pObjectList);
}
}
//****************************************************************************************
//
//
//
//****************************************************************************************
CDlgObjectProperties::CDlgObjectProperties(CWnd* pParent /*=NULL*/)
: CDialog(CDlgObjectProperties::IDD, pParent)
{
//{{AFX_DATA_INIT(CDlgObjectProperties)
//}}AFX_DATA_INIT
m_pObjectList = NULL;
ClearObjectDataSet();
m_nCurSel = LB_ERR; // nothing selected, important to start here since we have no data loaded in the dialog yet
// 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_eSearchType = eSingleSubdirectory;
m_popCurObjectPropertiesArray = NULL;
m_fDirty = FALSE;
m_nLastControlID = IDC_DOP_PROPNAME;
}
//****************************************************************************************
//
//
//
//****************************************************************************************
int CDlgObjectProperties::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 CDlgObjectProperties::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDlgObjectProperties)
DDX_Control(pDX, IDC_OBJECTLIST, m_lbObjectList);
//}}AFX_DATA_MAP
}
//****************************************************************************************
//
//
//
//****************************************************************************************
BEGIN_MESSAGE_MAP(CDlgObjectProperties, CDialog)
//{{AFX_MSG_MAP(CDlgObjectProperties)
ON_LBN_SELCHANGE(IDC_OBJECTLIST, OnSelchangeObjectlist)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDlgObjectProperties message handlers
BOOL CDlgObjectProperties::OnInitDialog()
{
CDialog::OnInitDialog();
m_nCurSel = LB_ERR;
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();
UpdateData(FALSE);
m_lbObjectList.SetCurSel(0); // get the ball rolling by showing the first weapon in the list
OnSelchangeObjectlist();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectProperties::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_DOP_PROPNAME;
//
// 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 * pControlPropName = GetDlgItem(IDC_DOP_PROPNAME);
CWnd * pControlPropPresent = GetDlgItem(IDC_DOP_PROPPRESENT);
CWnd * pControlPropEdit1 = GetDlgItem(IDC_DOP_PROPEDIT1);
CWnd * pControlPropEdit2 = GetDlgItem(IDC_DOP_PROPEDIT2);
CWnd * pControlPropEdit3 = GetDlgItem(IDC_DOP_PROPEDIT3);
if (!pControlPropName || !pControlPropPresent || !pControlPropEdit1 || !pControlPropEdit2 || !pControlPropEdit3)
return; // badness has occurred, but no way out of it at this point
CFont * pFontControlPropName = pControlPropName->GetFont();
CFont * pFontControlPropPresent = pControlPropPresent->GetFont();
CFont * pFontControlPropEdit1 = pControlPropEdit1->GetFont();
CFont * pFontControlPropEdit2 = pControlPropEdit2->GetFont();
CFont * pFontControlPropEdit3 = pControlPropEdit3->GetFont();
CRect crRectDlg;
CRect crRectPropName;
CRect crRectPropPresent;
CRect crRectPropEdit1;
CRect crRectPropEdit2;
CRect crRectPropEdit3;
GetWindowRect(crRectDlg);
pControlPropName->GetWindowRect(crRectPropName);
pControlPropPresent->GetWindowRect(crRectPropPresent);
pControlPropEdit1->GetWindowRect(crRectPropEdit1);
pControlPropEdit2->GetWindowRect(crRectPropEdit2);
pControlPropEdit3->GetWindowRect(crRectPropEdit3);
//
// Offset the rects relative to the dialog
//
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crRectPropName, 2);
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crRectPropPresent, 2);
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crRectPropEdit1, 2);
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crRectPropEdit2, 2);
::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crRectPropEdit3, 2);
// crRectPropName.OffsetRect(-crRectDlg.left, -crRectDlg.top);
// crRectPropPresent.OffsetRect(-crRectDlg.left, -crRectDlg.top);
// crRectPropEdit1.OffsetRect(-crRectDlg.left, -crRectDlg.top);
// crRectPropEdit2.OffsetRect(-crRectDlg.left, -crRectDlg.top);
// crRectPropEdit3.OffsetRect(-crRectDlg.left, -crRectDlg.top);
// for the first property we just unhide the appropriate boxes and set the property name
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.
pControlPropName->ShowWindow(SW_SHOW);
const char * szStaticText = NULL;
if (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[0]->szPropertyTagForDisplay[0])
{
szStaticText = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[0]->szPropertyTagForDisplay;
}
else
{
szStaticText =
m_fShowFullPropertyName ?
m_paPropertiesToEdit->ppProperties_To_Edit_Entry[0]->szPropertyTag :
GetEntryNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[0]->szPropertyTag );
}
pControlPropName->SetWindowText(szStaticText);
pControlPropPresent->ShowWindow(SW_SHOW);
pControlPropEdit1->ShowWindow(SW_SHOW);
// Next root ID is 1 after this set
int nCurrID = IDC_DOP_PROPNAME + 3;
// now see if we need to add the others
if (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[0]->ePropertyType == eVector3D)
{
pControlPropEdit2->ShowWindow(SW_SHOW);
pControlPropEdit3->ShowWindow(SW_SHOW);
}
else
{
pControlPropEdit2->ShowWindow(SW_HIDE);
pControlPropEdit3->ShowWindow(SW_HIDE);
}
nCurrID += 2; // this has to be incremented no matter what since the controls are actually there.
m_paPropertiesToEdit->ppProperties_To_Edit_Entry[0]->uiReserved1_CTRLID = IDC_DOP_PROPNAME;
int nDiffY = crRectPropEdit1.Height() + 5; // constant used for vertical padding (use largest control type, edit box)
HWND hWndTemp = NULL;
while (++nCurrentProperty < m_paPropertiesToEdit->nCount)
{
CWnd wndControlPropName ;
CWnd wndControlPropPresent ;
CWnd wndControlPropEdit1 ;
CWnd wndControlPropEdit2 ;
CWnd wndControlPropEdit3 ;
// BOOL fIsNumberOnly = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType != eLPSTR;
// we have to store off the ID for these properties
m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->uiReserved1_CTRLID = nCurrID;
crRectPropName.OffsetRect( 0, nDiffY);
crRectPropPresent.OffsetRect(0, nDiffY);
crRectPropEdit1.OffsetRect( 0, nDiffY);
crRectPropEdit2.OffsetRect( 0, nDiffY);
crRectPropEdit3.OffsetRect( 0, nDiffY);
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 :
GetEntryNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->szPropertyTag );
}
hWndTemp = ::CreateWindow("STATIC",
szStaticText,
WS_VISIBLE | SS_LEFT | WS_CHILD,
crRectPropName.left, crRectPropName.top, crRectPropName.Width(), crRectPropName.Height(),
GetSafeHwnd(), (HMENU)nCurrID, theApp.m_hInstance, NULL);
// ::SetWindowLong(hWndTemp, nCurrID, GWL_ID);
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPropName, (LPARAM)FALSE);
/* wndControlPropName.Create("STATIC",
szStaticText,
WS_VISIBLE | SS_LEFT | WS_CHILD,
crRectPropName,
this,
nCurrID,
NULL);
wndControlPropName.Detach();
*/
nCurrID++;
hWndTemp = ::CreateWindow("BUTTON",
"",
WS_VISIBLE | BS_CHECKBOX | WS_CHILD | BS_AUTOCHECKBOX,
crRectPropPresent.left, crRectPropPresent.top, crRectPropPresent.Width(), crRectPropPresent.Height(),
GetSafeHwnd(), (HMENU)nCurrID, theApp.m_hInstance, NULL);
// ::SetWindowLong(hWndTemp, nCurrID, GWL_ID);
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPropPresent, (LPARAM)FALSE);
/* wndControlPropPresent.Create("BUTTON",
_T(""),
WS_VISIBLE | BS_CHECKBOX | WS_CHILD,
crRectPropPresent,
this,
nCurrID,
NULL);
wndControlPropPresent.Detach();
*/
nCurrID++;
hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT",
"",
WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD ,
crRectPropEdit1.left, crRectPropEdit1.top, crRectPropEdit1.Width(), crRectPropEdit1.Height(),
GetSafeHwnd(), (HMENU)nCurrID, theApp.m_hInstance, NULL);
// ::SetWindowLong(hWndTemp, nCurrID, GWL_ID);
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPropEdit1, (LPARAM)FALSE);
/* wndControlPropEdit1.Create("EDIT",
_T(""),
WS_VISIBLE | ES_LEFT | WS_CHILD |
(fIsNumberOnly ? ES_NUMBER : 0), // keep them To entering wrong info
crRectPropEdit1,
this,
nCurrID,
NULL);
wndControlPropEdit1.Detach();
*/
nCurrID++;
if (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType == eVector3D)
{
hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT",
"",
WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD,
crRectPropEdit2.left, crRectPropEdit2.top, crRectPropEdit2.Width(), crRectPropEdit2.Height(),
GetSafeHwnd(), (HMENU)nCurrID, theApp.m_hInstance, NULL);
// ::SetWindowLong(hWndTemp, nCurrID, GWL_ID);
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPropEdit2, (LPARAM)FALSE);
/* wndControlPropEdit2.Create("EDIT",
_T(""),
WS_VISIBLE | ES_LEFT | WS_CHILD |
ES_NUMBER, // keep them To entering wrong info
crRectPropEdit2,
this,
nCurrID,
NULL);
wndControlPropEdit2.Detach();
*/
nCurrID++;
hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT",
"",
WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD,
crRectPropEdit3.left, crRectPropEdit3.top, crRectPropEdit3.Width(), crRectPropEdit3.Height(),
GetSafeHwnd(), (HMENU)nCurrID, theApp.m_hInstance, NULL);
// ::SetWindowLong(hWndTemp, nCurrID, GWL_ID);
::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPropEdit3, (LPARAM)FALSE);
/* wndControlPropEdit3.Create("EDIT",
_T(""),
WS_VISIBLE | ES_LEFT | WS_CHILD |
ES_NUMBER, // keep them To entering wrong info
crRectPropEdit3,
this,
nCurrID,
NULL);
wndControlPropEdit3.Detach();
*/
nCurrID++;
} // if we are entering a eVector3D property here
} // while we are iterating through the properties
m_nLastControlID = nCurrID;
} // end of CreateSubControlsForProperties()
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectProperties::OnOK()
{
//
// Validate the data and save any changes made since the last sel change
//
MoveCurSelDataToOrFromControls(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 CDlgObjectProperties::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 CDlgObjectProperties::SetObjectFilesDirectory(LPCSTR lpszDirectoryPath)
{
m_strObjectFilesRootDirectory = lpszDirectoryPath;
EndDirectoryWithBackSlash(m_strObjectFilesRootDirectory );
return TRUE;
}
//****************************************************************************************
//
// Sets the root file name type to search for like "*.data"
//
//****************************************************************************************
BOOL CDlgObjectProperties::SetFileNameToSearchSubdirectoriesFor(LPCSTR lpszFileSearchString)
{
m_strFileNameToSearchSubdirectoriesFor = lpszFileSearchString;
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectProperties::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 CDlgObjectProperties::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 CDlgObjectProperties::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 CDlgObjectProperties::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 CDlgObjectProperties::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;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::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
}
int nSel = m_lbObjectList.AddString((pObjectPropertiesArray->szObjectName + nPos));
m_lbObjectList.SetItemData(nSel, (DWORD) pObjectPropertiesArray);
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 CDlgObjectProperties::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...
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;
}
//****************************************************************************************
//
//****************************************************************************************
void CDlgObjectProperties::OnSelchangeObjectlist()
{
//
// First check what the old focus was, see if the data has changed, and if it has then we can
// update the weapons data structure and move to the next selection
//
// Load the current data into the variables, then copy that data to a weaponinfo structure
MoveCurSelDataToOrFromControls(FALSE);
//
// If we have selected something then we need to update info to the controls
//
m_nCurSel = m_lbObjectList.GetCurSel();
m_popCurObjectPropertiesArray = (CDOPPROPERTIES_OBJECT_PROPERTIES * )(void *)m_lbObjectList.GetItemData(m_nCurSel);
MoveCurSelDataToOrFromControls(TRUE);
EnableControlsForCurrentSelection();
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::DisableAllControls()
{
for (UINT i = IDC_DOP_PROPNAME; i < m_nLastControlID ; i++)
{
CWnd * pWnd = GetDlgItem(i);
if (pWnd)
pWnd->EnableWindow(FALSE);
}
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::EnableControlsForCurrentSelection()
{
// In addition to enabling disabling the various controls...
// We also have to set the read only text properly when we are done
//
// if there is not a current selection then disable all and move on
if (m_popCurObjectPropertiesArray == NULL)
{
DisableAllControls();
SetDlgItemText(IDC_READONLY, MyLoadStringTempBuffer(IDS_READONLY));
return FALSE;
}
BOOL fReadOnly = m_popCurObjectPropertiesArray->fReadOnly;
//
// If we got here then we have a selected item and need to enable/disable the controls properly
// based on the data object info structures
//
for (int i = 0; i < m_paPropertiesToEdit->nCount; i++)
{
// First is the first ID of the controls for this property. End is the first control of the next
// property.
UINT uiFirst = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[i]->uiReserved1_CTRLID;
CWnd * pWnd = GetDlgItem(uiFirst);
BOOL fPresent = m_popCurObjectPropertiesArray->ppObjectProperties[i]->fPresent;
if (pWnd)
{
pWnd->EnableWindow(!fReadOnly);
}
pWnd = GetDlgItem(uiFirst+1);
if (pWnd)
{
pWnd->EnableWindow(!fReadOnly);
}
pWnd = GetDlgItem(uiFirst+2);
if (pWnd)
{
pWnd->EnableWindow(!fReadOnly && fPresent);
}
if (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[i]->ePropertyType == eVector3D)
{
pWnd = GetDlgItem(uiFirst+3);
if (pWnd)
{
pWnd->EnableWindow(!fReadOnly && fPresent);
}
pWnd = GetDlgItem(uiFirst+4);
if (pWnd)
{
pWnd->EnableWindow(!fReadOnly && fPresent);
}
} // if for vector3d property type
} // for loop for property list
SetDlgItemText(IDC_READONLY, (fReadOnly ? MyLoadStringTempBuffer(IDS_READONLY) : _T("")));
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::MoveCurSelDataToOrFromControls(BOOL fToControls)
{
// if there is not a current selection then disable all and move on
if (m_popCurObjectPropertiesArray == NULL)
{
DisableAllControls();
SetDlgItemText(IDC_READONLY, MyLoadStringTempBuffer(IDS_READONLY));
return FALSE;
}
//
// If we are retrieving To the controls we need to save off what we have and
// see if it changed.
//
CDOPPROPERTIES_OBJECT_PROPERTIES * pPropertyArray = NULL;
if (!fToControls)
{
pPropertyArray = Allocate_CDOPPROPERTIES_OBJECT_PROPERTIES(
m_paPropertiesToEdit->nCount);
Copy_CDOPPROPERTIES_OBJECT_PROPERTIES(pPropertyArray, m_popCurObjectPropertiesArray);
}
UpdateControlData(fToControls); // put the data in the controls based on the current data pointer
//
// See if the data changed if we are reading To the controls
//
if (!fToControls)
{
if (!IsEqual_CDOPPROPERTIES_OBJECT_PROPERTIES(pPropertyArray, m_popCurObjectPropertiesArray))
{
m_popCurObjectPropertiesArray->fDirty = TRUE; // it changed
m_fDirty = TRUE; // at least one object has changed.
}
free(pPropertyArray);
}
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::GetBOOLFromButton(UINT uiID, BOOL * pfDest)
{
CButton * pWnd = (CButton *)GetDlgItem(uiID);
if (!pWnd)
return FALSE;
*pfDest = pWnd->GetCheck();
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::GetBOOLFromControl(UINT uiID, BOOL * pfDest)
{
CWnd * pWnd = GetDlgItem(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
GetDlgItemText(uiID, szTemp, 255);
*pfDest = FALSE;
if (!stricmp(szTemp, "true") ||
!stricmp(szTemp, "yes") ||
!stricmp(szTemp, "1"))
{
*pfDest = TRUE;
}
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::GetfloatFromControl(UINT uiID, float * pfltDest)
{
CWnd * pWnd = GetDlgItem(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
GetDlgItemText(uiID, szTemp, 255);
*pfltDest = (float)atof(szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::GetLPSTRFromControl(UINT uiID, LPSTR pszDest)
{
CWnd * pWnd = GetDlgItem(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
GetDlgItemText(uiID, szTemp, 255);
szTemp[255] = 0;
strcpy(pszDest, szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::GetintFromControl(UINT uiID, int * pnDest)
{
CWnd * pWnd = GetDlgItem(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
GetDlgItemText(uiID, szTemp, 255);
*pnDest = atoi(szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::GetVector3DFromControl(UINT uiID, float * pfltx, float * pflty, float * pfltz)
{
CWnd * pWnd = GetDlgItem(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
GetDlgItemText(uiID, szTemp, 255);
*pfltx = (float)atof(szTemp);
pWnd = GetDlgItem(uiID +1);
if (!pWnd)
return FALSE;
GetDlgItemText(uiID+1, szTemp, 255);
*pflty = (float)atof(szTemp);
pWnd = GetDlgItem(uiID +2);
if (!pWnd)
return FALSE;
GetDlgItemText(uiID+2, szTemp, 255);
*pfltz = (float)atof(szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::SetBOOLToButton(UINT uiID, BOOL fDest)
{
CButton * pWnd = (CButton *)GetDlgItem(uiID);
if (!pWnd)
return FALSE;
pWnd->SetCheck(fDest);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::SetBOOLToControl(UINT uiID, BOOL fSrc)
{
CWnd * pWnd = GetDlgItem(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
sprintf(szTemp, fSrc ? "true" : "false");
SetDlgItemText(uiID, szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::SetfloatToControl(UINT uiID, float fltSrc)
{
CWnd * pWnd = GetDlgItem(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
sprintf(szTemp, "%f", (double) fltSrc);
SetDlgItemText(uiID, szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::SetLPSTRToControl(UINT uiID, LPSTR pszSrc)
{
CWnd * pWnd = GetDlgItem(uiID);
if (!pWnd)
return FALSE;
SetDlgItemText(uiID, pszSrc);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::SetintToControl(UINT uiID, int nSrc)
{
CWnd * pWnd = GetDlgItem(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
sprintf(szTemp, "%d", nSrc);
SetDlgItemText(uiID, szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::SetVector3DToControl(UINT uiID, float fltx, float flty, float fltz)
{
CWnd * pWnd = GetDlgItem(uiID);
if (!pWnd)
return FALSE;
char szTemp[256];
sprintf(szTemp, "%f", (double) fltx);
SetDlgItemText(uiID, szTemp);
sprintf(szTemp, "%f", (double) flty);
SetDlgItemText(uiID + 1, szTemp);
sprintf(szTemp, "%f", (double) fltz);
SetDlgItemText(uiID + 2, szTemp);
return TRUE;
}
//****************************************************************************************
//
//****************************************************************************************
BOOL CDlgObjectProperties::UpdateControlData(BOOL fToControls)
{
if (!m_popCurObjectPropertiesArray)
return FALSE;
BOOL fReadOnly = m_popCurObjectPropertiesArray->fReadOnly;
if (fReadOnly && !fToControls)
return FALSE; // don't bother reading if we don't have to
//
//
for (int i = 0; i < m_paPropertiesToEdit->nCount; i++)
{
// First is the first ID of the controls for this property. End is the first control of the next
// property.
UINT uiFirst = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[i]->uiReserved1_CTRLID;
if (!fToControls)
{
GetBOOLFromButton(uiFirst + 1,&(m_popCurObjectPropertiesArray->ppObjectProperties[i]->fPresent) );
switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[i]->ePropertyType)
{
case efloat:
GetfloatFromControl(uiFirst + 2,&(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.fltValue));
break;
case eint:
GetintFromControl(uiFirst + 2,&(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.nValue));
break;
case eLPSTR:
GetLPSTRFromControl(uiFirst + 2,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.szValue));
break;
case eBOOL:
GetBOOLFromControl(uiFirst + 2,&(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.fValue));
break;
case eVector3D:
GetVector3DFromControl(uiFirst + 2,&(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.v3dValues.x),
&(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.v3dValues.y),
&(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.v3dValues.z));
break;
} // switch on property type
} // if !fFromControls
else
{
SetBOOLToButton(uiFirst + 1,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->fPresent) );
switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[i]->ePropertyType)
{
case efloat:
SetfloatToControl(uiFirst + 2,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.fltValue));
break;
case eint:
SetintToControl(uiFirst + 2,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.nValue));
break;
case eLPSTR:
SetLPSTRToControl(uiFirst + 2,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.szValue));
break;
case eBOOL:
SetBOOLToControl(uiFirst + 2,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.fValue));
break;
case eVector3D:
SetVector3DToControl(uiFirst + 2,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.v3dValues.x),
(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.v3dValues.y),
(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.v3dValues.z));
break;
} // switch on property type
}
} // for loop for property list
return TRUE;
}