2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
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.
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.
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/>.
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.
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.
26 ===========================================================================
29 #include "../../idlib/precompiled.h"
35 #include "PropertyList.h"
36 #include "entitydlg.h"
37 #include "PreviewDlg.h"
40 #include "../../renderer/model_local.h" // for idRenderModelPrt
42 void Select_Ungroup();
46 IMPLEMENT_DYNAMIC(CEntityDlg, CDialog)
47 CEntityDlg::CEntityDlg(CWnd* pParent /*=NULL*/)
48 : CDialog(CEntityDlg::IDD, pParent)
51 multipleEntities = false;
52 currentAnimation = NULL;
55 CEntityDlg::~CEntityDlg()
59 void CEntityDlg::DoDataExchange(CDataExchange* pDX)
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);
97 BOOL CEntityDlg::OnInitDialog()
99 CDialog::OnInitDialog();
100 listKeyVal.SetUpdateInspectors(true);
101 listKeyVal.SetDivider(100);
102 listVars.SetDivider(100);
103 staticFrame.SetWindowText ( "0" );
105 return TRUE; // return TRUE unless you set the focus to a control
106 // EXCEPTION: OCX Property Pages should return FALSE
109 int CEntityDlg::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
111 // TODO: Add your specialized code here and/or call the base class
113 return CDialog::OnToolHitTest(point, pTI);
117 void CEntityDlg::AddClassNames() {
118 comboClass.ResetContent();
119 for (eclass_t *pec = eclass; pec; pec = pec->next) {
120 comboClass.AddString(pec->name);
125 BEGIN_MESSAGE_MAP(CEntityDlg, CDialog)
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)
156 ON_BN_CLICKED(IDOK, OnOK)
159 void CEntityDlg::OnSize(UINT nType, int cx, int cy)
161 if (staticTitle.GetSafeHwnd() == NULL) {
164 CDialog::OnSize(nType, cx, cy);
165 CRect rect, crect, crect2;
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);
178 listKeyVal.SetWindowPos(NULL, 4, top, rect.Width() - 8, bh, SWP_SHOWWINDOW);
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);
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 );
202 //*************************************
204 //*************************************
205 int rightAnimAreaBorder = rect.right - 75 - crect.Width (); /*models, etc button width*/
207 btnStopAnim.GetWindowRect(crect);
208 btnStopAnim.SetWindowPos(NULL,rightAnimAreaBorder - crect.Width (),
209 top + 8 ,crect.Width(),crect.Height(),SWP_SHOWWINDOW);
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);
215 left -= crect.Width() + 4;
216 cbAnimations.GetWindowRect(crect);
217 cbAnimations.SetWindowPos(NULL,left-crect.Width (),top + 8 ,crect.Width(),crect.Height(),SWP_SHOWWINDOW);
219 staticFrame.GetWindowRect(crect);
220 staticFrame.SetWindowPos(NULL,rightAnimAreaBorder - crect.Width (),
221 top + 34 ,crect.Width(),crect.Height(),SWP_SHOWWINDOW);
223 left = rightAnimAreaBorder - crect.Width () - 4;
225 slFrameSlider.GetWindowRect(crect);
226 slFrameSlider.SetWindowPos(NULL,left - crect.Width (),
227 top + 32 ,crect.Width(),crect.Height(),SWP_SHOWWINDOW);
229 //*************************************
230 //*************************************
232 btn135.GetWindowRect(crect);
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);
240 btn180.SetWindowPos(NULL, 4, top, bh, bh, SWP_SHOWWINDOW);
241 btn360.SetWindowPos(NULL, 4 + 2 + 2 + bh * 2, top, bh, bh, SWP_SHOWWINDOW);
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);
249 void CEntityDlg::OnCbnSelchangeComboClass()
251 int index = comboClass.GetCurSel();
252 if (index != LB_ERR) {
254 comboClass.GetLBText(index, str);
255 eclass_t *ent = Eclass_ForName (str, false);
257 if (selected_brushes.next == &selected_brushes) {
258 editEntity = world_entity;
259 multipleEntities = false;
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;
269 listVars.ResetContent();
270 CPropertyItem *pi = new CPropertyItem("Usage:", ent->desc.c_str(), PIT_VAR, "");
271 listVars.AddPropItem(pi);
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);
279 listVars.Invalidate();
285 const char *CEntityDlg::TranslateString(const char *buf) {
286 static char buf2[32768];
292 for (i = 0; i < l; i++) {
293 if (buf[i] == '\n') {
308 void CEntityDlg::UpdateFromListBox() {
309 if (editEntity == NULL) {
312 int c = listKeyVal.GetCount();
313 for (int i = 0 ; i < c; i++) {
314 CPropertyItem* pItem = (CPropertyItem*)listKeyVal.GetItemDataPtr(i);
316 editEntity->epairs.Set(pItem->m_propName, pItem->m_curValue);
322 void CEntityDlg::SetKeyValPairs( bool updateAnims ) {
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, "");
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) {
337 pi->m_nItemType = PIT_EDIT;
340 pi->m_nItemType = PIT_EDIT;
341 //pi->m_cmbItems = "0|1";
344 pi->m_nItemType = PIT_COLOR;
347 pi->m_nItemType = PIT_MATERIAL;
350 pi->m_nItemType = PIT_MODEL;
353 pi->m_nItemType = PIT_GUI;
356 pi->m_nItemType = PIT_SOUND;
364 if (kv->GetKey().Icmp("model") == 0) {
365 pi->m_nItemType = PIT_MODEL;
367 if (kv->GetKey().Icmp("_color") == 0) {
368 pi->m_nItemType = PIT_COLOR;
370 if (kv->GetKey().Icmp("gui") == 0) {
371 pi->m_nItemType = PIT_GUI;
373 if (kv->GetKey().Icmp("gui2") == 0) {
374 pi->m_nItemType = PIT_GUI;
376 if (kv->GetKey().Icmp("gui3") == 0) {
377 pi->m_nItemType = PIT_GUI;
379 if (kv->GetKey().Icmp("s_shader") == 0) {
380 pi->m_nItemType = PIT_SOUND;
383 listKeyVal.AddPropItem(pi);
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 ) );
395 const idKeyValue* kv = editEntity->epairs.FindKey ( "anim" );
397 int selIndex = cbAnimations.FindStringExact( 0 , kv->GetValue().c_str() );
398 if ( selIndex != -1 ) {
399 cbAnimations.SetCurSel( selIndex );
400 OnCbnAnimationChange ();
407 void CEntityDlg::UpdateEntitySel(eclass_t *ent) {
409 assert ( ent->name );
410 int index = comboClass.FindString(-1, ent->name);
411 if (index != LB_ERR) {
412 comboClass.SetCurSel(index);
413 OnCbnSelchangeComboClass();
417 void CEntityDlg::OnLbnSelchangeListkeyval()
419 int index = listKeyVal.GetCurSel();
420 if (index != LB_ERR) {
422 listKeyVal.GetText(index, str);
424 for (i = 0; str[i] != '\t' && str[i] != '\0'; i++) {
427 idStr key = str.Left(i);
428 while (str[i] == '\t' && str[i] != '\0') {
432 idStr val = str.Right(str.GetLength() - i);
434 editKey.SetWindowText(key);
435 editVal.SetWindowText(val);
439 static int TabOrder[] = {
460 IDC_ENTITY_ANIMATIONS
463 int TabCount = sizeof(TabOrder) / sizeof(int);
465 void CEntityDlg::DelProp() {
468 if (editEntity == NULL) {
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 );
479 DeleteKey(editEntity, key);
480 Entity_UpdateCurveData( editEntity );
483 // refresh the prop listbox
485 Sys_UpdateWindows( W_ENTITY | W_XY | W_CAMERA );
489 BOOL CEntityDlg::PreTranslateMessage(MSG* pMsg)
492 if (pMsg->hwnd == editVal.GetSafeHwnd()) {
493 if (pMsg->message == WM_LBUTTONDOWN) {
499 if (pMsg->hwnd == editKey.GetSafeHwnd()) {
500 if (pMsg->message == WM_LBUTTONDOWN) {
506 if (GetFocus() == &editVal || GetFocus() == &editKey) {
507 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN ) {
514 if (GetFocus() == listKeyVal.GetEditBox()) {
515 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN ) {
516 listKeyVal.OnChangeEditBox();
517 listKeyVal.OnSelchange();
518 listKeyVal.OnKillfocusEditBox();
525 if (GetFocus() == &listKeyVal) {
526 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_DELETE && editEntity) {
532 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) {
533 if (pMsg->wParam == VK_ESCAPE) {
534 g_pParentWnd->GetCamera()->SetFocus();
540 if ( pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN ) {
541 // keeps ENTER from closing the dialog
545 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB) {
547 int id = GetFocus()->GetDlgCtrlID();
548 for (int i = 0; i < TabCount; i++) {
549 if (TabOrder[i] == id) {
554 CWnd *next = GetDlgItem(TabOrder[i]);
557 if (TabOrder[i] == IDC_EDIT_VAL) {
558 editVal.SetSel(0, -1);
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 ();
575 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_LEFT && pMsg->hwnd == slFrameSlider.GetSafeHwnd()) {
576 int pos = slFrameSlider.GetPos() - 1;
579 pos = slFrameSlider.GetRangeMax();
582 slFrameSlider.SetPos ( pos );
583 UpdateFromAnimationFrame ();
587 return CDialog::PreTranslateMessage(pMsg);
592 =======================================================================================================================
594 =======================================================================================================================
596 void CEntityDlg::AddProp() {
598 if (editEntity == NULL) {
603 editKey.GetWindowText(Key);
604 editVal.GetWindowText(Value);
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 );
610 if (multipleEntities) {
612 for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
614 Entity_SetName(b->owner, Value);
616 if ( ! ( ( isModel || isOrigin ) && ( b->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN ) ) ) {
617 SetKeyValue(b->owner, Key, Value);
624 Entity_SetName(editEntity, Value);
626 if ( ! ( ( isModel || isOrigin ) && ( editEntity->eclass->nShowFlags & ECLASS_WORLDSPAWN ) ) ) {
627 SetKeyValue(editEntity, Key, Value);
631 if ( isModel && !( editEntity->eclass->nShowFlags & ECLASS_WORLDSPAWN ) ) {
635 selected_brushes.next->modelHandle = renderModelManager->FindModel( Value );
636 if ( dynamic_cast<idRenderModelPrt*>( selected_brushes.next->modelHandle ) || dynamic_cast<idRenderModelLiquid*>( selected_brushes.next->modelHandle ) ) {
638 bo.ExpandSelf( 12.0f );
640 bo = selected_brushes.next->modelHandle->Bounds( NULL );
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 );
652 // refresh the prop listbox
654 Sys_UpdateWindows(W_ALL);
658 const char *CEntityDlg::AngleKey() {
659 if (editEntity == NULL) {
663 if (editEntity->eclass->nShowFlags & ECLASS_MOVER) {
671 void CEntityDlg::OnBnClickedE135()
673 if (editEntity == NULL) {
676 editKey.SetWindowText(AngleKey());
677 editVal.SetWindowText("135");
681 void CEntityDlg::OnBnClickedE90()
683 if (editEntity == NULL) {
686 editKey.SetWindowText(AngleKey());
687 editVal.SetWindowText("90");
691 void CEntityDlg::OnBnClickedE45()
693 if (editEntity == NULL) {
696 editKey.SetWindowText(AngleKey());
697 editVal.SetWindowText("45");
701 void CEntityDlg::OnBnClickedE180()
703 if (editEntity == NULL) {
706 editKey.SetWindowText(AngleKey());
707 editVal.SetWindowText("180");
711 void CEntityDlg::OnBnClickedE0()
713 if (editEntity == NULL) {
716 editKey.SetWindowText(AngleKey());
717 editVal.SetWindowText("0");
721 void CEntityDlg::OnBnClickedE225()
723 if (editEntity == NULL) {
726 editKey.SetWindowText(AngleKey());
727 editVal.SetWindowText("225");
731 void CEntityDlg::OnBnClickedE270()
733 if (editEntity == NULL) {
736 editKey.SetWindowText(AngleKey());
737 editVal.SetWindowText("270");
741 void CEntityDlg::OnBnClickedE315()
743 if (editEntity == NULL) {
746 editKey.SetWindowText(AngleKey());
747 editVal.SetWindowText("315");
751 void CEntityDlg::OnBnClickedEUp()
753 if (editEntity == NULL) {
756 editKey.SetWindowText(AngleKey());
757 editVal.SetWindowText("-1");
761 void CEntityDlg::OnBnClickedEDown()
763 if (editEntity == NULL) {
766 editKey.SetWindowText(AngleKey());
767 editVal.SetWindowText("-2");
771 CPreviewDlg *CEntityDlg::ShowModelChooser() {
772 static CPreviewDlg modelDlg;
773 modelDlg.SetMode(CPreviewDlg::MODELS);
775 if (modelDlg.GetSafeHwnd() == NULL) {
776 modelDlg.Create(MAKEINTRESOURCE(IDD_DIALOG_PREVIEW));
778 modelDlg.ShowWindow( SW_SHOW );
779 modelDlg.BringWindowToTop();
780 while (modelDlg.Waiting()) {
785 CPreviewDlg *CEntityDlg::ShowParticleChooser() {
786 static CPreviewDlg modelDlg;
787 modelDlg.SetMode(CPreviewDlg::PARTICLES);
789 if (modelDlg.GetSafeHwnd() == NULL) {
790 modelDlg.Create(MAKEINTRESOURCE(IDD_DIALOG_PREVIEW));
792 modelDlg.ShowWindow(SW_SHOW);
793 modelDlg.BringWindowToTop();
794 while (modelDlg.Waiting()) {
799 CPreviewDlg *CEntityDlg::ShowSkinChooser(entity_t *ent) {
800 static CPreviewDlg modelDlg;
801 modelDlg.SetMode(CPreviewDlg::SKINS);
803 if (modelDlg.GetSafeHwnd() == NULL) {
804 modelDlg.Create(MAKEINTRESOURCE(IDD_DIALOG_PREVIEW));
806 modelDlg.RebuildTree( ( ent ) ? ent->epairs.GetString( "model" ) : "" );
807 modelDlg.ShowWindow(SW_SHOW);
808 modelDlg.BringWindowToTop();
809 while (modelDlg.Waiting()) {
814 CPreviewDlg *CEntityDlg::ShowGuiChooser() {
815 static CPreviewDlg guiDlg;
816 guiDlg.SetMode(CPreviewDlg::GUIS);
818 if (guiDlg.GetSafeHwnd() == NULL) {
819 guiDlg.Create(MAKEINTRESOURCE(IDD_DIALOG_PREVIEW));
821 guiDlg.ShowWindow(SW_SHOW);
822 guiDlg.BringWindowToTop();
823 while (guiDlg.Waiting()) {
828 CPreviewDlg *CEntityDlg::ShowSoundChooser() {
829 static CPreviewDlg soundDlg;
830 soundDlg.SetMode(CPreviewDlg::SOUNDS);
832 if (soundDlg.GetSafeHwnd() == NULL) {
833 soundDlg.Create(MAKEINTRESOURCE(IDD_DIALOG_PREVIEW));
835 soundDlg.ShowWindow(SW_SHOW);
836 while (soundDlg.Waiting()) {
841 CPreviewDlg *CEntityDlg::ShowMaterialChooser() {
842 static CPreviewDlg matDlg;
843 matDlg.SetMode(CPreviewDlg::MATERIALS);
845 if (matDlg.GetSafeHwnd() == NULL) {
846 matDlg.Create(MAKEINTRESOURCE(IDD_DIALOG_PREVIEW));
848 matDlg.ShowWindow(SW_SHOW);
849 matDlg.BringWindowToTop();
850 while (matDlg.Waiting()) {
855 void CEntityDlg::AssignModel ()
857 OnBnClickedButtonModel();
859 void CEntityDlg::OnBnClickedButtonModel() {
860 CPreviewDlg *dlg = ShowModelChooser();
861 if (dlg->returnCode == IDOK) {
862 editKey.SetWindowText("model");
863 editVal.SetWindowText(dlg->mediaName);
868 void CEntityDlg::OnBnClickedButtonSound() {
869 CPreviewDlg *dlg = ShowSoundChooser();
870 if (dlg->returnCode == IDOK) {
871 editKey.SetWindowText("s_shader");
872 editVal.SetWindowText(dlg->mediaName);
877 void CEntityDlg::OnBnClickedButtonGui() {
878 CPreviewDlg *dlg = ShowGuiChooser();
879 if (dlg->returnCode == IDOK) {
880 editKey.SetWindowText("gui");
881 editVal.SetWindowText(dlg->mediaName);
886 void CEntityDlg::OnBnClickedButtonParticle() {
887 CPreviewDlg *dlg = ShowParticleChooser();
888 if (dlg->returnCode == IDOK) {
889 editKey.SetWindowText("model");
890 editVal.SetWindowText(dlg->mediaName);
895 void CEntityDlg::OnBnClickedButtonSkin() {
896 CPreviewDlg *dlg = ShowSkinChooser( editEntity );
897 if (dlg->returnCode == IDOK) {
898 editKey.SetWindowText("skin");
899 editVal.SetWindowText(dlg->mediaName);
905 void CEntityDlg::OnBnClickedButtonCurve() {
907 if ( dlg.DoModal() == IDOK ) {
909 idStr str = "curve_" + dlg.strCurveType;
910 editKey.SetWindowText( str );
911 idVec3 org = editEntity->origin;
913 str += org.ToString();
916 str += org.ToString();
919 str += org.ToString();
921 editVal.SetWindowText( str );
923 Entity_SetCurveData( editEntity );
928 void CEntityDlg::OnBnClickedButtonBrowse() {
932 void CEntityDlg::OnCbnDblclkComboClass()
934 // TODO: Add your control notification handler code here
938 // =======================================================================================================================
939 // CreateEntity Creates a new entity based on the currently selected brush and entity type.
940 // =======================================================================================================================
942 void CEntityDlg::CreateEntity() {
944 bool forceFixed = false;
946 // check to make sure we have a brush
947 CXYWnd *pWnd = g_pParentWnd->ActiveXY();
950 pWnd->GetClientRect(rctZ);
953 if (selected_brushes.next == &selected_brushes) {
954 pBrush = CreateEntityBrush(g_nSmartX, rctZ.Height() - 1 - g_nSmartY, pWnd);
959 if (selected_brushes.next == &selected_brushes) {
960 MessageBox("You must have a selected brush to create an entity", "info", 0);
965 int index = comboClass.GetCurSel();
966 if (index == LB_ERR) {
967 MessageBox("You must have a selected class to create an entity", "info", 0);
972 comboClass.GetLBText(index, str);
974 if (!stricmp(str, "worldspawn")) {
975 MessageBox("Can't create an entity with worldspawn.", "info", 0);
979 eclass_t *pecNew = Eclass_ForName (str, false);
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);
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);
995 petNew = Entity_Create(pecNew, forceFixed);
998 } else if ((GetAsyncKeyState(VK_SHIFT) & 0x8000)) {
1000 petNew = Entity_Create(pecNew, forceFixed);
1002 petNew = Entity_Create(pecNew, forceFixed);
1005 if (petNew == NULL) {
1006 MessageBox("Failed to create entity.", "info", 0);
1010 if (selected_brushes.next == &selected_brushes) {
1011 editEntity = world_entity;
1014 editEntity = selected_brushes.next->owner;
1019 Select_Brush(editEntity->brushes.onext);
1020 Sys_UpdateWindows(W_ALL);
1023 void CEntityDlg::OnBnClickedButtonCreate()
1028 void CEntityDlg::OnLbnDblclkListkeyval()
1032 editKey.GetWindowText( Key );
1033 editVal.GetWindowText( Value );
1034 if ( stricmp( Key, "script" ) == 0 ) {
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" );
1041 work = fileSystem->RelativePathToOSPath( Value );
1042 WinExec( va( "notepad.exe %s", work.c_str() ), SW_SHOW );
1046 void CEntityDlg::OnLbnSelchangeListVars() {
1050 void CEntityDlg::OnLbnDblclkListVars() {
1051 if (editEntity == NULL) {
1054 int sel = listVars.GetCurSel();
1055 CPropertyItem *pi = (CPropertyItem*)listVars.GetItemDataPtr(sel);
1057 if (editEntity->epairs.FindKey(pi->m_propName) == NULL) {
1058 editKey.SetWindowText(pi->m_propName);
1059 editVal.SetWindowText("");
1066 void CEntityDlg::UpdateKeyVal(const char *key, const char *val) {
1068 editEntity->epairs.Set(key, val);
1070 g_pParentWnd->GetCamera()->BuildEntityRenderState(editEntity, true);
1071 Entity_UpdateSoundEmitter(editEntity);
1076 void CEntityDlg::OnNMReleasedcaptureSlider1(NMHDR *pNMHDR, LRESULT *pResult)
1083 UpdateFromAnimationFrame ();
1088 void CEntityDlg::UpdateFromAnimationFrame ( bool updateKeyValueDisplay )
1090 int frame = slFrameSlider.GetPos ();
1091 editEntity->epairs.SetInt( "frame" , frame );
1092 SetDlgItemText ( IDC_ENTITY_CURRENT_ANIM , va ( "%i" , frame));
1093 if ( updateKeyValueDisplay ) {
1097 g_pParentWnd->GetCamera ()->BuildEntityRenderState (editEntity , true );
1098 Sys_UpdateWindows ( W_ALL );
1102 void CEntityDlg::OnCbnAnimationChange ()
1109 int sel = cbAnimations.GetCurSel();
1111 currentAnimation = NULL;
1115 cbAnimations.GetLBText( sel , animName );
1116 if ( animName.GetLength() > 0 ) {
1117 //preserve the existing frame number
1118 currFrame = editEntity->epairs.GetInt ( "frame" , "1" );
1120 editEntity->epairs.Set("anim" , animName.GetBuffer(0));
1121 SetKeyValPairs(false/*don't update anims combo box :)*/ );
1124 currentAnimation = gameEdit->ANIM_GetAnimFromEntityDef(editEntity->eclass->name , animName.GetBuffer(0));
1125 currentAnimationFrame = 0;
1127 if ( currentAnimation ) {
1128 slFrameSlider.SetRange( 1 , gameEdit->ANIM_GetNumFrames( currentAnimation ), TRUE );
1129 slFrameSlider.SetPos( currFrame );
1130 currentAnimationFrame = currFrame;
1133 Sys_UpdateWindows(W_ALL);
1138 void CEntityDlg::OnBnClickedStartAnimation()
1143 SetTimer ( 0 , 1000/24 , NULL );
1146 void CEntityDlg::OnBnClickedStopAnimation()
1151 void CEntityDlg::OnTimer(UINT nIDEvent)
1153 if ( !editEntity ) {
1154 OnBnClickedStopAnimation ();
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*/);
1164 Sys_UpdateWindows ( W_CAMERA | W_XY );
1168 void CEntityDlg::AddCurvePoints() {
1169 if ( editEntity == NULL || editEntity->curve == NULL ) {
1173 // add one point 64 units from the direction of the two points int he curve
1174 int c = editEntity->curve->GetNumValues();
1178 start = editEntity->curve->GetValue( c - 2 );
1179 end = editEntity->curve->GetValue( c - 1 );
1180 idVec3 dir = end - start;
1182 start = end + 64 * dir;
1183 } else if ( c > 0 ) {
1184 start = editEntity->curve->GetValue( 0 );
1188 start = editEntity->origin;
1191 editEntity->curve->AddValue( editEntity->curve->GetNumValues() * 100, start );
1193 if ( g_qeglobals.d_select_mode == sel_editpoint ) {
1194 g_qeglobals.d_select_mode = sel_brush;
1198 Sys_UpdateWindows( W_CAMERA | W_XY );
1202 void CEntityDlg::EditCurvePoints() {
1204 if ( editEntity == NULL || editEntity->curve == NULL ) {
1208 if ( g_qeglobals.d_select_mode == sel_editpoint ) {
1209 g_qeglobals.d_select_mode = sel_brush;
1213 g_qeglobals.d_select_mode = sel_editpoint;
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 );
1223 Sys_UpdateWindows( W_XY | W_CAMERA );
1227 void CEntityDlg::InsertCurvePoint() {
1228 if ( editEntity == NULL || editEntity->curve == NULL ) {
1232 if ( g_qeglobals.d_select_mode != sel_editpoint ) {
1236 if ( g_qeglobals.d_num_move_points == 0 ) {
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 ) {
1246 idCurve<idVec3> *newCurve = Entity_MakeCurve( editEntity );
1248 if ( newCurve == NULL ) {
1252 for ( int j = 0; j < editEntity->curve->GetNumValues(); j++ ) {
1257 start = editEntity->curve->GetValue( i - 1 );
1258 end = editEntity->curve->GetValue( i );
1262 start = editEntity->curve->GetValue( 0 );
1263 if ( editEntity->curve->GetNumValues() > 1 ) {
1265 start = editEntity->curve->GetValue ( 1 );
1266 idVec3 dir = end - start;
1268 start = end + 64 * dir;
1275 newCurve->AddValue( newCurve->GetNumValues() * 100, start );
1277 newCurve->AddValue( newCurve->GetNumValues() * 100, editEntity->curve->GetValue( j ) );
1279 delete editEntity->curve;
1280 editEntity->curve = newCurve;
1282 g_qeglobals.d_num_move_points = 0;
1286 UpdateEntityCurve();
1288 Sys_UpdateWindows( W_XY | W_CAMERA );
1292 void CEntityDlg::DeleteCurvePoint() {
1294 if ( editEntity == NULL || editEntity->curve == NULL ) {
1298 if ( g_qeglobals.d_select_mode != sel_editpoint ) {
1303 if ( g_qeglobals.d_num_move_points == 0 ) {
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;
1314 UpdateEntityCurve();
1316 Sys_UpdateWindows( W_XY | W_CAMERA );
1321 void CEntityDlg::UpdateEntityCurve() {
1323 if ( editEntity == NULL ) {
1327 Entity_UpdateCurveData( editEntity );
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 );
1339 Sys_UpdateWindows( W_ENTITY );
1343 void CEntityDlg::SelectCurvePointByRay(const idVec3 &org, const idVec3 &dir, int buttons) {
1348 if ( editEntity == NULL ) {
1351 // find the point closest to the ray
1352 float scale = g_pParentWnd->ActiveXY()->Scale();
1354 bestd = 8 / scale / 2;
1357 for (i = 0; i < g_qeglobals.d_numpoints; i++) {
1358 temp = g_qeglobals.d_points[i] - org;
1360 temp = org + d * dir;
1361 temp = g_qeglobals.d_points[i] - temp;
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 );