Counter Strike : Global Offensive Source Code
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.
 
 
 
 
 
 

2726 lines
77 KiB

//========= Copyright © 1996-2005, 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 "MapInstance.h"
#include "ObjectProperties.h"
#include "OP_Output.h"
#include "ToolManager.h"
#include "MainFrm.h"
#include "utlrbtree.h"
#include "options.h"
#include ".\op_output.h"
#include "hammer.h"
#include "custommessages.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
#define ICON_CONN_GOOD_EXTERNAL 4
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
{
if ( ValidateExternalConnections( pOutputConn, bShowHiddenTargets ) == true )
{
nIcon = ICON_CONN_GOOD_EXTERNAL;
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: Return true if all connections entries are valid for the given
// output connection. Return false otherwise
//------------------------------------------------------------------------------
bool COP_Output::ValidateExternalConnections(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;
}
POSITION pos = APP()->pMapDocTemplate->GetFirstDocPosition();
while( pos != NULL )
{
CDocument *pDoc = APP()->pMapDocTemplate->GetNextDoc( pos );
CMapDoc *pMapDoc = dynamic_cast< CMapDoc * >( pDoc );
if ( pMapDoc )
{
if ( CEntityConnection::ValidateTarget( pMapDoc->GetMapWorld()->EntityList_GetList(), bVisibilityCheck, pConnection->GetTargetName() ) == true )
{
if ( CEntityConnection::ValidateInput( pConnection->GetTargetName(), pConnection->GetInputName(), bVisibilityCheck, pMapDoc ) == true )
{
return true;
}
}
}
}
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 );
// If you hit this assert it means that an entity was deleted but not removed
// from this entity's list of targets.
ASSERT( pEntity != NULL );
if ( pEntity )
{
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 *pActiveDoc = CMapDoc::GetActiveMapDoc();
CMapDoc *pExternalDoc = NULL;
bool bMultipleDocs = false;
bool bFoundInActive = false;
CEntityConnection *pConnection = NULL;
if ( nCount > 0 )
{
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);
POSITION pos = APP()->pMapDocTemplate->GetFirstDocPosition();
while( pos != NULL )
{
CDocument *pDoc = APP()->pMapDocTemplate->GetNextDoc( pos );
CMapDoc *pMapDoc = dynamic_cast< CMapDoc * >( pDoc );
if ( pMapDoc )
{
CMapEntityList Found;
pMapDoc->FindEntitiesByName(Found, m_ListCtrl.GetItemText(nItem, TARGET_NAME_COLUMN), false);
FOR_EACH_OBJ( Found, pos )
{
CMapEntity *pEntity = Found.Element(pos);
Select.AddToTail(pEntity);
if ( pExternalDoc && pExternalDoc != pMapDoc )
{
bMultipleDocs = true;
}
if ( pMapDoc == pActiveDoc )
{
bFoundInActive = true;
}
pExternalDoc = pMapDoc;
}
}
}
}
}
if ( bFoundInActive == true )
{
pExternalDoc = pActiveDoc;
bMultipleDocs = false;
}
if ( bMultipleDocs == true )
{
MessageBox( "Entities with same target name exist across multiple documents.", "No Selection Done!", MB_ICONINFORMATION | MB_OK );
return;
}
else if ( Select.Count() > 0 )
{
pExternalDoc->SelectObjectList( &Select );
// (a bit squirly way of doing this)
if ( Select.Count()==1 )
{
GetMainWnd()->pObjectProperties->SetPageToInput(pConnection);
}
if ( pExternalDoc != pActiveDoc )
{
CMapDoc::SetActiveMapDoc( pExternalDoc );
CMapDoc::ActivateMapDoc( pExternalDoc );
GetMainWnd()->GlobalNotify( WM_MAPDOC_CHANGED );
pExternalDoc->UpdateAllViews( MAPVIEW_UPDATE_SELECTION | MAPVIEW_UPDATE_OBJECTS | MAPVIEW_OPTIONS_CHANGED | MAPVIEW_RENDER_NOW );
}
pExternalDoc->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_bIsInstanceIOProxy = false;
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_pImageList->Add(pApp->LoadIcon( IDI_OUTPUT_EXTERNAL ) );
}
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 )
{
const 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)
{
m_bIsInstanceIOProxy = false;
if ( pEntity && stricmp( pEntity->GetClassName(), "func_instance" ) == 0 )
{
CMapInstance *pMapInstance = pEntity->GetChildOfType( ( CMapInstance * )NULL );
if ( pMapInstance == NULL || pMapInstance->GetInstancedMap() == NULL )
{
return;
}
CMapEntityList entityList;
pMapInstance->GetInstancedMap()->FindEntitiesByClassName( entityList, "func_instance_io_proxy", false );
if ( entityList.Count() != 1 )
{
return;
}
CMapEntity *pInstanceParmsEntity = entityList.Element( 0 );
const char *pszTargetName = pInstanceParmsEntity->GetKeyValue( "targetname" );
m_bIsInstanceIOProxy = true;
const CMapEntityList *pEntityList = pMapInstance->GetInstancedMap()->GetMapWorld()->EntityList_GetList();
FOR_EACH_OBJ( *pEntityList, pos2 )
{
const CMapEntity *pTestEntity = pEntityList->Element( pos2 ).GetObject();
if (pTestEntity != NULL)
{
int nConnectionsCount = pTestEntity->Connections_GetCount();
for (int nConnection = 0; nConnection < nConnectionsCount; nConnection++)
{
CEntityConnection *pConnection = pTestEntity->Connections_Get( nConnection );
if ( strcmpi( pConnection->GetTargetName(), pszTargetName ) == 0 )
{
char temp[ 512 ];
sprintf( temp, "instance:%s;%s", pTestEntity->GetKeyValue( "targetname" ), pConnection->GetOutputName() );
m_ComboOutput.AddString( temp );
}
}
}
}
}
else
{
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 );
CMapEntity *pInstanceParmsEntity = GetTargetInstanceIOProxy();
if ( pInstanceParmsEntity != NULL )
{
m_bIsInstanceIOProxy = true;
int nConnectionsCount = pInstanceParmsEntity->Connections_GetCount();
for (int nConnection = 0; nConnection < nConnectionsCount; nConnection++)
{
CEntityConnection *pConnection = pInstanceParmsEntity->Connections_Get( nConnection );
char temp[ 512 ];
sprintf( temp, "instance:%s;%s", pConnection->GetTargetName(), pConnection->GetInputName() );
m_ComboInput.AddString( temp );
}
}
else
{
m_bIsInstanceIOProxy = false;
FOR_EACH_OBJ( *m_pMapEntityList, pos )
{
const CMapEntity *pEntity = m_pMapEntityList->Element(pos).GetObject();
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)
{
int 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.
}
CMapEntity *COP_Output::GetTargetInstanceIOProxy()
{
char szTarget[MAX_ENTITY_NAME_LEN];
CMapEntityList *pTargets = GetTarget(szTarget, sizeof(szTarget));
if (pTargets != NULL)
{
if ( pTargets->Count() == 1 )
{
CMapEntity *pEntity = pTargets->Element( 0 );
if ( stricmp( pEntity->GetClassName(), "func_instance" ) == 0 )
{
CMapInstance *pMapInstance = pEntity->GetChildOfType( ( CMapInstance * )NULL );
if ( pMapInstance != NULL && pMapInstance->GetInstancedMap() != NULL )
{
CMapEntityList entityList;
pMapInstance->GetInstancedMap()->FindEntitiesByClassName( entityList, "func_instance_io_proxy", false );
if ( entityList.Count() == 1 )
{
return entityList.Element( 0 );
}
}
}
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// 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.
//
if ( m_bIsInstanceIOProxy == false )
{
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();
}