You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2517 lines
71 KiB
2517 lines
71 KiB
![]()
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose: Implements a dialog for editing the input/output connections of a
|
||
|
// list of entities. The connections are displayed in a grid control,
|
||
|
// each row of the grid control representing a connection that is
|
||
|
// common to all entities being edited. For example, given these two ents:
|
||
|
//
|
||
|
// Button01
|
||
|
// OnDamaged Sound01 PlaySound 0 0
|
||
|
// OnPressed Door01 Open 0 0
|
||
|
//
|
||
|
// Button02
|
||
|
// OnPressed Door01 Open 0 0
|
||
|
//
|
||
|
// If these two entities were selected, the grid control would show:
|
||
|
//
|
||
|
// OnPressed Door01 Open 0 0
|
||
|
//
|
||
|
// because it is the only connection that is common to both entities.
|
||
|
// Editing an entry in the grid control modifies the corresponding
|
||
|
// connection in all selected entities.
|
||
|
//
|
||
|
// TODO: persist sort column index, sort directions, and column sizes
|
||
|
// TODO: implement an external mode, where the grid shows all connections to unselected ents
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "GlobalFunctions.h"
|
||
|
#include "MapDoc.h"
|
||
|
#include "MapEntity.h"
|
||
|
#include "MapWorld.h"
|
||
|
#include "ObjectProperties.h"
|
||
|
#include "OP_Output.h"
|
||
|
#include "ToolManager.h"
|
||
|
#include "MainFrm.h"
|
||
|
#include "utlrbtree.h"
|
||
|
#include "options.h"
|
||
|
#include ".\op_output.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include <tier0/memdbgon.h>
|
||
|
|
||
|
|
||
|
#pragma warning( disable : 4355 )
|
||
|
|
||
|
|
||
|
#define ICON_CONN_BAD 0
|
||
|
#define ICON_CONN_GOOD 1
|
||
|
#define ICON_CONN_BAD_GREY 2
|
||
|
#define ICON_CONN_GOOD_GREY 3
|
||
|
|
||
|
|
||
|
const char *PARAM_STRING_NONE = "<none>";
|
||
|
|
||
|
|
||
|
//
|
||
|
// Column indices for the list control.
|
||
|
//
|
||
|
const int ICON_COLUMN = 0;
|
||
|
const int OUTPUT_NAME_COLUMN = 1;
|
||
|
const int TARGET_NAME_COLUMN = 2;
|
||
|
const int INPUT_NAME_COLUMN = 3;
|
||
|
const int PARAMETER_COLUMN = 4;
|
||
|
const int DELAY_COLUMN = 5;
|
||
|
const int ONLY_ONCE_COLUMN = 6;
|
||
|
|
||
|
IMPLEMENT_DYNCREATE(COP_Output, CObjectPage)
|
||
|
|
||
|
|
||
|
BEGIN_MESSAGE_MAP(COP_Output, CObjectPage)
|
||
|
//{{AFX_MSG_MAP(COP_Output)
|
||
|
ON_BN_CLICKED(IDC_ADD, OnAdd)
|
||
|
ON_BN_CLICKED(IDC_DELETE, OnDelete)
|
||
|
ON_BN_CLICKED(IDC_COPY, OnCopy)
|
||
|
ON_WM_SIZE()
|
||
|
ON_BN_CLICKED(IDC_PASTE, OnPaste)
|
||
|
ON_BN_CLICKED(IDC_MARK, OnMark)
|
||
|
ON_BN_CLICKED(IDC_PICK_ENTITY, OnPickEntity)
|
||
|
ON_BN_CLICKED(IDC_PICK_ENTITY_PARAM, OnPickEntityParam)
|
||
|
ON_CBN_SELCHANGE(IDC_EDIT_CONN_INPUT, OnSelChangeInput)
|
||
|
ON_CBN_EDITUPDATE(IDC_EDIT_CONN_INPUT, OnEditUpdateInput)
|
||
|
ON_CBN_SELCHANGE(IDC_EDIT_CONN_OUTPUT, OnSelChangeOutput)
|
||
|
ON_CBN_EDITUPDATE(IDC_EDIT_CONN_OUTPUT, OnEditUpdateOutput)
|
||
|
ON_CBN_SELCHANGE(IDC_EDIT_CONN_PARAM, OnSelChangeParam)
|
||
|
ON_CBN_EDITUPDATE(IDC_EDIT_CONN_PARAM, OnEditUpdateParam)
|
||
|
ON_EN_CHANGE(IDC_EDIT_CONN_DELAY, OnEditDelay)
|
||
|
ON_BN_CLICKED(IDC_EDIT_CONN_FIRE_ONCE, OnFireOnce)
|
||
|
ON_BN_CLICKED(IDC_SHOWHIDDENTARGETS, OnShowHiddenTargetsAsBroken)
|
||
|
ON_WM_DESTROY()
|
||
|
//}}AFX_MSG_MAP
|
||
|
END_MESSAGE_MAP()
|
||
|
|
||
|
|
||
|
// ON_CBN_SELCHANGE(IDC_EDIT_CONN_TARGET, OnSelChangeTarget)
|
||
|
// ON_CBN_EDITUPDATE(IDC_EDIT_CONN_TARGET, OnEditUpdateTarget)
|
||
|
|
||
|
|
||
|
//
|
||
|
// Static data.
|
||
|
//
|
||
|
CEntityConnectionList *COP_Output::m_pConnectionBuffer = new CEntityConnectionList;
|
||
|
CImageList *COP_Output::m_pImageList = NULL;
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Returns true if any of the target entities in the connection list are visible.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
static bool AreAnyTargetEntitiesVisible( CEntityConnectionList *pList )
|
||
|
{
|
||
|
for ( int i=0; i < pList->Count(); i++ )
|
||
|
{
|
||
|
if ( pList->Element(i)->AreAnyTargetEntitiesVisible() )
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Compares by delays. Used as a secondary sort by all other columns.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
static int CALLBACK ListCompareDelaysSecondary(COutputConnection *pOutputConn1, COutputConnection *pOutputConn2, SortDirection_t eDirection)
|
||
|
{
|
||
|
CEntityConnectionList *pConnList1 = pOutputConn1->m_pConnList;
|
||
|
CEntityConnectionList *pConnList2 = pOutputConn2->m_pConnList;
|
||
|
CEntityConnection *pConn1 = pConnList1->Element(0);
|
||
|
CEntityConnection *pConn2 = pConnList2->Element(0);
|
||
|
return CEntityConnection::CompareDelaysSecondary(pConn1,pConn2,eDirection);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Compares by delays, does a secondary compare by output name.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
static int CALLBACK ListCompareDelays(COutputConnection *pOutputConn1, COutputConnection *pOutputConn2, SortDirection_t eDirection)
|
||
|
{
|
||
|
CEntityConnectionList *pConnList1 = pOutputConn1->m_pConnList;
|
||
|
CEntityConnectionList *pConnList2 = pOutputConn2->m_pConnList;
|
||
|
CEntityConnection *pConn1 = pConnList1->Element(0);
|
||
|
CEntityConnection *pConn2 = pConnList2->Element(0);
|
||
|
return CEntityConnection::CompareDelays(pConn1,pConn2,eDirection);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Compares by output name, does a secondary compare by delay.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
static int CALLBACK ListCompareOutputNames(COutputConnection *pOutputConn1, COutputConnection *pOutputConn2, SortDirection_t eDirection)
|
||
|
{
|
||
|
CEntityConnectionList *pConnList1 = pOutputConn1->m_pConnList;
|
||
|
CEntityConnectionList *pConnList2 = pOutputConn2->m_pConnList;
|
||
|
CEntityConnection *pConn1 = pConnList1->Element(0);
|
||
|
CEntityConnection *pConn2 = pConnList2->Element(0);
|
||
|
return CEntityConnection::CompareOutputNames(pConn1,pConn2,eDirection);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Compares by input name, does a secondary compare by delay.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
static int CALLBACK ListCompareInputNames(COutputConnection *pOutputConn1, COutputConnection *pOutputConn2, SortDirection_t eDirection)
|
||
|
{
|
||
|
CEntityConnectionList *pConnList1 = pOutputConn1->m_pConnList;
|
||
|
CEntityConnectionList *pConnList2 = pOutputConn2->m_pConnList;
|
||
|
CEntityConnection *pConn1 = pConnList1->Element(0);
|
||
|
CEntityConnection *pConn2 = pConnList2->Element(0);
|
||
|
return (CEntityConnection::CompareInputNames(pConn1,pConn2,eDirection));
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Compares by source name, does a secondary compare by delay.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
static int CALLBACK ListCompareSourceNames(COutputConnection *pOutputConn1, COutputConnection *pOutputConn2, SortDirection_t eDirection)
|
||
|
{
|
||
|
CEntityConnectionList *pConnList1 = pOutputConn1->m_pConnList;
|
||
|
CEntityConnectionList *pConnList2 = pOutputConn2->m_pConnList;
|
||
|
CEntityConnection *pConn1 = pConnList1->Element(0);
|
||
|
CEntityConnection *pConn2 = pConnList2->Element(0);
|
||
|
return (CEntityConnection::CompareSourceNames(pConn1,pConn2,eDirection));
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Compares by target name, does a secondary compare by delay.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
static int CALLBACK ListCompareTargetNames(COutputConnection *pOutputConn1, COutputConnection *pOutputConn2, SortDirection_t eDirection)
|
||
|
{
|
||
|
CEntityConnectionList *pConnList1 = pOutputConn1->m_pConnList;
|
||
|
CEntityConnectionList *pConnList2 = pOutputConn2->m_pConnList;
|
||
|
CEntityConnection *pConn1 = pConnList1->Element(0);
|
||
|
CEntityConnection *pConn2 = pConnList2->Element(0);
|
||
|
return (CEntityConnection::CompareTargetNames(pConn1,pConn2,eDirection));
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Called by the entity picker tool when an entity is picked. This
|
||
|
// stuffs the entity name into the smartedit control.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_OutputPickEntityTarget::OnNotifyPickEntity(CToolPickEntity *pTool)
|
||
|
{
|
||
|
//
|
||
|
// Update the edit control text with the entity name. This text will be
|
||
|
// stuffed into the local keyvalue storage in OnChangeSmartControl.
|
||
|
//
|
||
|
CMapEntityList Full;
|
||
|
CMapEntityList Partial;
|
||
|
pTool->GetSelectedEntities(Full, Partial);
|
||
|
CMapEntity *pEntity = Full.Element(0);
|
||
|
if (pEntity)
|
||
|
{
|
||
|
const char *pszName = pEntity->GetKeyValue("targetname");
|
||
|
if (!pszName)
|
||
|
{
|
||
|
pszName = "";
|
||
|
}
|
||
|
|
||
|
switch ( m_nDlgItem )
|
||
|
{
|
||
|
case IDC_EDIT_CONN_TARGET:
|
||
|
{
|
||
|
// FIXME: this should be called automatically, but it isn't
|
||
|
m_pDlg->m_ComboTarget.SelectItem(pszName);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IDC_EDIT_CONN_PARAM:
|
||
|
{
|
||
|
// FIXME: this should be called automatically, but it isn't
|
||
|
m_pDlg->GetDlgItem(m_nDlgItem)->SetWindowText(pszName);
|
||
|
m_pDlg->OnEditUpdateParam();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
m_pDlg->GetDlgItem(m_nDlgItem)->SetWindowText(pszName);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_pDlg->StopPicking();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Constructor.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
COP_Output::COP_Output(void)
|
||
|
: CObjectPage(COP_Output::IDD), m_ComboTarget( this )
|
||
|
{
|
||
|
m_bIgnoreTextChanged = false;
|
||
|
m_pObjectList = NULL;
|
||
|
m_pEditObjectRuntimeClass = RUNTIME_CLASS(editCMapClass);
|
||
|
m_nSortColumn = OUTPUT_NAME_COLUMN;
|
||
|
m_pMapEntityList = NULL;
|
||
|
m_fDelay = 0;
|
||
|
m_bPickingEntities = false;
|
||
|
|
||
|
bSkipEditControlRefresh = false;
|
||
|
//
|
||
|
// All columns initially sort in ascending order.
|
||
|
//
|
||
|
for (int i = 0; i < OUTPUT_LIST_NUM_COLUMNS; i++)
|
||
|
{
|
||
|
m_eSortDirection[i] = Sort_Ascending;
|
||
|
}
|
||
|
|
||
|
m_PickEntityTarget.AttachEntityDlg(this);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Destructor.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
COP_Output::~COP_Output(void)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
void COP_Output::OnTextChanged( const char *pText )
|
||
|
{
|
||
|
if ( m_bIgnoreTextChanged )
|
||
|
return;
|
||
|
|
||
|
// Updating the listbox data, will trigger the edit
|
||
|
// controls to update. They don't need to be
|
||
|
bSkipEditControlRefresh = true;
|
||
|
|
||
|
// Target has changed so we need to update for list of inputs
|
||
|
// that are valid for this target
|
||
|
FillInputList();
|
||
|
FilterInputList();
|
||
|
|
||
|
m_ComboInput.SetWindowText(m_strInput);
|
||
|
|
||
|
UpdateEditedTargets();
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose: Updates the validity flag on the given item in the list control
|
||
|
// Input : nItem -
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateItemValidity(int nItem)
|
||
|
{
|
||
|
COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
|
||
|
CEntityConnectionList *pConnectionList = pOutputConn->m_pConnList;
|
||
|
bool bShared = (m_EntityList.Count() == pConnectionList->Count());
|
||
|
|
||
|
bool bShowHiddenTargets = ShouldShowHiddenTargets();
|
||
|
|
||
|
int nIcon;
|
||
|
if (ValidateConnections(pOutputConn, bShowHiddenTargets))
|
||
|
{
|
||
|
if ( !bShowHiddenTargets && !AreAnyTargetEntitiesVisible( pConnectionList ) )
|
||
|
nIcon = ICON_CONN_GOOD_GREY;
|
||
|
else if ( bShared )
|
||
|
nIcon = ICON_CONN_GOOD;
|
||
|
else
|
||
|
nIcon = ICON_CONN_GOOD_GREY;
|
||
|
|
||
|
pOutputConn->m_bIsValid = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nIcon = (bShared ? ICON_CONN_BAD : ICON_CONN_BAD_GREY);
|
||
|
pOutputConn->m_bIsValid = false;
|
||
|
}
|
||
|
m_ListCtrl.SetItem(nItem,0,LVIF_IMAGE, 0, nIcon, 0, 0, 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose :
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateValidityButton(void)
|
||
|
{
|
||
|
CObjectProperties *pParent = (CObjectProperties*) GetParent();
|
||
|
|
||
|
// Get status of all connections
|
||
|
int nItemCount = m_ListCtrl.GetItemCount();
|
||
|
|
||
|
if (nItemCount == 0)
|
||
|
{
|
||
|
pParent->SetOutputButtonState(CONNECTION_NONE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (int nItem = 0; nItem < nItemCount; nItem++)
|
||
|
{
|
||
|
COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
|
||
|
if (!pOutputConn->m_bIsValid)
|
||
|
{
|
||
|
pParent->SetOutputButtonState(CONNECTION_BAD);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
pParent->SetOutputButtonState(CONNECTION_GOOD);
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose: Return true if all connections entries are valid for the given
|
||
|
// output connection. Return false otherwise
|
||
|
//------------------------------------------------------------------------------
|
||
|
bool COP_Output::ValidateConnections(COutputConnection *pOutputConn, bool bVisibilityCheck)
|
||
|
{
|
||
|
int nCount = pOutputConn->m_pConnList->Count();
|
||
|
for (int i = 0; i < nCount; i++)
|
||
|
{
|
||
|
CEntityConnection *pConnection = pOutputConn->m_pConnList->Element(i);
|
||
|
if (pConnection != NULL)
|
||
|
{
|
||
|
// Check validity of output for the list of entities
|
||
|
if (!CEntityConnection::ValidateOutput(pOutputConn->m_pEntityList,pConnection->GetOutputName()))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Check validity of target entity (is it in the map?)
|
||
|
if (!CEntityConnection::ValidateTarget(m_pMapEntityList, bVisibilityCheck, pConnection->GetTargetName()))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Check validity of input
|
||
|
if (!CEntityConnection::ValidateInput(pConnection->GetTargetName(), pConnection->GetInputName(), bVisibilityCheck))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : pEntity -
|
||
|
// bFirst -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::AddEntityConnections(CMapEntity *pEntity, bool bFirst)
|
||
|
{
|
||
|
m_ListCtrl.SetRedraw(FALSE);
|
||
|
|
||
|
//
|
||
|
// The first entity simply adds its connections to the list.
|
||
|
//
|
||
|
int nConnCount = pEntity->Connections_GetCount();
|
||
|
for (int i = 0; i < nConnCount; i++)
|
||
|
{
|
||
|
CEntityConnection *pConnection = pEntity->Connections_Get(i);
|
||
|
if (pConnection != NULL)
|
||
|
{
|
||
|
// First check if the connection already exists, if so just add to it
|
||
|
bool bFound = false;
|
||
|
int nItemCount = m_ListCtrl.GetItemCount();
|
||
|
|
||
|
if (nItemCount > 0)
|
||
|
{
|
||
|
for (int nItem = nItemCount - 1; nItem >= 0; nItem--)
|
||
|
{
|
||
|
COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
|
||
|
CEntityConnectionList *pConnList = pOutputConn->m_pConnList;
|
||
|
CEntityConnection *pTestConn = pConnList->Element(0);
|
||
|
if (pTestConn->CompareConnection(pConnection))
|
||
|
{
|
||
|
// Don't consolidate duplicate connections in the same entity
|
||
|
// Show them twice so the user will see
|
||
|
if ( pOutputConn->m_pEntityList->Find(pEntity) == -1)
|
||
|
{
|
||
|
pConnList->AddToTail(pConnection);
|
||
|
pOutputConn->m_pEntityList->AddToTail(pEntity);
|
||
|
bFound = true;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!bFound)
|
||
|
{
|
||
|
m_ListCtrl.SetItemCount(nItemCount + 1);
|
||
|
|
||
|
m_ListCtrl.InsertItem(LVIF_IMAGE, nItemCount, "", 0, 0, ICON_CONN_GOOD, 0);
|
||
|
|
||
|
m_ListCtrl.SetItemText(nItemCount, OUTPUT_NAME_COLUMN, pConnection->GetOutputName());
|
||
|
m_ListCtrl.SetItemText(nItemCount, TARGET_NAME_COLUMN, pConnection->GetTargetName());
|
||
|
m_ListCtrl.SetItemText(nItemCount, INPUT_NAME_COLUMN, pConnection->GetInputName());
|
||
|
|
||
|
// Build the string for the delay.
|
||
|
float fDelay = pConnection->GetDelay();
|
||
|
char szTemp[MAX_PATH];
|
||
|
sprintf(szTemp, "%.2f", fDelay);
|
||
|
m_ListCtrl.SetItemText(nItemCount, DELAY_COLUMN, szTemp);
|
||
|
|
||
|
// Fire once
|
||
|
m_ListCtrl.SetItemText(nItemCount, ONLY_ONCE_COLUMN, (pConnection->GetTimesToFire() == EVENT_FIRE_ALWAYS) ? "No" : "Yes");
|
||
|
m_ListCtrl.SetItemText(nItemCount, PARAMETER_COLUMN, pConnection->GetParam());
|
||
|
|
||
|
|
||
|
// Set list ctrl data
|
||
|
COutputConnection* pOutputConn = new COutputConnection;
|
||
|
pOutputConn->m_pConnList = new CEntityConnectionList;
|
||
|
pOutputConn->m_pEntityList = new CMapEntityList;
|
||
|
pOutputConn->m_pConnList->AddToTail(pConnection);
|
||
|
pOutputConn->m_pEntityList->AddToTail(pEntity);
|
||
|
pOutputConn->m_bOwnedByAll = true;
|
||
|
m_ListCtrl.SetItemData(nItemCount, (DWORD)pOutputConn);
|
||
|
|
||
|
nItemCount++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_ListCtrl.SetRedraw(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : pDX -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::DoDataExchange(CDataExchange *pDX)
|
||
|
{
|
||
|
CObjectPage::DoDataExchange(pDX);
|
||
|
|
||
|
//{{AFX_DATA_MAP(COP_Output)
|
||
|
DDX_Control(pDX, IDC_LIST, m_ListCtrl);
|
||
|
DDX_Text(pDX, IDC_EDIT_CONN_DELAY, m_fDelay);
|
||
|
DDX_CBString(pDX, IDC_EDIT_CONN_OUTPUT, m_strOutput);
|
||
|
DDX_CBString(pDX, IDC_EDIT_CONN_TARGET, m_strTarget);
|
||
|
DDX_CBString(pDX, IDC_EDIT_CONN_INPUT, m_strInput);
|
||
|
DDX_CBString(pDX, IDC_EDIT_CONN_PARAM, m_strParam);
|
||
|
DDX_Check(pDX, IDC_EDIT_CONN_FIRE_ONCE, m_bFireOnce);
|
||
|
DDX_Control(pDX, IDC_SHOWHIDDENTARGETS, m_ctlShowHiddenTargetsAsBroken);
|
||
|
DDX_Control(pDX, IDC_ADD, m_AddControl);
|
||
|
DDX_Control(pDX, IDC_PASTE, m_PasteControl);
|
||
|
DDX_Control(pDX, IDC_DELETE, m_DeleteControl);
|
||
|
|
||
|
//}}AFX_DATA_MAP
|
||
|
}
|
||
|
|
||
|
|
||
|
bool COP_Output::ShouldShowHiddenTargets()
|
||
|
{
|
||
|
return (Options.general.bShowHiddenTargetsAsBroken == TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose: Enables or Disables all edit controls
|
||
|
// Input : bValue -
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::EnableEditControls(bool bValue)
|
||
|
{
|
||
|
m_ComboOutput.EnableWindow(bValue);
|
||
|
EnableTarget(bValue);
|
||
|
m_ComboInput.EnableWindow(bValue);
|
||
|
|
||
|
CButton *pButton = (CButton *)GetDlgItem(IDC_EDIT_CONN_FIRE_ONCE);
|
||
|
pButton->EnableWindow(bValue);
|
||
|
|
||
|
CEdit *pDelayEdit = (CEdit *)GetDlgItem(IDC_EDIT_CONN_DELAY);
|
||
|
pDelayEdit->EnableWindow(bValue);
|
||
|
|
||
|
CComboBox *pParamCombo = (CComboBox *)GetDlgItem(IDC_EDIT_CONN_PARAM);
|
||
|
pParamCombo->EnableWindow(bValue);
|
||
|
GetDlgItem(IDC_PICK_ENTITY_PARAM)->EnableWindow( bValue );
|
||
|
|
||
|
// Clear any values
|
||
|
if (!bValue)
|
||
|
{
|
||
|
m_ComboTarget.ForceEditControlText( "" );
|
||
|
m_ComboInput.SetWindowText("");
|
||
|
m_ComboOutput.SetWindowText("");
|
||
|
pParamCombo->SetCurSel(0);
|
||
|
pDelayEdit->SetWindowText("0.0");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : *pMapEntityList -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::SetMapEntityList(const CMapEntityList *pMapEntityList)
|
||
|
{
|
||
|
m_pMapEntityList = pMapEntityList;
|
||
|
FillTargetList();
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose: Updates data displayed in edit controls
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateEditControls(void)
|
||
|
{
|
||
|
//
|
||
|
// Build a list of connections to edit.
|
||
|
//
|
||
|
m_EditList.RemoveAll();
|
||
|
|
||
|
m_AddControl.EnableWindow( ( m_bCanEdit ? TRUE : FALSE ) );
|
||
|
m_PasteControl.EnableWindow( ( m_bCanEdit ? TRUE : FALSE ) );
|
||
|
m_DeleteControl.EnableWindow( ( m_bCanEdit ? TRUE : FALSE ) );
|
||
|
|
||
|
// If nothing is selected, disable edit controls
|
||
|
if (!m_ListCtrl.IsWindowEnabled() || m_ListCtrl.GetSelectedCount() == 0)
|
||
|
{
|
||
|
EnableEditControls(false);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
|
||
|
{
|
||
|
|
||
|
if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
|
||
|
{
|
||
|
COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
|
||
|
m_EditList.AddVectorToTail(*pOutputConn->m_pConnList);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (m_EditList.Count() > 0)
|
||
|
{
|
||
|
SetConnection(&m_EditList);
|
||
|
|
||
|
FillOutputList();
|
||
|
FillInputList();
|
||
|
|
||
|
// We must ignore the text changed event here or else it'll set all selected outputs to the same value.
|
||
|
m_bIgnoreTextChanged = true;
|
||
|
m_ComboTarget.SelectItem(m_strTarget);
|
||
|
m_bIgnoreTextChanged = false;
|
||
|
|
||
|
m_ComboInput.SetWindowText(m_strInput);
|
||
|
m_ComboOutput.SetWindowText(m_strOutput);
|
||
|
m_CheckBoxFireOnce.SetCheck(m_bFireOnce);
|
||
|
|
||
|
CEdit *pDelayEdit = ( CEdit* )GetDlgItem( IDC_EDIT_CONN_DELAY );
|
||
|
char szTemp[MAX_PATH];
|
||
|
sprintf(szTemp, "%.2f", m_fDelay);
|
||
|
pDelayEdit->SetWindowText(szTemp);
|
||
|
|
||
|
CComboBox* pParamEdit = ( CComboBox* )GetDlgItem( IDC_EDIT_CONN_PARAM );
|
||
|
pParamEdit->SetWindowText(m_strParam);
|
||
|
|
||
|
FilterInputList();
|
||
|
|
||
|
//
|
||
|
// Update the UI state based on our current data.
|
||
|
//
|
||
|
char szBuf[MAX_IO_NAME_LEN];
|
||
|
|
||
|
CClassOutput *pOutput = GetOutput(szBuf, sizeof(szBuf));
|
||
|
UpdateCombosForSelectedOutput(pOutput);
|
||
|
|
||
|
CClassInput *pInput = GetInput(szBuf, sizeof(szBuf));
|
||
|
UpdateCombosForSelectedInput(pInput);
|
||
|
|
||
|
//CMapEntityList *pTarget = GetTarget(szBuf, sizeof(szBuf));
|
||
|
//UpdateCombosForSelectedTarget(pTarget);
|
||
|
}
|
||
|
|
||
|
if ( m_bCanEdit == false )
|
||
|
{
|
||
|
EnableEditControls( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Adds a connection to all entities being edited.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnAdd(void)
|
||
|
{
|
||
|
FOR_EACH_OBJ( m_EntityList, pos)
|
||
|
{
|
||
|
CMapEntity *pEntity = m_EntityList.Element(pos);
|
||
|
if (pEntity != NULL)
|
||
|
{
|
||
|
CEntityConnection *pConnection = new CEntityConnection;
|
||
|
pEntity->Connections_Add(pConnection);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
UpdateConnectionList();
|
||
|
|
||
|
// Set selection to new item, and move the focus to the output combo
|
||
|
// so they can just start editing.
|
||
|
int nCount = m_ListCtrl.GetItemCount();
|
||
|
SetSelectedItem(nCount - 1);
|
||
|
m_ListCtrl.EnsureVisible(nCount - 1, FALSE);
|
||
|
GetDlgItem(IDC_EDIT_CONN_OUTPUT)->SetFocus();
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose: Clear copy buffer
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::EmptyCopyBuffer(void)
|
||
|
{
|
||
|
// Delete any old connections
|
||
|
int nConnCount = m_pConnectionBuffer->Count();
|
||
|
for (int i = 0; i < nConnCount; i++)
|
||
|
{
|
||
|
CEntityConnection *pConnection = m_pConnectionBuffer->Element(i);
|
||
|
if (pConnection != NULL)
|
||
|
{
|
||
|
delete pConnection;
|
||
|
}
|
||
|
}
|
||
|
m_pConnectionBuffer->RemoveAll();
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Copies list of selected connections into copy buffer
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnCopy(void)
|
||
|
{
|
||
|
EmptyCopyBuffer();
|
||
|
|
||
|
if (m_ListCtrl.GetSelectedCount() != 0)
|
||
|
{
|
||
|
int nCount = m_ListCtrl.GetItemCount();
|
||
|
if (nCount > 0)
|
||
|
{
|
||
|
for (int nItem = nCount - 1; nItem >= 0; nItem--)
|
||
|
{
|
||
|
if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
|
||
|
{
|
||
|
//
|
||
|
// Each item in the list control is a list of identical connections that are contained
|
||
|
// in multiple entities. Add each selected connection to the selected entities.
|
||
|
//
|
||
|
COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
|
||
|
CEntityConnectionList *pConnList = pOutputConn->m_pConnList;
|
||
|
if (pConnList != NULL)
|
||
|
{
|
||
|
CEntityConnection *pConnection = pConnList->Element(0);
|
||
|
if (pConnection)
|
||
|
{
|
||
|
CEntityConnection *pNewConnection = new CEntityConnection;
|
||
|
*pNewConnection = *pConnection;
|
||
|
m_pConnectionBuffer->AddToTail(pNewConnection);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Adds a connection to all entities being edited.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnPaste(void)
|
||
|
{
|
||
|
// Early out
|
||
|
if (!m_pConnectionBuffer->Count())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CUtlVector<CEntityConnection *> NewConnections;
|
||
|
|
||
|
// Add connections from copy buffer to all selected entities
|
||
|
FOR_EACH_OBJ( m_EntityList, pos )
|
||
|
{
|
||
|
CMapEntity *pEntity = m_EntityList.Element(pos);
|
||
|
if (pEntity != NULL)
|
||
|
{
|
||
|
int nConnCount = m_pConnectionBuffer->Count();
|
||
|
for (int i = 0; i < nConnCount; i++)
|
||
|
{
|
||
|
CEntityConnection *pConnection = m_pConnectionBuffer->Element(i);
|
||
|
if (pConnection != NULL)
|
||
|
{
|
||
|
CEntityConnection *pNewConnection = new CEntityConnection;
|
||
|
*pNewConnection = *pConnection;
|
||
|
pEntity->Connections_Add(pNewConnection);
|
||
|
|
||
|
NewConnections.AddToTail(pNewConnection);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
UpdateConnectionList();
|
||
|
SortListByColumn(m_nSortColumn, m_eSortDirection[m_nSortColumn]);
|
||
|
SetSelectedConnections(NewConnections);
|
||
|
GetDlgItem(IDC_EDIT_CONN_OUTPUT)->SetFocus();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnPickEntity(void)
|
||
|
{
|
||
|
CButton *pButton = (CButton *)GetDlgItem(IDC_PICK_ENTITY);
|
||
|
Assert(pButton != NULL);
|
||
|
|
||
|
if (pButton != NULL)
|
||
|
{
|
||
|
if (pButton->GetCheck())
|
||
|
{
|
||
|
//
|
||
|
// Activate the entity picker tool.
|
||
|
//
|
||
|
m_bPickingEntities = true;
|
||
|
m_PickEntityTarget.AttachDlgItem( IDC_EDIT_CONN_TARGET );
|
||
|
CToolPickEntity *pTool = (CToolPickEntity *)ToolManager()->GetToolForID(TOOL_PICK_ENTITY);
|
||
|
pTool->Attach(&m_PickEntityTarget);
|
||
|
ToolManager()->SetTool(TOOL_PICK_ENTITY);
|
||
|
GetDlgItem(IDC_PICK_ENTITY_PARAM)->EnableWindow( false );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
StopPicking();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnPickEntityParam(void)
|
||
|
{
|
||
|
CButton *pButton = (CButton *)GetDlgItem(IDC_PICK_ENTITY_PARAM);
|
||
|
Assert(pButton != NULL);
|
||
|
|
||
|
if (pButton != NULL)
|
||
|
{
|
||
|
if (pButton->GetCheck())
|
||
|
{
|
||
|
//
|
||
|
// Activate the entity picker tool.
|
||
|
//
|
||
|
m_bPickingEntities = true;
|
||
|
m_PickEntityTarget.AttachDlgItem( IDC_EDIT_CONN_PARAM );
|
||
|
CToolPickEntity *pTool = (CToolPickEntity *)ToolManager()->GetToolForID(TOOL_PICK_ENTITY);
|
||
|
pTool->Attach(&m_PickEntityTarget);
|
||
|
ToolManager()->SetTool(TOOL_PICK_ENTITY);
|
||
|
GetDlgItem(IDC_PICK_ENTITY)->EnableWindow( false );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
StopPicking();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Deletes all selected items from the connection list, and removes the
|
||
|
// corresponding connections from the list of entities being edited.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnDelete(void)
|
||
|
{
|
||
|
if (m_ListCtrl.GetSelectedCount() != 0)
|
||
|
{
|
||
|
int nCount = m_ListCtrl.GetItemCount();
|
||
|
int nLastItem = 0;
|
||
|
if (nCount > 0)
|
||
|
{
|
||
|
for (int nItem = nCount - 1; nItem >= 0; nItem--)
|
||
|
{
|
||
|
if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
|
||
|
{
|
||
|
//
|
||
|
// Each item in the list control is a list of identical connections that are contained
|
||
|
// in multiple entities. Since we don't store the containing entity along with the connection,
|
||
|
// just try to remove all the connections in the list from all the selected entities.
|
||
|
//
|
||
|
COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
|
||
|
CEntityConnectionList *pConnList = pOutputConn->m_pConnList;
|
||
|
m_ListCtrl.DeleteItem(nItem);
|
||
|
|
||
|
if (pConnList != NULL)
|
||
|
{
|
||
|
int nConnCount = pConnList->Count();
|
||
|
for (int nConn = 0; nConn < nConnCount; nConn++)
|
||
|
{
|
||
|
CEntityConnection *pConnection = pConnList->Element(nConn);
|
||
|
if (pConnection != NULL)
|
||
|
{
|
||
|
//
|
||
|
// Remove the connection from all entities being edited.
|
||
|
//
|
||
|
FOR_EACH_OBJ( m_EntityList, pos )
|
||
|
{
|
||
|
CMapEntity *pEntity = m_EntityList.Element(pos);
|
||
|
if (pEntity != NULL)
|
||
|
{
|
||
|
pEntity->Connections_Remove(pConnection);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Remove the connection from the upstream list of all entities it targets.
|
||
|
//
|
||
|
CMapEntityList *pTargetList = pConnection->GetTargetEntityList();
|
||
|
if ( pTargetList )
|
||
|
{
|
||
|
FOR_EACH_OBJ( *pTargetList, pos2 )
|
||
|
{
|
||
|
CMapEntity *pEntity = pTargetList->Element( pos2 );
|
||
|
pEntity->Upstream_Remove( pConnection );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete pConnection;
|
||
|
}
|
||
|
|
||
|
delete pConnList;
|
||
|
}
|
||
|
// Keep track of last item so can set selection focus
|
||
|
nLastItem = nItem;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Set selection focus as point of deletion or on last item
|
||
|
int nNumItems = m_ListCtrl.GetItemCount()-1;
|
||
|
if (nLastItem > nNumItems)
|
||
|
{
|
||
|
nLastItem = nNumItems;
|
||
|
}
|
||
|
SetSelectedItem(nLastItem);
|
||
|
UpdateValidityButton();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose : Take the user to the output page of the selected entity that
|
||
|
// targets me.
|
||
|
// Input :
|
||
|
// Output :
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::OnMark(void)
|
||
|
{
|
||
|
int nCount = m_ListCtrl.GetItemCount();
|
||
|
CMapDoc* pDoc = CMapDoc::GetActiveMapDoc();
|
||
|
|
||
|
CEntityConnection *pConnection = NULL;
|
||
|
|
||
|
if (nCount > 0 && pDoc)
|
||
|
{
|
||
|
CMapObjectList Select;
|
||
|
|
||
|
for (int nItem = nCount - 1; nItem >= 0; nItem--)
|
||
|
{
|
||
|
if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
|
||
|
{
|
||
|
COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
|
||
|
pConnection = pOutputConn->m_pConnList->Element(0);
|
||
|
|
||
|
CMapDoc *pDocActive = CMapDoc::GetActiveMapDoc();
|
||
|
if ( pDocActive != NULL)
|
||
|
{
|
||
|
CMapEntityList Found;
|
||
|
pDocActive->FindEntitiesByName(Found, m_ListCtrl.GetItemText(nItem, TARGET_NAME_COLUMN), false);
|
||
|
|
||
|
FOR_EACH_OBJ( Found, pos )
|
||
|
{
|
||
|
CMapEntity *pEntity = Found.Element(pos);
|
||
|
Select.AddToTail(pEntity);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (Select.Count()>0)
|
||
|
{
|
||
|
pDoc->SelectObjectList(&Select);
|
||
|
|
||
|
// (a bit squirly way of doing this)
|
||
|
if ( Select.Count()==1 )
|
||
|
GetMainWnd()->pObjectProperties->SetPageToInput(pConnection);
|
||
|
|
||
|
pDoc->Center2DViewsOnSelection();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MessageBox("No entities were found with that targetname.", "No entities found", MB_ICONINFORMATION | MB_OK);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Sets up the list view columns, initial sort column.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
BOOL COP_Output::OnInitDialog(void)
|
||
|
{
|
||
|
CObjectPage::OnInitDialog();
|
||
|
|
||
|
m_ComboOutput.SubclassDlgItem(IDC_EDIT_CONN_OUTPUT, this);
|
||
|
m_ComboInput.SubclassDlgItem(IDC_EDIT_CONN_INPUT, this);
|
||
|
m_ComboTarget.SubclassDlgItem(IDC_EDIT_CONN_TARGET, this);
|
||
|
m_CheckBoxFireOnce.SubclassDlgItem(IDC_EDIT_CONN_FIRE_ONCE, this);
|
||
|
|
||
|
m_ListCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP);
|
||
|
|
||
|
m_ListCtrl.InsertColumn(ICON_COLUMN, "", LVCFMT_CENTER, 20);
|
||
|
m_ListCtrl.InsertColumn(OUTPUT_NAME_COLUMN, "My Output", LVCFMT_LEFT, 70);
|
||
|
m_ListCtrl.InsertColumn(TARGET_NAME_COLUMN, "Target Entity", LVCFMT_LEFT, 70);
|
||
|
m_ListCtrl.InsertColumn(INPUT_NAME_COLUMN, "Target Input", LVCFMT_LEFT, 70);
|
||
|
m_ListCtrl.InsertColumn(DELAY_COLUMN, "Delay", LVCFMT_LEFT, 70);
|
||
|
m_ListCtrl.InsertColumn(ONLY_ONCE_COLUMN, "Only Once", LVCFMT_LEFT, 70);
|
||
|
m_ListCtrl.InsertColumn(PARAMETER_COLUMN, "Parameter", LVCFMT_LEFT, 70);
|
||
|
|
||
|
UpdateConnectionList();
|
||
|
|
||
|
SetSortColumn(m_nSortColumn, m_eSortDirection[m_nSortColumn]);
|
||
|
|
||
|
// Force an update of the column header text so that the sort indicator is shown.
|
||
|
UpdateColumnHeaderText(m_nSortColumn, true, m_eSortDirection[m_nSortColumn]);
|
||
|
|
||
|
ResizeColumns();
|
||
|
|
||
|
m_strLastParam.Empty();
|
||
|
|
||
|
// Select the first item in the combo box
|
||
|
SetSelectedItem(0);
|
||
|
|
||
|
// Create image list. Is deleted automatically when listctrl is deleted
|
||
|
if (!m_pImageList)
|
||
|
{
|
||
|
CWinApp *pApp = AfxGetApp();
|
||
|
m_pImageList = new CImageList();
|
||
|
Assert(m_pImageList != NULL); // serious allocation failure checking
|
||
|
m_pImageList->Create(16, 16, TRUE, 1, 0);
|
||
|
m_pImageList->Add(pApp->LoadIcon( IDI_OUTPUTBAD ));
|
||
|
m_pImageList->Add(pApp->LoadIcon( IDI_OUTPUT ));
|
||
|
m_pImageList->Add(pApp->LoadIcon( IDI_OUTPUTBAD_GREY ));
|
||
|
m_pImageList->Add(pApp->LoadIcon( IDI_OUTPUT_GREY ));
|
||
|
|
||
|
}
|
||
|
m_ListCtrl.SetImageList(m_pImageList, LVSIL_SMALL );
|
||
|
|
||
|
// Apply the eyedropper image to the picker buttons.
|
||
|
CButton *pButton = (CButton *)GetDlgItem(IDC_PICK_ENTITY);
|
||
|
if (pButton)
|
||
|
{
|
||
|
CWinApp *pApp = AfxGetApp();
|
||
|
HICON hIcon = pApp->LoadIcon(IDI_EYEDROPPER);
|
||
|
pButton->SetIcon(hIcon);
|
||
|
}
|
||
|
|
||
|
pButton = (CButton *)GetDlgItem(IDC_PICK_ENTITY_PARAM);
|
||
|
if (pButton)
|
||
|
{
|
||
|
CWinApp *pApp = AfxGetApp();
|
||
|
HICON hIcon = pApp->LoadIcon(IDI_EYEDROPPER);
|
||
|
pButton->SetIcon(hIcon);
|
||
|
}
|
||
|
|
||
|
CAnchorDef anchorDefs[] =
|
||
|
{
|
||
|
CAnchorDef( IDC_LIST, k_eSimpleAnchorAllSides ),
|
||
|
CAnchorDef( IDC_OUTPUTS_STATIC_PANEL, k_eAnchorLeft, k_eAnchorBottom, k_eAnchorRight, k_eAnchorBottom ),
|
||
|
CAnchorDef( IDC_OUTPUT_LABEL, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_TARGETS_LABEL, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_VIA_INPUT_LABEL, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_PARAMETER_LABEL, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_DELAY_LABEL, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_EDIT_CONN_DELAY, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_EDIT_CONN_FIRE_ONCE, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_EDIT_CONN_PARAM, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_EDIT_CONN_INPUT, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_EDIT_CONN_TARGET, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_EDIT_CONN_OUTPUT, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_PICK_ENTITY, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_PICK_ENTITY_PARAM, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_MARK, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_ADD, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_COPY, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_PASTE, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_DELETE, k_eSimpleAnchorBottomSide ),
|
||
|
CAnchorDef( IDC_SHOWHIDDENTARGETS, k_eSimpleAnchorBottomRight )
|
||
|
};
|
||
|
m_AnchorMgr.Init( GetSafeHwnd(), anchorDefs, ARRAYSIZE( anchorDefs ) );
|
||
|
|
||
|
// Set the last state this was at.
|
||
|
m_ctlShowHiddenTargetsAsBroken.SetCheck( ShouldShowHiddenTargets() );
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : wParam -
|
||
|
// lParam -
|
||
|
// pResult -
|
||
|
// Output : Returns TRUE on success, FALSE on failure.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
BOOL COP_Output::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult)
|
||
|
{
|
||
|
NMHDR *pnmh = (NMHDR *)lParam;
|
||
|
|
||
|
if (pnmh->idFrom == IDC_LIST)
|
||
|
{
|
||
|
switch (pnmh->code)
|
||
|
{
|
||
|
case LVN_COLUMNCLICK:
|
||
|
{
|
||
|
NMLISTVIEW *pnmv = (NMLISTVIEW *)lParam;
|
||
|
if (pnmv->iSubItem < OUTPUT_LIST_NUM_COLUMNS)
|
||
|
{
|
||
|
SortDirection_t eSortDirection = m_eSortDirection[pnmv->iSubItem];
|
||
|
|
||
|
//
|
||
|
// If they clicked on the current sort column, reverse the sort direction.
|
||
|
//
|
||
|
if (pnmv->iSubItem == m_nSortColumn)
|
||
|
{
|
||
|
if (m_eSortDirection[m_nSortColumn] == Sort_Ascending)
|
||
|
{
|
||
|
eSortDirection = Sort_Descending;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
eSortDirection = Sort_Ascending;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Update the sort column and sort the list.
|
||
|
//
|
||
|
SetSortColumn(pnmv->iSubItem, eSortDirection);
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
case NM_DBLCLK:
|
||
|
{
|
||
|
OnMark();
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
case LVN_ITEMCHANGED:
|
||
|
{
|
||
|
NMLISTVIEW *pnmv = (NMLISTVIEW *)lParam;
|
||
|
if ( ( pnmv->uNewState & LVIS_SELECTED ) != ( pnmv->uOldState & LVIS_SELECTED ) )
|
||
|
{
|
||
|
// Listbox selection has changed so update edit controls
|
||
|
if (!bSkipEditControlRefresh)
|
||
|
{
|
||
|
UpdateEditControls();
|
||
|
}
|
||
|
bSkipEditControlRefresh = false;
|
||
|
|
||
|
// Forget the saved param, because it was for a different I/O connection.
|
||
|
m_strLastParam.Empty();
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return(CObjectPage::OnNotify(wParam, lParam, pResult));
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Empties the contents of the connections list control, freeing the
|
||
|
// connection list hanging off of each row.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::RemoveAllEntityConnections(void)
|
||
|
{
|
||
|
m_ListCtrl.SetRedraw(FALSE);
|
||
|
|
||
|
int nCount = m_ListCtrl.GetItemCount();
|
||
|
if (nCount > 0)
|
||
|
{
|
||
|
for (int nItem = nCount - 1; nItem >= 0; nItem--)
|
||
|
{
|
||
|
COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
|
||
|
CEntityConnectionList *pConnList = pOutputConn->m_pConnList;
|
||
|
CMapEntityList *pEntityList = pOutputConn->m_pEntityList;
|
||
|
|
||
|
m_ListCtrl.DeleteItem(nItem);
|
||
|
|
||
|
delete pOutputConn;
|
||
|
delete pConnList;
|
||
|
delete pEntityList;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_ListCtrl.SetRedraw(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : Mode -
|
||
|
// pData -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateData( int Mode, PVOID pData, bool bCanEdit )
|
||
|
{
|
||
|
__super::UpdateData( Mode, pData, bCanEdit );
|
||
|
|
||
|
if (!IsWindow(m_hWnd))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
switch (Mode)
|
||
|
{
|
||
|
case LoadFirstData:
|
||
|
{
|
||
|
// m_ListCtrl.DeleteAllItems();
|
||
|
// UpdateConnectionList();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case LoadData:
|
||
|
{
|
||
|
// m_ListCtrl.DeleteAllItems();
|
||
|
// UpdateConnectionList();
|
||
|
// SetSelectedItem(0);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case LoadFinished:
|
||
|
{
|
||
|
m_ListCtrl.DeleteAllItems();
|
||
|
UpdateConnectionList();
|
||
|
SetSelectedItem(0);
|
||
|
SortListByColumn(m_nSortColumn, m_eSortDirection[m_nSortColumn]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
UpdateEditControls();
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose: Generates list of map entites that are being edited from the
|
||
|
// m_pObject list
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateEntityList(void)
|
||
|
{
|
||
|
// Clear old entity list
|
||
|
m_EntityList.RemoveAll();
|
||
|
|
||
|
if (m_pObjectList != NULL)
|
||
|
{
|
||
|
FOR_EACH_OBJ( *m_pObjectList, pos )
|
||
|
{
|
||
|
CMapClass *pObject = m_pObjectList->Element(pos);
|
||
|
|
||
|
if ((pObject != NULL) && (pObject->IsMapClass(MAPCLASS_TYPE(CMapEntity))) )
|
||
|
{
|
||
|
CMapEntity *pEntity = (CMapEntity *)pObject;
|
||
|
m_EntityList.AddToTail(pEntity);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : nColumn -
|
||
|
// eDirection -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::SetSortColumn(int nColumn, SortDirection_t eDirection)
|
||
|
{
|
||
|
Assert(nColumn < OUTPUT_LIST_NUM_COLUMNS);
|
||
|
|
||
|
//
|
||
|
// If the sort column changed, update the old sort column header text.
|
||
|
//
|
||
|
if (m_nSortColumn != nColumn)
|
||
|
{
|
||
|
UpdateColumnHeaderText(m_nSortColumn, false, eDirection);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If the sort column or direction changed, update the new sort column header text.
|
||
|
//
|
||
|
if ((m_nSortColumn != nColumn) || (m_eSortDirection[m_nSortColumn] != eDirection))
|
||
|
{
|
||
|
UpdateColumnHeaderText(nColumn, true, eDirection);
|
||
|
}
|
||
|
|
||
|
m_nSortColumn = nColumn;
|
||
|
m_eSortDirection[m_nSortColumn] = eDirection;
|
||
|
|
||
|
SortListByColumn(m_nSortColumn, m_eSortDirection[m_nSortColumn]);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Sorts the outputs list by column.
|
||
|
// Input : nColumn - Index of column by which to sort.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::SortListByColumn(int nColumn, SortDirection_t eDirection)
|
||
|
{
|
||
|
PFNLVCOMPARE pfnSort = NULL;
|
||
|
|
||
|
switch (nColumn)
|
||
|
{
|
||
|
case ONLY_ONCE_COLUMN:
|
||
|
{
|
||
|
//No Sort
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case PARAMETER_COLUMN:
|
||
|
{
|
||
|
//No Sort
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case OUTPUT_NAME_COLUMN:
|
||
|
{
|
||
|
pfnSort = (PFNLVCOMPARE)ListCompareOutputNames;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case TARGET_NAME_COLUMN:
|
||
|
{
|
||
|
pfnSort = (PFNLVCOMPARE)ListCompareTargetNames;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case INPUT_NAME_COLUMN:
|
||
|
{
|
||
|
pfnSort = (PFNLVCOMPARE)ListCompareInputNames;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case DELAY_COLUMN:
|
||
|
{
|
||
|
pfnSort = (PFNLVCOMPARE)ListCompareDelays;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
Assert(FALSE);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pfnSort != NULL)
|
||
|
{
|
||
|
m_ListCtrl.SortItems(pfnSort, (DWORD)eDirection);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::ResizeColumns(void)
|
||
|
{
|
||
|
if (m_ListCtrl.GetItemCount() > 0)
|
||
|
{
|
||
|
m_ListCtrl.SetColumnWidth(OUTPUT_NAME_COLUMN, LVSCW_AUTOSIZE);
|
||
|
m_ListCtrl.SetColumnWidth(TARGET_NAME_COLUMN, LVSCW_AUTOSIZE);
|
||
|
m_ListCtrl.SetColumnWidth(INPUT_NAME_COLUMN, LVSCW_AUTOSIZE);
|
||
|
m_ListCtrl.SetColumnWidth(DELAY_COLUMN, LVSCW_AUTOSIZE_USEHEADER);
|
||
|
m_ListCtrl.SetColumnWidth(ONLY_ONCE_COLUMN, LVSCW_AUTOSIZE_USEHEADER);
|
||
|
m_ListCtrl.SetColumnWidth(PARAMETER_COLUMN, LVSCW_AUTOSIZE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateConnectionList(void)
|
||
|
{
|
||
|
// Get list of all entities in the world
|
||
|
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
|
||
|
Assert(pDoc != NULL);
|
||
|
if (!pDoc)
|
||
|
return;
|
||
|
|
||
|
CMapWorld *pWorld = pDoc->GetMapWorld();
|
||
|
Assert(pWorld != NULL); // dvs: I've seen pWorld be NULL on app shutdown, not sure why we ended up here though
|
||
|
if (!pWorld)
|
||
|
return;
|
||
|
|
||
|
SetMapEntityList(pWorld->EntityList_GetList());
|
||
|
|
||
|
UpdateEntityList();
|
||
|
RemoveAllEntityConnections();
|
||
|
|
||
|
bool bFirst = true;
|
||
|
|
||
|
FOR_EACH_OBJ( m_EntityList, pos )
|
||
|
{
|
||
|
CMapEntity *pEntity = m_EntityList.Element(pos);
|
||
|
if (pEntity != NULL)
|
||
|
{
|
||
|
AddEntityConnections(pEntity, bFirst);
|
||
|
bFirst = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update validity flag on all items
|
||
|
for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
|
||
|
{
|
||
|
UpdateItemValidity(nItem);
|
||
|
}
|
||
|
UpdateValidityButton();
|
||
|
|
||
|
ResizeColumns();
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose: Set the selected item in the listbox by index.
|
||
|
// Input : nSelectItem -
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::SetSelectedItem(int nSelectItem)
|
||
|
{
|
||
|
m_ListCtrl.SetRedraw(FALSE);
|
||
|
|
||
|
// Set selected item to be active and all others to false
|
||
|
int nItemCount = m_ListCtrl.GetItemCount();
|
||
|
for (int nItem = 0; nItem < nItemCount; nItem++)
|
||
|
{
|
||
|
if (nItem == nSelectItem)
|
||
|
{
|
||
|
m_ListCtrl.SetItemState(nItem, (unsigned int)LVIS_SELECTED, (unsigned int)LVIS_SELECTED);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_ListCtrl.SetItemState(nItem, (unsigned int)~LVIS_SELECTED, (unsigned int)LVIS_SELECTED);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_ListCtrl.SetRedraw(TRUE);
|
||
|
|
||
|
// Selected item has changed so update edit controls
|
||
|
UpdateEditControls();
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose: Set the selected item in the listbox
|
||
|
// Input : pConnection
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::SetSelectedConnection(CEntityConnection *pConnection)
|
||
|
{
|
||
|
m_ListCtrl.SetRedraw(FALSE);
|
||
|
|
||
|
// Set selected item to be active and all others to false
|
||
|
int nItemCount = m_ListCtrl.GetItemCount();
|
||
|
for (int nItem = 0; nItem < nItemCount; nItem++)
|
||
|
{
|
||
|
COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
|
||
|
CEntityConnectionList *pTestList = pOutputConn->m_pConnList;
|
||
|
|
||
|
if (pTestList->Element(0) == pConnection)
|
||
|
{
|
||
|
m_ListCtrl.SetItemState(nItem,LVIS_SELECTED,LVIS_SELECTED);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_ListCtrl.SetItemState(nItem, (unsigned int)~LVIS_SELECTED, (unsigned int)LVIS_SELECTED);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_ListCtrl.SetRedraw(TRUE);
|
||
|
|
||
|
// Selected item has changed so update edit controls
|
||
|
UpdateEditControls();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Selects the list box entries that correspond to the connections in
|
||
|
// the given list.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::SetSelectedConnections(CEntityConnectionList &List)
|
||
|
{
|
||
|
m_ListCtrl.SetRedraw(FALSE);
|
||
|
|
||
|
int nConnCount = List.Count();
|
||
|
|
||
|
int nItemCount = m_ListCtrl.GetItemCount();
|
||
|
for (int nItem = 0; nItem < nItemCount; nItem++)
|
||
|
{
|
||
|
COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
|
||
|
CEntityConnectionList *pConnList = pOutputConn->m_pConnList;
|
||
|
|
||
|
// See if this row's list holds any of the connections in the given list.
|
||
|
bool bFound = false;
|
||
|
for (int nConn = 0; nConn < nConnCount; nConn++)
|
||
|
{
|
||
|
CEntityConnection *pConn = List.Element(nConn);
|
||
|
if (pConnList->Find(pConn) != -1)
|
||
|
{
|
||
|
bFound = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_ListCtrl.SetItemState(nItem, bFound ? LVIS_SELECTED : ~LVIS_SELECTED, LVIS_SELECTED);
|
||
|
}
|
||
|
|
||
|
m_ListCtrl.SetRedraw(TRUE);
|
||
|
|
||
|
UpdateEditControls();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Adds or removes the little 'V' or '^' sort indicator as appropriate.
|
||
|
// Input : nColumn - Index of column to update.
|
||
|
// bSortColumn - true if this column is the sort column, false if not.
|
||
|
// eDirection - Direction of sort, Sort_Ascending or Sort_Descending.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateColumnHeaderText(int nColumn, bool bIsSortColumn, SortDirection_t eDirection)
|
||
|
{
|
||
|
char szHeaderText[MAX_PATH];
|
||
|
|
||
|
LVCOLUMN Column;
|
||
|
memset(&Column, 0, sizeof(Column));
|
||
|
Column.mask = LVCF_TEXT;
|
||
|
Column.pszText = szHeaderText;
|
||
|
Column.cchTextMax = sizeof(szHeaderText);
|
||
|
m_ListCtrl.GetColumn(nColumn, &Column);
|
||
|
|
||
|
int nMarker = 0;
|
||
|
|
||
|
if (szHeaderText[0] != '\0')
|
||
|
{
|
||
|
nMarker = strlen(szHeaderText) - 1;
|
||
|
char chMarker = szHeaderText[nMarker];
|
||
|
|
||
|
if ((chMarker == '>') || (chMarker == '<'))
|
||
|
{
|
||
|
nMarker -= 2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nMarker++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bIsSortColumn)
|
||
|
{
|
||
|
if (nMarker != 0)
|
||
|
{
|
||
|
szHeaderText[nMarker++] = ' ';
|
||
|
szHeaderText[nMarker++] = ' ';
|
||
|
}
|
||
|
|
||
|
szHeaderText[nMarker++] = (eDirection == Sort_Ascending) ? '>' : '<';
|
||
|
}
|
||
|
|
||
|
szHeaderText[nMarker] = '\0';
|
||
|
|
||
|
m_ListCtrl.SetColumn(nColumn, &Column);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Called when our window is being destroyed.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnDestroy(void)
|
||
|
{
|
||
|
m_ListCtrl.EnableWindow(false);
|
||
|
RemoveAllEntityConnections();
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateEditedFireOnce(void)
|
||
|
{
|
||
|
// Get new delay
|
||
|
CButton *pButton = ( CButton* )GetDlgItem( IDC_EDIT_CONN_FIRE_ONCE );
|
||
|
|
||
|
if (pButton->IsWindowEnabled())
|
||
|
{
|
||
|
int nChecked = (pButton->GetState()&0x0003); // Checked state
|
||
|
|
||
|
// Update the connections
|
||
|
int nConnCount = m_EditList.Count();
|
||
|
for (int nConn = 0; nConn < nConnCount; nConn++)
|
||
|
{
|
||
|
CEntityConnection *pConnection = m_EditList.Element(nConn);
|
||
|
if (pConnection != NULL)
|
||
|
{
|
||
|
pConnection->SetTimesToFire(nChecked?1:EVENT_FIRE_ALWAYS);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update the list box
|
||
|
for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
|
||
|
{
|
||
|
if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
|
||
|
{
|
||
|
m_ListCtrl.SetItemText(nItem, ONLY_ONCE_COLUMN, nChecked ? "Yes" : "No");
|
||
|
}
|
||
|
}
|
||
|
ResizeColumns();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateEditedDelays(void)
|
||
|
{
|
||
|
// Get new delay
|
||
|
CEdit *pDelayEdit = ( CEdit* )GetDlgItem( IDC_EDIT_CONN_DELAY );
|
||
|
|
||
|
if (pDelayEdit->IsWindowEnabled())
|
||
|
{
|
||
|
char strDelay[MAX_IO_NAME_LEN];
|
||
|
pDelayEdit->GetWindowText(strDelay, sizeof(strDelay));
|
||
|
float flDelay = atof(strDelay);
|
||
|
|
||
|
// Update the connections
|
||
|
int nConnCount = m_EditList.Count();
|
||
|
for (int nConn = 0; nConn < nConnCount; nConn++)
|
||
|
{
|
||
|
CEntityConnection *pConnection = m_EditList.Element(nConn);
|
||
|
if (pConnection != NULL)
|
||
|
{
|
||
|
pConnection->SetDelay(flDelay);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update the list box
|
||
|
for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
|
||
|
{
|
||
|
if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
|
||
|
{
|
||
|
m_ListCtrl.SetItemText(nItem, DELAY_COLUMN, strDelay);
|
||
|
}
|
||
|
}
|
||
|
ResizeColumns();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose: Parameters have changed. Update connections and listbox
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateEditedParams(void)
|
||
|
{
|
||
|
CComboBox *pParamEdit = ( CComboBox* )GetDlgItem( IDC_EDIT_CONN_PARAM );
|
||
|
|
||
|
if (pParamEdit->IsWindowEnabled())
|
||
|
{
|
||
|
char strParam[MAX_IO_NAME_LEN];
|
||
|
pParamEdit->GetWindowText(strParam, sizeof(strParam));
|
||
|
if (!strcmp(strParam, PARAM_STRING_NONE))
|
||
|
{
|
||
|
strParam[0] = '\0';
|
||
|
}
|
||
|
|
||
|
// Update the connections
|
||
|
int nConnCount = m_EditList.Count();
|
||
|
for (int nConn = 0; nConn < nConnCount; nConn++)
|
||
|
{
|
||
|
CEntityConnection *pConnection = m_EditList.Element(nConn);
|
||
|
if (pConnection != NULL)
|
||
|
{
|
||
|
pConnection->SetParam(strParam);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update the list box
|
||
|
for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
|
||
|
{
|
||
|
if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
|
||
|
{
|
||
|
m_ListCtrl.SetItemText(nItem, PARAMETER_COLUMN, strParam);
|
||
|
}
|
||
|
}
|
||
|
ResizeColumns();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose: Inputs have changed. Update connections and listbox
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateEditedInputs(void)
|
||
|
{
|
||
|
// Get the new name
|
||
|
char strInput[MAX_IO_NAME_LEN];
|
||
|
GetInput(strInput, sizeof(strInput));
|
||
|
|
||
|
// Update the connections
|
||
|
int nConnCount = m_EditList.Count();
|
||
|
for (int nConn = 0; nConn < nConnCount; nConn++)
|
||
|
{
|
||
|
CEntityConnection *pConnection = m_EditList.Element(nConn);
|
||
|
if (pConnection != NULL)
|
||
|
{
|
||
|
pConnection->SetInputName(strInput);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update the list box
|
||
|
for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
|
||
|
{
|
||
|
if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
|
||
|
{
|
||
|
m_ListCtrl.SetItemText(nItem, INPUT_NAME_COLUMN, strInput);
|
||
|
UpdateItemValidity(nItem);
|
||
|
}
|
||
|
}
|
||
|
UpdateValidityButton();
|
||
|
ResizeColumns();
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose: Outputs have changed. Update connections and listbox
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateEditedOutputs()
|
||
|
{
|
||
|
// Get the new name
|
||
|
char strOutput[MAX_IO_NAME_LEN];
|
||
|
GetOutput(strOutput, sizeof(strOutput));
|
||
|
|
||
|
// Update the connections
|
||
|
int nConnCount = m_EditList.Count();
|
||
|
for (int nConn = 0; nConn < nConnCount; nConn++)
|
||
|
{
|
||
|
CEntityConnection *pConnection = m_EditList.Element(nConn);
|
||
|
if (pConnection != NULL)
|
||
|
{
|
||
|
pConnection->SetOutputName(strOutput);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update the list box
|
||
|
for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
|
||
|
{
|
||
|
if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
|
||
|
{
|
||
|
m_ListCtrl.SetItemText(nItem, OUTPUT_NAME_COLUMN, strOutput);
|
||
|
UpdateItemValidity(nItem);
|
||
|
}
|
||
|
}
|
||
|
UpdateValidityButton();
|
||
|
ResizeColumns();
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose: Targets have changed. Update connections and listbox
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateEditedTargets(void)
|
||
|
{
|
||
|
// Get the new target name
|
||
|
char strTarget[MAX_IO_NAME_LEN];
|
||
|
GetTarget(strTarget, sizeof(strTarget));
|
||
|
|
||
|
// Update the connections
|
||
|
int nConnCount = m_EditList.Count();
|
||
|
for (int nConn = 0; nConn < nConnCount; nConn++)
|
||
|
{
|
||
|
CEntityConnection *pConnection = m_EditList.Element(nConn);
|
||
|
if (pConnection != NULL)
|
||
|
{
|
||
|
pConnection->SetTargetName(strTarget);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update the list box
|
||
|
for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
|
||
|
{
|
||
|
if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
|
||
|
{
|
||
|
m_ListCtrl.SetItemText(nItem, TARGET_NAME_COLUMN, strTarget);
|
||
|
UpdateItemValidity(nItem);
|
||
|
}
|
||
|
}
|
||
|
UpdateValidityButton();
|
||
|
ResizeColumns();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Enables or diables the target combo box and the eyedropper button.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::EnableTarget(bool bEnable)
|
||
|
{
|
||
|
m_ComboTarget.EnableWindow(bEnable);
|
||
|
GetDlgItem(IDC_PICK_ENTITY)->EnableWindow(bEnable);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : *pConnection -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::SetConnection(CEntityConnectionList *pConnectionList)
|
||
|
{
|
||
|
Assert(pConnectionList != NULL);
|
||
|
|
||
|
// Fill edit boxes. Disable for multiple connections have incompatible data
|
||
|
bool bFirst = true;
|
||
|
CButton* pFireEdit = ( CButton* )GetDlgItem( IDC_EDIT_CONN_FIRE_ONCE );
|
||
|
CEdit* pDelayEdit = ( CEdit* )GetDlgItem( IDC_EDIT_CONN_DELAY );
|
||
|
CComboBox* pParamEdit = ( CComboBox* )GetDlgItem( IDC_EDIT_CONN_PARAM );
|
||
|
|
||
|
m_ComboOutput.EnableWindow(true);
|
||
|
EnableTarget(true);
|
||
|
m_ComboInput.EnableWindow(true);
|
||
|
pFireEdit->EnableWindow(true);
|
||
|
pDelayEdit->EnableWindow(true);
|
||
|
pParamEdit->EnableWindow(true);
|
||
|
GetDlgItem(IDC_PICK_ENTITY_PARAM)->EnableWindow( false );
|
||
|
m_bEntityParamTarget = false;
|
||
|
|
||
|
int nConnCount = pConnectionList->Count();
|
||
|
for (int nConn = 0; nConn < nConnCount; nConn++)
|
||
|
{
|
||
|
CEntityConnection *pConnection = (CEntityConnection *)pConnectionList->Element(nConn);
|
||
|
if (pConnection == NULL)
|
||
|
continue;
|
||
|
|
||
|
// Fill in output name, disable for non-compatible connections
|
||
|
if (m_ComboOutput.IsWindowEnabled())
|
||
|
{
|
||
|
if (bFirst)
|
||
|
{
|
||
|
m_strOutput = pConnection->GetOutputName();
|
||
|
}
|
||
|
else if (m_strOutput != pConnection->GetOutputName())
|
||
|
{
|
||
|
m_strOutput.Empty();
|
||
|
m_ComboOutput.EnableWindow(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Fill in target name, disable for non-compatible connections
|
||
|
if (m_ComboTarget.IsWindowEnabled())
|
||
|
{
|
||
|
if (bFirst)
|
||
|
{
|
||
|
m_strTarget = pConnection->GetTargetName();
|
||
|
}
|
||
|
else if (m_strTarget != pConnection->GetTargetName())
|
||
|
{
|
||
|
m_strTarget.Empty();
|
||
|
EnableTarget(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Fill in input name, disable for non-compatible connections
|
||
|
if (m_ComboInput.IsWindowEnabled())
|
||
|
{
|
||
|
if (bFirst)
|
||
|
{
|
||
|
m_strInput = pConnection->GetInputName();
|
||
|
}
|
||
|
else if (m_strInput != pConnection->GetInputName())
|
||
|
{
|
||
|
m_strInput.Empty();
|
||
|
m_ComboInput.EnableWindow(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Fill in parameters, disable for non-compatible connections
|
||
|
if (pParamEdit->IsWindowEnabled())
|
||
|
{
|
||
|
if (bFirst)
|
||
|
{
|
||
|
m_strParam = pConnection->GetParam();
|
||
|
m_bNoParamEdit = false;
|
||
|
}
|
||
|
else if (m_strParam != pConnection->GetParam())
|
||
|
{
|
||
|
m_strParam.Empty();
|
||
|
pParamEdit->EnableWindow(false);
|
||
|
GetDlgItem(IDC_PICK_ENTITY_PARAM)->EnableWindow( false );
|
||
|
m_bNoParamEdit = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Fill in delay, disable for non-compatible connections
|
||
|
if (pDelayEdit->IsWindowEnabled())
|
||
|
{
|
||
|
if (bFirst)
|
||
|
{
|
||
|
m_fDelay = pConnection->GetDelay();
|
||
|
}
|
||
|
else if (m_fDelay != pConnection->GetDelay())
|
||
|
{
|
||
|
m_fDelay = 0;
|
||
|
pDelayEdit->EnableWindow(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Set fire once flag, disable for non-compatible connections
|
||
|
if (pFireEdit->IsWindowEnabled())
|
||
|
{
|
||
|
if (bFirst)
|
||
|
{
|
||
|
m_bFireOnce = (pConnection->GetTimesToFire() == -1) ? false : true;
|
||
|
}
|
||
|
else if (m_bFireOnce != pConnection->GetTimesToFire())
|
||
|
{
|
||
|
m_bFireOnce = false;
|
||
|
pFireEdit->EnableWindow(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bFirst = false;
|
||
|
}
|
||
|
|
||
|
// Put a <none> in param box if no param
|
||
|
if (strlen(m_strParam) == 0)
|
||
|
{
|
||
|
m_strParam = PARAM_STRING_NONE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Adds all of an entity's outputs from its class definition to the
|
||
|
// outputs combo box.
|
||
|
// Input : pEntity - Entity whose outputs are to be added to the combo box.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::AddEntityOutputs(CMapEntity *pEntity)
|
||
|
{
|
||
|
GDclass *pClass = pEntity->GetClass();
|
||
|
if (pClass != NULL)
|
||
|
{
|
||
|
int nCount = pClass->GetOutputCount();
|
||
|
for (int i = 0; i < nCount; i++)
|
||
|
{
|
||
|
CClassOutput *pOutput = pClass->GetOutput(i);
|
||
|
int nIndex = m_ComboOutput.AddString(pOutput->GetName());
|
||
|
if (nIndex >= 0)
|
||
|
{
|
||
|
m_ComboOutput.SetItemDataPtr(nIndex, pOutput);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::FillInputList(void)
|
||
|
{
|
||
|
if (!m_pMapEntityList)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Add all entity inputs to the inputs combo box.
|
||
|
//
|
||
|
m_ComboInput.SetRedraw(FALSE);
|
||
|
m_ComboInput.ResetContent();
|
||
|
|
||
|
// CUtlVector<GDclass*> classCache;
|
||
|
CUtlRBTree<int,int> classCache;
|
||
|
SetDefLessFunc( classCache );
|
||
|
|
||
|
FOR_EACH_OBJ( *m_pMapEntityList, pos )
|
||
|
{
|
||
|
CMapEntity *pEntity = m_pMapEntityList->Element(pos);
|
||
|
Assert(pEntity != NULL);
|
||
|
|
||
|
if (pEntity == NULL)
|
||
|
continue;
|
||
|
|
||
|
//
|
||
|
// Get the entity's class, which contains the list of inputs that this entity exposes.
|
||
|
//
|
||
|
GDclass *pClass = pEntity->GetClass();
|
||
|
|
||
|
if (pClass == NULL)
|
||
|
continue;
|
||
|
|
||
|
// check if class was already added
|
||
|
if ( classCache.Find( (int)pClass ) != -1 )
|
||
|
continue;
|
||
|
|
||
|
classCache.Insert( (int)pClass );
|
||
|
|
||
|
//
|
||
|
// Add this class' inputs to the list.
|
||
|
//
|
||
|
int nCount = pClass->GetInputCount();
|
||
|
for (int i = 0; i < nCount; i++)
|
||
|
{
|
||
|
CClassInput *pInput = pClass->GetInput(i);
|
||
|
bool bAddInput = true;
|
||
|
|
||
|
//
|
||
|
// Don't add the input to the combo box if another input with the same name
|
||
|
// and type is already there.
|
||
|
//
|
||
|
int nIndex = m_ComboInput.FindStringExact(-1, pInput->GetName());
|
||
|
if (nIndex != CB_ERR)
|
||
|
{
|
||
|
CClassInput *pExistingInput = (CClassInput *)m_ComboInput.GetItemDataPtr(nIndex);
|
||
|
if (pExistingInput->GetType() == pInput->GetType())
|
||
|
{
|
||
|
bAddInput = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bAddInput)
|
||
|
{
|
||
|
nIndex = m_ComboInput.AddString(pInput->GetName());
|
||
|
if (nIndex >= 0)
|
||
|
{
|
||
|
m_ComboInput.SetItemDataPtr(nIndex, pInput);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_ComboInput.SetRedraw(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Fills the list of outputs with outputs common to all the selected entities.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::FillOutputList(void)
|
||
|
{
|
||
|
if ( m_EntityList.Count() == 0 )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Determine what the currently selected output is (if any).
|
||
|
//
|
||
|
CClassOutput *pSelectedOutput;
|
||
|
int nOutput = m_ComboOutput.GetCurSel();
|
||
|
if (nOutput != CB_ERR)
|
||
|
{
|
||
|
pSelectedOutput = (CClassOutput *)m_ComboOutput.GetItemDataPtr(nOutput);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pSelectedOutput = NULL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Add the entity outputs to the outputs combo box.
|
||
|
//
|
||
|
m_ComboOutput.SetRedraw(FALSE);
|
||
|
m_ComboOutput.ResetContent();
|
||
|
|
||
|
bool bFirst = true;
|
||
|
|
||
|
FOR_EACH_OBJ( m_EntityList, pos )
|
||
|
{
|
||
|
CMapEntity *pEntity = m_EntityList.Element(pos);
|
||
|
|
||
|
if (bFirst)
|
||
|
{
|
||
|
//
|
||
|
// The first entity adds its outputs to the list.
|
||
|
//
|
||
|
AddEntityOutputs(pEntity);
|
||
|
bFirst = false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// All subsequent entities filter the output list.
|
||
|
//
|
||
|
FilterEntityOutputs(pEntity);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (m_ComboOutput.GetCount() == 0)
|
||
|
{
|
||
|
m_ComboOutput.EnableWindow(false);
|
||
|
}
|
||
|
|
||
|
m_ComboOutput.SetRedraw(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Fills the list of targets with entities that have "targetname" keys.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::FillTargetList(void)
|
||
|
{
|
||
|
m_bIgnoreTextChanged = true;
|
||
|
m_ComboTarget.SetEntityList(m_pMapEntityList);
|
||
|
m_bIgnoreTextChanged = false;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Removes all outputs from the outputs combo box that are NOT present
|
||
|
// in the given entity's output list. Used when multiple entities are
|
||
|
// selected into the Entity Properties dialog.
|
||
|
// Input : pEntity - Entity to use for filter.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::FilterEntityOutputs(CMapEntity *pEntity)
|
||
|
{
|
||
|
//
|
||
|
// Make sure that this entity has a valid class to use for filtering.
|
||
|
//
|
||
|
GDclass *pClass = pEntity->GetClass();
|
||
|
if (pClass == NULL)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Remove any outputs from the combo box that are not in the class.
|
||
|
//
|
||
|
char szText[MAX_PATH];
|
||
|
|
||
|
int nCount = m_ComboOutput.GetCount();
|
||
|
if (nCount > 0)
|
||
|
{
|
||
|
for (int i = nCount - 1; i >= 0; i--)
|
||
|
{
|
||
|
if (m_ComboOutput.GetLBText(i, szText) != CB_ERR)
|
||
|
{
|
||
|
if (pClass->FindOutput(szText) == NULL)
|
||
|
{
|
||
|
m_ComboOutput.DeleteString(i);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::FilterOutputList(void)
|
||
|
{
|
||
|
// dvs: Possibly unnecessary. For example, if they choose an input, then
|
||
|
// choose an incompatible output, the input will become red to indicate
|
||
|
// the incompatibilty. So maybe the outputs can always contain the set of
|
||
|
// all outputs common to the selected entities.
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Filters the list of inputs based on the current selected target.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::FilterInputList(void)
|
||
|
{
|
||
|
char szTarget[MAX_ENTITY_NAME_LEN];
|
||
|
CMapEntityList *pTargets = GetTarget(szTarget, sizeof(szTarget));
|
||
|
|
||
|
if (pTargets != NULL)
|
||
|
{
|
||
|
//
|
||
|
// Remove all items from the inputs combo that:
|
||
|
//
|
||
|
// 1) Are not compatible with the currently selected output, OR
|
||
|
// 2) Are not found in the currently selected targets list.
|
||
|
//
|
||
|
int nCount = m_ComboInput.GetCount();
|
||
|
if (nCount > 0)
|
||
|
{
|
||
|
for (int i = nCount - 1; i >= 0; i--)
|
||
|
{
|
||
|
CClassInput *pInput = (CClassInput *)m_ComboInput.GetItemDataPtr(i);
|
||
|
if (!MapEntityList_HasInput(pTargets, pInput->GetName(), pInput->GetType()))
|
||
|
{
|
||
|
m_ComboInput.DeleteString(i);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::FilterTargetList(void)
|
||
|
{
|
||
|
#if 0 // Not used...
|
||
|
char szInput[MAX_IO_NAME_LEN];
|
||
|
CClassInput *pInput = GetInput(szInput, sizeof(szInput));
|
||
|
|
||
|
//
|
||
|
// Remove all items from the targets combo that:
|
||
|
//
|
||
|
// 1) Do not have the selected input name OR
|
||
|
// 2) Do not have inputs that are compatible with the selected output.
|
||
|
//
|
||
|
int nCount = m_ComboTarget.GetCount();
|
||
|
if (nCount > 0)
|
||
|
{
|
||
|
for (int i = nCount - 1; i >= 0; i--)
|
||
|
{
|
||
|
CMapEntityList *pTargets = (CMapEntityList *)m_ComboTarget.GetItemDataPtr(i);
|
||
|
|
||
|
if (!MapEntityList_HasInput(pTargets, pInput->GetName(), pInput->GetType()))
|
||
|
{
|
||
|
m_ComboTarget.DeleteString(i);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Returns the currently selected input, NULL if unknown.
|
||
|
// Input : szInput - Receives the text in the Input combo edit control.
|
||
|
// nSize - Size of buffer pointed to by szInput.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CClassInput *COP_Output::GetInput(char *szInput, int nSize)
|
||
|
{
|
||
|
szInput[0] = '\0';
|
||
|
|
||
|
int nCurSel = m_ComboInput.GetCurSel();
|
||
|
if (nCurSel == CB_ERR)
|
||
|
{
|
||
|
if (m_ComboInput.GetWindowText(szInput, nSize) > 0)
|
||
|
{
|
||
|
nCurSel = m_ComboInput.FindStringExact(-1, szInput);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CClassInput *pInput = NULL;
|
||
|
if (nCurSel != CB_ERR)
|
||
|
{
|
||
|
m_ComboInput.GetLBText(nCurSel, szInput);
|
||
|
pInput = (CClassInput *)m_ComboInput.GetItemDataPtr(nCurSel);
|
||
|
}
|
||
|
|
||
|
return(pInput);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Returns the currently selected output, NULL if unknown.
|
||
|
// Input : szOutput - Receives the text in the Output combo edit control.
|
||
|
// nSize - Size of buffer pointed to by szOutput.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CClassOutput *COP_Output::GetOutput(char *szOutput, int nSize)
|
||
|
{
|
||
|
szOutput[0] = '\0';
|
||
|
|
||
|
int nCurSel = m_ComboOutput.GetCurSel();
|
||
|
if (nCurSel == CB_ERR)
|
||
|
{
|
||
|
if (m_ComboOutput.GetWindowText(szOutput, nSize) > 0)
|
||
|
{
|
||
|
nCurSel = m_ComboOutput.FindStringExact(-1, szOutput);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CClassOutput *pOutput = NULL;
|
||
|
if (nCurSel != CB_ERR)
|
||
|
{
|
||
|
m_ComboOutput.GetLBText(nCurSel, szOutput);
|
||
|
pOutput = (CClassOutput *)m_ComboOutput.GetItemDataPtr(nCurSel);
|
||
|
}
|
||
|
|
||
|
return(pOutput);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Returns the currently selected target list, NULL if unknown.
|
||
|
// Input : szTarget - Receives the text in the Target combo edit control.
|
||
|
// nSize - Size of buffer pointed to by szTarget.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CMapEntityList *COP_Output::GetTarget(char *szTarget, int nSize)
|
||
|
{
|
||
|
szTarget[0] = '\0';
|
||
|
|
||
|
CString str = m_ComboTarget.GetCurrentItem();
|
||
|
Q_strncpy( szTarget, str, nSize );
|
||
|
|
||
|
return m_ComboTarget.GetSubEntityList( szTarget );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Called when the contents of the delay edit box change.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnEditDelay(void)
|
||
|
{
|
||
|
UpdateEditedDelays();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Called when the contents of the target combo edit box change.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnFireOnce(void)
|
||
|
{
|
||
|
UpdateEditedFireOnce();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Called when they change the "Show Hidden Targets" checkbox.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnShowHiddenTargetsAsBroken()
|
||
|
{
|
||
|
// Remember the last state of this checkbox.
|
||
|
Options.general.bShowHiddenTargetsAsBroken = (m_ctlShowHiddenTargetsAsBroken.GetCheck() != FALSE);
|
||
|
|
||
|
// Refresh.
|
||
|
int nCount = m_ListCtrl.GetItemCount();
|
||
|
for ( int i=0; i < nCount; i++ )
|
||
|
{
|
||
|
UpdateItemValidity( i );
|
||
|
}
|
||
|
//UpdateConnectionList();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: React to the input combo box being changed
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::InputChanged(void)
|
||
|
{
|
||
|
// Updating the listbox data, will trigger the edit
|
||
|
// controls to update. They don't need to be
|
||
|
bSkipEditControlRefresh = true;
|
||
|
|
||
|
char szInput[MAX_IO_NAME_LEN];
|
||
|
CClassInput *pInput = GetInput(szInput, sizeof(szInput));
|
||
|
UpdateCombosForSelectedInput(pInput);
|
||
|
UpdateEditedInputs();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Called when selection of input combo box chages
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnSelChangeInput(void)
|
||
|
{
|
||
|
InputChanged();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Called when the contents of the input combo edit box change.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnEditUpdateInput(void)
|
||
|
{
|
||
|
InputChanged();
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Purpose: React to the output combo box being changed
|
||
|
//------------------------------------------------------------------------------
|
||
|
void COP_Output::OutputChanged(void)
|
||
|
{
|
||
|
// Updating the listbox data, will trigger the edit
|
||
|
// controls to update. They don't need to be
|
||
|
bSkipEditControlRefresh = true;
|
||
|
|
||
|
char szOutput[MAX_IO_NAME_LEN];
|
||
|
CClassOutput *pOutput = GetOutput(szOutput, sizeof(szOutput));
|
||
|
UpdateCombosForSelectedOutput(pOutput);
|
||
|
UpdateEditedOutputs();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Called when selection of output combo box chages
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnSelChangeOutput(void)
|
||
|
{
|
||
|
OutputChanged();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Called when the contents of the output combo edit box change.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnEditUpdateOutput(void)
|
||
|
{
|
||
|
OutputChanged();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Called when selection of parameter combo box chages
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnSelChangeParam(void)
|
||
|
{
|
||
|
// If user picked <none> selection (the only valid one) clear window text
|
||
|
CComboBox *pParamEdit = ( CComboBox* )GetDlgItem( IDC_EDIT_CONN_PARAM );
|
||
|
if (pParamEdit->GetCurSel() != CB_ERR)
|
||
|
{
|
||
|
pParamEdit->SetWindowText("");
|
||
|
}
|
||
|
|
||
|
UpdateEditedParams();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Called when the contents of the parameter combo edit box change.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::OnEditUpdateParam(void)
|
||
|
{
|
||
|
UpdateEditedParams();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Updates the dialog based on the currently selected input.
|
||
|
// Input : pInput - Pointer to the input that is selected, NULL if none or
|
||
|
// ambiguous/unresolved.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateCombosForSelectedInput(CClassInput *pInput)
|
||
|
{
|
||
|
// Enable / Disable param box based on input type if allowed
|
||
|
if (!m_bNoParamEdit)
|
||
|
{
|
||
|
CComboBox *pParamCombo = (CComboBox *)GetDlgItem(IDC_EDIT_CONN_PARAM);
|
||
|
bool bEnable = ((!pInput) || (pInput && (pInput->GetType() != iotVoid)));
|
||
|
if (!bEnable)
|
||
|
{
|
||
|
// Save the param so we can restore it if they switch right back.
|
||
|
CString strTemp;
|
||
|
pParamCombo->GetWindowText(strTemp);
|
||
|
if (strTemp.Compare(PARAM_STRING_NONE))
|
||
|
{
|
||
|
m_strLastParam = strTemp;
|
||
|
}
|
||
|
|
||
|
// Switch back to <none> if we're disabling the parameter combo.
|
||
|
pParamCombo->SetCurSel(0);
|
||
|
}
|
||
|
else if (!m_strLastParam.IsEmpty())
|
||
|
{
|
||
|
pParamCombo->SetWindowText(m_strLastParam);
|
||
|
}
|
||
|
|
||
|
UpdateEditedParams();
|
||
|
pParamCombo->EnableWindow(bEnable);
|
||
|
m_bEntityParamTarget = pInput && (pInput->GetType() == iotEHandle);
|
||
|
GetDlgItem(IDC_PICK_ENTITY_PARAM)->EnableWindow( m_bEntityParamTarget );
|
||
|
}
|
||
|
|
||
|
if (pInput != NULL)
|
||
|
{
|
||
|
//
|
||
|
// Known input, render it in black.
|
||
|
//
|
||
|
m_ComboInput.SetTextColor(RGB(0, 0, 0));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Unknown input, render it in red.
|
||
|
//
|
||
|
m_ComboInput.SetTextColor(RGB(255, 0, 0));
|
||
|
}
|
||
|
m_ComboInput.RedrawWindow();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Updates the dialog based on the currently selected output.
|
||
|
// Input : pOutput - Pointer to the output that is selected, NULL if none or
|
||
|
// ambiguous/unresolved.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::UpdateCombosForSelectedOutput(CClassOutput *pOutput)
|
||
|
{
|
||
|
if (pOutput != NULL)
|
||
|
{
|
||
|
//
|
||
|
// Known output, render it in black.
|
||
|
//
|
||
|
m_ComboOutput.SetTextColor(RGB(0, 0, 0));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Unknown output, render it in red.
|
||
|
//
|
||
|
m_ComboOutput.SetTextColor(RGB(255, 0, 0));
|
||
|
}
|
||
|
m_ComboOutput.RedrawWindow();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Stops entity picking.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void COP_Output::StopPicking(void)
|
||
|
{
|
||
|
if (m_bPickingEntities)
|
||
|
{
|
||
|
m_bPickingEntities = false;
|
||
|
ToolManager()->SetTool(TOOL_POINTER);
|
||
|
|
||
|
CButton *pButton = (CButton *)GetDlgItem(IDC_PICK_ENTITY);
|
||
|
if (pButton)
|
||
|
{
|
||
|
pButton->SetCheck(0);
|
||
|
}
|
||
|
|
||
|
pButton = (CButton *)GetDlgItem(IDC_PICK_ENTITY_PARAM);
|
||
|
if (pButton)
|
||
|
{
|
||
|
pButton->SetCheck(0);
|
||
|
}
|
||
|
|
||
|
if ( m_ComboTarget.IsWindowEnabled() )
|
||
|
{
|
||
|
GetDlgItem(IDC_PICK_ENTITY)->EnableWindow( true );
|
||
|
}
|
||
|
|
||
|
CComboBox* pParamEdit = ( CComboBox* )GetDlgItem( IDC_EDIT_CONN_PARAM );
|
||
|
if ( pParamEdit->IsWindowEnabled() )
|
||
|
{
|
||
|
GetDlgItem(IDC_PICK_ENTITY_PARAM)->EnableWindow( m_bEntityParamTarget );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void COP_Output::OnSize( UINT nType, int cx, int cy )
|
||
|
{
|
||
|
m_AnchorMgr.OnSize();
|
||
|
}
|