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

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Implements a dialog for editing the input/output connections of a
  4. // list of entities. The connections are displayed in a grid control,
  5. // each row of the grid control representing a connection that is
  6. // common to all entities being edited. For example, given these two ents:
  7. //
  8. // Button01
  9. // OnDamaged Sound01 PlaySound 0 0
  10. // OnPressed Door01 Open 0 0
  11. //
  12. // Button02
  13. // OnPressed Door01 Open 0 0
  14. //
  15. // If these two entities were selected, the grid control would show:
  16. //
  17. // OnPressed Door01 Open 0 0
  18. //
  19. // because it is the only connection that is common to both entities.
  20. // Editing an entry in the grid control modifies the corresponding
  21. // connection in all selected entities.
  22. //
  23. // TODO: persist sort column index, sort directions, and column sizes
  24. // TODO: implement an external mode, where the grid shows all connections to unselected ents
  25. //
  26. //=============================================================================//
  27. #include "stdafx.h"
  28. #include "GlobalFunctions.h"
  29. #include "MapDoc.h"
  30. #include "MapEntity.h"
  31. #include "MapWorld.h"
  32. #include "MapInstance.h"
  33. #include "ObjectProperties.h"
  34. #include "OP_Output.h"
  35. #include "ToolManager.h"
  36. #include "MainFrm.h"
  37. #include "utlrbtree.h"
  38. #include "options.h"
  39. #include ".\op_output.h"
  40. #include "hammer.h"
  41. #include "custommessages.h"
  42. // memdbgon must be the last include file in a .cpp file!!!
  43. #include <tier0/memdbgon.h>
  44. #pragma warning( disable : 4355 )
  45. #define ICON_CONN_BAD 0
  46. #define ICON_CONN_GOOD 1
  47. #define ICON_CONN_BAD_GREY 2
  48. #define ICON_CONN_GOOD_GREY 3
  49. #define ICON_CONN_GOOD_EXTERNAL 4
  50. const char *PARAM_STRING_NONE = "<none>";
  51. //
  52. // Column indices for the list control.
  53. //
  54. const int ICON_COLUMN = 0;
  55. const int OUTPUT_NAME_COLUMN = 1;
  56. const int TARGET_NAME_COLUMN = 2;
  57. const int INPUT_NAME_COLUMN = 3;
  58. const int PARAMETER_COLUMN = 4;
  59. const int DELAY_COLUMN = 5;
  60. const int ONLY_ONCE_COLUMN = 6;
  61. IMPLEMENT_DYNCREATE(COP_Output, CObjectPage)
  62. BEGIN_MESSAGE_MAP(COP_Output, CObjectPage)
  63. //{{AFX_MSG_MAP(COP_Output)
  64. ON_BN_CLICKED(IDC_ADD, OnAdd)
  65. ON_BN_CLICKED(IDC_DELETE, OnDelete)
  66. ON_BN_CLICKED(IDC_COPY, OnCopy)
  67. ON_WM_SIZE()
  68. ON_BN_CLICKED(IDC_PASTE, OnPaste)
  69. ON_BN_CLICKED(IDC_MARK, OnMark)
  70. ON_BN_CLICKED(IDC_PICK_ENTITY, OnPickEntity)
  71. ON_BN_CLICKED(IDC_PICK_ENTITY_PARAM, OnPickEntityParam)
  72. ON_CBN_SELCHANGE(IDC_EDIT_CONN_INPUT, OnSelChangeInput)
  73. ON_CBN_EDITUPDATE(IDC_EDIT_CONN_INPUT, OnEditUpdateInput)
  74. ON_CBN_SELCHANGE(IDC_EDIT_CONN_OUTPUT, OnSelChangeOutput)
  75. ON_CBN_EDITUPDATE(IDC_EDIT_CONN_OUTPUT, OnEditUpdateOutput)
  76. ON_CBN_SELCHANGE(IDC_EDIT_CONN_PARAM, OnSelChangeParam)
  77. ON_CBN_EDITUPDATE(IDC_EDIT_CONN_PARAM, OnEditUpdateParam)
  78. ON_EN_CHANGE(IDC_EDIT_CONN_DELAY, OnEditDelay)
  79. ON_BN_CLICKED(IDC_EDIT_CONN_FIRE_ONCE, OnFireOnce)
  80. ON_BN_CLICKED(IDC_SHOWHIDDENTARGETS, OnShowHiddenTargetsAsBroken)
  81. ON_WM_DESTROY()
  82. //}}AFX_MSG_MAP
  83. END_MESSAGE_MAP()
  84. // ON_CBN_SELCHANGE(IDC_EDIT_CONN_TARGET, OnSelChangeTarget)
  85. // ON_CBN_EDITUPDATE(IDC_EDIT_CONN_TARGET, OnEditUpdateTarget)
  86. //
  87. // Static data.
  88. //
  89. CEntityConnectionList *COP_Output::m_pConnectionBuffer = new CEntityConnectionList;
  90. CImageList *COP_Output::m_pImageList = NULL;
  91. //-----------------------------------------------------------------------------
  92. // Returns true if any of the target entities in the connection list are visible.
  93. //-----------------------------------------------------------------------------
  94. static bool AreAnyTargetEntitiesVisible( CEntityConnectionList *pList )
  95. {
  96. for ( int i=0; i < pList->Count(); i++ )
  97. {
  98. if ( pList->Element(i)->AreAnyTargetEntitiesVisible() )
  99. return true;
  100. }
  101. return false;
  102. }
  103. //-----------------------------------------------------------------------------
  104. // Purpose: Compares by delays. Used as a secondary sort by all other columns.
  105. //-----------------------------------------------------------------------------
  106. static int CALLBACK ListCompareDelaysSecondary(COutputConnection *pOutputConn1, COutputConnection *pOutputConn2, SortDirection_t eDirection)
  107. {
  108. CEntityConnectionList *pConnList1 = pOutputConn1->m_pConnList;
  109. CEntityConnectionList *pConnList2 = pOutputConn2->m_pConnList;
  110. CEntityConnection *pConn1 = pConnList1->Element(0);
  111. CEntityConnection *pConn2 = pConnList2->Element(0);
  112. return CEntityConnection::CompareDelaysSecondary(pConn1,pConn2,eDirection);
  113. }
  114. //-----------------------------------------------------------------------------
  115. // Purpose: Compares by delays, does a secondary compare by output name.
  116. //-----------------------------------------------------------------------------
  117. static int CALLBACK ListCompareDelays(COutputConnection *pOutputConn1, COutputConnection *pOutputConn2, SortDirection_t eDirection)
  118. {
  119. CEntityConnectionList *pConnList1 = pOutputConn1->m_pConnList;
  120. CEntityConnectionList *pConnList2 = pOutputConn2->m_pConnList;
  121. CEntityConnection *pConn1 = pConnList1->Element(0);
  122. CEntityConnection *pConn2 = pConnList2->Element(0);
  123. return CEntityConnection::CompareDelays(pConn1,pConn2,eDirection);
  124. }
  125. //-----------------------------------------------------------------------------
  126. // Purpose: Compares by output name, does a secondary compare by delay.
  127. //-----------------------------------------------------------------------------
  128. static int CALLBACK ListCompareOutputNames(COutputConnection *pOutputConn1, COutputConnection *pOutputConn2, SortDirection_t eDirection)
  129. {
  130. CEntityConnectionList *pConnList1 = pOutputConn1->m_pConnList;
  131. CEntityConnectionList *pConnList2 = pOutputConn2->m_pConnList;
  132. CEntityConnection *pConn1 = pConnList1->Element(0);
  133. CEntityConnection *pConn2 = pConnList2->Element(0);
  134. return CEntityConnection::CompareOutputNames(pConn1,pConn2,eDirection);
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Purpose: Compares by input name, does a secondary compare by delay.
  138. //-----------------------------------------------------------------------------
  139. static int CALLBACK ListCompareInputNames(COutputConnection *pOutputConn1, COutputConnection *pOutputConn2, SortDirection_t eDirection)
  140. {
  141. CEntityConnectionList *pConnList1 = pOutputConn1->m_pConnList;
  142. CEntityConnectionList *pConnList2 = pOutputConn2->m_pConnList;
  143. CEntityConnection *pConn1 = pConnList1->Element(0);
  144. CEntityConnection *pConn2 = pConnList2->Element(0);
  145. return (CEntityConnection::CompareInputNames(pConn1,pConn2,eDirection));
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Purpose: Compares by source name, does a secondary compare by delay.
  149. //-----------------------------------------------------------------------------
  150. static int CALLBACK ListCompareSourceNames(COutputConnection *pOutputConn1, COutputConnection *pOutputConn2, SortDirection_t eDirection)
  151. {
  152. CEntityConnectionList *pConnList1 = pOutputConn1->m_pConnList;
  153. CEntityConnectionList *pConnList2 = pOutputConn2->m_pConnList;
  154. CEntityConnection *pConn1 = pConnList1->Element(0);
  155. CEntityConnection *pConn2 = pConnList2->Element(0);
  156. return (CEntityConnection::CompareSourceNames(pConn1,pConn2,eDirection));
  157. }
  158. //-----------------------------------------------------------------------------
  159. // Purpose: Compares by target name, does a secondary compare by delay.
  160. //-----------------------------------------------------------------------------
  161. static int CALLBACK ListCompareTargetNames(COutputConnection *pOutputConn1, COutputConnection *pOutputConn2, SortDirection_t eDirection)
  162. {
  163. CEntityConnectionList *pConnList1 = pOutputConn1->m_pConnList;
  164. CEntityConnectionList *pConnList2 = pOutputConn2->m_pConnList;
  165. CEntityConnection *pConn1 = pConnList1->Element(0);
  166. CEntityConnection *pConn2 = pConnList2->Element(0);
  167. return (CEntityConnection::CompareTargetNames(pConn1,pConn2,eDirection));
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Purpose: Called by the entity picker tool when an entity is picked. This
  171. // stuffs the entity name into the smartedit control.
  172. //-----------------------------------------------------------------------------
  173. void COP_OutputPickEntityTarget::OnNotifyPickEntity(CToolPickEntity *pTool)
  174. {
  175. //
  176. // Update the edit control text with the entity name. This text will be
  177. // stuffed into the local keyvalue storage in OnChangeSmartControl.
  178. //
  179. CMapEntityList Full;
  180. CMapEntityList Partial;
  181. pTool->GetSelectedEntities(Full, Partial);
  182. CMapEntity *pEntity = Full.Element(0);
  183. if (pEntity)
  184. {
  185. const char *pszName = pEntity->GetKeyValue("targetname");
  186. if (!pszName)
  187. {
  188. pszName = "";
  189. }
  190. switch ( m_nDlgItem )
  191. {
  192. case IDC_EDIT_CONN_TARGET:
  193. {
  194. // FIXME: this should be called automatically, but it isn't
  195. m_pDlg->m_ComboTarget.SelectItem(pszName);
  196. break;
  197. }
  198. case IDC_EDIT_CONN_PARAM:
  199. {
  200. // FIXME: this should be called automatically, but it isn't
  201. m_pDlg->GetDlgItem(m_nDlgItem)->SetWindowText(pszName);
  202. m_pDlg->OnEditUpdateParam();
  203. break;
  204. }
  205. default:
  206. {
  207. m_pDlg->GetDlgItem(m_nDlgItem)->SetWindowText(pszName);
  208. break;
  209. }
  210. }
  211. }
  212. m_pDlg->StopPicking();
  213. }
  214. //-----------------------------------------------------------------------------
  215. // Purpose: Constructor.
  216. //-----------------------------------------------------------------------------
  217. COP_Output::COP_Output(void)
  218. : CObjectPage(COP_Output::IDD), m_ComboTarget( this )
  219. {
  220. m_bIgnoreTextChanged = false;
  221. m_pObjectList = NULL;
  222. m_pEditObjectRuntimeClass = RUNTIME_CLASS(editCMapClass);
  223. m_nSortColumn = OUTPUT_NAME_COLUMN;
  224. m_pMapEntityList = NULL;
  225. m_fDelay = 0;
  226. m_bPickingEntities = false;
  227. bSkipEditControlRefresh = false;
  228. //
  229. // All columns initially sort in ascending order.
  230. //
  231. for (int i = 0; i < OUTPUT_LIST_NUM_COLUMNS; i++)
  232. {
  233. m_eSortDirection[i] = Sort_Ascending;
  234. }
  235. m_PickEntityTarget.AttachEntityDlg(this);
  236. }
  237. //-----------------------------------------------------------------------------
  238. // Purpose: Destructor.
  239. //-----------------------------------------------------------------------------
  240. COP_Output::~COP_Output(void)
  241. {
  242. }
  243. void COP_Output::OnTextChanged( const char *pText )
  244. {
  245. if ( m_bIgnoreTextChanged )
  246. return;
  247. // Updating the listbox data, will trigger the edit
  248. // controls to update. They don't need to be
  249. bSkipEditControlRefresh = true;
  250. // Target has changed so we need to update for list of inputs
  251. // that are valid for this target
  252. FillInputList();
  253. FilterInputList();
  254. m_ComboInput.SetWindowText(m_strInput);
  255. UpdateEditedTargets();
  256. }
  257. //------------------------------------------------------------------------------
  258. // Purpose: Updates the validity flag on the given item in the list control
  259. // Input : nItem -
  260. //------------------------------------------------------------------------------
  261. void COP_Output::UpdateItemValidity(int nItem)
  262. {
  263. COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
  264. CEntityConnectionList *pConnectionList = pOutputConn->m_pConnList;
  265. bool bShared = (m_EntityList.Count() == pConnectionList->Count());
  266. bool bShowHiddenTargets = ShouldShowHiddenTargets();
  267. int nIcon;
  268. if (ValidateConnections(pOutputConn, bShowHiddenTargets))
  269. {
  270. if ( !bShowHiddenTargets && !AreAnyTargetEntitiesVisible( pConnectionList ) )
  271. nIcon = ICON_CONN_GOOD_GREY;
  272. else if ( bShared )
  273. nIcon = ICON_CONN_GOOD;
  274. else
  275. nIcon = ICON_CONN_GOOD_GREY;
  276. pOutputConn->m_bIsValid = true;
  277. }
  278. else
  279. {
  280. if ( ValidateExternalConnections( pOutputConn, bShowHiddenTargets ) == true )
  281. {
  282. nIcon = ICON_CONN_GOOD_EXTERNAL;
  283. pOutputConn->m_bIsValid = true;
  284. }
  285. else
  286. {
  287. nIcon = (bShared ? ICON_CONN_BAD : ICON_CONN_BAD_GREY);
  288. pOutputConn->m_bIsValid = false;
  289. }
  290. }
  291. m_ListCtrl.SetItem(nItem,0,LVIF_IMAGE, 0, nIcon, 0, 0, 0 );
  292. }
  293. //------------------------------------------------------------------------------
  294. // Purpose :
  295. //------------------------------------------------------------------------------
  296. void COP_Output::UpdateValidityButton(void)
  297. {
  298. CObjectProperties *pParent = (CObjectProperties*) GetParent();
  299. // Get status of all connections
  300. int nItemCount = m_ListCtrl.GetItemCount();
  301. if (nItemCount == 0)
  302. {
  303. pParent->SetOutputButtonState(CONNECTION_NONE);
  304. return;
  305. }
  306. for (int nItem = 0; nItem < nItemCount; nItem++)
  307. {
  308. COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
  309. if (!pOutputConn->m_bIsValid)
  310. {
  311. pParent->SetOutputButtonState(CONNECTION_BAD);
  312. return;
  313. }
  314. }
  315. pParent->SetOutputButtonState(CONNECTION_GOOD);
  316. }
  317. //------------------------------------------------------------------------------
  318. // Purpose: Return true if all connections entries are valid for the given
  319. // output connection. Return false otherwise
  320. //------------------------------------------------------------------------------
  321. bool COP_Output::ValidateConnections(COutputConnection *pOutputConn, bool bVisibilityCheck)
  322. {
  323. int nCount = pOutputConn->m_pConnList->Count();
  324. for (int i = 0; i < nCount; i++)
  325. {
  326. CEntityConnection *pConnection = pOutputConn->m_pConnList->Element(i);
  327. if (pConnection != NULL)
  328. {
  329. // Check validity of output for the list of entities
  330. if (!CEntityConnection::ValidateOutput(pOutputConn->m_pEntityList,pConnection->GetOutputName()))
  331. {
  332. return false;
  333. }
  334. // Check validity of target entity (is it in the map?)
  335. if (!CEntityConnection::ValidateTarget(m_pMapEntityList, bVisibilityCheck, pConnection->GetTargetName()))
  336. {
  337. return false;
  338. }
  339. // Check validity of input
  340. if (!CEntityConnection::ValidateInput(pConnection->GetTargetName(), pConnection->GetInputName(), bVisibilityCheck))
  341. {
  342. return false;
  343. }
  344. }
  345. }
  346. return true;
  347. }
  348. //------------------------------------------------------------------------------
  349. // Purpose: Return true if all connections entries are valid for the given
  350. // output connection. Return false otherwise
  351. //------------------------------------------------------------------------------
  352. bool COP_Output::ValidateExternalConnections(COutputConnection *pOutputConn, bool bVisibilityCheck)
  353. {
  354. int nCount = pOutputConn->m_pConnList->Count();
  355. for (int i = 0; i < nCount; i++)
  356. {
  357. CEntityConnection *pConnection = pOutputConn->m_pConnList->Element(i);
  358. if (pConnection != NULL)
  359. {
  360. // Check validity of output for the list of entities
  361. if (!CEntityConnection::ValidateOutput(pOutputConn->m_pEntityList,pConnection->GetOutputName()))
  362. {
  363. return false;
  364. }
  365. POSITION pos = APP()->pMapDocTemplate->GetFirstDocPosition();
  366. while( pos != NULL )
  367. {
  368. CDocument *pDoc = APP()->pMapDocTemplate->GetNextDoc( pos );
  369. CMapDoc *pMapDoc = dynamic_cast< CMapDoc * >( pDoc );
  370. if ( pMapDoc )
  371. {
  372. if ( CEntityConnection::ValidateTarget( pMapDoc->GetMapWorld()->EntityList_GetList(), bVisibilityCheck, pConnection->GetTargetName() ) == true )
  373. {
  374. if ( CEntityConnection::ValidateInput( pConnection->GetTargetName(), pConnection->GetInputName(), bVisibilityCheck, pMapDoc ) == true )
  375. {
  376. return true;
  377. }
  378. }
  379. }
  380. }
  381. return false;
  382. }
  383. }
  384. return true;
  385. }
  386. //-----------------------------------------------------------------------------
  387. // Purpose:
  388. // Input : pEntity -
  389. // bFirst -
  390. //-----------------------------------------------------------------------------
  391. void COP_Output::AddEntityConnections(CMapEntity *pEntity, bool bFirst)
  392. {
  393. m_ListCtrl.SetRedraw(FALSE);
  394. //
  395. // The first entity simply adds its connections to the list.
  396. //
  397. int nConnCount = pEntity->Connections_GetCount();
  398. for (int i = 0; i < nConnCount; i++)
  399. {
  400. CEntityConnection *pConnection = pEntity->Connections_Get(i);
  401. if (pConnection != NULL)
  402. {
  403. // First check if the connection already exists, if so just add to it
  404. bool bFound = false;
  405. int nItemCount = m_ListCtrl.GetItemCount();
  406. if (nItemCount > 0)
  407. {
  408. for (int nItem = nItemCount - 1; nItem >= 0; nItem--)
  409. {
  410. COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
  411. CEntityConnectionList *pConnList = pOutputConn->m_pConnList;
  412. CEntityConnection *pTestConn = pConnList->Element(0);
  413. if (pTestConn->CompareConnection(pConnection))
  414. {
  415. // Don't consolidate duplicate connections in the same entity
  416. // Show them twice so the user will see
  417. if ( pOutputConn->m_pEntityList->Find(pEntity) == -1)
  418. {
  419. pConnList->AddToTail(pConnection);
  420. pOutputConn->m_pEntityList->AddToTail(pEntity);
  421. bFound = true;
  422. break;
  423. }
  424. }
  425. }
  426. }
  427. if (!bFound)
  428. {
  429. m_ListCtrl.SetItemCount(nItemCount + 1);
  430. m_ListCtrl.InsertItem(LVIF_IMAGE, nItemCount, "", 0, 0, ICON_CONN_GOOD, 0);
  431. m_ListCtrl.SetItemText(nItemCount, OUTPUT_NAME_COLUMN, pConnection->GetOutputName());
  432. m_ListCtrl.SetItemText(nItemCount, TARGET_NAME_COLUMN, pConnection->GetTargetName());
  433. m_ListCtrl.SetItemText(nItemCount, INPUT_NAME_COLUMN, pConnection->GetInputName());
  434. // Build the string for the delay.
  435. float fDelay = pConnection->GetDelay();
  436. char szTemp[MAX_PATH];
  437. sprintf(szTemp, "%.2f", fDelay);
  438. m_ListCtrl.SetItemText(nItemCount, DELAY_COLUMN, szTemp);
  439. // Fire once
  440. m_ListCtrl.SetItemText(nItemCount, ONLY_ONCE_COLUMN, (pConnection->GetTimesToFire() == EVENT_FIRE_ALWAYS) ? "No" : "Yes");
  441. m_ListCtrl.SetItemText(nItemCount, PARAMETER_COLUMN, pConnection->GetParam());
  442. // Set list ctrl data
  443. COutputConnection* pOutputConn = new COutputConnection;
  444. pOutputConn->m_pConnList = new CEntityConnectionList;
  445. pOutputConn->m_pEntityList = new CMapEntityList;
  446. pOutputConn->m_pConnList->AddToTail(pConnection);
  447. pOutputConn->m_pEntityList->AddToTail(pEntity);
  448. pOutputConn->m_bOwnedByAll = true;
  449. m_ListCtrl.SetItemData(nItemCount, (DWORD)pOutputConn);
  450. nItemCount++;
  451. }
  452. }
  453. }
  454. m_ListCtrl.SetRedraw(TRUE);
  455. }
  456. //-----------------------------------------------------------------------------
  457. // Purpose:
  458. // Input : pDX -
  459. //-----------------------------------------------------------------------------
  460. void COP_Output::DoDataExchange(CDataExchange *pDX)
  461. {
  462. CObjectPage::DoDataExchange(pDX);
  463. //{{AFX_DATA_MAP(COP_Output)
  464. DDX_Control(pDX, IDC_LIST, m_ListCtrl);
  465. DDX_Text(pDX, IDC_EDIT_CONN_DELAY, m_fDelay);
  466. DDX_CBString(pDX, IDC_EDIT_CONN_OUTPUT, m_strOutput);
  467. DDX_CBString(pDX, IDC_EDIT_CONN_TARGET, m_strTarget);
  468. DDX_CBString(pDX, IDC_EDIT_CONN_INPUT, m_strInput);
  469. DDX_CBString(pDX, IDC_EDIT_CONN_PARAM, m_strParam);
  470. DDX_Check(pDX, IDC_EDIT_CONN_FIRE_ONCE, m_bFireOnce);
  471. DDX_Control(pDX, IDC_SHOWHIDDENTARGETS, m_ctlShowHiddenTargetsAsBroken);
  472. DDX_Control(pDX, IDC_ADD, m_AddControl);
  473. DDX_Control(pDX, IDC_PASTE, m_PasteControl);
  474. DDX_Control(pDX, IDC_DELETE, m_DeleteControl);
  475. //}}AFX_DATA_MAP
  476. }
  477. bool COP_Output::ShouldShowHiddenTargets()
  478. {
  479. return (Options.general.bShowHiddenTargetsAsBroken == TRUE);
  480. }
  481. //------------------------------------------------------------------------------
  482. // Purpose: Enables or Disables all edit controls
  483. // Input : bValue -
  484. //------------------------------------------------------------------------------
  485. void COP_Output::EnableEditControls(bool bValue)
  486. {
  487. m_ComboOutput.EnableWindow(bValue);
  488. EnableTarget(bValue);
  489. m_ComboInput.EnableWindow(bValue);
  490. CButton *pButton = (CButton *)GetDlgItem(IDC_EDIT_CONN_FIRE_ONCE);
  491. pButton->EnableWindow(bValue);
  492. CEdit *pDelayEdit = (CEdit *)GetDlgItem(IDC_EDIT_CONN_DELAY);
  493. pDelayEdit->EnableWindow(bValue);
  494. CComboBox *pParamCombo = (CComboBox *)GetDlgItem(IDC_EDIT_CONN_PARAM);
  495. pParamCombo->EnableWindow(bValue);
  496. GetDlgItem(IDC_PICK_ENTITY_PARAM)->EnableWindow( bValue );
  497. // Clear any values
  498. if (!bValue)
  499. {
  500. m_ComboTarget.ForceEditControlText( "" );
  501. m_ComboInput.SetWindowText("");
  502. m_ComboOutput.SetWindowText("");
  503. pParamCombo->SetCurSel(0);
  504. pDelayEdit->SetWindowText("0.0");
  505. }
  506. }
  507. //-----------------------------------------------------------------------------
  508. // Purpose:
  509. // Input : *pMapEntityList -
  510. //-----------------------------------------------------------------------------
  511. void COP_Output::SetMapEntityList(const CMapEntityList *pMapEntityList)
  512. {
  513. m_pMapEntityList = pMapEntityList;
  514. FillTargetList();
  515. }
  516. //------------------------------------------------------------------------------
  517. // Purpose: Updates data displayed in edit controls
  518. //------------------------------------------------------------------------------
  519. void COP_Output::UpdateEditControls(void)
  520. {
  521. //
  522. // Build a list of connections to edit.
  523. //
  524. m_EditList.RemoveAll();
  525. m_AddControl.EnableWindow( ( m_bCanEdit ? TRUE : FALSE ) );
  526. m_PasteControl.EnableWindow( ( m_bCanEdit ? TRUE : FALSE ) );
  527. m_DeleteControl.EnableWindow( ( m_bCanEdit ? TRUE : FALSE ) );
  528. // If nothing is selected, disable edit controls
  529. if (!m_ListCtrl.IsWindowEnabled() || m_ListCtrl.GetSelectedCount() == 0)
  530. {
  531. EnableEditControls(false);
  532. return;
  533. }
  534. for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
  535. {
  536. if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
  537. {
  538. COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
  539. m_EditList.AddVectorToTail(*pOutputConn->m_pConnList);
  540. }
  541. }
  542. if (m_EditList.Count() > 0)
  543. {
  544. SetConnection(&m_EditList);
  545. FillOutputList();
  546. FillInputList();
  547. // We must ignore the text changed event here or else it'll set all selected outputs to the same value.
  548. m_bIgnoreTextChanged = true;
  549. m_ComboTarget.SelectItem(m_strTarget);
  550. m_bIgnoreTextChanged = false;
  551. m_ComboInput.SetWindowText(m_strInput);
  552. m_ComboOutput.SetWindowText(m_strOutput);
  553. m_CheckBoxFireOnce.SetCheck(m_bFireOnce);
  554. CEdit *pDelayEdit = ( CEdit* )GetDlgItem( IDC_EDIT_CONN_DELAY );
  555. char szTemp[MAX_PATH];
  556. sprintf(szTemp, "%.2f", m_fDelay);
  557. pDelayEdit->SetWindowText(szTemp);
  558. CComboBox* pParamEdit = ( CComboBox* )GetDlgItem( IDC_EDIT_CONN_PARAM );
  559. pParamEdit->SetWindowText(m_strParam);
  560. FilterInputList();
  561. //
  562. // Update the UI state based on our current data.
  563. //
  564. char szBuf[MAX_IO_NAME_LEN];
  565. CClassOutput *pOutput = GetOutput(szBuf, sizeof(szBuf));
  566. UpdateCombosForSelectedOutput(pOutput);
  567. CClassInput *pInput = GetInput(szBuf, sizeof(szBuf));
  568. UpdateCombosForSelectedInput(pInput);
  569. //CMapEntityList *pTarget = GetTarget(szBuf, sizeof(szBuf));
  570. //UpdateCombosForSelectedTarget(pTarget);
  571. }
  572. if ( m_bCanEdit == false )
  573. {
  574. EnableEditControls( false );
  575. }
  576. }
  577. //-----------------------------------------------------------------------------
  578. // Purpose: Adds a connection to all entities being edited.
  579. //-----------------------------------------------------------------------------
  580. void COP_Output::OnAdd(void)
  581. {
  582. FOR_EACH_OBJ( m_EntityList, pos)
  583. {
  584. CMapEntity *pEntity = m_EntityList.Element(pos);
  585. if (pEntity != NULL)
  586. {
  587. CEntityConnection *pConnection = new CEntityConnection;
  588. pEntity->Connections_Add(pConnection);
  589. }
  590. }
  591. UpdateConnectionList();
  592. // Set selection to new item, and move the focus to the output combo
  593. // so they can just start editing.
  594. int nCount = m_ListCtrl.GetItemCount();
  595. SetSelectedItem(nCount - 1);
  596. m_ListCtrl.EnsureVisible(nCount - 1, FALSE);
  597. GetDlgItem(IDC_EDIT_CONN_OUTPUT)->SetFocus();
  598. }
  599. //------------------------------------------------------------------------------
  600. // Purpose: Clear copy buffer
  601. //------------------------------------------------------------------------------
  602. void COP_Output::EmptyCopyBuffer(void)
  603. {
  604. // Delete any old connections
  605. int nConnCount = m_pConnectionBuffer->Count();
  606. for (int i = 0; i < nConnCount; i++)
  607. {
  608. CEntityConnection *pConnection = m_pConnectionBuffer->Element(i);
  609. if (pConnection != NULL)
  610. {
  611. delete pConnection;
  612. }
  613. }
  614. m_pConnectionBuffer->RemoveAll();
  615. }
  616. //-----------------------------------------------------------------------------
  617. // Purpose: Copies list of selected connections into copy buffer
  618. //-----------------------------------------------------------------------------
  619. void COP_Output::OnCopy(void)
  620. {
  621. EmptyCopyBuffer();
  622. if (m_ListCtrl.GetSelectedCount() != 0)
  623. {
  624. int nCount = m_ListCtrl.GetItemCount();
  625. if (nCount > 0)
  626. {
  627. for (int nItem = nCount - 1; nItem >= 0; nItem--)
  628. {
  629. if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
  630. {
  631. //
  632. // Each item in the list control is a list of identical connections that are contained
  633. // in multiple entities. Add each selected connection to the selected entities.
  634. //
  635. COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
  636. CEntityConnectionList *pConnList = pOutputConn->m_pConnList;
  637. if (pConnList != NULL)
  638. {
  639. CEntityConnection *pConnection = pConnList->Element(0);
  640. if (pConnection)
  641. {
  642. CEntityConnection *pNewConnection = new CEntityConnection;
  643. *pNewConnection = *pConnection;
  644. m_pConnectionBuffer->AddToTail(pNewConnection);
  645. }
  646. }
  647. }
  648. }
  649. }
  650. }
  651. }
  652. //-----------------------------------------------------------------------------
  653. // Purpose: Adds a connection to all entities being edited.
  654. //-----------------------------------------------------------------------------
  655. void COP_Output::OnPaste(void)
  656. {
  657. // Early out
  658. if (!m_pConnectionBuffer->Count())
  659. {
  660. return;
  661. }
  662. CUtlVector<CEntityConnection *> NewConnections;
  663. // Add connections from copy buffer to all selected entities
  664. FOR_EACH_OBJ( m_EntityList, pos )
  665. {
  666. CMapEntity *pEntity = m_EntityList.Element(pos);
  667. if (pEntity != NULL)
  668. {
  669. int nConnCount = m_pConnectionBuffer->Count();
  670. for (int i = 0; i < nConnCount; i++)
  671. {
  672. CEntityConnection *pConnection = m_pConnectionBuffer->Element(i);
  673. if (pConnection != NULL)
  674. {
  675. CEntityConnection *pNewConnection = new CEntityConnection;
  676. *pNewConnection = *pConnection;
  677. pEntity->Connections_Add(pNewConnection);
  678. NewConnections.AddToTail(pNewConnection);
  679. }
  680. }
  681. }
  682. }
  683. UpdateConnectionList();
  684. SortListByColumn(m_nSortColumn, m_eSortDirection[m_nSortColumn]);
  685. SetSelectedConnections(NewConnections);
  686. GetDlgItem(IDC_EDIT_CONN_OUTPUT)->SetFocus();
  687. }
  688. //-----------------------------------------------------------------------------
  689. // Purpose:
  690. //-----------------------------------------------------------------------------
  691. void COP_Output::OnPickEntity(void)
  692. {
  693. CButton *pButton = (CButton *)GetDlgItem(IDC_PICK_ENTITY);
  694. Assert(pButton != NULL);
  695. if (pButton != NULL)
  696. {
  697. if (pButton->GetCheck())
  698. {
  699. //
  700. // Activate the entity picker tool.
  701. //
  702. m_bPickingEntities = true;
  703. m_PickEntityTarget.AttachDlgItem( IDC_EDIT_CONN_TARGET );
  704. CToolPickEntity *pTool = (CToolPickEntity *)ToolManager()->GetToolForID(TOOL_PICK_ENTITY);
  705. pTool->Attach(&m_PickEntityTarget);
  706. ToolManager()->SetTool(TOOL_PICK_ENTITY);
  707. GetDlgItem(IDC_PICK_ENTITY_PARAM)->EnableWindow( false );
  708. }
  709. else
  710. {
  711. StopPicking();
  712. }
  713. }
  714. }
  715. //-----------------------------------------------------------------------------
  716. // Purpose:
  717. //-----------------------------------------------------------------------------
  718. void COP_Output::OnPickEntityParam(void)
  719. {
  720. CButton *pButton = (CButton *)GetDlgItem(IDC_PICK_ENTITY_PARAM);
  721. Assert(pButton != NULL);
  722. if (pButton != NULL)
  723. {
  724. if (pButton->GetCheck())
  725. {
  726. //
  727. // Activate the entity picker tool.
  728. //
  729. m_bPickingEntities = true;
  730. m_PickEntityTarget.AttachDlgItem( IDC_EDIT_CONN_PARAM );
  731. CToolPickEntity *pTool = (CToolPickEntity *)ToolManager()->GetToolForID(TOOL_PICK_ENTITY);
  732. pTool->Attach(&m_PickEntityTarget);
  733. ToolManager()->SetTool(TOOL_PICK_ENTITY);
  734. GetDlgItem(IDC_PICK_ENTITY)->EnableWindow( false );
  735. }
  736. else
  737. {
  738. StopPicking();
  739. }
  740. }
  741. }
  742. //-----------------------------------------------------------------------------
  743. // Purpose: Deletes all selected items from the connection list, and removes the
  744. // corresponding connections from the list of entities being edited.
  745. //-----------------------------------------------------------------------------
  746. void COP_Output::OnDelete(void)
  747. {
  748. if (m_ListCtrl.GetSelectedCount() != 0)
  749. {
  750. int nCount = m_ListCtrl.GetItemCount();
  751. int nLastItem = 0;
  752. if (nCount > 0)
  753. {
  754. for (int nItem = nCount - 1; nItem >= 0; nItem--)
  755. {
  756. if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
  757. {
  758. //
  759. // Each item in the list control is a list of identical connections that are contained
  760. // in multiple entities. Since we don't store the containing entity along with the connection,
  761. // just try to remove all the connections in the list from all the selected entities.
  762. //
  763. COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
  764. CEntityConnectionList *pConnList = pOutputConn->m_pConnList;
  765. m_ListCtrl.DeleteItem(nItem);
  766. if (pConnList != NULL)
  767. {
  768. int nConnCount = pConnList->Count();
  769. for (int nConn = 0; nConn < nConnCount; nConn++)
  770. {
  771. CEntityConnection *pConnection = pConnList->Element(nConn);
  772. if (pConnection != NULL)
  773. {
  774. //
  775. // Remove the connection from all entities being edited.
  776. //
  777. FOR_EACH_OBJ( m_EntityList, pos )
  778. {
  779. CMapEntity *pEntity = m_EntityList.Element(pos);
  780. if (pEntity != NULL)
  781. {
  782. pEntity->Connections_Remove(pConnection);
  783. }
  784. }
  785. //
  786. // Remove the connection from the upstream list of all entities it targets.
  787. //
  788. CMapEntityList *pTargetList = pConnection->GetTargetEntityList();
  789. if ( pTargetList )
  790. {
  791. FOR_EACH_OBJ( *pTargetList, pos2 )
  792. {
  793. CMapEntity *pEntity = pTargetList->Element( pos2 );
  794. // If you hit this assert it means that an entity was deleted but not removed
  795. // from this entity's list of targets.
  796. ASSERT( pEntity != NULL );
  797. if ( pEntity )
  798. {
  799. pEntity->Upstream_Remove( pConnection );
  800. }
  801. }
  802. }
  803. }
  804. delete pConnection;
  805. }
  806. delete pConnList;
  807. }
  808. // Keep track of last item so can set selection focus
  809. nLastItem = nItem;
  810. }
  811. }
  812. }
  813. // Set selection focus as point of deletion or on last item
  814. int nNumItems = m_ListCtrl.GetItemCount()-1;
  815. if (nLastItem > nNumItems)
  816. {
  817. nLastItem = nNumItems;
  818. }
  819. SetSelectedItem(nLastItem);
  820. UpdateValidityButton();
  821. }
  822. }
  823. //------------------------------------------------------------------------------
  824. // Purpose : Take the user to the output page of the selected entity that
  825. // targets me.
  826. // Input :
  827. // Output :
  828. //------------------------------------------------------------------------------
  829. void COP_Output::OnMark(void)
  830. {
  831. int nCount = m_ListCtrl.GetItemCount();
  832. CMapDoc *pActiveDoc = CMapDoc::GetActiveMapDoc();
  833. CMapDoc *pExternalDoc = NULL;
  834. bool bMultipleDocs = false;
  835. bool bFoundInActive = false;
  836. CEntityConnection *pConnection = NULL;
  837. if ( nCount > 0 )
  838. {
  839. CMapObjectList Select;
  840. for (int nItem = nCount - 1; nItem >= 0; nItem--)
  841. {
  842. if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
  843. {
  844. COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
  845. pConnection = pOutputConn->m_pConnList->Element(0);
  846. POSITION pos = APP()->pMapDocTemplate->GetFirstDocPosition();
  847. while( pos != NULL )
  848. {
  849. CDocument *pDoc = APP()->pMapDocTemplate->GetNextDoc( pos );
  850. CMapDoc *pMapDoc = dynamic_cast< CMapDoc * >( pDoc );
  851. if ( pMapDoc )
  852. {
  853. CMapEntityList Found;
  854. pMapDoc->FindEntitiesByName(Found, m_ListCtrl.GetItemText(nItem, TARGET_NAME_COLUMN), false);
  855. FOR_EACH_OBJ( Found, pos )
  856. {
  857. CMapEntity *pEntity = Found.Element(pos);
  858. Select.AddToTail(pEntity);
  859. if ( pExternalDoc && pExternalDoc != pMapDoc )
  860. {
  861. bMultipleDocs = true;
  862. }
  863. if ( pMapDoc == pActiveDoc )
  864. {
  865. bFoundInActive = true;
  866. }
  867. pExternalDoc = pMapDoc;
  868. }
  869. }
  870. }
  871. }
  872. }
  873. if ( bFoundInActive == true )
  874. {
  875. pExternalDoc = pActiveDoc;
  876. bMultipleDocs = false;
  877. }
  878. if ( bMultipleDocs == true )
  879. {
  880. MessageBox( "Entities with same target name exist across multiple documents.", "No Selection Done!", MB_ICONINFORMATION | MB_OK );
  881. return;
  882. }
  883. else if ( Select.Count() > 0 )
  884. {
  885. pExternalDoc->SelectObjectList( &Select );
  886. // (a bit squirly way of doing this)
  887. if ( Select.Count()==1 )
  888. {
  889. GetMainWnd()->pObjectProperties->SetPageToInput(pConnection);
  890. }
  891. if ( pExternalDoc != pActiveDoc )
  892. {
  893. CMapDoc::SetActiveMapDoc( pExternalDoc );
  894. CMapDoc::ActivateMapDoc( pExternalDoc );
  895. GetMainWnd()->GlobalNotify( WM_MAPDOC_CHANGED );
  896. pExternalDoc->UpdateAllViews( MAPVIEW_UPDATE_SELECTION | MAPVIEW_UPDATE_OBJECTS | MAPVIEW_OPTIONS_CHANGED | MAPVIEW_RENDER_NOW );
  897. }
  898. pExternalDoc->Center2DViewsOnSelection();
  899. }
  900. else
  901. {
  902. MessageBox("No entities were found with that targetname.", "No entities found", MB_ICONINFORMATION | MB_OK);
  903. return;
  904. }
  905. }
  906. }
  907. //-----------------------------------------------------------------------------
  908. // Purpose: Sets up the list view columns, initial sort column.
  909. //-----------------------------------------------------------------------------
  910. BOOL COP_Output::OnInitDialog(void)
  911. {
  912. CObjectPage::OnInitDialog();
  913. m_bIsInstanceIOProxy = false;
  914. m_ComboOutput.SubclassDlgItem(IDC_EDIT_CONN_OUTPUT, this);
  915. m_ComboInput.SubclassDlgItem(IDC_EDIT_CONN_INPUT, this);
  916. m_ComboTarget.SubclassDlgItem(IDC_EDIT_CONN_TARGET, this);
  917. m_CheckBoxFireOnce.SubclassDlgItem(IDC_EDIT_CONN_FIRE_ONCE, this);
  918. m_ListCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP);
  919. m_ListCtrl.InsertColumn(ICON_COLUMN, "", LVCFMT_CENTER, 20);
  920. m_ListCtrl.InsertColumn(OUTPUT_NAME_COLUMN, "My Output", LVCFMT_LEFT, 70);
  921. m_ListCtrl.InsertColumn(TARGET_NAME_COLUMN, "Target Entity", LVCFMT_LEFT, 70);
  922. m_ListCtrl.InsertColumn(INPUT_NAME_COLUMN, "Target Input", LVCFMT_LEFT, 70);
  923. m_ListCtrl.InsertColumn(DELAY_COLUMN, "Delay", LVCFMT_LEFT, 70);
  924. m_ListCtrl.InsertColumn(ONLY_ONCE_COLUMN, "Only Once", LVCFMT_LEFT, 70);
  925. m_ListCtrl.InsertColumn(PARAMETER_COLUMN, "Parameter", LVCFMT_LEFT, 70);
  926. UpdateConnectionList();
  927. SetSortColumn(m_nSortColumn, m_eSortDirection[m_nSortColumn]);
  928. // Force an update of the column header text so that the sort indicator is shown.
  929. UpdateColumnHeaderText(m_nSortColumn, true, m_eSortDirection[m_nSortColumn]);
  930. ResizeColumns();
  931. m_strLastParam.Empty();
  932. // Select the first item in the combo box
  933. SetSelectedItem(0);
  934. // Create image list. Is deleted automatically when listctrl is deleted
  935. if (!m_pImageList)
  936. {
  937. CWinApp *pApp = AfxGetApp();
  938. m_pImageList = new CImageList();
  939. Assert(m_pImageList != NULL); // serious allocation failure checking
  940. m_pImageList->Create(16, 16, TRUE, 1, 0);
  941. m_pImageList->Add(pApp->LoadIcon( IDI_OUTPUTBAD ));
  942. m_pImageList->Add(pApp->LoadIcon( IDI_OUTPUT ));
  943. m_pImageList->Add(pApp->LoadIcon( IDI_OUTPUTBAD_GREY ));
  944. m_pImageList->Add(pApp->LoadIcon( IDI_OUTPUT_GREY ));
  945. m_pImageList->Add(pApp->LoadIcon( IDI_OUTPUT_EXTERNAL ) );
  946. }
  947. m_ListCtrl.SetImageList(m_pImageList, LVSIL_SMALL );
  948. // Apply the eyedropper image to the picker buttons.
  949. CButton *pButton = (CButton *)GetDlgItem(IDC_PICK_ENTITY);
  950. if (pButton)
  951. {
  952. CWinApp *pApp = AfxGetApp();
  953. HICON hIcon = pApp->LoadIcon(IDI_EYEDROPPER);
  954. pButton->SetIcon(hIcon);
  955. }
  956. pButton = (CButton *)GetDlgItem(IDC_PICK_ENTITY_PARAM);
  957. if (pButton)
  958. {
  959. CWinApp *pApp = AfxGetApp();
  960. HICON hIcon = pApp->LoadIcon(IDI_EYEDROPPER);
  961. pButton->SetIcon(hIcon);
  962. }
  963. CAnchorDef anchorDefs[] =
  964. {
  965. CAnchorDef( IDC_LIST, k_eSimpleAnchorAllSides ),
  966. CAnchorDef( IDC_OUTPUTS_STATIC_PANEL, k_eAnchorLeft, k_eAnchorBottom, k_eAnchorRight, k_eAnchorBottom ),
  967. CAnchorDef( IDC_OUTPUT_LABEL, k_eSimpleAnchorBottomSide ),
  968. CAnchorDef( IDC_TARGETS_LABEL, k_eSimpleAnchorBottomSide ),
  969. CAnchorDef( IDC_VIA_INPUT_LABEL, k_eSimpleAnchorBottomSide ),
  970. CAnchorDef( IDC_PARAMETER_LABEL, k_eSimpleAnchorBottomSide ),
  971. CAnchorDef( IDC_DELAY_LABEL, k_eSimpleAnchorBottomSide ),
  972. CAnchorDef( IDC_EDIT_CONN_DELAY, k_eSimpleAnchorBottomSide ),
  973. CAnchorDef( IDC_EDIT_CONN_FIRE_ONCE, k_eSimpleAnchorBottomSide ),
  974. CAnchorDef( IDC_EDIT_CONN_PARAM, k_eSimpleAnchorBottomSide ),
  975. CAnchorDef( IDC_EDIT_CONN_INPUT, k_eSimpleAnchorBottomSide ),
  976. CAnchorDef( IDC_EDIT_CONN_TARGET, k_eSimpleAnchorBottomSide ),
  977. CAnchorDef( IDC_EDIT_CONN_OUTPUT, k_eSimpleAnchorBottomSide ),
  978. CAnchorDef( IDC_PICK_ENTITY, k_eSimpleAnchorBottomSide ),
  979. CAnchorDef( IDC_PICK_ENTITY_PARAM, k_eSimpleAnchorBottomSide ),
  980. CAnchorDef( IDC_MARK, k_eSimpleAnchorBottomSide ),
  981. CAnchorDef( IDC_ADD, k_eSimpleAnchorBottomSide ),
  982. CAnchorDef( IDC_COPY, k_eSimpleAnchorBottomSide ),
  983. CAnchorDef( IDC_PASTE, k_eSimpleAnchorBottomSide ),
  984. CAnchorDef( IDC_DELETE, k_eSimpleAnchorBottomSide ),
  985. CAnchorDef( IDC_SHOWHIDDENTARGETS, k_eSimpleAnchorBottomRight )
  986. };
  987. m_AnchorMgr.Init( GetSafeHwnd(), anchorDefs, ARRAYSIZE( anchorDefs ) );
  988. // Set the last state this was at.
  989. m_ctlShowHiddenTargetsAsBroken.SetCheck( ShouldShowHiddenTargets() );
  990. return(TRUE);
  991. }
  992. //-----------------------------------------------------------------------------
  993. // Purpose:
  994. // Input : wParam -
  995. // lParam -
  996. // pResult -
  997. // Output : Returns TRUE on success, FALSE on failure.
  998. //-----------------------------------------------------------------------------
  999. BOOL COP_Output::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult)
  1000. {
  1001. NMHDR *pnmh = (NMHDR *)lParam;
  1002. if (pnmh->idFrom == IDC_LIST)
  1003. {
  1004. switch (pnmh->code)
  1005. {
  1006. case LVN_COLUMNCLICK:
  1007. {
  1008. NMLISTVIEW *pnmv = (NMLISTVIEW *)lParam;
  1009. if (pnmv->iSubItem < OUTPUT_LIST_NUM_COLUMNS)
  1010. {
  1011. SortDirection_t eSortDirection = m_eSortDirection[pnmv->iSubItem];
  1012. //
  1013. // If they clicked on the current sort column, reverse the sort direction.
  1014. //
  1015. if (pnmv->iSubItem == m_nSortColumn)
  1016. {
  1017. if (m_eSortDirection[m_nSortColumn] == Sort_Ascending)
  1018. {
  1019. eSortDirection = Sort_Descending;
  1020. }
  1021. else
  1022. {
  1023. eSortDirection = Sort_Ascending;
  1024. }
  1025. }
  1026. //
  1027. // Update the sort column and sort the list.
  1028. //
  1029. SetSortColumn(pnmv->iSubItem, eSortDirection);
  1030. }
  1031. return(TRUE);
  1032. }
  1033. case NM_DBLCLK:
  1034. {
  1035. OnMark();
  1036. return(TRUE);
  1037. }
  1038. case LVN_ITEMCHANGED:
  1039. {
  1040. NMLISTVIEW *pnmv = (NMLISTVIEW *)lParam;
  1041. if ( ( pnmv->uNewState & LVIS_SELECTED ) != ( pnmv->uOldState & LVIS_SELECTED ) )
  1042. {
  1043. // Listbox selection has changed so update edit controls
  1044. if (!bSkipEditControlRefresh)
  1045. {
  1046. UpdateEditControls();
  1047. }
  1048. bSkipEditControlRefresh = false;
  1049. // Forget the saved param, because it was for a different I/O connection.
  1050. m_strLastParam.Empty();
  1051. }
  1052. return(TRUE);
  1053. }
  1054. }
  1055. }
  1056. return(CObjectPage::OnNotify(wParam, lParam, pResult));
  1057. }
  1058. //-----------------------------------------------------------------------------
  1059. // Purpose: Empties the contents of the connections list control, freeing the
  1060. // connection list hanging off of each row.
  1061. //-----------------------------------------------------------------------------
  1062. void COP_Output::RemoveAllEntityConnections(void)
  1063. {
  1064. m_ListCtrl.SetRedraw(FALSE);
  1065. int nCount = m_ListCtrl.GetItemCount();
  1066. if (nCount > 0)
  1067. {
  1068. for (int nItem = nCount - 1; nItem >= 0; nItem--)
  1069. {
  1070. COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
  1071. CEntityConnectionList *pConnList = pOutputConn->m_pConnList;
  1072. CMapEntityList *pEntityList = pOutputConn->m_pEntityList;
  1073. m_ListCtrl.DeleteItem(nItem);
  1074. delete pOutputConn;
  1075. delete pConnList;
  1076. delete pEntityList;
  1077. }
  1078. }
  1079. m_ListCtrl.SetRedraw(TRUE);
  1080. }
  1081. //-----------------------------------------------------------------------------
  1082. // Purpose:
  1083. // Input : Mode -
  1084. // pData -
  1085. //-----------------------------------------------------------------------------
  1086. void COP_Output::UpdateData( int Mode, PVOID pData, bool bCanEdit )
  1087. {
  1088. __super::UpdateData( Mode, pData, bCanEdit );
  1089. if (!IsWindow(m_hWnd))
  1090. {
  1091. return;
  1092. }
  1093. switch (Mode)
  1094. {
  1095. case LoadFirstData:
  1096. {
  1097. // m_ListCtrl.DeleteAllItems();
  1098. // UpdateConnectionList();
  1099. break;
  1100. }
  1101. case LoadData:
  1102. {
  1103. // m_ListCtrl.DeleteAllItems();
  1104. // UpdateConnectionList();
  1105. // SetSelectedItem(0);
  1106. break;
  1107. }
  1108. case LoadFinished:
  1109. {
  1110. m_ListCtrl.DeleteAllItems();
  1111. UpdateConnectionList();
  1112. SetSelectedItem(0);
  1113. SortListByColumn(m_nSortColumn, m_eSortDirection[m_nSortColumn]);
  1114. }
  1115. }
  1116. UpdateEditControls();
  1117. }
  1118. //------------------------------------------------------------------------------
  1119. // Purpose: Generates list of map entites that are being edited from the
  1120. // m_pObject list
  1121. //------------------------------------------------------------------------------
  1122. void COP_Output::UpdateEntityList(void)
  1123. {
  1124. // Clear old entity list
  1125. m_EntityList.RemoveAll();
  1126. if (m_pObjectList != NULL)
  1127. {
  1128. FOR_EACH_OBJ( *m_pObjectList, pos )
  1129. {
  1130. const CMapClass *pObject = m_pObjectList->Element(pos);
  1131. if ((pObject != NULL) && (pObject->IsMapClass(MAPCLASS_TYPE(CMapEntity))) )
  1132. {
  1133. CMapEntity *pEntity = (CMapEntity *)pObject;
  1134. m_EntityList.AddToTail(pEntity);
  1135. }
  1136. }
  1137. }
  1138. }
  1139. //-----------------------------------------------------------------------------
  1140. // Purpose:
  1141. // Input : nColumn -
  1142. // eDirection -
  1143. //-----------------------------------------------------------------------------
  1144. void COP_Output::SetSortColumn(int nColumn, SortDirection_t eDirection)
  1145. {
  1146. Assert(nColumn < OUTPUT_LIST_NUM_COLUMNS);
  1147. //
  1148. // If the sort column changed, update the old sort column header text.
  1149. //
  1150. if (m_nSortColumn != nColumn)
  1151. {
  1152. UpdateColumnHeaderText(m_nSortColumn, false, eDirection);
  1153. }
  1154. //
  1155. // If the sort column or direction changed, update the new sort column header text.
  1156. //
  1157. if ((m_nSortColumn != nColumn) || (m_eSortDirection[m_nSortColumn] != eDirection))
  1158. {
  1159. UpdateColumnHeaderText(nColumn, true, eDirection);
  1160. }
  1161. m_nSortColumn = nColumn;
  1162. m_eSortDirection[m_nSortColumn] = eDirection;
  1163. SortListByColumn(m_nSortColumn, m_eSortDirection[m_nSortColumn]);
  1164. }
  1165. //-----------------------------------------------------------------------------
  1166. // Purpose: Sorts the outputs list by column.
  1167. // Input : nColumn - Index of column by which to sort.
  1168. //-----------------------------------------------------------------------------
  1169. void COP_Output::SortListByColumn(int nColumn, SortDirection_t eDirection)
  1170. {
  1171. PFNLVCOMPARE pfnSort = NULL;
  1172. switch (nColumn)
  1173. {
  1174. case ONLY_ONCE_COLUMN:
  1175. {
  1176. //No Sort
  1177. break;
  1178. }
  1179. case PARAMETER_COLUMN:
  1180. {
  1181. //No Sort
  1182. break;
  1183. }
  1184. case OUTPUT_NAME_COLUMN:
  1185. {
  1186. pfnSort = (PFNLVCOMPARE)ListCompareOutputNames;
  1187. break;
  1188. }
  1189. case TARGET_NAME_COLUMN:
  1190. {
  1191. pfnSort = (PFNLVCOMPARE)ListCompareTargetNames;
  1192. break;
  1193. }
  1194. case INPUT_NAME_COLUMN:
  1195. {
  1196. pfnSort = (PFNLVCOMPARE)ListCompareInputNames;
  1197. break;
  1198. }
  1199. case DELAY_COLUMN:
  1200. {
  1201. pfnSort = (PFNLVCOMPARE)ListCompareDelays;
  1202. break;
  1203. }
  1204. default:
  1205. {
  1206. Assert(FALSE);
  1207. break;
  1208. }
  1209. }
  1210. if (pfnSort != NULL)
  1211. {
  1212. m_ListCtrl.SortItems(pfnSort, (DWORD)eDirection);
  1213. }
  1214. }
  1215. //-----------------------------------------------------------------------------
  1216. // Purpose:
  1217. //-----------------------------------------------------------------------------
  1218. void COP_Output::ResizeColumns(void)
  1219. {
  1220. if (m_ListCtrl.GetItemCount() > 0)
  1221. {
  1222. m_ListCtrl.SetColumnWidth(OUTPUT_NAME_COLUMN, LVSCW_AUTOSIZE);
  1223. m_ListCtrl.SetColumnWidth(TARGET_NAME_COLUMN, LVSCW_AUTOSIZE);
  1224. m_ListCtrl.SetColumnWidth(INPUT_NAME_COLUMN, LVSCW_AUTOSIZE);
  1225. m_ListCtrl.SetColumnWidth(DELAY_COLUMN, LVSCW_AUTOSIZE_USEHEADER);
  1226. m_ListCtrl.SetColumnWidth(ONLY_ONCE_COLUMN, LVSCW_AUTOSIZE_USEHEADER);
  1227. m_ListCtrl.SetColumnWidth(PARAMETER_COLUMN, LVSCW_AUTOSIZE);
  1228. }
  1229. }
  1230. //-----------------------------------------------------------------------------
  1231. // Purpose:
  1232. //-----------------------------------------------------------------------------
  1233. void COP_Output::UpdateConnectionList(void)
  1234. {
  1235. // Get list of all entities in the world
  1236. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  1237. Assert(pDoc != NULL);
  1238. if (!pDoc)
  1239. return;
  1240. CMapWorld *pWorld = pDoc->GetMapWorld();
  1241. Assert(pWorld != NULL); // dvs: I've seen pWorld be NULL on app shutdown, not sure why we ended up here though
  1242. if (!pWorld)
  1243. return;
  1244. SetMapEntityList(pWorld->EntityList_GetList());
  1245. UpdateEntityList();
  1246. RemoveAllEntityConnections();
  1247. bool bFirst = true;
  1248. FOR_EACH_OBJ( m_EntityList, pos )
  1249. {
  1250. CMapEntity *pEntity = m_EntityList.Element(pos);
  1251. if (pEntity != NULL)
  1252. {
  1253. AddEntityConnections(pEntity, bFirst);
  1254. bFirst = false;
  1255. }
  1256. }
  1257. // Update validity flag on all items
  1258. for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
  1259. {
  1260. UpdateItemValidity(nItem);
  1261. }
  1262. UpdateValidityButton();
  1263. ResizeColumns();
  1264. }
  1265. //------------------------------------------------------------------------------
  1266. // Purpose: Set the selected item in the listbox by index.
  1267. // Input : nSelectItem -
  1268. //------------------------------------------------------------------------------
  1269. void COP_Output::SetSelectedItem(int nSelectItem)
  1270. {
  1271. m_ListCtrl.SetRedraw(FALSE);
  1272. // Set selected item to be active and all others to false
  1273. int nItemCount = m_ListCtrl.GetItemCount();
  1274. for (int nItem = 0; nItem < nItemCount; nItem++)
  1275. {
  1276. if (nItem == nSelectItem)
  1277. {
  1278. m_ListCtrl.SetItemState(nItem, (unsigned int)LVIS_SELECTED, (unsigned int)LVIS_SELECTED);
  1279. }
  1280. else
  1281. {
  1282. m_ListCtrl.SetItemState(nItem, (unsigned int)~LVIS_SELECTED, (unsigned int)LVIS_SELECTED);
  1283. }
  1284. }
  1285. m_ListCtrl.SetRedraw(TRUE);
  1286. // Selected item has changed so update edit controls
  1287. UpdateEditControls();
  1288. }
  1289. //------------------------------------------------------------------------------
  1290. // Purpose: Set the selected item in the listbox
  1291. // Input : pConnection
  1292. //------------------------------------------------------------------------------
  1293. void COP_Output::SetSelectedConnection(CEntityConnection *pConnection)
  1294. {
  1295. m_ListCtrl.SetRedraw(FALSE);
  1296. // Set selected item to be active and all others to false
  1297. int nItemCount = m_ListCtrl.GetItemCount();
  1298. for (int nItem = 0; nItem < nItemCount; nItem++)
  1299. {
  1300. COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
  1301. CEntityConnectionList *pTestList = pOutputConn->m_pConnList;
  1302. if (pTestList->Element(0) == pConnection)
  1303. {
  1304. m_ListCtrl.SetItemState(nItem,LVIS_SELECTED,LVIS_SELECTED);
  1305. }
  1306. else
  1307. {
  1308. m_ListCtrl.SetItemState(nItem, (unsigned int)~LVIS_SELECTED, (unsigned int)LVIS_SELECTED);
  1309. }
  1310. }
  1311. m_ListCtrl.SetRedraw(TRUE);
  1312. // Selected item has changed so update edit controls
  1313. UpdateEditControls();
  1314. }
  1315. //-----------------------------------------------------------------------------
  1316. // Purpose: Selects the list box entries that correspond to the connections in
  1317. // the given list.
  1318. //-----------------------------------------------------------------------------
  1319. void COP_Output::SetSelectedConnections(CEntityConnectionList &List)
  1320. {
  1321. m_ListCtrl.SetRedraw(FALSE);
  1322. int nConnCount = List.Count();
  1323. int nItemCount = m_ListCtrl.GetItemCount();
  1324. for (int nItem = 0; nItem < nItemCount; nItem++)
  1325. {
  1326. COutputConnection *pOutputConn = (COutputConnection *)m_ListCtrl.GetItemData(nItem);
  1327. CEntityConnectionList *pConnList = pOutputConn->m_pConnList;
  1328. // See if this row's list holds any of the connections in the given list.
  1329. bool bFound = false;
  1330. for (int nConn = 0; nConn < nConnCount; nConn++)
  1331. {
  1332. CEntityConnection *pConn = List.Element(nConn);
  1333. if (pConnList->Find(pConn) != -1)
  1334. {
  1335. bFound = true;
  1336. break;
  1337. }
  1338. }
  1339. m_ListCtrl.SetItemState(nItem, bFound ? LVIS_SELECTED : ~LVIS_SELECTED, LVIS_SELECTED);
  1340. }
  1341. m_ListCtrl.SetRedraw(TRUE);
  1342. UpdateEditControls();
  1343. }
  1344. //-----------------------------------------------------------------------------
  1345. // Purpose: Adds or removes the little 'V' or '^' sort indicator as appropriate.
  1346. // Input : nColumn - Index of column to update.
  1347. // bSortColumn - true if this column is the sort column, false if not.
  1348. // eDirection - Direction of sort, Sort_Ascending or Sort_Descending.
  1349. //-----------------------------------------------------------------------------
  1350. void COP_Output::UpdateColumnHeaderText(int nColumn, bool bIsSortColumn, SortDirection_t eDirection)
  1351. {
  1352. char szHeaderText[MAX_PATH];
  1353. LVCOLUMN Column;
  1354. memset(&Column, 0, sizeof(Column));
  1355. Column.mask = LVCF_TEXT;
  1356. Column.pszText = szHeaderText;
  1357. Column.cchTextMax = sizeof(szHeaderText);
  1358. m_ListCtrl.GetColumn(nColumn, &Column);
  1359. int nMarker = 0;
  1360. if (szHeaderText[0] != '\0')
  1361. {
  1362. nMarker = strlen(szHeaderText) - 1;
  1363. char chMarker = szHeaderText[nMarker];
  1364. if ((chMarker == '>') || (chMarker == '<'))
  1365. {
  1366. nMarker -= 2;
  1367. }
  1368. else
  1369. {
  1370. nMarker++;
  1371. }
  1372. }
  1373. if (bIsSortColumn)
  1374. {
  1375. if (nMarker != 0)
  1376. {
  1377. szHeaderText[nMarker++] = ' ';
  1378. szHeaderText[nMarker++] = ' ';
  1379. }
  1380. szHeaderText[nMarker++] = (eDirection == Sort_Ascending) ? '>' : '<';
  1381. }
  1382. szHeaderText[nMarker] = '\0';
  1383. m_ListCtrl.SetColumn(nColumn, &Column);
  1384. }
  1385. //-----------------------------------------------------------------------------
  1386. // Purpose: Called when our window is being destroyed.
  1387. //-----------------------------------------------------------------------------
  1388. void COP_Output::OnDestroy(void)
  1389. {
  1390. m_ListCtrl.EnableWindow(false);
  1391. RemoveAllEntityConnections();
  1392. }
  1393. //------------------------------------------------------------------------------
  1394. // Purpose:
  1395. //------------------------------------------------------------------------------
  1396. void COP_Output::UpdateEditedFireOnce(void)
  1397. {
  1398. // Get new delay
  1399. CButton *pButton = ( CButton* )GetDlgItem( IDC_EDIT_CONN_FIRE_ONCE );
  1400. if (pButton->IsWindowEnabled())
  1401. {
  1402. int nChecked = (pButton->GetState()&0x0003); // Checked state
  1403. // Update the connections
  1404. int nConnCount = m_EditList.Count();
  1405. for (int nConn = 0; nConn < nConnCount; nConn++)
  1406. {
  1407. CEntityConnection *pConnection = m_EditList.Element(nConn);
  1408. if (pConnection != NULL)
  1409. {
  1410. pConnection->SetTimesToFire(nChecked?1:EVENT_FIRE_ALWAYS);
  1411. }
  1412. }
  1413. // Update the list box
  1414. for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
  1415. {
  1416. if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
  1417. {
  1418. m_ListCtrl.SetItemText(nItem, ONLY_ONCE_COLUMN, nChecked ? "Yes" : "No");
  1419. }
  1420. }
  1421. ResizeColumns();
  1422. }
  1423. }
  1424. //------------------------------------------------------------------------------
  1425. // Purpose:
  1426. //------------------------------------------------------------------------------
  1427. void COP_Output::UpdateEditedDelays(void)
  1428. {
  1429. // Get new delay
  1430. CEdit *pDelayEdit = ( CEdit* )GetDlgItem( IDC_EDIT_CONN_DELAY );
  1431. if (pDelayEdit->IsWindowEnabled())
  1432. {
  1433. char strDelay[MAX_IO_NAME_LEN];
  1434. pDelayEdit->GetWindowText(strDelay, sizeof(strDelay));
  1435. float flDelay = atof(strDelay);
  1436. // Update the connections
  1437. int nConnCount = m_EditList.Count();
  1438. for (int nConn = 0; nConn < nConnCount; nConn++)
  1439. {
  1440. CEntityConnection *pConnection = m_EditList.Element(nConn);
  1441. if (pConnection != NULL)
  1442. {
  1443. pConnection->SetDelay(flDelay);
  1444. }
  1445. }
  1446. // Update the list box
  1447. for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
  1448. {
  1449. if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
  1450. {
  1451. m_ListCtrl.SetItemText(nItem, DELAY_COLUMN, strDelay);
  1452. }
  1453. }
  1454. ResizeColumns();
  1455. }
  1456. }
  1457. //------------------------------------------------------------------------------
  1458. // Purpose: Parameters have changed. Update connections and listbox
  1459. //------------------------------------------------------------------------------
  1460. void COP_Output::UpdateEditedParams(void)
  1461. {
  1462. CComboBox *pParamEdit = ( CComboBox* )GetDlgItem( IDC_EDIT_CONN_PARAM );
  1463. if (pParamEdit->IsWindowEnabled())
  1464. {
  1465. char strParam[MAX_IO_NAME_LEN];
  1466. pParamEdit->GetWindowText(strParam, sizeof(strParam));
  1467. if (!strcmp(strParam, PARAM_STRING_NONE))
  1468. {
  1469. strParam[0] = '\0';
  1470. }
  1471. // Update the connections
  1472. int nConnCount = m_EditList.Count();
  1473. for (int nConn = 0; nConn < nConnCount; nConn++)
  1474. {
  1475. CEntityConnection *pConnection = m_EditList.Element(nConn);
  1476. if (pConnection != NULL)
  1477. {
  1478. pConnection->SetParam(strParam);
  1479. }
  1480. }
  1481. // Update the list box
  1482. for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
  1483. {
  1484. if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
  1485. {
  1486. m_ListCtrl.SetItemText(nItem, PARAMETER_COLUMN, strParam);
  1487. }
  1488. }
  1489. ResizeColumns();
  1490. }
  1491. }
  1492. //------------------------------------------------------------------------------
  1493. // Purpose: Inputs have changed. Update connections and listbox
  1494. //------------------------------------------------------------------------------
  1495. void COP_Output::UpdateEditedInputs(void)
  1496. {
  1497. // Get the new name
  1498. char strInput[MAX_IO_NAME_LEN];
  1499. GetInput(strInput, sizeof(strInput));
  1500. // Update the connections
  1501. int nConnCount = m_EditList.Count();
  1502. for (int nConn = 0; nConn < nConnCount; nConn++)
  1503. {
  1504. CEntityConnection *pConnection = m_EditList.Element(nConn);
  1505. if (pConnection != NULL)
  1506. {
  1507. pConnection->SetInputName(strInput);
  1508. }
  1509. }
  1510. // Update the list box
  1511. for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
  1512. {
  1513. if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
  1514. {
  1515. m_ListCtrl.SetItemText(nItem, INPUT_NAME_COLUMN, strInput);
  1516. UpdateItemValidity(nItem);
  1517. }
  1518. }
  1519. UpdateValidityButton();
  1520. ResizeColumns();
  1521. }
  1522. //------------------------------------------------------------------------------
  1523. // Purpose: Outputs have changed. Update connections and listbox
  1524. //------------------------------------------------------------------------------
  1525. void COP_Output::UpdateEditedOutputs()
  1526. {
  1527. // Get the new name
  1528. char strOutput[MAX_IO_NAME_LEN];
  1529. GetOutput(strOutput, sizeof(strOutput));
  1530. // Update the connections
  1531. int nConnCount = m_EditList.Count();
  1532. for (int nConn = 0; nConn < nConnCount; nConn++)
  1533. {
  1534. CEntityConnection *pConnection = m_EditList.Element(nConn);
  1535. if (pConnection != NULL)
  1536. {
  1537. pConnection->SetOutputName(strOutput);
  1538. }
  1539. }
  1540. // Update the list box
  1541. for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
  1542. {
  1543. if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
  1544. {
  1545. m_ListCtrl.SetItemText(nItem, OUTPUT_NAME_COLUMN, strOutput);
  1546. UpdateItemValidity(nItem);
  1547. }
  1548. }
  1549. UpdateValidityButton();
  1550. ResizeColumns();
  1551. }
  1552. //------------------------------------------------------------------------------
  1553. // Purpose: Targets have changed. Update connections and listbox
  1554. //------------------------------------------------------------------------------
  1555. void COP_Output::UpdateEditedTargets(void)
  1556. {
  1557. // Get the new target name
  1558. char strTarget[MAX_IO_NAME_LEN];
  1559. GetTarget(strTarget, sizeof(strTarget));
  1560. // Update the connections
  1561. int nConnCount = m_EditList.Count();
  1562. for (int nConn = 0; nConn < nConnCount; nConn++)
  1563. {
  1564. CEntityConnection *pConnection = m_EditList.Element(nConn);
  1565. if (pConnection != NULL)
  1566. {
  1567. pConnection->SetTargetName(strTarget);
  1568. }
  1569. }
  1570. // Update the list box
  1571. for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
  1572. {
  1573. if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
  1574. {
  1575. m_ListCtrl.SetItemText(nItem, TARGET_NAME_COLUMN, strTarget);
  1576. UpdateItemValidity(nItem);
  1577. }
  1578. }
  1579. UpdateValidityButton();
  1580. ResizeColumns();
  1581. }
  1582. //-----------------------------------------------------------------------------
  1583. // Purpose: Enables or diables the target combo box and the eyedropper button.
  1584. //-----------------------------------------------------------------------------
  1585. void COP_Output::EnableTarget(bool bEnable)
  1586. {
  1587. m_ComboTarget.EnableWindow(bEnable);
  1588. GetDlgItem(IDC_PICK_ENTITY)->EnableWindow(bEnable);
  1589. }
  1590. //-----------------------------------------------------------------------------
  1591. // Purpose:
  1592. // Input : *pConnection -
  1593. //-----------------------------------------------------------------------------
  1594. void COP_Output::SetConnection(CEntityConnectionList *pConnectionList)
  1595. {
  1596. Assert(pConnectionList != NULL);
  1597. // Fill edit boxes. Disable for multiple connections have incompatible data
  1598. bool bFirst = true;
  1599. CButton* pFireEdit = ( CButton* )GetDlgItem( IDC_EDIT_CONN_FIRE_ONCE );
  1600. CEdit* pDelayEdit = ( CEdit* )GetDlgItem( IDC_EDIT_CONN_DELAY );
  1601. CComboBox* pParamEdit = ( CComboBox* )GetDlgItem( IDC_EDIT_CONN_PARAM );
  1602. m_ComboOutput.EnableWindow(true);
  1603. EnableTarget(true);
  1604. m_ComboInput.EnableWindow(true);
  1605. pFireEdit->EnableWindow(true);
  1606. pDelayEdit->EnableWindow(true);
  1607. pParamEdit->EnableWindow(true);
  1608. GetDlgItem(IDC_PICK_ENTITY_PARAM)->EnableWindow( false );
  1609. m_bEntityParamTarget = false;
  1610. int nConnCount = pConnectionList->Count();
  1611. for (int nConn = 0; nConn < nConnCount; nConn++)
  1612. {
  1613. CEntityConnection *pConnection = (CEntityConnection *)pConnectionList->Element(nConn);
  1614. if (pConnection == NULL)
  1615. continue;
  1616. // Fill in output name, disable for non-compatible connections
  1617. if (m_ComboOutput.IsWindowEnabled())
  1618. {
  1619. if (bFirst)
  1620. {
  1621. m_strOutput = pConnection->GetOutputName();
  1622. }
  1623. else if (m_strOutput != pConnection->GetOutputName())
  1624. {
  1625. m_strOutput.Empty();
  1626. m_ComboOutput.EnableWindow(false);
  1627. }
  1628. }
  1629. // Fill in target name, disable for non-compatible connections
  1630. if (m_ComboTarget.IsWindowEnabled())
  1631. {
  1632. if (bFirst)
  1633. {
  1634. m_strTarget = pConnection->GetTargetName();
  1635. }
  1636. else if (m_strTarget != pConnection->GetTargetName())
  1637. {
  1638. m_strTarget.Empty();
  1639. EnableTarget(false);
  1640. }
  1641. }
  1642. // Fill in input name, disable for non-compatible connections
  1643. if (m_ComboInput.IsWindowEnabled())
  1644. {
  1645. if (bFirst)
  1646. {
  1647. m_strInput = pConnection->GetInputName();
  1648. }
  1649. else if (m_strInput != pConnection->GetInputName())
  1650. {
  1651. m_strInput.Empty();
  1652. m_ComboInput.EnableWindow(false);
  1653. }
  1654. }
  1655. // Fill in parameters, disable for non-compatible connections
  1656. if (pParamEdit->IsWindowEnabled())
  1657. {
  1658. if (bFirst)
  1659. {
  1660. m_strParam = pConnection->GetParam();
  1661. m_bNoParamEdit = false;
  1662. }
  1663. else if (m_strParam != pConnection->GetParam())
  1664. {
  1665. m_strParam.Empty();
  1666. pParamEdit->EnableWindow(false);
  1667. GetDlgItem(IDC_PICK_ENTITY_PARAM)->EnableWindow( false );
  1668. m_bNoParamEdit = true;
  1669. }
  1670. }
  1671. // Fill in delay, disable for non-compatible connections
  1672. if (pDelayEdit->IsWindowEnabled())
  1673. {
  1674. if (bFirst)
  1675. {
  1676. m_fDelay = pConnection->GetDelay();
  1677. }
  1678. else if (m_fDelay != pConnection->GetDelay())
  1679. {
  1680. m_fDelay = 0;
  1681. pDelayEdit->EnableWindow(false);
  1682. }
  1683. }
  1684. // Set fire once flag, disable for non-compatible connections
  1685. if (pFireEdit->IsWindowEnabled())
  1686. {
  1687. if (bFirst)
  1688. {
  1689. m_bFireOnce = (pConnection->GetTimesToFire() == -1) ? false : true;
  1690. }
  1691. else if (m_bFireOnce != pConnection->GetTimesToFire())
  1692. {
  1693. m_bFireOnce = false;
  1694. pFireEdit->EnableWindow(false);
  1695. }
  1696. }
  1697. bFirst = false;
  1698. }
  1699. // Put a <none> in param box if no param
  1700. if (strlen(m_strParam) == 0)
  1701. {
  1702. m_strParam = PARAM_STRING_NONE;
  1703. }
  1704. }
  1705. //-----------------------------------------------------------------------------
  1706. // Purpose: Adds all of an entity's outputs from its class definition to the
  1707. // outputs combo box.
  1708. // Input : pEntity - Entity whose outputs are to be added to the combo box.
  1709. //-----------------------------------------------------------------------------
  1710. void COP_Output::AddEntityOutputs(CMapEntity *pEntity)
  1711. {
  1712. m_bIsInstanceIOProxy = false;
  1713. if ( pEntity && stricmp( pEntity->GetClassName(), "func_instance" ) == 0 )
  1714. {
  1715. CMapInstance *pMapInstance = pEntity->GetChildOfType( ( CMapInstance * )NULL );
  1716. if ( pMapInstance == NULL || pMapInstance->GetInstancedMap() == NULL )
  1717. {
  1718. return;
  1719. }
  1720. CMapEntityList entityList;
  1721. pMapInstance->GetInstancedMap()->FindEntitiesByClassName( entityList, "func_instance_io_proxy", false );
  1722. if ( entityList.Count() != 1 )
  1723. {
  1724. return;
  1725. }
  1726. CMapEntity *pInstanceParmsEntity = entityList.Element( 0 );
  1727. const char *pszTargetName = pInstanceParmsEntity->GetKeyValue( "targetname" );
  1728. m_bIsInstanceIOProxy = true;
  1729. const CMapEntityList *pEntityList = pMapInstance->GetInstancedMap()->GetMapWorld()->EntityList_GetList();
  1730. FOR_EACH_OBJ( *pEntityList, pos2 )
  1731. {
  1732. const CMapEntity *pTestEntity = pEntityList->Element( pos2 ).GetObject();
  1733. if (pTestEntity != NULL)
  1734. {
  1735. int nConnectionsCount = pTestEntity->Connections_GetCount();
  1736. for (int nConnection = 0; nConnection < nConnectionsCount; nConnection++)
  1737. {
  1738. CEntityConnection *pConnection = pTestEntity->Connections_Get( nConnection );
  1739. if ( strcmpi( pConnection->GetTargetName(), pszTargetName ) == 0 )
  1740. {
  1741. char temp[ 512 ];
  1742. sprintf( temp, "instance:%s;%s", pTestEntity->GetKeyValue( "targetname" ), pConnection->GetOutputName() );
  1743. m_ComboOutput.AddString( temp );
  1744. }
  1745. }
  1746. }
  1747. }
  1748. }
  1749. else
  1750. {
  1751. GDclass *pClass = pEntity->GetClass();
  1752. if (pClass != NULL)
  1753. {
  1754. int nCount = pClass->GetOutputCount();
  1755. for (int i = 0; i < nCount; i++)
  1756. {
  1757. CClassOutput *pOutput = pClass->GetOutput(i);
  1758. int nIndex = m_ComboOutput.AddString(pOutput->GetName());
  1759. if (nIndex >= 0)
  1760. {
  1761. m_ComboOutput.SetItemDataPtr(nIndex, pOutput);
  1762. }
  1763. }
  1764. }
  1765. }
  1766. }
  1767. //-----------------------------------------------------------------------------
  1768. // Purpose:
  1769. //-----------------------------------------------------------------------------
  1770. void COP_Output::FillInputList(void)
  1771. {
  1772. if (!m_pMapEntityList)
  1773. {
  1774. return;
  1775. }
  1776. //
  1777. // Add all entity inputs to the inputs combo box.
  1778. //
  1779. m_ComboInput.SetRedraw(FALSE);
  1780. m_ComboInput.ResetContent();
  1781. // CUtlVector<GDclass*> classCache;
  1782. CUtlRBTree<int,int> classCache;
  1783. SetDefLessFunc( classCache );
  1784. CMapEntity *pInstanceParmsEntity = GetTargetInstanceIOProxy();
  1785. if ( pInstanceParmsEntity != NULL )
  1786. {
  1787. m_bIsInstanceIOProxy = true;
  1788. int nConnectionsCount = pInstanceParmsEntity->Connections_GetCount();
  1789. for (int nConnection = 0; nConnection < nConnectionsCount; nConnection++)
  1790. {
  1791. CEntityConnection *pConnection = pInstanceParmsEntity->Connections_Get( nConnection );
  1792. char temp[ 512 ];
  1793. sprintf( temp, "instance:%s;%s", pConnection->GetTargetName(), pConnection->GetInputName() );
  1794. m_ComboInput.AddString( temp );
  1795. }
  1796. }
  1797. else
  1798. {
  1799. m_bIsInstanceIOProxy = false;
  1800. FOR_EACH_OBJ( *m_pMapEntityList, pos )
  1801. {
  1802. const CMapEntity *pEntity = m_pMapEntityList->Element(pos).GetObject();
  1803. Assert(pEntity != NULL);
  1804. if (pEntity == NULL)
  1805. continue;
  1806. //
  1807. // Get the entity's class, which contains the list of inputs that this entity exposes.
  1808. //
  1809. GDclass *pClass = pEntity->GetClass();
  1810. if (pClass == NULL)
  1811. continue;
  1812. // check if class was already added
  1813. if ( classCache.Find( (int)pClass ) != -1 )
  1814. continue;
  1815. classCache.Insert( (int)pClass );
  1816. //
  1817. // Add this class' inputs to the list.
  1818. //
  1819. int nCount = pClass->GetInputCount();
  1820. for (int i = 0; i < nCount; i++)
  1821. {
  1822. CClassInput *pInput = pClass->GetInput(i);
  1823. bool bAddInput = true;
  1824. //
  1825. // Don't add the input to the combo box if another input with the same name
  1826. // and type is already there.
  1827. //
  1828. int nIndex = m_ComboInput.FindStringExact(-1, pInput->GetName());
  1829. if (nIndex != CB_ERR)
  1830. {
  1831. CClassInput *pExistingInput = (CClassInput *)m_ComboInput.GetItemDataPtr(nIndex);
  1832. if (pExistingInput->GetType() == pInput->GetType())
  1833. {
  1834. bAddInput = false;
  1835. }
  1836. }
  1837. if (bAddInput)
  1838. {
  1839. int nIndex = m_ComboInput.AddString(pInput->GetName());
  1840. if (nIndex >= 0)
  1841. {
  1842. m_ComboInput.SetItemDataPtr(nIndex, pInput);
  1843. }
  1844. }
  1845. }
  1846. }
  1847. }
  1848. m_ComboInput.SetRedraw(TRUE);
  1849. }
  1850. //-----------------------------------------------------------------------------
  1851. // Purpose: Fills the list of outputs with outputs common to all the selected entities.
  1852. //-----------------------------------------------------------------------------
  1853. void COP_Output::FillOutputList(void)
  1854. {
  1855. if ( m_EntityList.Count() == 0 )
  1856. {
  1857. return;
  1858. }
  1859. //
  1860. // Determine what the currently selected output is (if any).
  1861. //
  1862. CClassOutput *pSelectedOutput;
  1863. int nOutput = m_ComboOutput.GetCurSel();
  1864. if (nOutput != CB_ERR)
  1865. {
  1866. pSelectedOutput = (CClassOutput *)m_ComboOutput.GetItemDataPtr(nOutput);
  1867. }
  1868. else
  1869. {
  1870. pSelectedOutput = NULL;
  1871. }
  1872. //
  1873. // Add the entity outputs to the outputs combo box.
  1874. //
  1875. m_ComboOutput.SetRedraw(FALSE);
  1876. m_ComboOutput.ResetContent();
  1877. bool bFirst = true;
  1878. FOR_EACH_OBJ( m_EntityList, pos )
  1879. {
  1880. CMapEntity *pEntity = m_EntityList.Element(pos);
  1881. if (bFirst)
  1882. {
  1883. //
  1884. // The first entity adds its outputs to the list.
  1885. //
  1886. AddEntityOutputs(pEntity);
  1887. bFirst = false;
  1888. }
  1889. else
  1890. {
  1891. //
  1892. // All subsequent entities filter the output list.
  1893. //
  1894. FilterEntityOutputs(pEntity);
  1895. }
  1896. }
  1897. if (m_ComboOutput.GetCount() == 0)
  1898. {
  1899. m_ComboOutput.EnableWindow(false);
  1900. }
  1901. m_ComboOutput.SetRedraw(TRUE);
  1902. }
  1903. //-----------------------------------------------------------------------------
  1904. // Purpose: Fills the list of targets with entities that have "targetname" keys.
  1905. //-----------------------------------------------------------------------------
  1906. void COP_Output::FillTargetList(void)
  1907. {
  1908. m_bIgnoreTextChanged = true;
  1909. m_ComboTarget.SetEntityList(m_pMapEntityList);
  1910. m_bIgnoreTextChanged = false;
  1911. }
  1912. //-----------------------------------------------------------------------------
  1913. // Purpose: Removes all outputs from the outputs combo box that are NOT present
  1914. // in the given entity's output list. Used when multiple entities are
  1915. // selected into the Entity Properties dialog.
  1916. // Input : pEntity - Entity to use for filter.
  1917. //-----------------------------------------------------------------------------
  1918. void COP_Output::FilterEntityOutputs(CMapEntity *pEntity)
  1919. {
  1920. //
  1921. // Make sure that this entity has a valid class to use for filtering.
  1922. //
  1923. GDclass *pClass = pEntity->GetClass();
  1924. if (pClass == NULL)
  1925. {
  1926. return;
  1927. }
  1928. //
  1929. // Remove any outputs from the combo box that are not in the class.
  1930. //
  1931. char szText[MAX_PATH];
  1932. int nCount = m_ComboOutput.GetCount();
  1933. if (nCount > 0)
  1934. {
  1935. for (int i = nCount - 1; i >= 0; i--)
  1936. {
  1937. if (m_ComboOutput.GetLBText(i, szText) != CB_ERR)
  1938. {
  1939. if (pClass->FindOutput(szText) == NULL)
  1940. {
  1941. m_ComboOutput.DeleteString(i);
  1942. }
  1943. }
  1944. }
  1945. }
  1946. }
  1947. //-----------------------------------------------------------------------------
  1948. // Purpose:
  1949. //-----------------------------------------------------------------------------
  1950. void COP_Output::FilterOutputList(void)
  1951. {
  1952. // dvs: Possibly unnecessary. For example, if they choose an input, then
  1953. // choose an incompatible output, the input will become red to indicate
  1954. // the incompatibilty. So maybe the outputs can always contain the set of
  1955. // all outputs common to the selected entities.
  1956. }
  1957. CMapEntity *COP_Output::GetTargetInstanceIOProxy()
  1958. {
  1959. char szTarget[MAX_ENTITY_NAME_LEN];
  1960. CMapEntityList *pTargets = GetTarget(szTarget, sizeof(szTarget));
  1961. if (pTargets != NULL)
  1962. {
  1963. if ( pTargets->Count() == 1 )
  1964. {
  1965. CMapEntity *pEntity = pTargets->Element( 0 );
  1966. if ( stricmp( pEntity->GetClassName(), "func_instance" ) == 0 )
  1967. {
  1968. CMapInstance *pMapInstance = pEntity->GetChildOfType( ( CMapInstance * )NULL );
  1969. if ( pMapInstance != NULL && pMapInstance->GetInstancedMap() != NULL )
  1970. {
  1971. CMapEntityList entityList;
  1972. pMapInstance->GetInstancedMap()->FindEntitiesByClassName( entityList, "func_instance_io_proxy", false );
  1973. if ( entityList.Count() == 1 )
  1974. {
  1975. return entityList.Element( 0 );
  1976. }
  1977. }
  1978. }
  1979. }
  1980. }
  1981. return NULL;
  1982. }
  1983. //-----------------------------------------------------------------------------
  1984. // Purpose: Filters the list of inputs based on the current selected target.
  1985. //-----------------------------------------------------------------------------
  1986. void COP_Output::FilterInputList(void)
  1987. {
  1988. char szTarget[MAX_ENTITY_NAME_LEN];
  1989. CMapEntityList *pTargets = GetTarget(szTarget, sizeof(szTarget));
  1990. if (pTargets != NULL)
  1991. {
  1992. //
  1993. // Remove all items from the inputs combo that:
  1994. //
  1995. // 1) Are not compatible with the currently selected output, OR
  1996. // 2) Are not found in the currently selected targets list.
  1997. //
  1998. if ( m_bIsInstanceIOProxy == false )
  1999. {
  2000. int nCount = m_ComboInput.GetCount();
  2001. if (nCount > 0)
  2002. {
  2003. for (int i = nCount - 1; i >= 0; i--)
  2004. {
  2005. CClassInput *pInput = (CClassInput *)m_ComboInput.GetItemDataPtr(i);
  2006. if (!MapEntityList_HasInput(pTargets, pInput->GetName(), pInput->GetType()))
  2007. {
  2008. m_ComboInput.DeleteString(i);
  2009. }
  2010. }
  2011. }
  2012. }
  2013. }
  2014. }
  2015. //-----------------------------------------------------------------------------
  2016. // Purpose:
  2017. //-----------------------------------------------------------------------------
  2018. void COP_Output::FilterTargetList(void)
  2019. {
  2020. #if 0 // Not used...
  2021. char szInput[MAX_IO_NAME_LEN];
  2022. CClassInput *pInput = GetInput(szInput, sizeof(szInput));
  2023. //
  2024. // Remove all items from the targets combo that:
  2025. //
  2026. // 1) Do not have the selected input name OR
  2027. // 2) Do not have inputs that are compatible with the selected output.
  2028. //
  2029. int nCount = m_ComboTarget.GetCount();
  2030. if (nCount > 0)
  2031. {
  2032. for (int i = nCount - 1; i >= 0; i--)
  2033. {
  2034. CMapEntityList *pTargets = (CMapEntityList *)m_ComboTarget.GetItemDataPtr(i);
  2035. if (!MapEntityList_HasInput(pTargets, pInput->GetName(), pInput->GetType()))
  2036. {
  2037. m_ComboTarget.DeleteString(i);
  2038. }
  2039. }
  2040. }
  2041. #endif
  2042. }
  2043. //-----------------------------------------------------------------------------
  2044. // Purpose: Returns the currently selected input, NULL if unknown.
  2045. // Input : szInput - Receives the text in the Input combo edit control.
  2046. // nSize - Size of buffer pointed to by szInput.
  2047. //-----------------------------------------------------------------------------
  2048. CClassInput *COP_Output::GetInput(char *szInput, int nSize)
  2049. {
  2050. szInput[0] = '\0';
  2051. int nCurSel = m_ComboInput.GetCurSel();
  2052. if (nCurSel == CB_ERR)
  2053. {
  2054. if (m_ComboInput.GetWindowText(szInput, nSize) > 0)
  2055. {
  2056. nCurSel = m_ComboInput.FindStringExact(-1, szInput);
  2057. }
  2058. }
  2059. CClassInput *pInput = NULL;
  2060. if (nCurSel != CB_ERR)
  2061. {
  2062. m_ComboInput.GetLBText(nCurSel, szInput);
  2063. pInput = (CClassInput *)m_ComboInput.GetItemDataPtr(nCurSel);
  2064. }
  2065. return(pInput);
  2066. }
  2067. //-----------------------------------------------------------------------------
  2068. // Purpose: Returns the currently selected output, NULL if unknown.
  2069. // Input : szOutput - Receives the text in the Output combo edit control.
  2070. // nSize - Size of buffer pointed to by szOutput.
  2071. //-----------------------------------------------------------------------------
  2072. CClassOutput *COP_Output::GetOutput(char *szOutput, int nSize)
  2073. {
  2074. szOutput[0] = '\0';
  2075. int nCurSel = m_ComboOutput.GetCurSel();
  2076. if (nCurSel == CB_ERR)
  2077. {
  2078. if (m_ComboOutput.GetWindowText(szOutput, nSize) > 0)
  2079. {
  2080. nCurSel = m_ComboOutput.FindStringExact(-1, szOutput);
  2081. }
  2082. }
  2083. CClassOutput *pOutput = NULL;
  2084. if (nCurSel != CB_ERR)
  2085. {
  2086. m_ComboOutput.GetLBText(nCurSel, szOutput);
  2087. pOutput = (CClassOutput *)m_ComboOutput.GetItemDataPtr(nCurSel);
  2088. }
  2089. return(pOutput);
  2090. }
  2091. //-----------------------------------------------------------------------------
  2092. // Purpose: Returns the currently selected target list, NULL if unknown.
  2093. // Input : szTarget - Receives the text in the Target combo edit control.
  2094. // nSize - Size of buffer pointed to by szTarget.
  2095. //-----------------------------------------------------------------------------
  2096. CMapEntityList *COP_Output::GetTarget(char *szTarget, int nSize)
  2097. {
  2098. szTarget[0] = '\0';
  2099. CString str = m_ComboTarget.GetCurrentItem();
  2100. Q_strncpy( szTarget, str, nSize );
  2101. return m_ComboTarget.GetSubEntityList( szTarget );
  2102. }
  2103. //-----------------------------------------------------------------------------
  2104. // Purpose: Called when the contents of the delay edit box change.
  2105. //-----------------------------------------------------------------------------
  2106. void COP_Output::OnEditDelay(void)
  2107. {
  2108. UpdateEditedDelays();
  2109. }
  2110. //-----------------------------------------------------------------------------
  2111. // Purpose: Called when the contents of the target combo edit box change.
  2112. //-----------------------------------------------------------------------------
  2113. void COP_Output::OnFireOnce(void)
  2114. {
  2115. UpdateEditedFireOnce();
  2116. }
  2117. //-----------------------------------------------------------------------------
  2118. // Purpose: Called when they change the "Show Hidden Targets" checkbox.
  2119. //-----------------------------------------------------------------------------
  2120. void COP_Output::OnShowHiddenTargetsAsBroken()
  2121. {
  2122. // Remember the last state of this checkbox.
  2123. Options.general.bShowHiddenTargetsAsBroken = (m_ctlShowHiddenTargetsAsBroken.GetCheck() != FALSE);
  2124. // Refresh.
  2125. int nCount = m_ListCtrl.GetItemCount();
  2126. for ( int i=0; i < nCount; i++ )
  2127. {
  2128. UpdateItemValidity( i );
  2129. }
  2130. //UpdateConnectionList();
  2131. }
  2132. //-----------------------------------------------------------------------------
  2133. // Purpose: React to the input combo box being changed
  2134. //-----------------------------------------------------------------------------
  2135. void COP_Output::InputChanged(void)
  2136. {
  2137. // Updating the listbox data, will trigger the edit
  2138. // controls to update. They don't need to be
  2139. bSkipEditControlRefresh = true;
  2140. char szInput[MAX_IO_NAME_LEN];
  2141. CClassInput *pInput = GetInput(szInput, sizeof(szInput));
  2142. UpdateCombosForSelectedInput(pInput);
  2143. UpdateEditedInputs();
  2144. }
  2145. //-----------------------------------------------------------------------------
  2146. // Purpose: Called when selection of input combo box chages
  2147. //-----------------------------------------------------------------------------
  2148. void COP_Output::OnSelChangeInput(void)
  2149. {
  2150. InputChanged();
  2151. }
  2152. //-----------------------------------------------------------------------------
  2153. // Purpose: Called when the contents of the input combo edit box change.
  2154. //-----------------------------------------------------------------------------
  2155. void COP_Output::OnEditUpdateInput(void)
  2156. {
  2157. InputChanged();
  2158. }
  2159. //------------------------------------------------------------------------------
  2160. // Purpose: React to the output combo box being changed
  2161. //------------------------------------------------------------------------------
  2162. void COP_Output::OutputChanged(void)
  2163. {
  2164. // Updating the listbox data, will trigger the edit
  2165. // controls to update. They don't need to be
  2166. bSkipEditControlRefresh = true;
  2167. char szOutput[MAX_IO_NAME_LEN];
  2168. CClassOutput *pOutput = GetOutput(szOutput, sizeof(szOutput));
  2169. UpdateCombosForSelectedOutput(pOutput);
  2170. UpdateEditedOutputs();
  2171. }
  2172. //-----------------------------------------------------------------------------
  2173. // Purpose: Called when selection of output combo box chages
  2174. //-----------------------------------------------------------------------------
  2175. void COP_Output::OnSelChangeOutput(void)
  2176. {
  2177. OutputChanged();
  2178. }
  2179. //-----------------------------------------------------------------------------
  2180. // Purpose: Called when the contents of the output combo edit box change.
  2181. //-----------------------------------------------------------------------------
  2182. void COP_Output::OnEditUpdateOutput(void)
  2183. {
  2184. OutputChanged();
  2185. }
  2186. //-----------------------------------------------------------------------------
  2187. // Purpose: Called when selection of parameter combo box chages
  2188. //-----------------------------------------------------------------------------
  2189. void COP_Output::OnSelChangeParam(void)
  2190. {
  2191. // If user picked <none> selection (the only valid one) clear window text
  2192. CComboBox *pParamEdit = ( CComboBox* )GetDlgItem( IDC_EDIT_CONN_PARAM );
  2193. if (pParamEdit->GetCurSel() != CB_ERR)
  2194. {
  2195. pParamEdit->SetWindowText("");
  2196. }
  2197. UpdateEditedParams();
  2198. }
  2199. //-----------------------------------------------------------------------------
  2200. // Purpose: Called when the contents of the parameter combo edit box change.
  2201. //-----------------------------------------------------------------------------
  2202. void COP_Output::OnEditUpdateParam(void)
  2203. {
  2204. UpdateEditedParams();
  2205. }
  2206. //-----------------------------------------------------------------------------
  2207. // Purpose: Updates the dialog based on the currently selected input.
  2208. // Input : pInput - Pointer to the input that is selected, NULL if none or
  2209. // ambiguous/unresolved.
  2210. //-----------------------------------------------------------------------------
  2211. void COP_Output::UpdateCombosForSelectedInput(CClassInput *pInput)
  2212. {
  2213. // Enable / Disable param box based on input type if allowed
  2214. if (!m_bNoParamEdit)
  2215. {
  2216. CComboBox *pParamCombo = (CComboBox *)GetDlgItem(IDC_EDIT_CONN_PARAM);
  2217. bool bEnable = ((!pInput) || (pInput && (pInput->GetType() != iotVoid)));
  2218. if (!bEnable)
  2219. {
  2220. // Save the param so we can restore it if they switch right back.
  2221. CString strTemp;
  2222. pParamCombo->GetWindowText(strTemp);
  2223. if (strTemp.Compare(PARAM_STRING_NONE))
  2224. {
  2225. m_strLastParam = strTemp;
  2226. }
  2227. // Switch back to <none> if we're disabling the parameter combo.
  2228. pParamCombo->SetCurSel(0);
  2229. }
  2230. else if (!m_strLastParam.IsEmpty())
  2231. {
  2232. pParamCombo->SetWindowText(m_strLastParam);
  2233. }
  2234. UpdateEditedParams();
  2235. pParamCombo->EnableWindow(bEnable);
  2236. m_bEntityParamTarget = pInput && (pInput->GetType() == iotEHandle);
  2237. GetDlgItem(IDC_PICK_ENTITY_PARAM)->EnableWindow( m_bEntityParamTarget );
  2238. }
  2239. if (pInput != NULL)
  2240. {
  2241. //
  2242. // Known input, render it in black.
  2243. //
  2244. m_ComboInput.SetTextColor(RGB(0, 0, 0));
  2245. }
  2246. else
  2247. {
  2248. //
  2249. // Unknown input, render it in red.
  2250. //
  2251. m_ComboInput.SetTextColor(RGB(255, 0, 0));
  2252. }
  2253. m_ComboInput.RedrawWindow();
  2254. }
  2255. //-----------------------------------------------------------------------------
  2256. // Purpose: Updates the dialog based on the currently selected output.
  2257. // Input : pOutput - Pointer to the output that is selected, NULL if none or
  2258. // ambiguous/unresolved.
  2259. //-----------------------------------------------------------------------------
  2260. void COP_Output::UpdateCombosForSelectedOutput(CClassOutput *pOutput)
  2261. {
  2262. if (pOutput != NULL)
  2263. {
  2264. //
  2265. // Known output, render it in black.
  2266. //
  2267. m_ComboOutput.SetTextColor(RGB(0, 0, 0));
  2268. }
  2269. else
  2270. {
  2271. //
  2272. // Unknown output, render it in red.
  2273. //
  2274. m_ComboOutput.SetTextColor(RGB(255, 0, 0));
  2275. }
  2276. m_ComboOutput.RedrawWindow();
  2277. }
  2278. //-----------------------------------------------------------------------------
  2279. // Purpose: Stops entity picking.
  2280. //-----------------------------------------------------------------------------
  2281. void COP_Output::StopPicking(void)
  2282. {
  2283. if (m_bPickingEntities)
  2284. {
  2285. m_bPickingEntities = false;
  2286. ToolManager()->SetTool(TOOL_POINTER);
  2287. CButton *pButton = (CButton *)GetDlgItem(IDC_PICK_ENTITY);
  2288. if (pButton)
  2289. {
  2290. pButton->SetCheck(0);
  2291. }
  2292. pButton = (CButton *)GetDlgItem(IDC_PICK_ENTITY_PARAM);
  2293. if (pButton)
  2294. {
  2295. pButton->SetCheck(0);
  2296. }
  2297. if ( m_ComboTarget.IsWindowEnabled() )
  2298. {
  2299. GetDlgItem(IDC_PICK_ENTITY)->EnableWindow( true );
  2300. }
  2301. CComboBox* pParamEdit = ( CComboBox* )GetDlgItem( IDC_EDIT_CONN_PARAM );
  2302. if ( pParamEdit->IsWindowEnabled() )
  2303. {
  2304. GetDlgItem(IDC_PICK_ENTITY_PARAM)->EnableWindow( m_bEntityParamTarget );
  2305. }
  2306. }
  2307. }
  2308. void COP_Output::OnSize( UINT nType, int cx, int cy )
  2309. {
  2310. m_AnchorMgr.OnSize();
  2311. }