1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "tools/edit_gui_common.h"
30
31
32 #include "qe3.h"
33 #include "Radiant.h"
34 #include "GLWidget.h"
35 #include "PropertyList.h"
36 #include "entitydlg.h"
37 #include "PreviewDlg.h"
38 #include "CurveDlg.h"
39
40 #include "../../renderer/model_local.h" // for idRenderModelPrt
41
42 void Select_Ungroup();
43
44 // CEntityDlg dialog
45
IMPLEMENT_DYNAMIC(CEntityDlg,CDialog)46 IMPLEMENT_DYNAMIC(CEntityDlg, CDialog)
47 CEntityDlg::CEntityDlg(CWnd* pParent /*=NULL*/)
48 : CDialog(CEntityDlg::IDD, pParent)
49 {
50 editEntity = NULL;
51 multipleEntities = false;
52 currentAnimation = NULL;
53 }
54
~CEntityDlg()55 CEntityDlg::~CEntityDlg()
56 {
57 }
58
DoDataExchange(CDataExchange * pDX)59 void CEntityDlg::DoDataExchange(CDataExchange* pDX)
60 {
61 CDialog::DoDataExchange(pDX);
62 DDX_Control(pDX, IDC_LIST_KEYVAL, listKeyVal);
63 DDX_Control(pDX, IDC_COMBO_CLASS, comboClass);
64 DDX_Control(pDX, IDC_EDIT_KEY, editKey);
65 DDX_Control(pDX, IDC_EDIT_VAL, editVal);
66 DDX_Control(pDX, IDC_STATIC_TITLE, staticTitle);
67 DDX_Control(pDX, IDC_STATIC_KEY, staticKey);
68 DDX_Control(pDX, IDC_STATIC_VAL, staticVal);
69 DDX_Control(pDX, IDC_BUTTON_BROWSE, btnBrowse);
70 DDX_Control(pDX, IDC_E_135, btn135);
71 DDX_Control(pDX, IDC_E_90, btn90);
72 DDX_Control(pDX, IDC_E_45, btn45);
73 DDX_Control(pDX, IDC_E_180, btn180);
74 DDX_Control(pDX, IDC_E_0, btn360);
75 DDX_Control(pDX, IDC_E_225, btn225);
76 DDX_Control(pDX, IDC_E_270, btn270);
77 DDX_Control(pDX, IDC_E_315, btn315);
78 DDX_Control(pDX, IDC_E_UP, btnUp);
79 DDX_Control(pDX, IDC_E_DOWN, btnDown);
80 DDX_Control(pDX, IDC_BUTTON_MODEL, btnModel);
81 DDX_Control(pDX, IDC_BUTTON_SOUND, btnSound);
82 DDX_Control(pDX, IDC_BUTTON_GUI, btnGui);
83 DDX_Control(pDX, IDC_BUTTON_PARTICLE, btnParticle);
84 DDX_Control(pDX, IDC_BUTTON_SKIN, btnSkin);
85 DDX_Control(pDX, IDC_BUTTON_CURVE, btnCurve);
86 DDX_Control(pDX, IDC_BUTTON_CREATE, btnCreate);
87 DDX_Control(pDX, IDC_LIST_VARS, listVars);
88 DDX_Control(pDX, IDC_ENTITY_ANIMATIONS , cbAnimations);
89 DDX_Control(pDX, IDC_ANIMATION_SLIDER , slFrameSlider);
90 DDX_Control(pDX, IDC_ENTITY_CURRENT_ANIM , staticFrame);
91 DDX_Control(pDX, IDC_ENTITY_PLAY_ANIM , btnPlayAnim);
92 DDX_Control(pDX, IDC_ENTITY_STOP_ANIM , btnStopAnim);
93 }
94
95
96
OnInitDialog()97 BOOL CEntityDlg::OnInitDialog()
98 {
99 CDialog::OnInitDialog();
100 listKeyVal.SetUpdateInspectors(true);
101 listKeyVal.SetDivider(100);
102 listVars.SetDivider(100);
103 staticFrame.SetWindowText ( "0" );
104
105 return TRUE; // return TRUE unless you set the focus to a control
106 // EXCEPTION: OCX Property Pages should return FALSE
107 }
108
OnToolHitTest(CPoint point,TOOLINFO * pTI) const109 int CEntityDlg::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
110 {
111 // TODO: Add your specialized code here and/or call the base class
112
113 return CDialog::OnToolHitTest(point, pTI);
114 }
115
116
AddClassNames()117 void CEntityDlg::AddClassNames() {
118 comboClass.ResetContent();
119 for (eclass_t *pec = eclass; pec; pec = pec->next) {
120 comboClass.AddString(pec->name);
121 }
122
123 }
124
BEGIN_MESSAGE_MAP(CEntityDlg,CDialog)125 BEGIN_MESSAGE_MAP(CEntityDlg, CDialog)
126 ON_WM_SIZE()
127 ON_CBN_SELCHANGE(IDC_COMBO_CLASS, OnCbnSelchangeComboClass)
128 ON_LBN_SELCHANGE(IDC_LIST_KEYVAL, OnLbnSelchangeListkeyval)
129 ON_BN_CLICKED(IDC_E_135, OnBnClickedE135)
130 ON_BN_CLICKED(IDC_E_90, OnBnClickedE90)
131 ON_BN_CLICKED(IDC_E_45, OnBnClickedE45)
132 ON_BN_CLICKED(IDC_E_180, OnBnClickedE180)
133 ON_BN_CLICKED(IDC_E_0, OnBnClickedE0)
134 ON_BN_CLICKED(IDC_E_225, OnBnClickedE225)
135 ON_BN_CLICKED(IDC_E_270, OnBnClickedE270)
136 ON_BN_CLICKED(IDC_E_315, OnBnClickedE315)
137 ON_BN_CLICKED(IDC_E_UP, OnBnClickedEUp)
138 ON_BN_CLICKED(IDC_E_DOWN, OnBnClickedEDown)
139 ON_BN_CLICKED(IDC_BUTTON_MODEL, OnBnClickedButtonModel)
140 ON_BN_CLICKED(IDC_BUTTON_SOUND, OnBnClickedButtonSound)
141 ON_BN_CLICKED(IDC_BUTTON_GUI, OnBnClickedButtonGui)
142 ON_BN_CLICKED(IDC_BUTTON_BROWSE, OnBnClickedButtonBrowse)
143 ON_CBN_DBLCLK(IDC_COMBO_CLASS, OnCbnDblclkComboClass)
144 ON_BN_CLICKED(IDC_BUTTON_CREATE, OnBnClickedButtonCreate)
145 ON_LBN_DBLCLK(IDC_LIST_KEYVAL, OnLbnDblclkListkeyval)
146 ON_LBN_SELCHANGE(IDC_LIST_VARS, OnLbnSelchangeListVars)
147 ON_LBN_DBLCLK(IDC_LIST_VARS, OnLbnDblclkListVars)
148 ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_ANIMATION_SLIDER, OnNMReleasedcaptureSlider1)
149 ON_BN_CLICKED(IDC_BUTTON_PARTICLE, OnBnClickedButtonParticle)
150 ON_BN_CLICKED(IDC_BUTTON_SKIN, OnBnClickedButtonSkin)
151 ON_BN_CLICKED(IDC_BUTTON_CURVE, OnBnClickedButtonCurve)
152 ON_CBN_SELCHANGE(IDC_ENTITY_ANIMATIONS, OnCbnAnimationChange)
153 ON_BN_CLICKED(IDC_ENTITY_PLAY_ANIM , OnBnClickedStartAnimation)
154 ON_BN_CLICKED(IDC_ENTITY_STOP_ANIM , OnBnClickedStopAnimation)
155 ON_WM_TIMER()
156 ON_BN_CLICKED(IDOK, OnOK)
157 END_MESSAGE_MAP()
158
159 void CEntityDlg::OnSize(UINT nType, int cx, int cy)
160 {
161 if (staticTitle.GetSafeHwnd() == NULL) {
162 return;
163 }
164 CDialog::OnSize(nType, cx, cy);
165 CRect rect, crect, crect2;
166 GetClientRect(rect);
167 int bh = (float)rect.Height() * (rect.Height() - 210) / rect.Height() / 2;
168 staticTitle.GetWindowRect(crect);
169 staticTitle.SetWindowPos(NULL, 4, 4, rect.Width() -8, crect.Height(), SWP_SHOWWINDOW);
170 int top = 4 + crect.Height() + 4;
171 comboClass.GetWindowRect(crect);
172 btnCreate.GetWindowRect(crect2);
173 comboClass.SetWindowPos(NULL, 4, top, rect.Width() - 12 - crect2.Width(), crect.Height(), SWP_SHOWWINDOW);
174 btnCreate.SetWindowPos(NULL, rect.Width() - crect2.Width() - 4, top, crect2.Width(), crect.Height(), SWP_SHOWWINDOW);
175 top += crect.Height() + 4;
176 listVars.SetWindowPos(NULL, 4, top, rect.Width() - 8, bh, SWP_SHOWWINDOW);
177 top += bh + 4;
178 listKeyVal.SetWindowPos(NULL, 4, top, rect.Width() - 8, bh, SWP_SHOWWINDOW);
179 top += bh + 4;
180 staticKey.GetWindowRect(crect);
181 staticKey.SetWindowPos(NULL, 4, top + 2, crect.Width(), crect.Height(), SWP_SHOWWINDOW);
182 int left = 4 + crect.Width() + 4;
183 int pad = crect.Width();
184 editKey.GetWindowRect(crect);
185 editKey.SetWindowPos(NULL, left, top, rect.Width() - 12 - pad, crect.Height(), SWP_SHOWWINDOW);
186 top += crect.Height() + 4;
187 staticVal.GetWindowRect(crect);
188 staticVal.SetWindowPos(NULL, 4, top + 2, crect.Width(), crect.Height(), SWP_SHOWWINDOW);
189 editVal.GetWindowRect(crect);
190 bh = crect.Height();
191 editVal.SetWindowPos(NULL, left, top, rect.Width() - 16 - bh - pad, crect.Height(), SWP_SHOWWINDOW);
192 btnBrowse.SetWindowPos(NULL, rect.right - 4 - bh, top, bh, bh, SWP_SHOWWINDOW);
193 top += crect.Height() + 8;
194 btnModel.GetWindowRect(crect);
195 btnModel.SetWindowPos(NULL, rect.right - 4 - crect.Width(), top + 8, crect.Width(), crect.Height(), SWP_SHOWWINDOW);
196 btnSound.SetWindowPos(NULL, rect.right - 4 - crect.Width(), top + 12 + crect.Height(), crect.Width(), crect.Height(), SWP_SHOWWINDOW);
197 btnGui.SetWindowPos(NULL, rect.right - 4 - crect.Width(), top + 16 + crect.Height() * 2, crect.Width(), crect.Height(), SWP_SHOWWINDOW);
198 btnParticle.SetWindowPos(NULL, rect.right - 8 - (crect.Width() * 2), top + 16 + crect.Height() * 2, crect.Width(), crect.Height(), SWP_SHOWWINDOW);
199 btnSkin.SetWindowPos( NULL, rect.right - 8 - ( crect.Width() * 2 ), top + 12 + crect.Height(), crect.Width(), crect.Height(), SWP_SHOWWINDOW );
200 btnCurve.SetWindowPos( NULL, rect.right - 8 - ( crect.Width() * 2 ), top + 8, crect.Width(), crect.Height(), SWP_SHOWWINDOW );
201
202 //*************************************
203 //animation controls
204 //*************************************
205 int rightAnimAreaBorder = rect.right - 75 - crect.Width (); /*models, etc button width*/
206
207 btnStopAnim.GetWindowRect(crect);
208 btnStopAnim.SetWindowPos(NULL,rightAnimAreaBorder - crect.Width (),
209 top + 8 ,crect.Width(),crect.Height(),SWP_SHOWWINDOW);
210
211 left = rightAnimAreaBorder - crect.Width() - 4;
212 btnPlayAnim.GetWindowRect(crect);
213 btnPlayAnim.SetWindowPos(NULL,left-crect.Width () ,top + 8 , crect.Width(),crect.Height(),SWP_SHOWWINDOW);
214
215 left -= crect.Width() + 4;
216 cbAnimations.GetWindowRect(crect);
217 cbAnimations.SetWindowPos(NULL,left-crect.Width (),top + 8 ,crect.Width(),crect.Height(),SWP_SHOWWINDOW);
218
219 staticFrame.GetWindowRect(crect);
220 staticFrame.SetWindowPos(NULL,rightAnimAreaBorder - crect.Width (),
221 top + 34 ,crect.Width(),crect.Height(),SWP_SHOWWINDOW);
222
223 left = rightAnimAreaBorder - crect.Width () - 4;
224
225 slFrameSlider.GetWindowRect(crect);
226 slFrameSlider.SetWindowPos(NULL,left - crect.Width (),
227 top + 32 ,crect.Width(),crect.Height(),SWP_SHOWWINDOW);
228
229 //*************************************
230 //*************************************
231
232 btn135.GetWindowRect(crect);
233 bh = crect.Width();
234 btn135.SetWindowPos(NULL, 4, top, bh, bh, SWP_SHOWWINDOW);
235 btn90.SetWindowPos(NULL, 4 + 2 + bh, top, bh, bh, SWP_SHOWWINDOW);
236 btn45.SetWindowPos(NULL, 4 + 2 + 2 + bh * 2, top, bh, bh, SWP_SHOWWINDOW);
237 btnUp.SetWindowPos(NULL, 4 + 2 + 2 + 6 + bh * 3, top + bh / 2,bh,bh, SWP_SHOWWINDOW);
238 btnDown.SetWindowPos(NULL, 4 + 2 + 2 + 6 + bh *3, top + bh / 2 + bh + 2,bh,bh, SWP_SHOWWINDOW);
239 top += bh + 2;
240 btn180.SetWindowPos(NULL, 4, top, bh, bh, SWP_SHOWWINDOW);
241 btn360.SetWindowPos(NULL, 4 + 2 + 2 + bh * 2, top, bh, bh, SWP_SHOWWINDOW);
242 top += bh + 2;
243 btn225.SetWindowPos(NULL, 4, top, bh, bh, SWP_SHOWWINDOW);
244 btn270.SetWindowPos(NULL, 4 + 2 + bh, top, bh, bh, SWP_SHOWWINDOW);
245 btn315.SetWindowPos(NULL, 4 + 2 + 2 + bh * 2, top, bh, bh, SWP_SHOWWINDOW);
246 Invalidate();
247 }
248
OnCbnSelchangeComboClass()249 void CEntityDlg::OnCbnSelchangeComboClass()
250 {
251 int index = comboClass.GetCurSel();
252 if (index != LB_ERR) {
253 CString str;
254 comboClass.GetLBText(index, str);
255 eclass_t *ent = Eclass_ForName (str, false);
256 if (ent) {
257 if (selected_brushes.next == &selected_brushes) {
258 editEntity = world_entity;
259 multipleEntities = false;
260 } else {
261 editEntity = selected_brushes.next->owner;
262 for (brush_t *b = selected_brushes.next->next; b != &selected_brushes; b = b->next) {
263 if (b->owner != editEntity) {
264 multipleEntities = true;
265 break;
266 }
267 }
268 }
269 listVars.ResetContent();
270 CPropertyItem *pi = new CPropertyItem("Usage:", ent->desc.c_str(), PIT_VAR, "");
271 listVars.AddPropItem(pi);
272
273 int c = ent->vars.Num();
274 for (int i = 0; i < c; i++) {
275 pi = new CPropertyItem(ent->vars[i].name.c_str(), ent->vars[i].desc.c_str(), PIT_VAR, "");
276 pi->SetData(ent->vars[i].type);
277 listVars.AddPropItem(pi);
278 }
279 listVars.Invalidate();
280 SetKeyValPairs();
281 }
282 }
283 }
284
TranslateString(const char * buf)285 const char *CEntityDlg::TranslateString(const char *buf) {
286 static char buf2[32768];
287 int i, l;
288 char *out;
289
290 l = strlen(buf);
291 out = buf2;
292 for (i = 0; i < l; i++) {
293 if (buf[i] == '\n') {
294 *out++ = '\r';
295 *out++ = '\n';
296 }
297 else {
298 *out++ = buf[i];
299 }
300 }
301
302 *out++ = 0;
303
304 return buf2;
305
306 }
307
UpdateFromListBox()308 void CEntityDlg::UpdateFromListBox() {
309 if (editEntity == NULL) {
310 return;
311 }
312 int c = listKeyVal.GetCount();
313 for (int i = 0 ; i < c; i++) {
314 CPropertyItem* pItem = (CPropertyItem*)listKeyVal.GetItemDataPtr(i);
315 if (pItem) {
316 editEntity->epairs.Set(pItem->m_propName, pItem->m_curValue);
317 }
318 }
319 SetKeyValPairs();
320 }
321
SetKeyValPairs(bool updateAnims)322 void CEntityDlg::SetKeyValPairs( bool updateAnims ) {
323 if (editEntity) {
324 listKeyVal.ResetContent();
325 int c = editEntity->epairs.GetNumKeyVals();
326 for (int i = 0; i < c; i++) {
327 const idKeyValue *kv = editEntity->epairs.GetKeyVal(i);
328 CPropertyItem *pi = new CPropertyItem(kv->GetKey().c_str(), kv->GetValue().c_str(), PIT_EDIT, "");
329 bool found = false;
330 int vc = editEntity->eclass->vars.Num();
331 for (int j = 0; j < vc; j++) {
332 if (editEntity->eclass->vars[j].name.Icmp(kv->GetKey()) == 0) {
333 switch (editEntity->eclass->vars[j].type) {
334 case EVAR_STRING :
335 case EVAR_INT :
336 case EVAR_FLOAT :
337 pi->m_nItemType = PIT_EDIT;
338 break;
339 case EVAR_BOOL :
340 pi->m_nItemType = PIT_EDIT;
341 //pi->m_cmbItems = "0|1";
342 break;
343 case EVAR_COLOR :
344 pi->m_nItemType = PIT_COLOR;
345 break;
346 case EVAR_MATERIAL :
347 pi->m_nItemType = PIT_MATERIAL;
348 break;
349 case EVAR_MODEL :
350 pi->m_nItemType = PIT_MODEL;
351 break;
352 case EVAR_GUI :
353 pi->m_nItemType = PIT_GUI;
354 break;
355 case EVAR_SOUND :
356 pi->m_nItemType = PIT_SOUND;
357 break;
358 }
359 found = true;
360 break;
361 }
362 }
363 if (!found) {
364 if (kv->GetKey().Icmp("model") == 0) {
365 pi->m_nItemType = PIT_MODEL;
366 }
367 if (kv->GetKey().Icmp("_color") == 0) {
368 pi->m_nItemType = PIT_COLOR;
369 }
370 if (kv->GetKey().Icmp("gui") == 0) {
371 pi->m_nItemType = PIT_GUI;
372 }
373 if (kv->GetKey().Icmp("gui2") == 0) {
374 pi->m_nItemType = PIT_GUI;
375 }
376 if (kv->GetKey().Icmp("gui3") == 0) {
377 pi->m_nItemType = PIT_GUI;
378 }
379 if (kv->GetKey().Icmp("s_shader") == 0) {
380 pi->m_nItemType = PIT_SOUND;
381 }
382 }
383 listKeyVal.AddPropItem(pi);
384 }
385
386 if ( updateAnims ) {
387 int i, num;
388
389 cbAnimations.ResetContent();
390 num = gameEdit->ANIM_GetNumAnimsFromEntityDef( &editEntity->eclass->defArgs );
391 for( i = 0; i < num; i++ ) {
392 cbAnimations.AddString( gameEdit->ANIM_GetAnimNameFromEntityDef( &editEntity->eclass->defArgs, i ) );
393 }
394
395 const idKeyValue* kv = editEntity->epairs.FindKey ( "anim" );
396 if ( kv ) {
397 int selIndex = cbAnimations.FindStringExact( 0 , kv->GetValue().c_str() );
398 if ( selIndex != -1 ) {
399 cbAnimations.SetCurSel( selIndex );
400 OnCbnAnimationChange ();
401 }
402 }
403 }
404 }
405 }
406
UpdateEntitySel(eclass_t * ent)407 void CEntityDlg::UpdateEntitySel(eclass_t *ent) {
408 assert ( ent );
409 assert ( ent->name );
410 int index = comboClass.FindString(-1, ent->name);
411 if (index != LB_ERR) {
412 comboClass.SetCurSel(index);
413 OnCbnSelchangeComboClass();
414 }
415 }
416
OnLbnSelchangeListkeyval()417 void CEntityDlg::OnLbnSelchangeListkeyval()
418 {
419 int index = listKeyVal.GetCurSel();
420 if (index != LB_ERR) {
421 CString str;
422 listKeyVal.GetText(index, str);
423 int i;
424 for (i = 0; str[i] != '\t' && str[i] != '\0'; i++) {
425 }
426
427 idStr key = str.Left(i);
428 while (str[i] == '\t' && str[i] != '\0') {
429 i++;
430 }
431
432 idStr val = str.Right(str.GetLength() - i);
433
434 editKey.SetWindowText(key);
435 editVal.SetWindowText(val);
436 }
437 }
438
439 static int TabOrder[] = {
440 IDC_COMBO_CLASS,
441 IDC_BUTTON_CREATE,
442 //IDC_EDIT_INFO,
443 IDC_LIST_KEYVAL,
444 IDC_EDIT_KEY,
445 IDC_EDIT_VAL,
446 IDC_BUTTON_BROWSE,
447 IDC_E_135,
448 IDC_E_90,
449 IDC_E_45,
450 IDC_E_180,
451 IDC_E_0,
452 IDC_E_225,
453 IDC_E_270,
454 IDC_E_315,
455 IDC_E_UP,
456 IDC_E_DOWN,
457 IDC_BUTTON_MODEL,
458 IDC_BUTTON_SOUND,
459 IDC_BUTTON_GUI,
460 IDC_ENTITY_ANIMATIONS
461 };
462
463 int TabCount = sizeof(TabOrder) / sizeof(int);
464
DelProp()465 void CEntityDlg::DelProp() {
466 CString key;
467
468 if (editEntity == NULL) {
469 return;
470 }
471
472 editKey.GetWindowText(key);
473 if (multipleEntities) {
474 for (brush_t *b = selected_brushes.next; b != &selected_brushes; b = b->next) {
475 DeleteKey(b->owner, key);
476 Entity_UpdateCurveData( b->owner );
477 }
478 } else {
479 DeleteKey(editEntity, key);
480 Entity_UpdateCurveData( editEntity );
481 }
482
483 // refresh the prop listbox
484 SetKeyValPairs();
485 Sys_UpdateWindows( W_ENTITY | W_XY | W_CAMERA );
486 }
487
488
PreTranslateMessage(MSG * pMsg)489 BOOL CEntityDlg::PreTranslateMessage(MSG* pMsg)
490 {
491
492 if (pMsg->hwnd == editVal.GetSafeHwnd()) {
493 if (pMsg->message == WM_LBUTTONDOWN) {
494 editVal.SetFocus();
495 return TRUE;
496 }
497 }
498
499 if (pMsg->hwnd == editKey.GetSafeHwnd()) {
500 if (pMsg->message == WM_LBUTTONDOWN) {
501 editKey.SetFocus();
502 return TRUE;
503 }
504 }
505
506 if (GetFocus() == &editVal || GetFocus() == &editKey) {
507 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN ) {
508 AddProp();
509 return TRUE;
510 }
511
512 }
513
514 if (GetFocus() == listKeyVal.GetEditBox()) {
515 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN ) {
516 listKeyVal.OnChangeEditBox();
517 listKeyVal.OnSelchange();
518 listKeyVal.OnKillfocusEditBox();
519 AddProp();
520 SetKeyValPairs();
521 return TRUE;
522 }
523 }
524
525 if (GetFocus() == &listKeyVal) {
526 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_DELETE && editEntity) {
527 DelProp();
528 return TRUE;
529 }
530 }
531
532 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) {
533 if (pMsg->wParam == VK_ESCAPE) {
534 g_pParentWnd->GetCamera()->SetFocus();
535 Select_Deselect();
536 }
537 return TRUE;
538 }
539
540 if ( pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN ) {
541 // keeps ENTER from closing the dialog
542 return TRUE;
543 }
544
545 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB) {
546 if (GetFocus()) {
547 int id = GetFocus()->GetDlgCtrlID();
548 for (int i = 0; i < TabCount; i++) {
549 if (TabOrder[i] == id) {
550 i++;
551 if (i >= TabCount) {
552 i = 0;
553 }
554 CWnd *next = GetDlgItem(TabOrder[i]);
555 if (next) {
556 next->SetFocus();
557 if (TabOrder[i] == IDC_EDIT_VAL) {
558 editVal.SetSel(0, -1);
559 }
560 return TRUE;
561 }
562 }
563 }
564 }
565 }
566
567 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RIGHT && pMsg->hwnd == slFrameSlider.GetSafeHwnd()) {
568 int pos = slFrameSlider.GetPos() + 1;
569 pos = (pos % slFrameSlider.GetRangeMax());
570 slFrameSlider.SetPos ( pos );
571 UpdateFromAnimationFrame ();
572 return TRUE;
573 }
574
575 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_LEFT && pMsg->hwnd == slFrameSlider.GetSafeHwnd()) {
576 int pos = slFrameSlider.GetPos() - 1;
577
578 if ( pos < 1 ) {
579 pos = slFrameSlider.GetRangeMax();
580 }
581
582 slFrameSlider.SetPos ( pos );
583 UpdateFromAnimationFrame ();
584 return TRUE;
585 }
586
587 return CDialog::PreTranslateMessage(pMsg);
588 }
589
590
591 /*
592 =======================================================================================================================
593 AddProp
594 =======================================================================================================================
595 */
AddProp()596 void CEntityDlg::AddProp() {
597
598 if (editEntity == NULL) {
599 return;
600 }
601
602 CString Key, Value;
603 editKey.GetWindowText(Key);
604 editVal.GetWindowText(Value);
605
606 bool isName = (stricmp(Key, "name") == 0);
607 bool isModel = static_cast<bool>((stricmp(Key, "model") == 0 && Value.GetLength() > 0));
608 bool isOrigin = ( idStr::Icmp( Key, "origin" ) == 0 );
609
610 if (multipleEntities) {
611 brush_t *b;
612 for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
613 if (isName) {
614 Entity_SetName(b->owner, Value);
615 } else {
616 if ( ! ( ( isModel || isOrigin ) && ( b->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN ) ) ) {
617 SetKeyValue(b->owner, Key, Value);
618 }
619 }
620 }
621 }
622 else {
623 if (isName) {
624 Entity_SetName(editEntity, Value);
625 } else {
626 if ( ! ( ( isModel || isOrigin ) && ( editEntity->eclass->nShowFlags & ECLASS_WORLDSPAWN ) ) ) {
627 SetKeyValue(editEntity, Key, Value);
628 }
629 }
630
631 if ( isModel && !( editEntity->eclass->nShowFlags & ECLASS_WORLDSPAWN ) ) {
632 idBounds bo;
633 idVec3 mins, maxs;
634
635 selected_brushes.next->modelHandle = renderModelManager->FindModel( Value );
636 if ( dynamic_cast<idRenderModelPrt*>( selected_brushes.next->modelHandle ) || dynamic_cast<idRenderModelLiquid*>( selected_brushes.next->modelHandle ) ) {
637 bo.Zero();
638 bo.ExpandSelf( 12.0f );
639 } else {
640 bo = selected_brushes.next->modelHandle->Bounds( NULL );
641 }
642
643 VectorCopy(bo[0], mins);
644 VectorCopy(bo[1], maxs);
645 VectorAdd(mins, editEntity->origin, mins);
646 VectorAdd(maxs, editEntity->origin, maxs);
647 Brush_RebuildBrush(selected_brushes.next, mins, maxs, false);
648 Brush_Build ( selected_brushes.next , false, false , false, true );
649 }
650 }
651
652 // refresh the prop listbox
653 SetKeyValPairs();
654 Sys_UpdateWindows(W_ALL);
655
656 }
657
AngleKey()658 const char *CEntityDlg::AngleKey() {
659 if (editEntity == NULL) {
660 return "";
661 }
662
663 if (editEntity->eclass->nShowFlags & ECLASS_MOVER) {
664 return "movedir";
665 }
666
667 return "angle";
668 }
669
670
OnBnClickedE135()671 void CEntityDlg::OnBnClickedE135()
672 {
673 if (editEntity == NULL) {
674 return;
675 }
676 editKey.SetWindowText(AngleKey());
677 editVal.SetWindowText("135");
678 AddProp();
679 }
680
OnBnClickedE90()681 void CEntityDlg::OnBnClickedE90()
682 {
683 if (editEntity == NULL) {
684 return;
685 }
686 editKey.SetWindowText(AngleKey());
687 editVal.SetWindowText("90");
688 AddProp();
689 }
690
OnBnClickedE45()691 void CEntityDlg::OnBnClickedE45()
692 {
693 if (editEntity == NULL) {
694 return;
695 }
696 editKey.SetWindowText(AngleKey());
697 editVal.SetWindowText("45");
698 AddProp();
699 }
700
OnBnClickedE180()701 void CEntityDlg::OnBnClickedE180()
702 {
703 if (editEntity == NULL) {
704 return;
705 }
706 editKey.SetWindowText(AngleKey());
707 editVal.SetWindowText("180");
708 AddProp();
709 }
710
OnBnClickedE0()711 void CEntityDlg::OnBnClickedE0()
712 {
713 if (editEntity == NULL) {
714 return;
715 }
716 editKey.SetWindowText(AngleKey());
717 editVal.SetWindowText("0");
718 AddProp();
719 }
720
OnBnClickedE225()721 void CEntityDlg::OnBnClickedE225()
722 {
723 if (editEntity == NULL) {
724 return;
725 }
726 editKey.SetWindowText(AngleKey());
727 editVal.SetWindowText("225");
728 AddProp();
729 }
730
OnBnClickedE270()731 void CEntityDlg::OnBnClickedE270()
732 {
733 if (editEntity == NULL) {
734 return;
735 }
736 editKey.SetWindowText(AngleKey());
737 editVal.SetWindowText("270");
738 AddProp();
739 }
740
OnBnClickedE315()741 void CEntityDlg::OnBnClickedE315()
742 {
743 if (editEntity == NULL) {
744 return;
745 }
746 editKey.SetWindowText(AngleKey());
747 editVal.SetWindowText("315");
748 AddProp();
749 }
750
OnBnClickedEUp()751 void CEntityDlg::OnBnClickedEUp()
752 {
753 if (editEntity == NULL) {
754 return;
755 }
756 editKey.SetWindowText(AngleKey());
757 editVal.SetWindowText("-1");
758 AddProp();
759 }
760
OnBnClickedEDown()761 void CEntityDlg::OnBnClickedEDown()
762 {
763 if (editEntity == NULL) {
764 return;
765 }
766 editKey.SetWindowText(AngleKey());
767 editVal.SetWindowText("-2");
768 AddProp();
769 }
770
ShowModelChooser()771 CPreviewDlg *CEntityDlg::ShowModelChooser() {
772 static CPreviewDlg modelDlg;
773 modelDlg.SetMode(CPreviewDlg::MODELS);
774 modelDlg.SetModal();
775 if (modelDlg.GetSafeHwnd() == NULL) {
776 modelDlg.Create(MAKEINTRESOURCE(IDD_DIALOG_PREVIEW));
777 }
778 modelDlg.ShowWindow( SW_SHOW );
779 modelDlg.BringWindowToTop();
780 while (modelDlg.Waiting()) {
781 }
782 return &modelDlg;
783 }
784
ShowParticleChooser()785 CPreviewDlg *CEntityDlg::ShowParticleChooser() {
786 static CPreviewDlg modelDlg;
787 modelDlg.SetMode(CPreviewDlg::PARTICLES);
788 modelDlg.SetModal();
789 if (modelDlg.GetSafeHwnd() == NULL) {
790 modelDlg.Create(MAKEINTRESOURCE(IDD_DIALOG_PREVIEW));
791 }
792 modelDlg.ShowWindow(SW_SHOW);
793 modelDlg.BringWindowToTop();
794 while (modelDlg.Waiting()) {
795 }
796 return &modelDlg;
797 }
798
ShowSkinChooser(entity_t * ent)799 CPreviewDlg *CEntityDlg::ShowSkinChooser(entity_t *ent) {
800 static CPreviewDlg modelDlg;
801 modelDlg.SetMode(CPreviewDlg::SKINS);
802 modelDlg.SetModal();
803 if (modelDlg.GetSafeHwnd() == NULL) {
804 modelDlg.Create(MAKEINTRESOURCE(IDD_DIALOG_PREVIEW));
805 }
806 modelDlg.RebuildTree( ( ent ) ? ent->epairs.GetString( "model" ) : "" );
807 modelDlg.ShowWindow(SW_SHOW);
808 modelDlg.BringWindowToTop();
809 while (modelDlg.Waiting()) {
810 }
811 return &modelDlg;
812 }
813
ShowGuiChooser()814 CPreviewDlg *CEntityDlg::ShowGuiChooser() {
815 static CPreviewDlg guiDlg;
816 guiDlg.SetMode(CPreviewDlg::GUIS);
817 guiDlg.SetModal();
818 if (guiDlg.GetSafeHwnd() == NULL) {
819 guiDlg.Create(MAKEINTRESOURCE(IDD_DIALOG_PREVIEW));
820 }
821 guiDlg.ShowWindow(SW_SHOW);
822 guiDlg.BringWindowToTop();
823 while (guiDlg.Waiting()) {
824 }
825 return &guiDlg;
826 }
827
ShowSoundChooser()828 CPreviewDlg *CEntityDlg::ShowSoundChooser() {
829 static CPreviewDlg soundDlg;
830 soundDlg.SetMode(CPreviewDlg::SOUNDS);
831 soundDlg.SetModal();
832 if (soundDlg.GetSafeHwnd() == NULL) {
833 soundDlg.Create(MAKEINTRESOURCE(IDD_DIALOG_PREVIEW));
834 }
835 soundDlg.ShowWindow(SW_SHOW);
836 while (soundDlg.Waiting()) {
837 }
838 return &soundDlg;
839 }
840
ShowMaterialChooser()841 CPreviewDlg *CEntityDlg::ShowMaterialChooser() {
842 static CPreviewDlg matDlg;
843 matDlg.SetMode(CPreviewDlg::MATERIALS);
844 matDlg.SetModal();
845 if (matDlg.GetSafeHwnd() == NULL) {
846 matDlg.Create(MAKEINTRESOURCE(IDD_DIALOG_PREVIEW));
847 }
848 matDlg.ShowWindow(SW_SHOW);
849 matDlg.BringWindowToTop();
850 while (matDlg.Waiting()) {
851 }
852 return &matDlg;
853 }
854
AssignModel()855 void CEntityDlg::AssignModel ()
856 {
857 OnBnClickedButtonModel();
858 }
OnBnClickedButtonModel()859 void CEntityDlg::OnBnClickedButtonModel() {
860 CPreviewDlg *dlg = ShowModelChooser();
861 if (dlg->returnCode == IDOK) {
862 editKey.SetWindowText("model");
863 editVal.SetWindowText(dlg->mediaName);
864 AddProp();
865 }
866 }
867
OnBnClickedButtonSound()868 void CEntityDlg::OnBnClickedButtonSound() {
869 CPreviewDlg *dlg = ShowSoundChooser();
870 if (dlg->returnCode == IDOK) {
871 editKey.SetWindowText("s_shader");
872 editVal.SetWindowText(dlg->mediaName);
873 AddProp();
874 }
875 }
876
OnBnClickedButtonGui()877 void CEntityDlg::OnBnClickedButtonGui() {
878 CPreviewDlg *dlg = ShowGuiChooser();
879 if (dlg->returnCode == IDOK) {
880 editKey.SetWindowText("gui");
881 editVal.SetWindowText(dlg->mediaName);
882 AddProp();
883 }
884 }
885
OnBnClickedButtonParticle()886 void CEntityDlg::OnBnClickedButtonParticle() {
887 CPreviewDlg *dlg = ShowParticleChooser();
888 if (dlg->returnCode == IDOK) {
889 editKey.SetWindowText("model");
890 editVal.SetWindowText(dlg->mediaName);
891 AddProp();
892 }
893 }
894
OnBnClickedButtonSkin()895 void CEntityDlg::OnBnClickedButtonSkin() {
896 CPreviewDlg *dlg = ShowSkinChooser( editEntity );
897 if (dlg->returnCode == IDOK) {
898 editKey.SetWindowText("skin");
899 editVal.SetWindowText(dlg->mediaName);
900 AddProp();
901 }
902
903 }
904
OnBnClickedButtonCurve()905 void CEntityDlg::OnBnClickedButtonCurve() {
906 CCurveDlg dlg;
907 if ( dlg.DoModal() == IDOK ) {
908 if ( editEntity ) {
909 idStr str = "curve_" + dlg.strCurveType;
910 editKey.SetWindowText( str );
911 idVec3 org = editEntity->origin;
912 str = "3 ( ";
913 str += org.ToString();
914 org.x += 64;
915 str += " ";
916 str += org.ToString();
917 org.y += 64;
918 str += " ";
919 str += org.ToString();
920 str += " )";
921 editVal.SetWindowText( str );
922 AddProp();
923 Entity_SetCurveData( editEntity );
924 }
925 }
926 }
927
OnBnClickedButtonBrowse()928 void CEntityDlg::OnBnClickedButtonBrowse() {
929 DelProp();
930 }
931
OnCbnDblclkComboClass()932 void CEntityDlg::OnCbnDblclkComboClass()
933 {
934 // TODO: Add your control notification handler code here
935 }
936
937 //
938 // =======================================================================================================================
939 // CreateEntity Creates a new entity based on the currently selected brush and entity type.
940 // =======================================================================================================================
941 //
CreateEntity()942 void CEntityDlg::CreateEntity() {
943 entity_t *petNew;
944 bool forceFixed = false;
945
946 // check to make sure we have a brush
947 CXYWnd *pWnd = g_pParentWnd->ActiveXY();
948 if (pWnd) {
949 CRect rctZ;
950 pWnd->GetClientRect(rctZ);
951
952 brush_t *pBrush;
953 if (selected_brushes.next == &selected_brushes) {
954 pBrush = CreateEntityBrush(g_nSmartX, rctZ.Height() - 1 - g_nSmartY, pWnd);
955 forceFixed = true;
956 }
957 }
958 else {
959 if (selected_brushes.next == &selected_brushes) {
960 MessageBox("You must have a selected brush to create an entity", "info", 0);
961 return;
962 }
963 }
964
965 int index = comboClass.GetCurSel();
966 if (index == LB_ERR) {
967 MessageBox("You must have a selected class to create an entity", "info", 0);
968 return;
969 }
970
971 CString str;
972 comboClass.GetLBText(index, str);
973
974 if (!stricmp(str, "worldspawn")) {
975 MessageBox("Can't create an entity with worldspawn.", "info", 0);
976 return;
977 }
978
979 eclass_t *pecNew = Eclass_ForName (str, false);
980
981 // create it
982 if ((GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
983 // MAJOR hack for xian
984 extern void Brush_CopyList(brush_t *pFrom, brush_t *pTo);
985 brush_t temp_brushes;
986 temp_brushes.next = &temp_brushes;
987 Brush_CopyList(&selected_brushes, &temp_brushes);
988 Select_Deselect();
989 brush_t *pBrush = temp_brushes.next;
990 while (pBrush != NULL && pBrush != &temp_brushes) {
991 brush_t *pNext = pBrush->next;
992 Brush_RemoveFromList(pBrush);
993 Brush_AddToList(pBrush, &selected_brushes);
994 pBrush = pNext;
995 petNew = Entity_Create(pecNew, forceFixed);
996 Select_Deselect();
997 }
998 } else if ((GetAsyncKeyState(VK_SHIFT) & 0x8000)) {
999 Select_Ungroup();
1000 petNew = Entity_Create(pecNew, forceFixed);
1001 } else {
1002 petNew = Entity_Create(pecNew, forceFixed);
1003 }
1004
1005 if (petNew == NULL) {
1006 MessageBox("Failed to create entity.", "info", 0);
1007 return;
1008 }
1009
1010 if (selected_brushes.next == &selected_brushes) {
1011 editEntity = world_entity;
1012 }
1013 else {
1014 editEntity = selected_brushes.next->owner;
1015 }
1016
1017 SetKeyValPairs();
1018 Select_Deselect();
1019 Select_Brush(editEntity->brushes.onext);
1020 Sys_UpdateWindows(W_ALL);
1021 }
1022
OnBnClickedButtonCreate()1023 void CEntityDlg::OnBnClickedButtonCreate()
1024 {
1025 CreateEntity();
1026 }
1027
OnLbnDblclkListkeyval()1028 void CEntityDlg::OnLbnDblclkListkeyval()
1029 {
1030 CString Key, Value;
1031 idStr work;
1032 editKey.GetWindowText( Key );
1033 editVal.GetWindowText( Value );
1034 if ( stricmp( Key, "script" ) == 0 ) {
1035 Key = Value;
1036 Value = "script/" + Key;
1037 if ( fileSystem->ReadFile( Value, NULL, NULL ) == -1) {
1038 sprintf( work, "// Script for %s\n// \n\nvoid main() {\n\n}\n\n", currentmap );
1039 fileSystem->WriteFile( Value, work.c_str(), work.Length(), "fs_devpath" );
1040 }
1041 work = fileSystem->RelativePathToOSPath( Value );
1042 WinExec( va( "notepad.exe %s", work.c_str() ), SW_SHOW );
1043 }
1044 }
1045
OnLbnSelchangeListVars()1046 void CEntityDlg::OnLbnSelchangeListVars() {
1047
1048 }
1049
OnLbnDblclkListVars()1050 void CEntityDlg::OnLbnDblclkListVars() {
1051 if (editEntity == NULL) {
1052 return;
1053 }
1054 int sel = listVars.GetCurSel();
1055 CPropertyItem *pi = (CPropertyItem*)listVars.GetItemDataPtr(sel);
1056 if (pi) {
1057 if (editEntity->epairs.FindKey(pi->m_propName) == NULL) {
1058 editKey.SetWindowText(pi->m_propName);
1059 editVal.SetWindowText("");
1060 editVal.SetFocus();
1061 }
1062 }
1063 }
1064
1065
UpdateKeyVal(const char * key,const char * val)1066 void CEntityDlg::UpdateKeyVal(const char *key, const char *val) {
1067 if (editEntity) {
1068 editEntity->epairs.Set(key, val);
1069 SetKeyValPairs();
1070 g_pParentWnd->GetCamera()->BuildEntityRenderState(editEntity, true);
1071 Entity_UpdateSoundEmitter(editEntity);
1072 }
1073 }
1074
1075
OnNMReleasedcaptureSlider1(NMHDR * pNMHDR,LRESULT * pResult)1076 void CEntityDlg::OnNMReleasedcaptureSlider1(NMHDR *pNMHDR, LRESULT *pResult)
1077 {
1078 if ( !editEntity )
1079 {
1080 return;
1081 }
1082
1083 UpdateFromAnimationFrame ();
1084
1085 *pResult = 0;
1086 }
1087
UpdateFromAnimationFrame(bool updateKeyValueDisplay)1088 void CEntityDlg::UpdateFromAnimationFrame ( bool updateKeyValueDisplay )
1089 {
1090 int frame = slFrameSlider.GetPos ();
1091 editEntity->epairs.SetInt( "frame" , frame );
1092 SetDlgItemText ( IDC_ENTITY_CURRENT_ANIM , va ( "%i" , frame));
1093 if ( updateKeyValueDisplay ) {
1094 SetKeyValPairs();
1095 }
1096
1097 g_pParentWnd->GetCamera ()->BuildEntityRenderState (editEntity , true );
1098 Sys_UpdateWindows ( W_ALL );
1099
1100 }
1101
OnCbnAnimationChange()1102 void CEntityDlg::OnCbnAnimationChange ()
1103 {
1104 if ( !editEntity )
1105 {
1106 return;
1107 }
1108
1109 int sel = cbAnimations.GetCurSel();
1110 CString animName;
1111 currentAnimation = NULL;
1112 int currFrame = 0;
1113
1114 if ( sel != -1 ) {
1115 cbAnimations.GetLBText( sel , animName );
1116 if ( animName.GetLength() > 0 ) {
1117 //preserve the existing frame number
1118 currFrame = editEntity->epairs.GetInt ( "frame" , "1" );
1119
1120 editEntity->epairs.Set("anim" , animName.GetBuffer(0));
1121 SetKeyValPairs(false/*don't update anims combo box :)*/ );
1122
1123 //update the slider
1124 currentAnimation = gameEdit->ANIM_GetAnimFromEntityDef(editEntity->eclass->name , animName.GetBuffer(0));
1125 currentAnimationFrame = 0;
1126
1127 if ( currentAnimation ) {
1128 slFrameSlider.SetRange( 1 , gameEdit->ANIM_GetNumFrames( currentAnimation ), TRUE );
1129 slFrameSlider.SetPos( currFrame );
1130 currentAnimationFrame = currFrame;
1131 }
1132
1133 Sys_UpdateWindows(W_ALL);
1134 }
1135 }
1136 }
1137
OnBnClickedStartAnimation()1138 void CEntityDlg::OnBnClickedStartAnimation()
1139 {
1140 if (!editEntity) {
1141 return;
1142 }
1143 SetTimer ( 0 , 1000/24 , NULL );
1144 }
1145
OnBnClickedStopAnimation()1146 void CEntityDlg::OnBnClickedStopAnimation()
1147 {
1148 KillTimer ( 0 );
1149 }
1150
OnTimer(UINT nIDEvent)1151 void CEntityDlg::OnTimer(UINT nIDEvent)
1152 {
1153 if ( !editEntity ) {
1154 OnBnClickedStopAnimation ();
1155 return;
1156 }
1157
1158 if ( currentAnimation ) {
1159 currentAnimationFrame = ( (currentAnimationFrame++) % gameEdit->ANIM_GetNumFrames( currentAnimation ) );
1160 editEntity->epairs.SetInt ( "frame" , currentAnimationFrame );
1161 slFrameSlider.SetPos ( currentAnimationFrame );
1162 UpdateFromAnimationFrame (false/*don't update key/value display*/);
1163
1164 Sys_UpdateWindows ( W_CAMERA | W_XY );
1165 }
1166 }
1167
AddCurvePoints()1168 void CEntityDlg::AddCurvePoints() {
1169 if ( editEntity == NULL || editEntity->curve == NULL ) {
1170 return;
1171 }
1172
1173 // add one point 64 units from the direction of the two points int he curve
1174 int c = editEntity->curve->GetNumValues();
1175 idVec3 start;
1176 idVec3 end;
1177 if ( c > 1 ) {
1178 start = editEntity->curve->GetValue( c - 2 );
1179 end = editEntity->curve->GetValue( c - 1 );
1180 idVec3 dir = end - start;
1181 dir.Normalize();
1182 start = end + 64 * dir;
1183 } else if ( c > 0 ) {
1184 start = editEntity->curve->GetValue( 0 );
1185 start.x += 64;
1186 start.y += 64;
1187 } else {
1188 start = editEntity->origin;
1189 }
1190
1191 editEntity->curve->AddValue( editEntity->curve->GetNumValues() * 100, start );
1192
1193 if ( g_qeglobals.d_select_mode == sel_editpoint ) {
1194 g_qeglobals.d_select_mode = sel_brush;
1195 EditCurvePoints();
1196 }
1197
1198 Sys_UpdateWindows( W_CAMERA | W_XY );
1199
1200 }
1201
EditCurvePoints()1202 void CEntityDlg::EditCurvePoints() {
1203
1204 if ( editEntity == NULL || editEntity->curve == NULL ) {
1205 return;
1206 }
1207
1208 if ( g_qeglobals.d_select_mode == sel_editpoint ) {
1209 g_qeglobals.d_select_mode = sel_brush;
1210 return;
1211 }
1212
1213 g_qeglobals.d_select_mode = sel_editpoint;
1214
1215 g_qeglobals.d_numpoints = 0;
1216 g_qeglobals.d_num_move_points = 0;
1217 int c = editEntity->curve->GetNumValues();
1218 for ( int i = 0; i < c; i++ ) {
1219 if ( g_qeglobals.d_numpoints < MAX_POINTS - 1 ) {
1220 g_qeglobals.d_points[g_qeglobals.d_numpoints++] = editEntity->curve->GetValue( i );
1221 }
1222 }
1223 Sys_UpdateWindows( W_XY | W_CAMERA );
1224
1225 }
1226
InsertCurvePoint()1227 void CEntityDlg::InsertCurvePoint() {
1228 if ( editEntity == NULL || editEntity->curve == NULL ) {
1229 return;
1230 }
1231
1232 if ( g_qeglobals.d_select_mode != sel_editpoint ) {
1233 return;
1234 }
1235
1236 if ( g_qeglobals.d_num_move_points == 0 ) {
1237 return;
1238 }
1239
1240 for ( int i = 0; i < editEntity->curve->GetNumValues(); i++ ) {
1241 if ( PointInMoveList( editEntity->curve->GetValueAddress( i ) ) >= 0 ) {
1242 if ( i == editEntity->curve->GetNumValues() - 1 ) {
1243 // just do an add
1244 AddCurvePoints();
1245 } else {
1246 idCurve<idVec3> *newCurve = Entity_MakeCurve( editEntity );
1247
1248 if ( newCurve == NULL ) {
1249 return;
1250 }
1251
1252 for ( int j = 0; j < editEntity->curve->GetNumValues(); j++ ) {
1253 if ( j == i ) {
1254 idVec3 start;
1255 idVec3 end;
1256 if ( i > 0 ) {
1257 start = editEntity->curve->GetValue( i - 1 );
1258 end = editEntity->curve->GetValue( i );
1259 start += end;
1260 start *= 0.5f;
1261 } else {
1262 start = editEntity->curve->GetValue( 0 );
1263 if ( editEntity->curve->GetNumValues() > 1 ) {
1264 end = start;
1265 start = editEntity->curve->GetValue ( 1 );
1266 idVec3 dir = end - start;
1267 dir.Normalize();
1268 start = end + 64 * dir;
1269 } else {
1270 end = start;
1271 end.x += 64;
1272 end.y += 64;
1273 }
1274 }
1275 newCurve->AddValue( newCurve->GetNumValues() * 100, start );
1276 }
1277 newCurve->AddValue( newCurve->GetNumValues() * 100, editEntity->curve->GetValue( j ) );
1278 }
1279 delete editEntity->curve;
1280 editEntity->curve = newCurve;
1281 }
1282 g_qeglobals.d_num_move_points = 0;
1283 break;
1284 }
1285 }
1286 UpdateEntityCurve();
1287
1288 Sys_UpdateWindows( W_XY | W_CAMERA );
1289
1290 }
1291
DeleteCurvePoint()1292 void CEntityDlg::DeleteCurvePoint() {
1293
1294 if ( editEntity == NULL || editEntity->curve == NULL ) {
1295 return;
1296 }
1297
1298 if ( g_qeglobals.d_select_mode != sel_editpoint ) {
1299 return;
1300 }
1301
1302
1303 if ( g_qeglobals.d_num_move_points == 0 ) {
1304 return;
1305 }
1306
1307 for ( int i = 0; i < editEntity->curve->GetNumValues(); i++ ) {
1308 if ( PointInMoveList( editEntity->curve->GetValueAddress( i ) ) >= 0 ) {
1309 editEntity->curve->RemoveIndex( i );
1310 g_qeglobals.d_num_move_points = 0;
1311 break;
1312 }
1313 }
1314 UpdateEntityCurve();
1315
1316 Sys_UpdateWindows( W_XY | W_CAMERA );
1317
1318 }
1319
1320
UpdateEntityCurve()1321 void CEntityDlg::UpdateEntityCurve() {
1322
1323 if ( editEntity == NULL ) {
1324 return;
1325 }
1326
1327 Entity_UpdateCurveData( editEntity );
1328
1329 if ( g_qeglobals.d_select_mode == sel_editpoint ) {
1330 g_qeglobals.d_numpoints = 0;
1331 int c = editEntity->curve->GetNumValues();
1332 for ( int i = 0; i < c; i++ ) {
1333 if ( g_qeglobals.d_numpoints < MAX_POINTS - 1 ) {
1334 g_qeglobals.d_points[g_qeglobals.d_numpoints++] = editEntity->curve->GetValue( i );
1335 }
1336 }
1337 }
1338
1339 Sys_UpdateWindows( W_ENTITY );
1340 }
1341
1342
SelectCurvePointByRay(const idVec3 & org,const idVec3 & dir,int buttons)1343 void CEntityDlg::SelectCurvePointByRay(const idVec3 &org, const idVec3 &dir, int buttons) {
1344 int i, besti;
1345 float d, bestd;
1346 idVec3 temp;
1347
1348 if ( editEntity == NULL ) {
1349 return;
1350 }
1351 // find the point closest to the ray
1352 float scale = g_pParentWnd->ActiveXY()->Scale();
1353 besti = -1;
1354 bestd = 8 / scale / 2;
1355 //bestd = 8;
1356
1357 for (i = 0; i < g_qeglobals.d_numpoints; i++) {
1358 temp = g_qeglobals.d_points[i] - org;
1359 d = temp * dir;
1360 temp = org + d * dir;
1361 temp = g_qeglobals.d_points[i] - temp;
1362 d = temp.Length();
1363 if ( d <= bestd ) {
1364 bestd = d;
1365 besti = i;
1366 }
1367 }
1368
1369 if (besti == -1) {
1370 return;
1371 }
1372
1373 g_qeglobals.d_num_move_points = 0;
1374 assert ( besti < editEntity->curve->GetNumValues() );
1375 g_qeglobals.d_move_points[ g_qeglobals.d_num_move_points++ ] = editEntity->curve->GetValueAddress( besti );
1376 }
1377