diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/op_output.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'hammer/op_output.cpp')
| -rw-r--r-- | hammer/op_output.cpp | 2516 |
1 files changed, 2516 insertions, 0 deletions
diff --git a/hammer/op_output.cpp b/hammer/op_output.cpp new file mode 100644 index 0000000..c5c9d8b --- /dev/null +++ b/hammer/op_output.cpp @@ -0,0 +1,2516 @@ +//========= 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(); +} |