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"
32 #include "../../game/game.h"
33 #include "../../sys/win32/win_local.h"
34 #include "../../sys/win32/rc/common_resource.h"
35 #include "../../sys/win32/rc/Radiant_resource.h"
36 #include "../../sys/win32/rc/ParticleEditor_resource.h"
37 #include "../comafx/DialogName.h"
38 #include "../comafx/VectorCtl.h"
39 #include "../comafx/DialogColorPicker.h"
40 #include "../radiant/GLWidget.h"
41 #include "../radiant/PreviewDlg.h"
43 #include "DialogParticleEditor.h"
45 #ifdef ID_DEBUG_MEMORY
51 const int StageEnableID[] = {
53 IDC_BUTTON_BROWSEMATERIAL,
57 IDC_BUTTON_BROWSECOLOR,
59 IDC_BUTTON_BROWSEFADECOLOR,
63 IDC_EDIT_FADEFRACTION,
65 IDC_SLIDER_FADEFRACTION,
75 IDC_CHECK_WORLDGRAVITY,
88 IDC_EDIT_DIRECTIONPARM,
94 IDC_EDIT_ORIENTATIONPARM1,
95 IDC_EDIT_ORIENTATIONPARM2,
100 IDC_SLIDER_ROTATIONFROM,
101 IDC_EDIT_ROTATIONFROM,
103 IDC_SLIDER_ROTATIONTO,
108 IDC_SLIDER_ASPECTFROM,
112 IDC_COMBO_CUSTOMPATH,
113 IDC_CHECK_ENTITYCOLOR,
116 const int StageIDCount = sizeof( StageEnableID ) / sizeof ( const int );
118 const int EditEnableID[] = {
125 IDC_BUTTON_DROPEMITTER,
127 IDC_BUTTON_BROWSECOLOR_ENTITY
130 const int EditIDCount = sizeof ( EditEnableID ) / sizeof ( const int );
133 CDialogParticleEditor *g_ParticleDialog = NULL;
141 void ParticleEditorInit( const idDict *spawnArgs ) {
143 if ( renderSystem->IsFullScreen() ) {
144 common->Printf( "Cannot run the particle editor in fullscreen mode.\n"
145 "Set r_fullscreen to 0 and vid_restart.\n" );
149 if ( g_ParticleDialog == NULL ) {
151 g_ParticleDialog = new CDialogParticleEditor();
154 if ( g_ParticleDialog->GetSafeHwnd() == NULL) {
155 g_ParticleDialog->Create( IDD_DIALOG_PARTICLE_EDITOR );
157 // FIXME: restore position
159 g_AFDialog->SetWindowPos( NULL, rct.left, rct.top, 0, 0, SWP_NOSIZE );
163 idKeyInput::ClearStates();
165 g_ParticleDialog->ShowWindow( SW_SHOW );
166 g_ParticleDialog->SetFocus();
169 idStr str = spawnArgs->GetString( "model" );
170 str.StripFileExtension();
171 g_ParticleDialog->SelectParticle( str );
172 g_ParticleDialog->SetParticleVisualization( static_cast<int>( CDialogParticleEditor::SELECTED ) );
175 cvarSystem->SetCVarBool( "r_useCachedDynamicModels", false );
184 void ParticleEditorRun( void ) {
186 MSG *msg = AfxGetCurrentMessage(); // TODO Robert fix me!!
188 MSG *msg = &m_msgCur;
191 while( ::PeekMessage(msg, NULL, NULL, NULL, PM_NOREMOVE) ) {
193 if ( !AfxGetApp()->PumpMessage() ) {
200 ParticleEditorShutdown
203 void ParticleEditorShutdown( void ) {
204 delete g_ParticleDialog;
205 g_ParticleDialog = NULL;
209 // CDialogParticleEditor dialog
211 IMPLEMENT_DYNAMIC(CDialogParticleEditor, CDialog)
212 CDialogParticleEditor::CDialogParticleEditor(CWnd* pParent /*=NULL*/)
213 : CDialog(CDialogParticleEditor::IDD, pParent)
221 , fadeFraction(_T(""))
233 , directionParm(_T(""))
240 , rotationFrom(_T(""))
247 , customParms(_T(""))
252 , randomDistribution(TRUE)
253 , initialAngle(_T(""))
254 , boundsExpansion(_T(""))
256 , particleMode(FALSE)
258 visualization = TESTMODEL;
262 CDialogParticleEditor::~CDialogParticleEditor() {
265 void CDialogParticleEditor::DoDataExchange(CDataExchange* pDX) {
266 CDialog::DoDataExchange(pDX);
267 DDX_Text(pDX, IDC_EDIT_DEPTHHACK, depthHack);
268 DDX_Check(pDX, IDC_CHECK_WORLDGRAVITY, worldGravity);
269 DDX_Check(pDX, IDC_CHECK_ENTITYCOLOR, entityColor);
270 DDX_Control(pDX, IDC_COMBO_PARTICLES, comboParticle);
271 DDX_Control(pDX, IDC_LIST_STAGES, listStages);
272 DDX_Text(pDX, IDC_COMBO_CUSTOMPATH, customPath );
273 DDX_Text(pDX, IDC_EDIT_CUSTOMPARMS, customParms );
274 DDX_Text(pDX, IDC_EDIT_MATERIAL, matName);
275 DDX_Text(pDX, IDC_EDIT_ANIMFRAMES, animFrames);
276 DDX_Text(pDX, IDC_EDIT_ANIMRATE, animRate);
277 DDX_Text(pDX, IDC_EDIT_COLOR, color);
278 DDX_Text(pDX, IDC_EDIT_FADECOLOR, fadeColor);
279 DDX_Text(pDX, IDC_EDIT_FADEIN, fadeIn);
280 DDX_Text(pDX, IDC_EDIT_FADEOUT, fadeOut);
281 DDX_Text(pDX, IDC_EDIT_FADEFRACTION, fadeFraction);
282 DDX_Text(pDX, IDC_EDIT_COUNT, count);
283 DDX_Text(pDX, IDC_EDIT_TIME, time);
284 DDX_Text(pDX, IDC_EDIT_TIMEOFFSET, timeOffset);
285 DDX_Text(pDX, IDC_EDIT_DEADTIME, deadTime);
286 DDX_Text(pDX, IDC_EDIT_GRAVITY, gravity);
287 DDX_Text(pDX, IDC_EDIT_BUNCHING, bunching);
288 DDX_Text(pDX, IDC_EDIT_OFFSET, offset);
289 DDX_Text(pDX, IDC_EDIT_XSIZE, xSize);
290 DDX_Text(pDX, IDC_EDIT_YSIZE, ySize);
291 DDX_Text(pDX, IDC_EDIT_ZSIZE, zSize);
292 DDX_Text(pDX, IDC_EDIT_RINGOFFSET, ringOffset);
293 DDX_Text(pDX, IDC_EDIT_CYCLES, cycles);
294 DDX_Control(pDX, IDC_STATIC_DIRPARM, staticDirectionParm);
295 DDX_Text(pDX, IDC_EDIT_DIRECTIONPARM, directionParm);
296 DDX_Text(pDX, IDC_EDIT_SPEEDFROM, speedFrom);
297 DDX_Text(pDX, IDC_EDIT_SPEEDTO, speedTo);
298 DDX_Text(pDX, IDC_EDIT_ROTATIONFROM, rotationFrom);
299 DDX_Text(pDX, IDC_EDIT_ROTATIONTO, rotationTo);
300 DDX_Text(pDX, IDC_EDIT_SIZEFROM, sizeFrom);
301 DDX_Text(pDX, IDC_EDIT_SIZETO, sizeTo);
302 DDX_Text(pDX, IDC_EDIT_ASPECTFROM, aspectFrom);
303 DDX_Text(pDX, IDC_EDIT_ASPECTTO, aspectTo);
304 DDX_Text(pDX, IDC_EDIT_ORIENTATIONPARM1, trails);
305 DDX_Text(pDX, IDC_EDIT_ORIENTATIONPARM2, trailTime);
306 DDX_Check(pDX, IDC_CHECK_RANDOMDISTRIBUTION, randomDistribution);
307 DDX_Text(pDX, IDC_EDIT_INITIALANGLE, initialAngle);
308 DDX_Text(pDX, IDC_EDIT_BOUNDSEXPANSION, boundsExpansion);
309 DDX_Text(pDX, IDC_STATIC_DESC, customDesc);
310 DDX_Control(pDX, IDC_EDIT_RINGOFFSET, editRingOffset);
311 DDX_Radio(pDX, IDC_RADIO_RECT, distribution);
312 DDX_Radio(pDX, IDC_RADIO_CONE, direction);
313 DDX_Radio(pDX, IDC_RADIO_VIEW, orientation);
314 DDX_Control(pDX, IDC_SLIDER_BUNCHING, sliderBunching);
315 DDX_Control(pDX, IDC_SLIDER_FADEIN, sliderFadeIn);
316 DDX_Control(pDX, IDC_SLIDER_FADEOUT, sliderFadeOut);
317 DDX_Control(pDX, IDC_SLIDER_FADEFRACTION, sliderFadeFraction);
318 DDX_Control(pDX, IDC_SLIDER_COUNT, sliderCount);
319 DDX_Control(pDX, IDC_SLIDER_TIME, sliderTime);
320 DDX_Control(pDX, IDC_SLIDER_GRAVITY, sliderGravity);
321 DDX_Control(pDX, IDC_SLIDER_SPEEDFROM, sliderSpeedFrom);
322 DDX_Control(pDX, IDC_SLIDER_SPEEDTO, sliderSpeedTo);
323 DDX_Control(pDX, IDC_SLIDER_ROTATIONFROM, sliderRotationFrom);
324 DDX_Control(pDX, IDC_SLIDER_ROTATIONTO, sliderRotationTo);
325 DDX_Control(pDX, IDC_SLIDER_SIZEFROM, sliderSizeFrom);
326 DDX_Control(pDX, IDC_SLIDER_SIZETO, sliderSizeTo);
327 DDX_Control(pDX, IDC_SLIDER_ASPECTFROM, sliderAspectFrom);
328 DDX_Control(pDX, IDC_SLIDER_ASPECTTO, sliderAspectTo);
329 DDX_Control(pDX, IDC_BUTTON_VECTOR, vectorControl);
333 BEGIN_MESSAGE_MAP(CDialogParticleEditor, CDialog)
334 ON_BN_CLICKED(IDC_BUTTON_ADDSTAGE, OnBnClickedButtonAddstage)
335 ON_BN_CLICKED(IDC_BUTTON_REMOVESTAGE, OnBnClickedButtonRemovestage)
336 ON_BN_CLICKED(IDC_BUTTON_BROWSEMATERIAL, OnBnClickedButtonBrowsematerial)
337 ON_BN_CLICKED(IDC_BUTTON_BROWSECOLOR, OnBnClickedButtonBrowsecolor)
338 ON_BN_CLICKED(IDC_BUTTON_BROWSEFADECOLOR, OnBnClickedButtonBrowsefadecolor)
339 ON_BN_CLICKED(IDC_BUTTON_BROWSECOLOR_ENTITY, OnBnClickedButtonBrowseEntitycolor)
340 ON_BN_CLICKED(IDC_BUTTON_UPDATE, OnBnClickedButtonUpdate)
341 ON_CBN_SELCHANGE(IDC_COMBO_PARTICLES, OnCbnSelchangeComboParticles)
342 ON_CBN_SELCHANGE(IDC_COMBO_CUSTOMPATH, OnCbnSelchangeComboPath)
343 ON_BN_CLICKED(IDC_RADIO_RECT, OnBnClickedRadioRect)
344 ON_BN_CLICKED(IDC_RADIO_SPHERE, OnBnClickedRadioSphere)
345 ON_BN_CLICKED(IDC_RADIO_CYLINDER, OnBnClickedRadioCylinder)
346 ON_BN_CLICKED(IDC_RADIO_CONE, OnBnClickedRadioCone)
347 ON_BN_CLICKED(IDC_RADIO_OUTWARD, OnBnClickedRadioOutward)
348 ON_BN_CLICKED(IDC_RADIO_VIEW, OnBnClickedRadioView)
349 ON_BN_CLICKED(IDC_RADIO_AIMED, OnBnClickedRadioAimed)
350 ON_BN_CLICKED(IDC_RADIO_X, OnBnClickedRadioX)
351 ON_BN_CLICKED(IDC_RADIO_Y, OnBnClickedRadioY)
352 ON_BN_CLICKED(IDC_RADIO_Z, OnBnClickedRadioZ)
353 ON_BN_CLICKED(IDC_BUTTON_HIDESTAGE, OnBnClickedButtonHidestage)
354 ON_BN_CLICKED(IDC_BUTTON_SHOWSTAGE, OnBnClickedButtonShowstage)
355 ON_BN_CLICKED(IDC_CHECK_WORLDGRAVITY, OnBnClickedWorldGravity)
356 ON_BN_CLICKED(IDC_CHECK_ENTITYCOLOR, OnBnClickedEntityColor)
357 ON_LBN_SELCHANGE(IDC_LIST_STAGES, OnLbnSelchangeListStages)
358 ON_BN_CLICKED(IDC_BUTTON_NEW, OnBnClickedButtonNew)
359 ON_BN_CLICKED(IDC_BUTTON_SAVE_PARTICLE, OnBnClickedButtonSave)
360 ON_BN_CLICKED(IDC_BUTTON_SAVE_PARTICLE_AS, OnBnClickedButtonSaveAs)
361 ON_BN_CLICKED(IDC_BUTTON_SAVE_PARTICLEENTITIES, OnBnClickedButtonSaveParticles)
362 ON_BN_CLICKED(IDC_BUTTON_TESTMODEL, OnBnClickedTestModel)
363 ON_BN_CLICKED(IDC_BUTTON_IMPACT, OnBnClickedImpact)
364 ON_BN_CLICKED(IDC_BUTTON_MUZZLE, OnBnClickedMuzzle)
365 ON_BN_CLICKED(IDC_BUTTON_FLIGHT, OnBnClickedFlight)
366 ON_BN_CLICKED(IDC_BUTTON_SELECTED, OnBnClickedSelected)
367 ON_BN_CLICKED(IDC_BUTTON_DOOM, OnBnClickedDoom)
368 ON_BN_CLICKED(IDC_CHECK_EDITPARTICLEMODE, OnBnClickedParticleMode)
369 ON_BN_CLICKED(IDC_BUTTON_DROPEMITTER, OnBtnDrop)
370 ON_BN_CLICKED(IDC_BUTTON_YUP, OnBtnYup)
371 ON_BN_CLICKED(IDC_BUTTON_YDN, OnBtnYdn)
372 ON_BN_CLICKED(IDC_BUTTON_XDN, OnBtnXdn)
373 ON_BN_CLICKED(IDC_BUTTON_XUP, OnBtnXup)
374 ON_BN_CLICKED(IDC_BUTTON_ZUP, OnBtnZup)
375 ON_BN_CLICKED(IDC_BUTTON_ZDN, OnBtnZdn)
380 // CDialogParticleEditor message handlers
382 void CDialogParticleEditor::OnBnClickedParticleMode() {
383 particleMode = !particleMode;
384 cvarSystem->SetCVarInteger( "g_editEntityMode", ( particleMode ) ? 4 : 0 );
385 EnableEditControls();
389 void CDialogParticleEditor::OnBnClickedButtonSaveAs() {
390 idDeclParticle *idp = GetCurParticle();
394 DialogName dlg("New Particle");
395 if (dlg.DoModal() == IDOK) {
396 if ( declManager->FindType( DECL_PARTICLE, dlg.m_strName, false ) ) {
397 MessageBox( "Particle already exists!", "Particle exists", MB_OK );
400 CFileDialog dlgSave( TRUE, "prt", NULL, OFN_CREATEPROMPT, "Particle Files (*.prt)|*.prt||All Files (*.*)|*.*||", AfxGetMainWnd() );
401 if ( dlgSave.DoModal() == IDOK ) {
403 fileName = fileSystem->OSPathToRelativePath( dlgSave.m_ofn.lpstrFile );
404 idDeclParticle *decl = dynamic_cast<idDeclParticle*>( declManager->CreateNewDecl( DECL_PARTICLE, dlg.m_strName, fileName ) );
406 decl->stages.DeleteContents( true );
407 decl->depthHack = idp->depthHack;
408 for ( int i = 0; i < idp->stages.Num(); i++ ) {
409 idParticleStage *stage = new idParticleStage();
410 *stage = *idp->stages[i];
411 decl->stages.Append( stage );
414 int index = comboParticle.FindStringExact( -1, dlg.m_strName );
416 comboParticle.SetCurSel( index );
418 OnBnClickedButtonSave();
419 OnCbnSelchangeComboParticles();
420 OnBnClickedButtonUpdate();
427 void CDialogParticleEditor::OnBnClickedButtonSaveParticles() {
428 cmdSystem->BufferCommandText( CMD_EXEC_NOW, "saveParticles" );
429 CWnd *wnd = GetDlgItem( IDC_BUTTON_SAVE_PARTICLEENTITIES );
431 wnd->EnableWindow( FALSE );
435 void CDialogParticleEditor::OnBnClickedButtonAddstage() {
439 void CDialogParticleEditor::OnBnClickedButtonRemovestage() {
443 void CDialogParticleEditor::OnBnClickedButtonBrowsematerial() {
444 CPreviewDlg matDlg( this );
445 matDlg.SetMode(CPreviewDlg::MATERIALS, "particles" );
446 matDlg.SetDisablePreview( true );
447 if ( matDlg.DoModal() == IDOK ) {
448 matName = matDlg.mediaName;
454 void CDialogParticleEditor::OnBnClickedButtonBrowsecolor() {
457 idParticleStage *ps = GetCurStage();
461 r = ps->color.x * 255.0f;
462 g = ps->color.y * 255.0f;
463 b = ps->color.z * 255.0f;
465 if ( DoNewColor( &r, &g, &b, &ob ) ) {
466 color.Format( "%f %f %f %f", (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, 1.0f );
472 void CDialogParticleEditor::OnBnClickedButtonBrowseEntitycolor() {
475 idList<idEntity*> list;
479 int count = gameEdit->GetSelectedEntities( list.Ptr(), list.Num() );
480 list.SetNum( count );
483 const idDict *dict = gameEdit->EntityGetSpawnArgs( list[0] );
485 idVec3 clr = dict->GetVector( "_color", "1 1 1" );
490 if ( DoNewColor( &r, &g, &b, &ob ) ) {
491 for ( int i = 0; i < count; i++ ) {
492 dict = gameEdit->EntityGetSpawnArgs( list[i] );
493 const char *name = dict->GetString( "name" );
494 idEntity *ent = gameEdit->FindEntity( name );
496 gameEdit->EntitySetColor( ent, idVec3( (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f ) );
497 str = va( "%f %f %f", (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f );
499 dict2.Set( "_color", str );
500 gameEdit->EntityChangeSpawnArgs( ent, &dict2 );
501 gameEdit->MapSetEntityKeyVal( name, "_color", str );
506 CWnd *wnd = GetDlgItem( IDC_BUTTON_SAVE_PARTICLEENTITIES );
508 wnd->EnableWindow( TRUE );
514 void CDialogParticleEditor::OnBnClickedButtonBrowsefadecolor() {
517 idParticleStage *ps = GetCurStage();
521 r = ps->fadeColor.x * 255.0f;
522 g = ps->fadeColor.y * 255.0f;
523 b = ps->fadeColor.z * 255.0f;
525 if ( DoNewColor( &r, &g, &b, &ob ) ) {
526 fadeColor.Format( "%f %f %f %f", (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, 1.0f );
532 void CDialogParticleEditor::OnBnClickedButtonUpdate() {
538 void CDialogParticleEditor::SelectParticle( const char *name ) {
539 int index = comboParticle.FindString( 0, name );
541 comboParticle.SetCurSel( index );
542 UpdateParticleData();
546 idDeclParticle *CDialogParticleEditor::GetCurParticle() {
547 int sel = comboParticle.GetCurSel();
548 if ( sel == CB_ERR ) {
551 int index = comboParticle.GetItemData( sel );
552 return static_cast<idDeclParticle *>( const_cast<idDecl *>( declManager->DeclByIndex( DECL_PARTICLE, index ) ) );
555 void CDialogParticleEditor::UpdateParticleData() {
557 listStages.ResetContent();
558 idDeclParticle *idp = GetCurParticle();
562 for ( int i = 0; i < idp->stages.Num(); i++ ) {
563 int index = listStages.AddString( va( "stage %i", i ) );
565 listStages.SetItemData( index, i );
568 listStages.SetCurSel( 0 );
569 OnLbnSelchangeListStages();
570 CWnd *wnd = GetDlgItem( IDC_STATIC_INFILE );
572 wnd->SetWindowText( va( "Particle file: %s", idp->GetFileName() ) );
578 void CDialogParticleEditor::OnCbnSelchangeComboParticles() {
579 UpdateParticleData();
583 void CDialogParticleEditor::OnCbnSelchangeComboPath() {
589 void CDialogParticleEditor::UpdateControlInfo() {
590 CWnd *wnd = GetDlgItem( IDC_EDIT_RINGOFFSET );
592 wnd->EnableWindow( distribution == 2 );
594 wnd = GetDlgItem( IDC_STATIC_DIRPARM );
596 wnd->SetWindowText( (direction == 0 ) ? "Angle" : "Upward Bias" );
598 wnd = GetDlgItem( IDC_EDIT_ORIENTATIONPARM1 );
600 wnd->EnableWindow( orientation == 1 );
602 wnd = GetDlgItem( IDC_EDIT_ORIENTATIONPARM2 );
604 wnd->EnableWindow( orientation == 1 );
607 idParticleStage *ps = GetCurStage();
611 sliderBunching.SetValuePos( ps->spawnBunching );
612 sliderFadeIn.SetValuePos( ps->fadeInFraction );
613 sliderFadeOut.SetValuePos( ps->fadeOutFraction );
614 sliderFadeFraction.SetValuePos( ps->fadeIndexFraction );
615 sliderCount.SetValuePos( ps->totalParticles );
616 sliderTime.SetValuePos( ps->particleLife );
617 sliderGravity.SetValuePos( ps->gravity );
618 sliderSpeedFrom.SetValuePos( ps->speed.from );
619 sliderSpeedTo.SetValuePos( ps->speed.to );
620 sliderRotationFrom.SetValuePos( ps->rotationSpeed.from );
621 sliderRotationTo.SetValuePos( ps->rotationSpeed.to );
622 sliderSizeFrom.SetValuePos( ps->size.from );
623 sliderSizeTo.SetValuePos( ps->size.to );
624 sliderAspectFrom.SetValuePos( ps->aspect.from );
625 sliderAspectTo.SetValuePos( ps->aspect.to );
628 void CDialogParticleEditor::OnBnClickedRadioRect() {
635 void CDialogParticleEditor::OnBnClickedRadioSphere() {
642 void CDialogParticleEditor::OnBnClickedRadioCylinder() {
649 void CDialogParticleEditor::OnBnClickedRadioCone() {
656 void CDialogParticleEditor::OnBnClickedRadioOutward() {
663 void CDialogParticleEditor::OnBnClickedRadioView() {
670 void CDialogParticleEditor::OnBnClickedRadioAimed() {
677 void CDialogParticleEditor::OnBnClickedRadioX() {
684 void CDialogParticleEditor::OnBnClickedRadioY() {
691 void CDialogParticleEditor::OnBnClickedRadioZ() {
698 void CDialogParticleEditor::OnBnClickedDoom() {
699 ::SetFocus(win32.hWnd);
703 void CDialogParticleEditor::OnBnClickedTestModel() {
704 visualization = TESTMODEL;
708 void CDialogParticleEditor::OnBnClickedImpact() {
709 visualization = IMPACT;
713 void CDialogParticleEditor::OnBnClickedMuzzle(){
714 visualization = MUZZLE;
718 void CDialogParticleEditor::OnBnClickedFlight() {
719 visualization = FLIGHT;
723 void CDialogParticleEditor::OnBnClickedSelected() {
724 visualization = SELECTED;
728 void CDialogParticleEditor::SetParticleVisualization( int i ) {
733 void CDialogParticleEditor::SetParticleView() {
734 idDeclParticle *idp = GetCurParticle();
738 cmdSystem->BufferCommandText( CMD_EXEC_NOW, "testmodel" );
740 switch ( visualization ) {
742 str = idp->GetName();
743 str.SetFileExtension( ".prt" );
744 cmdSystem->BufferCommandText( CMD_EXEC_NOW, va("testmodel %s\n", str.c_str() ) );
747 str = idp->GetName();
748 str.SetFileExtension( ".prt" );
749 cvarSystem->SetCVarInteger( "g_testParticle", TEST_PARTICLE_IMPACT );
750 cvarSystem->SetCVarString( "g_testParticleName", str );
753 str = idp->GetName();
754 str.SetFileExtension( ".prt" );
755 cvarSystem->SetCVarInteger( "g_testParticle", TEST_PARTICLE_MUZZLE );
756 cvarSystem->SetCVarString( "g_testParticleName", str );
759 str = idp->GetName();
760 str.SetFileExtension( ".prt" );
761 cvarSystem->SetCVarInteger( "g_testParticle", TEST_PARTICLE_FLIGHT );
762 cvarSystem->SetCVarString( "g_testParticleName", str );
765 str = idp->GetName();
766 str.SetFileExtension( ".prt" );
767 cvarSystem->SetCVarInteger( "g_testParticle", TEST_PARTICLE_FLIGHT );
768 SetSelectedModel( str );
773 void CDialogParticleEditor::SetSelectedModel( const char *val ) {
774 idList<idEntity*> list;
778 int count = gameEdit->GetSelectedEntities( list.Ptr(), list.Num() );
779 list.SetNum( count );
782 for ( int i = 0; i < count; i++ ) {
783 const idDict *dict = gameEdit->EntityGetSpawnArgs( list[i] );
784 if ( dict == NULL ) {
787 const char *name = dict->GetString( "name" );
788 gameEdit->EntitySetModel( list[i], val );
789 gameEdit->EntityUpdateVisuals( list[i] );
790 gameEdit->EntityGetAxis( list[i], axis );
791 vectorControl.SetidAxis( axis );
792 gameEdit->MapSetEntityKeyVal( name, "model", val );
794 CWnd *wnd = GetDlgItem( IDC_BUTTON_SAVE_PARTICLEENTITIES );
796 wnd->EnableWindow( TRUE );
802 void CDialogParticleEditor::OnBnClickedButtonHidestage() {
806 void CDialogParticleEditor::OnBnClickedButtonShowstage() {
811 void CDialogParticleEditor::OnBnClickedWorldGravity() {
812 worldGravity = !worldGravity;
817 void CDialogParticleEditor::OnBnClickedEntityColor() {
818 entityColor = !entityColor;
824 void CDialogParticleEditor::AddStage() {
826 idDeclParticle *idp = GetCurParticle();
831 idParticleStage *stage = new idParticleStage;
833 if ((GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
834 idParticleStage *source = GetCurStage();
835 if ( source == NULL ) {
843 int newIndex = idp->stages.Append( stage );
844 int index = listStages.AddString( va( "stage %i", newIndex ) );
845 listStages.SetCurSel( index );
846 listStages.SetItemData( index, newIndex );
848 EnableStageControls();
851 void CDialogParticleEditor::RemoveStage() {
852 idDeclParticle *idp = GetCurParticle();
857 if ( MessageBox( "Are you sure you want to remove this stage?", "Remove Stage", MB_YESNO | MB_ICONQUESTION ) != IDYES ) {
861 int index = listStages.GetCurSel();
863 int newIndex = listStages.GetItemData( index );
864 if ( newIndex >= 0 && newIndex < idp->stages.Num() ) {
865 idp->stages.RemoveIndex( newIndex );
866 index += ( index >= 1 ) ? -1 : 1;
867 newIndex = comboParticle.FindStringExact( -1, idp->GetName() );
869 if ( newIndex >= 0 ) {
870 comboParticle.SetCurSel( newIndex );
872 OnCbnSelchangeComboParticles();
873 listStages.SetCurSel( index );
877 EnableStageControls();
880 void CDialogParticleEditor::ShowStage() {
881 idParticleStage *ps = GetCurStage();
886 int index = listStages.GetCurSel();
887 int newIndex = listStages.GetItemData( index );
888 listStages.DeleteString ( index );
889 listStages.InsertString( index, va("stage %i", index ) );
890 listStages.SetItemData( index, newIndex );
891 listStages.SetCurSel( index );
892 EnableStageControls();
895 void CDialogParticleEditor::HideStage() {
896 idParticleStage *ps = GetCurStage();
901 int index = listStages.GetCurSel();
902 int newIndex = listStages.GetItemData( index );
903 listStages.DeleteString ( index );
904 listStages.InsertString( index, va("stage %i (H) ", index ) );
905 listStages.SetItemData( index, newIndex );
906 listStages.SetCurSel( index );
907 EnableStageControls();
910 idParticleStage *CDialogParticleEditor::GetCurStage() {
911 idDeclParticle *idp = GetCurParticle();
912 int sel = listStages.GetCurSel();
913 int index = listStages.GetItemData( sel );
914 if ( idp == NULL || sel == LB_ERR || index >= idp->stages.Num() ) {
917 return idp->stages[index];
920 void CDialogParticleEditor::ClearDlgVars() {
956 worldGravity = FALSE;
958 randomDistribution = TRUE;
964 void CDialogParticleEditor::CurStageToDlgVars() {
966 // go ahead and get the two system vars too
967 idDeclParticle *idp = GetCurParticle();
972 depthHack = va( "%.3f", idp->depthHack );
974 idParticleStage *ps = GetCurStage();
978 matName = ps->material->GetName();
979 animFrames = va( "%i", ps->animationFrames );
980 animRate = va( "%i", ps->animationRate );
981 color = ps->color.ToString();
982 fadeColor = ps->fadeColor.ToString();
983 fadeIn = va( "%.3f", ps->fadeInFraction );
984 fadeOut = va( "%.3f", ps->fadeOutFraction );
985 fadeFraction = va( "%.3f", ps->fadeIndexFraction );
986 count = va( "%i", ps->totalParticles );
987 time = va( "%.3f", ps->particleLife );
988 timeOffset = va( "%.3f", ps->timeOffset );
989 deadTime = va( "%.3f", ps->deadTime );
990 gravity = va( "%.3f", ps->gravity );
991 bunching = va( "%.3f", ps->spawnBunching );
992 offset = ps->offset.ToString( 0 );
993 xSize = va( "%.3f", ps->distributionParms[0] );
994 ySize = va( "%.3f", ps->distributionParms[1] );
995 zSize = va( "%.3f", ps->distributionParms[2] );
996 ringOffset = va( "%.3f", ps->distributionParms[3] );
997 directionParm = va( "%.3f", ps->directionParms[0] );
998 direction = ps->directionType;
999 orientation = ps->orientation;
1000 distribution = ps->distributionType;
1001 speedFrom = va( "%.3f", ps->speed.from );
1002 speedTo = va( "%.3f", ps->speed.to );
1003 rotationFrom = va( "%.3f", ps->rotationSpeed.from );
1004 rotationTo = va( "%.3f", ps->rotationSpeed.to );
1005 sizeFrom = va( "%.3f", ps->size.from );
1006 sizeTo = va( "%.3f", ps->size.to );
1007 aspectFrom = va( "%.3f", ps->aspect.from );
1008 aspectTo = va( "%.3f", ps->aspect.to );
1009 trails = va( "%f", ps->orientationParms[0] );
1010 trailTime = va( "%.3f", ps->orientationParms[1] );
1011 cycles = va( "%.3f", ps->cycles );
1012 customPath = ps->GetCustomPathName();
1014 customDesc = ps->GetCustomPathDesc();
1015 if ( ps->customPathType != PPATH_STANDARD ) {
1016 for ( int i = 0; i < ps->NumCustomPathParms(); i++ ) {
1017 customParms += va( "%.1f ", ps->customPathParms[i] );
1020 worldGravity = ps->worldGravity;
1021 initialAngle = va( "%.3f", ps->initialAngle );
1022 boundsExpansion = va( "%.3f", ps->boundsExpansion );
1023 randomDistribution = ps->randomDistribution;
1024 entityColor = ps->entityColor;
1025 UpdateData( FALSE );
1028 void CDialogParticleEditor::DlgVarsToCurStage() {
1030 // go ahead and set the two system vars too
1031 idDeclParticle *idp = GetCurParticle();
1032 if ( idp == NULL ) {
1035 idp->depthHack = atof( depthHack );
1037 idParticleStage *ps = GetCurStage();
1041 ps->material = declManager->FindMaterial( matName );
1042 ps->animationFrames = atoi( animFrames );
1043 ps->animationRate = atoi( animRate );
1044 sscanf( color, "%f %f %f %f", &ps->color.x, &ps->color.y, &ps->color.z, &ps->color.w );
1045 sscanf( fadeColor, "%f %f %f %f", &ps->fadeColor.x, &ps->fadeColor.y, &ps->fadeColor.z, &ps->fadeColor.w );
1046 ps->fadeInFraction = atof( fadeIn );
1047 ps->fadeOutFraction = atof( fadeOut );
1048 ps->fadeIndexFraction = atof( fadeFraction );
1049 ps->totalParticles = atoi( count );
1050 ps->particleLife = atof( time );
1051 ps->timeOffset = atof( timeOffset );
1052 ps->deadTime = atof( deadTime );
1053 ps->gravity = atof( gravity );
1054 ps->spawnBunching = atof( bunching );
1055 sscanf( offset, "%f %f %f", &ps->offset.x, &ps->offset.y, &ps->offset.z );
1056 ps->distributionParms[0] = atof( xSize );
1057 ps->distributionParms[1] = atof( ySize );
1058 ps->distributionParms[2] = atof( zSize );
1059 ps->distributionParms[3] = atof( ringOffset );
1060 ps->directionParms[0] = atof( directionParm );
1061 ps->directionType = static_cast<prtDirection_t>( direction );
1062 ps->orientation = static_cast<prtOrientation_t>( orientation );
1063 ps->distributionType = static_cast<prtDistribution_t>( distribution );
1064 ps->speed.from = atof( speedFrom );
1065 ps->speed.to = atof( speedTo );
1066 ps->rotationSpeed.from = atof( rotationFrom );
1067 ps->rotationSpeed.to = atof( rotationTo );
1068 ps->size.from = atof( sizeFrom );
1069 ps->size.to = atof( sizeTo );
1070 ps->aspect.from = atof( aspectFrom );
1071 ps->aspect.to = atof( aspectTo );
1072 ps->orientationParms[0] = atof( trails );
1073 ps->orientationParms[1] = atof( trailTime );
1074 ps->worldGravity = ( worldGravity == TRUE );
1075 ps->cycles = atof( cycles );
1076 ps->cycleMsec = ( ps->particleLife + ps->deadTime ) * 1000;
1078 sscanf( customParms, "%f %f %f %f %f %f %f %f", &ps->customPathParms[0], &ps->customPathParms[1], &ps->customPathParms[2],
1079 &ps->customPathParms[3], &ps->customPathParms[4], &ps->customPathParms[5],
1080 &ps->customPathParms[6], &ps->customPathParms[7] );
1082 ps->SetCustomPathType( customPath );
1084 ps->initialAngle = atof( initialAngle );
1085 ps->boundsExpansion = atof( boundsExpansion );
1086 ps->randomDistribution = ( randomDistribution != FALSE );
1087 ps->entityColor = ( entityColor == TRUE );
1091 void CDialogParticleEditor::ShowCurrentStage() {
1093 idParticleStage *ps = GetCurStage();
1097 CurStageToDlgVars();
1098 UpdateControlInfo();
1101 void CDialogParticleEditor::OnLbnSelchangeListStages() {
1103 EnableStageControls();
1106 void CDialogParticleEditor::OnBnClickedButtonNew() {
1107 DialogName dlg("New Particle");
1108 if (dlg.DoModal() == IDOK) {
1109 CFileDialog dlgSave( TRUE, "prt", NULL, OFN_CREATEPROMPT, "Particle Files (*.prt)|*.prt||All Files (*.*)|*.*||", AfxGetMainWnd() );
1110 if ( dlgSave.DoModal() == IDOK ) {
1111 if ( declManager->FindType( DECL_PARTICLE, dlg.m_strName, false ) ) {
1112 MessageBox( "Particle already exists!", "Particle exists", MB_OK );
1116 fileName = fileSystem->OSPathToRelativePath( dlgSave.m_ofn.lpstrFile );
1117 idDecl *decl = declManager->CreateNewDecl( DECL_PARTICLE, dlg.m_strName, fileName );
1119 if ( MessageBox( "Copy current particle?", "Copy current", MB_YESNO | MB_ICONQUESTION ) == IDYES ) {
1120 MessageBox( "Copy current particle not implemented yet.. Stay tuned" );
1123 int index = comboParticle.FindStringExact( -1, dlg.m_strName );
1125 comboParticle.SetCurSel( index );
1127 OnBnClickedButtonSave();
1128 OnCbnSelchangeComboParticles();
1134 void CDialogParticleEditor::OnBnClickedButtonSave() {
1135 idDeclParticle *idp = GetCurParticle();
1136 if ( idp == NULL ) {
1140 if ( strstr( idp->GetFileName(), "implicit" ) ) {
1141 // defaulted, need to choose a file
1142 CFileDialog dlgSave( FALSE, "prt", NULL, OFN_OVERWRITEPROMPT, "Particle Files (*.prt)|*.prt||All Files (*.*)|*.*||", AfxGetMainWnd() );
1143 if ( dlgSave.DoModal() == IDOK ) {
1145 fileName = fileSystem->OSPathToRelativePath( dlgSave.m_ofn.lpstrFile );
1146 idp->Save( fileName );
1155 void CDialogParticleEditor::EnumParticles() {
1157 comboParticle.ResetContent();
1158 for ( int i = 0; i < declManager->GetNumDecls( DECL_PARTICLE ); i++ ) {
1159 const idDecl *idp = declManager->DeclByIndex( DECL_PARTICLE, i );
1160 int index = comboParticle.AddString( idp->GetName() );
1162 comboParticle.SetItemData( index, i );
1165 comboParticle.SetCurSel( 0 );
1166 OnCbnSelchangeComboParticles();
1169 void CDialogParticleEditor::OnDestroy() {
1170 com_editors &= ~EDITOR_PARTICLE;
1171 return CDialog::OnDestroy();
1174 void VectorCallBack( idQuat rotation ) {
1175 if ( g_ParticleDialog && g_ParticleDialog->GetSafeHwnd() ) {
1176 g_ParticleDialog->SetVectorControlUpdate( rotation );
1180 void CDialogParticleEditor::SetVectorControlUpdate( idQuat rotation ) {
1181 if ( particleMode ) {
1182 idList<idEntity*> list;
1185 int count = gameEdit->GetSelectedEntities( list.Ptr(), list.Num() );
1186 list.SetNum( count );
1189 for ( int i = 0; i < count; i++ ) {
1190 const idDict *dict = gameEdit->EntityGetSpawnArgs( list[i] );
1191 if ( dict == NULL ) {
1194 const char *name = dict->GetString( "name" );
1195 gameEdit->EntitySetAxis( list[i], rotation.ToMat3() );
1196 gameEdit->EntityUpdateVisuals( list[i] );
1197 gameEdit->MapSetEntityKeyVal( name, "rotation", rotation.ToMat3().ToString() );
1199 CWnd *wnd = GetDlgItem( IDC_BUTTON_SAVE_PARTICLEENTITIES );
1201 wnd->EnableWindow( TRUE );
1207 BOOL CDialogParticleEditor::OnInitDialog() {
1209 com_editors |= EDITOR_PARTICLE;
1211 particleMode = ( cvarSystem->GetCVarInteger( "g_editEntityMode" ) == 4 );
1212 mapModified = false;
1214 CDialog::OnInitDialog();
1216 sliderBunching.SetRange( 0, 20 );
1217 sliderBunching.SetValueRange( 0.0f, 1.0f );
1218 sliderFadeIn.SetRange( 0, 20 );
1219 sliderFadeIn.SetValueRange( 0.0f, 1.0f );
1220 sliderFadeOut.SetRange( 0, 20 );
1221 sliderFadeOut.SetValueRange( 0.0f, 1.0f );
1222 sliderCount.SetRange( 0, 1024 );
1223 sliderCount.SetValueRange( 0, 4096 );
1224 sliderTime.SetRange( 0, 200 );
1225 sliderTime.SetValueRange( 0.0f, 10.0f );
1226 sliderGravity.SetRange( 0, 600 );
1227 sliderGravity.SetValueRange( -300.0f, 300.0f );
1228 sliderSpeedFrom.SetRange( 0, 600 );
1229 sliderSpeedFrom.SetValueRange( -300.0f, 300.0f );
1230 sliderSpeedTo.SetRange( 0, 600 );
1231 sliderSpeedTo.SetValueRange( -300.0f, 300.0f );
1232 sliderRotationFrom.SetRange( 0, 100 );
1233 sliderRotationFrom.SetValueRange( 0.0f, 100.0f );
1234 sliderRotationTo.SetRange( 0, 100 );
1235 sliderRotationTo.SetValueRange( 0.0f, 100.0f );
1236 sliderSizeFrom.SetRange( 0, 256 );
1237 sliderSizeFrom.SetValueRange( 0.0f, 128.0f );
1238 sliderSizeTo.SetRange( 0, 256 );
1239 sliderSizeTo.SetValueRange( 0.0f, 128.0f );
1240 sliderAspectFrom.SetRange( 0, 256 );
1241 sliderAspectFrom.SetValueRange( 0.0f, 128.0f );
1242 sliderAspectTo.SetRange( 0, 256 );
1243 sliderAspectTo.SetValueRange( 0.0f, 128.0f );
1244 sliderFadeFraction.SetRange( 0, 20 );
1245 sliderFadeFraction.SetValueRange( 0.0f, 1.0f );
1250 toolTipCtrl.Create( this );
1251 toolTipCtrl.Activate( TRUE );
1253 CWnd* wnd = GetWindow( GW_CHILD );
1256 if ( str.LoadString( wnd->GetDlgCtrlID() ) ) {
1257 toolTipCtrl.AddTool( wnd, str );
1259 wnd = wnd->GetWindow( GW_HWNDNEXT );
1262 wnd = GetDlgItem( IDC_BUTTON_SAVE_PARTICLEENTITIES );
1264 wnd->EnableWindow( FALSE );
1266 EnableEditControls();
1268 vectorControl.SetVectorChangingCallback( VectorCallBack );
1270 return TRUE; // return TRUE unless you set the focus to a control
1271 // EXCEPTION: OCX Property Pages should return FALSE
1274 void CDialogParticleEditor::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar ) {
1275 CDialog::OnHScroll( nSBCode, nPos, pScrollBar );
1276 CSliderCtrl *ctrl = dynamic_cast< CSliderCtrl* >( pScrollBar );
1280 if ( ctrl == &sliderBunching ) {
1282 bunching = va( "%.3f", sliderBunching.GetValue() );
1283 DlgVarsToCurStage();
1284 CurStageToDlgVars();
1285 } else if ( ctrl == &sliderFadeIn ) {
1286 fadeIn = va( "%.3f", sliderFadeIn.GetValue() );
1287 DlgVarsToCurStage();
1288 CurStageToDlgVars();
1289 } else if ( ctrl == &sliderFadeOut ) {
1290 fadeOut = va( "%.3f", sliderFadeOut.GetValue() );
1291 DlgVarsToCurStage();
1292 CurStageToDlgVars();
1293 } else if ( ctrl == &sliderFadeFraction ) {
1294 fadeFraction = va( "%.3f", sliderFadeFraction.GetValue() );
1295 DlgVarsToCurStage();
1296 CurStageToDlgVars();
1297 } else if ( ctrl == &sliderCount ) {
1298 count = va( "%i", (int)sliderCount.GetValue() );
1299 DlgVarsToCurStage();
1300 CurStageToDlgVars();
1301 } else if ( ctrl == &sliderTime ) {
1302 time = va( "%.3f", sliderTime.GetValue() );
1303 DlgVarsToCurStage();
1304 CurStageToDlgVars();
1305 } else if ( ctrl == &sliderGravity ) {
1306 gravity = va( "%.3f", sliderGravity.GetValue() );
1307 DlgVarsToCurStage();
1308 CurStageToDlgVars();
1309 } else if ( ctrl == &sliderSpeedFrom ) {
1310 speedFrom = va( "%.3f", sliderSpeedFrom.GetValue() );
1311 DlgVarsToCurStage();
1312 CurStageToDlgVars();
1313 } else if ( ctrl == &sliderSpeedTo ) {
1314 speedTo = va( "%.3f", sliderSpeedTo.GetValue() );
1315 DlgVarsToCurStage();
1316 CurStageToDlgVars();
1317 } else if ( ctrl == &sliderRotationFrom ) {
1318 rotationFrom = va( "%.3f", sliderRotationFrom.GetValue() );
1319 DlgVarsToCurStage();
1320 CurStageToDlgVars();
1321 } else if ( ctrl == &sliderRotationTo ) {
1322 rotationTo = va( "%.3f", sliderRotationTo.GetValue() );
1323 DlgVarsToCurStage();
1324 CurStageToDlgVars();
1325 } else if ( ctrl == &sliderSizeFrom ) {
1326 sizeFrom = va( "%.3f", sliderSizeFrom.GetValue() );
1327 DlgVarsToCurStage();
1328 CurStageToDlgVars();
1329 } else if ( ctrl == &sliderSizeTo ) {
1330 sizeTo = va( "%.3f", sliderSizeTo.GetValue() );
1331 DlgVarsToCurStage();
1332 CurStageToDlgVars();
1333 } else if ( ctrl == &sliderAspectFrom ) {
1334 aspectFrom = va( "%.3f", sliderAspectFrom.GetValue() );
1335 DlgVarsToCurStage();
1336 CurStageToDlgVars();
1337 } else if ( ctrl == &sliderAspectTo ) {
1338 aspectTo = va( "%.3f", sliderAspectTo.GetValue() );
1339 DlgVarsToCurStage();
1340 CurStageToDlgVars();
1345 BOOL CDialogParticleEditor::PreTranslateMessage(MSG *pMsg) {
1346 if ( pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST ) {
1347 toolTipCtrl.RelayEvent( pMsg );
1349 return CDialog::PreTranslateMessage(pMsg);
1352 void CDialogParticleEditor::EnableStageControls() {
1353 idParticleStage *stage = GetCurStage();
1354 bool b = ( stage && stage->hidden ) ? false : true;
1355 for ( int i = 0; i < StageIDCount; i++ ) {
1356 CWnd *wnd = GetDlgItem( StageEnableID[ i ] );
1358 wnd->EnableWindow( b );
1363 void CDialogParticleEditor::EnableEditControls() {
1364 for ( int i = 0; i < EditIDCount; i++ ) {
1365 CWnd *wnd = GetDlgItem( EditEnableID[ i ] );
1367 wnd->EnableWindow( particleMode );
1372 void CDialogParticleEditor::UpdateSelectedOrigin( float x, float y, float z ) {
1373 idList<idEntity*> list;
1375 idVec3 vec(x, y, z);
1378 int count = gameEdit->GetSelectedEntities( list.Ptr(), list.Num() );
1379 list.SetNum( count );
1382 for ( int i = 0; i < count; i++ ) {
1383 const idDict *dict = gameEdit->EntityGetSpawnArgs( list[i] );
1384 if ( dict == NULL ) {
1387 const char *name = dict->GetString( "name" );
1388 gameEdit->EntityTranslate( list[i], vec );
1389 gameEdit->EntityUpdateVisuals( list[i] );
1390 gameEdit->MapEntityTranslate( name, vec );
1392 CWnd *wnd = GetDlgItem( IDC_BUTTON_SAVE_PARTICLEENTITIES );
1394 wnd->EnableWindow( TRUE );
1399 void CDialogParticleEditor::OnBtnYup()
1401 UpdateSelectedOrigin(0, 8, 0);
1404 void CDialogParticleEditor::OnBtnYdn()
1406 UpdateSelectedOrigin(0, -8, 0);
1409 void CDialogParticleEditor::OnBtnXdn()
1411 UpdateSelectedOrigin(-8, 0, 0);
1414 void CDialogParticleEditor::OnBtnXup()
1416 UpdateSelectedOrigin(8, 0, 0);
1419 void CDialogParticleEditor::OnBtnZup()
1421 UpdateSelectedOrigin(0, 0, 8);
1424 void CDialogParticleEditor::OnBtnZdn()
1426 UpdateSelectedOrigin(0, 0, -8);
1429 void CDialogParticleEditor::OnBtnDrop()
1436 idAngles viewAngles;
1438 if ( !gameEdit->PlayerIsValid() ) {
1442 gameEdit->PlayerGetViewAngles( viewAngles );
1443 gameEdit->PlayerGetEyePosition( org );
1445 org += idAngles( 0, viewAngles.yaw, 0 ).ToForward() * 80 + idVec3( 0, 0, 1 );
1446 args.Set("origin", org.ToString());
1447 args.Set("classname", "func_emitter");
1448 args.Set("angle", va( "%f", viewAngles.yaw + 180 ));
1450 idDeclParticle *idp = GetCurParticle();
1451 if ( idp == NULL ) {
1454 idStr str = idp->GetName();
1455 str.SetFileExtension( ".prt" );
1457 args.Set("model", str);
1459 idStr name = gameEdit->GetUniqueEntityName( "func_emitter" );
1460 bool nameValid = false;
1461 while (!nameValid) {
1462 DialogName dlg("Name Particle", this);
1463 dlg.m_strName = name;
1464 if (dlg.DoModal() == IDOK) {
1465 idEntity *gameEnt = gameEdit->FindEntity( dlg.m_strName );
1467 if (MessageBox("Please choose another name", "Duplicate Entity Name!", MB_OKCANCEL) == IDCANCEL) {
1472 name = dlg.m_strName;
1477 args.Set("name", name.c_str());
1479 idEntity *ent = NULL;
1480 gameEdit->SpawnEntityDef( args, &ent );
1482 gameEdit->EntityUpdateChangeableSpawnArgs( ent, NULL );
1483 gameEdit->ClearEntitySelection();
1484 gameEdit->AddSelectedEntity( ent );
1487 gameEdit->MapAddEntity( &args );
1490 void CDialogParticleEditor::OnOK()
1492 // never return on OK as windows will map this at times when you don't want
1493 // ENTER closing the dialog