2016-03-12 01:20:51 +01:00
|
|
|
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation
|
|
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
2016-03-11 14:57:17 +01:00
|
|
|
|
|
|
|
// PropertyComboBox.cpp : implementation file
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "PropertyComboBox.h"
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
#undef new
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
#undef THIS_FILE
|
|
|
|
static char THIS_FILE[] = __FILE__;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// CPropertyComboBox
|
|
|
|
|
|
|
|
CPropertyComboBox::CPropertyComboBox()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CPropertyComboBox::~CPropertyComboBox()
|
|
|
|
{
|
|
|
|
// delete current property list
|
|
|
|
FORDELETELIST(CPropertyID, pid_lnNode, m_lhProperties, itDel)
|
|
|
|
{
|
|
|
|
delete &itDel.Current();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPropertyComboBox::SetDialogPtr( CPropertyComboBar *pDialog)
|
|
|
|
{
|
|
|
|
m_pDialog = pDialog;
|
|
|
|
DisableCombo();
|
|
|
|
}
|
|
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CPropertyComboBox, CComboBox)
|
|
|
|
//{{AFX_MSG_MAP(CPropertyComboBox)
|
|
|
|
ON_WM_CONTEXTMENU()
|
|
|
|
ON_CONTROL_REFLECT(CBN_SELCHANGE, OnSelchange)
|
|
|
|
ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropdown)
|
|
|
|
//}}AFX_MSG_MAP
|
|
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// CPropertyComboBox message handlers
|
|
|
|
|
|
|
|
void CPropertyComboBox::OnContextMenu(CWnd* pWnd, CPoint point)
|
|
|
|
{
|
|
|
|
INDEX i=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPropertyComboBox::JoinProperties( CEntity *penEntity, BOOL bIntersect)
|
|
|
|
{
|
|
|
|
// if we should add all of this entity's properties (if this is first entity)
|
|
|
|
if( !bIntersect)
|
|
|
|
{
|
|
|
|
// obtain entity class ptr
|
|
|
|
CDLLEntityClass *pdecDLLClass = penEntity->GetClass()->ec_pdecDLLClass;
|
|
|
|
// for all classes in hierarchy of this entity
|
|
|
|
for(;pdecDLLClass!=NULL; pdecDLLClass = pdecDLLClass->dec_pdecBase)
|
|
|
|
{
|
|
|
|
// for all properties
|
|
|
|
for(INDEX iProperty=0; iProperty<pdecDLLClass->dec_ctProperties; iProperty++)
|
|
|
|
{
|
|
|
|
CEntityProperty &epProperty = pdecDLLClass->dec_aepProperties[iProperty];
|
|
|
|
// don't add properties with no name
|
|
|
|
if( epProperty.ep_strName != CTString("") )
|
|
|
|
{
|
|
|
|
CAnimData *pAD = NULL;
|
|
|
|
// remember anim data
|
|
|
|
if( epProperty.ep_eptType == CEntityProperty::EPT_ANIMATION)
|
|
|
|
{
|
|
|
|
pAD = penEntity->GetAnimData( epProperty.ep_slOffset);
|
|
|
|
}
|
|
|
|
// create current CPropertyID
|
|
|
|
CPropertyID *pPropertyID = new CPropertyID( epProperty.ep_strName,
|
|
|
|
epProperty.ep_eptType, &epProperty, pAD);
|
|
|
|
// if we should add all of this entity's properties (if this is first entity)
|
|
|
|
// and add it into list
|
|
|
|
m_lhProperties.AddTail( pPropertyID->pid_lnNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// in case of intersecting properties we should take one of existing properties in list
|
|
|
|
// and see if investigating entity has property with same descriptive name
|
|
|
|
// If not, remove it that existing property.
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FORDELETELIST(CPropertyID, pid_lnNode, m_lhProperties, itProp)
|
|
|
|
{
|
|
|
|
CTString strCurrentName = itProp->pid_strName;
|
|
|
|
CEntityProperty::PropertyType eptCurrentType = itProp->pid_eptType;
|
|
|
|
// mark that property with same name is not found
|
|
|
|
BOOL bSameFound = FALSE;
|
|
|
|
|
|
|
|
// obtain entity class ptr
|
|
|
|
CDLLEntityClass *pdecDLLClass = penEntity->GetClass()->ec_pdecDLLClass;
|
|
|
|
// for all classes in hierarchy of this entity
|
|
|
|
for(; pdecDLLClass!=NULL; pdecDLLClass = pdecDLLClass->dec_pdecBase)
|
|
|
|
{
|
|
|
|
// for all properties
|
|
|
|
for(INDEX iProperty=0; iProperty<pdecDLLClass->dec_ctProperties; iProperty++)
|
|
|
|
{
|
|
|
|
CEntityProperty &epProperty = pdecDLLClass->dec_aepProperties[iProperty];
|
|
|
|
CAnimData *pAD = NULL;
|
|
|
|
// remember anim data
|
|
|
|
if( epProperty.ep_eptType == CEntityProperty::EPT_ANIMATION)
|
|
|
|
{
|
|
|
|
pAD = penEntity->GetAnimData( epProperty.ep_slOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
// create current CPropertyID
|
|
|
|
CPropertyID PropertyID = CPropertyID( epProperty.ep_strName, epProperty.ep_eptType,
|
|
|
|
&epProperty, pAD);
|
|
|
|
|
|
|
|
// is this property same as one we are investigating
|
|
|
|
if( (strCurrentName == PropertyID.pid_strName) &&
|
|
|
|
(eptCurrentType == PropertyID.pid_eptType) )
|
|
|
|
{
|
|
|
|
// if propperty is enum, enum ptr must also be the same
|
|
|
|
if( itProp->pid_eptType == CEntityProperty::EPT_ENUM)
|
|
|
|
{
|
|
|
|
// only then,
|
|
|
|
if( itProp->pid_penpProperty->ep_pepetEnumType ==
|
|
|
|
PropertyID.pid_penpProperty->ep_pepetEnumType)
|
|
|
|
{
|
|
|
|
// same property is found
|
|
|
|
bSameFound = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bSameFound = FALSE;
|
|
|
|
}
|
|
|
|
goto pcb_OutLoop_JoinProperties;
|
|
|
|
}
|
|
|
|
// if propperty is animation, anim data ptr must be the same
|
|
|
|
else if( itProp->pid_eptType == CEntityProperty::EPT_ANIMATION)
|
|
|
|
{
|
|
|
|
if(itProp->pid_padAnimData == PropertyID.pid_padAnimData)
|
|
|
|
{
|
|
|
|
// same property is found
|
|
|
|
bSameFound = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bSameFound = FALSE;
|
|
|
|
}
|
|
|
|
goto pcb_OutLoop_JoinProperties;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// same property is found
|
|
|
|
bSameFound = TRUE;
|
|
|
|
goto pcb_OutLoop_JoinProperties;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pcb_OutLoop_JoinProperties:;
|
|
|
|
// if property with same name is not found
|
|
|
|
if( !bSameFound)
|
|
|
|
{
|
|
|
|
// remove our investigating property from list
|
|
|
|
itProp->pid_lnNode.Remove();
|
|
|
|
// and delete it
|
|
|
|
delete &itProp.Current();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL CPropertyComboBox::OnIdle(LONG lCount)
|
|
|
|
{
|
|
|
|
// get active document
|
|
|
|
CWorldEditorDoc* pDoc = theApp.GetActiveDocument();
|
|
|
|
|
|
|
|
// if document ptr has changed
|
|
|
|
// or if document was closed (pDoc == NULL and pLastDoc != NULL)
|
|
|
|
// or if mode was changed
|
|
|
|
// or if selection was changed from last OnIdle, refresh properties
|
|
|
|
if( (m_pLastDoc != pDoc) ||
|
|
|
|
((pDoc == NULL) && (m_pLastDoc != NULL)) ||
|
|
|
|
((pDoc != NULL) && (m_iLastMode != pDoc->m_iMode)) ||
|
|
|
|
((pDoc != NULL) && !pDoc->m_chSelections.IsUpToDate( m_udComboEntries)) )
|
|
|
|
{
|
|
|
|
// refresh selected members message
|
|
|
|
if( (pDoc != NULL))
|
|
|
|
{
|
|
|
|
pDoc->SetStatusLineModeInfoMessage();
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove all combo entries
|
|
|
|
ResetContent();
|
|
|
|
// if document exists and mode is entities
|
|
|
|
if( (pDoc != NULL) && (pDoc->m_iMode == ENTITY_MODE) )
|
|
|
|
{
|
|
|
|
// delete current property list
|
|
|
|
FORDELETELIST(CPropertyID, pid_lnNode, m_lhProperties, itDel)
|
|
|
|
{
|
|
|
|
delete &itDel.Current();
|
|
|
|
}
|
|
|
|
|
|
|
|
// lock selection's dynamic container
|
|
|
|
pDoc->m_selEntitySelection.Lock();
|
|
|
|
|
|
|
|
// for each of the selected entities
|
|
|
|
FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
|
|
|
|
{
|
|
|
|
// if this is first entity in dynamic container
|
|
|
|
if( pDoc->m_selEntitySelection.Pointer(0) == iten)
|
|
|
|
{
|
|
|
|
// add all of its properties into joint list but don't intersect with existing ones
|
|
|
|
JoinProperties( iten, FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// intersect entity's properties with existing ones
|
|
|
|
JoinProperties( iten, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// unlock selection's dynamic container
|
|
|
|
pDoc->m_selEntitySelection.Unlock();
|
|
|
|
|
|
|
|
if( pDoc->m_selEntitySelection.Count() != 0)
|
|
|
|
{
|
|
|
|
// ----------------- Add spawn flags property
|
|
|
|
CPropertyID *ppidSpawnFlags = new CPropertyID( "Spawn flags (Alt+Shift+S)",
|
|
|
|
CEntityProperty::EPT_SPAWNFLAGS, NULL, NULL);
|
|
|
|
m_lhProperties.AddTail( ppidSpawnFlags->pid_lnNode);
|
|
|
|
// ----------------- Add parent entity property
|
|
|
|
CPropertyID *ppidParent = new CPropertyID( "Parent (Alt+Shift+A)",
|
|
|
|
CEntityProperty::EPT_PARENT, NULL, NULL);
|
|
|
|
m_lhProperties.AddTail( ppidParent->pid_lnNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
// if there are some intersecting properties
|
|
|
|
if( !m_lhProperties.IsEmpty())
|
|
|
|
{
|
|
|
|
// add intersecting properties of selected entities into combo box
|
|
|
|
FOREACHINLIST(CPropertyID, pid_lnNode, m_lhProperties, itProp)
|
|
|
|
{
|
|
|
|
char achrShortcutKey[ 64] = "";
|
|
|
|
if( itProp->pid_chrShortcutKey != 0)
|
|
|
|
{
|
|
|
|
sprintf( achrShortcutKey, " (%c)", itProp->pid_chrShortcutKey);
|
|
|
|
}
|
|
|
|
// add property name and shortcut key
|
|
|
|
INDEX iAddedAs = AddString( CString(itProp->pid_strName + achrShortcutKey));
|
|
|
|
// set ptr to property ID object
|
|
|
|
SetItemData( iAddedAs, (ULONG) &*itProp);
|
|
|
|
// enable combo
|
|
|
|
EnableWindow();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// if there are no properties to choose from
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DisableCombo();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// if there are no document or application is not in edit entitiy mode
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DisableCombo();
|
|
|
|
}
|
|
|
|
|
|
|
|
// index of property that is selected (trying to keep the same property active)
|
|
|
|
INDEX iSelectedProperty = 0;
|
|
|
|
// for all members in combo box
|
|
|
|
for( INDEX iMembers = 0; iMembers<GetCount(); iMembers++)
|
|
|
|
{
|
|
|
|
CPropertyID *ppidPropertyID = (CPropertyID *) GetItemData( iMembers);
|
|
|
|
// if this is valid property
|
|
|
|
if( ppidPropertyID != NULL)
|
|
|
|
{
|
|
|
|
// if name of this property is same as last selected property name
|
|
|
|
if( ppidPropertyID->pid_strName == m_strLastPropertyName)
|
|
|
|
{
|
|
|
|
// mark this property as selected by default
|
|
|
|
iSelectedProperty = iMembers;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// select entity 0 by default
|
|
|
|
SetCurSel( iSelectedProperty);
|
|
|
|
// mark possible document change
|
|
|
|
m_pLastDoc = pDoc;
|
|
|
|
// set new mode
|
|
|
|
if( pDoc != NULL)
|
|
|
|
{
|
|
|
|
m_iLastMode = pDoc->m_iMode;
|
|
|
|
}
|
|
|
|
m_pDialog->ArrangeControls();
|
|
|
|
// if edit color property is active
|
|
|
|
if( m_pDialog->m_EditColorCtrl.IsWindowVisible())
|
|
|
|
{
|
|
|
|
// invalidate it so it will be refreshed properly
|
|
|
|
m_pDialog->m_EditColorCtrl.Invalidate( FALSE);
|
|
|
|
}
|
|
|
|
m_udComboEntries.MarkUpdated();
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPropertyComboBox::OnSelchange()
|
|
|
|
{
|
|
|
|
SelectProperty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPropertyComboBox::SelectProperty(void)
|
|
|
|
{
|
|
|
|
CPropertyID *ppidPropertyID = (CPropertyID *) GetItemData( GetCurSel());
|
|
|
|
// must be valid property
|
|
|
|
ASSERT( ppidPropertyID != NULL);
|
|
|
|
// remember name of this property as last selected property name
|
|
|
|
m_strLastPropertyName = ppidPropertyID->pid_strName;
|
|
|
|
// show/hide appropriate editing propterty controls
|
|
|
|
m_pDialog->ArrangeControls();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPropertyComboBox::DisableCombo()
|
|
|
|
{
|
|
|
|
// remove all combo entries
|
|
|
|
ResetContent();
|
|
|
|
// set default message
|
|
|
|
INDEX iAddedAs = AddString( L"None Available");
|
|
|
|
// set invalid ptr
|
|
|
|
SetItemData( iAddedAs, NULL);
|
|
|
|
// disable combo
|
|
|
|
EnableWindow( FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPropertyComboBox::OnDropdown()
|
|
|
|
{
|
|
|
|
INDEX ctItems = GetCount();
|
|
|
|
if( ctItems == CB_ERR) return;
|
|
|
|
|
|
|
|
CRect rectCombo;
|
|
|
|
GetWindowRect( &rectCombo);
|
|
|
|
|
|
|
|
PIX pixScreenHeight = ::GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
PIX pixMaxHeight = pixScreenHeight - rectCombo.top;
|
|
|
|
|
|
|
|
m_pDialog->ScreenToClient( &rectCombo);
|
|
|
|
PIX pixNewHeight = GetItemHeight(0)*(ctItems+2);
|
|
|
|
rectCombo.bottom = rectCombo.top + ClampUp( pixNewHeight, pixMaxHeight);
|
|
|
|
MoveWindow( rectCombo);
|
|
|
|
}
|