mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-12-01 14:15:53 +01:00
355 lines
11 KiB
C++
355 lines
11 KiB
C++
|
/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
|
||
|
|
||
|
// 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);
|
||
|
}
|