/* =========================================================================== Doom 3 GPL Source Code Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). Doom 3 Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Doom 3 Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Doom 3 Source Code. If not, see . 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. 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. =========================================================================== */ #include "../../idlib/precompiled.h" #pragma hdrstop #include "../../game/game.h" #include "../../sys/win32/win_local.h" #include "../../sys/win32/rc/common_resource.h" #include "../../sys/win32/rc/Radiant_resource.h" #include "../../sys/win32/rc/ParticleEditor_resource.h" #include "../comafx/DialogName.h" #include "../comafx/VectorCtl.h" #include "../comafx/DialogColorPicker.h" #include "../radiant/GLWidget.h" #include "../radiant/PreviewDlg.h" #include "DialogParticleEditor.h" #ifdef ID_DEBUG_MEMORY #undef new #undef DEBUG_NEW #define DEBUG_NEW new #endif const int StageEnableID[] = { IDC_EDIT_MATERIAL, IDC_BUTTON_BROWSEMATERIAL, IDC_EDIT_ANIMFRAMES, IDC_EDIT_ANIMRATE, IDC_EDIT_COLOR, IDC_BUTTON_BROWSECOLOR, IDC_EDIT_FADECOLOR, IDC_BUTTON_BROWSEFADECOLOR, IDC_EDIT_FADEIN, IDC_SLIDER_FADEIN, IDC_EDIT_FADEOUT, IDC_EDIT_FADEFRACTION, IDC_SLIDER_FADEOUT, IDC_SLIDER_FADEFRACTION, IDC_EDIT_BUNCHING, IDC_SLIDER_BUNCHING, IDC_EDIT_COUNT, IDC_SLIDER_COUNT, IDC_EDIT_TIME, IDC_SLIDER_TIME, IDC_EDIT_CYCLES, IDC_EDIT_TIMEOFFSET, IDC_EDIT_DEADTIME, IDC_CHECK_WORLDGRAVITY, IDC_EDIT_GRAVITY, IDC_SLIDER_GRAVITY, IDC_RADIO_RECT, IDC_RADIO_CYLINDER, IDC_RADIO_SPHERE, IDC_EDIT_OFFSET, IDC_EDIT_XSIZE, IDC_EDIT_YSIZE, IDC_EDIT_ZSIZE, IDC_EDIT_RINGOFFSET, IDC_RADIO_CONE, IDC_RADIO_OUTWARD, IDC_EDIT_DIRECTIONPARM, IDC_RADIO_AIMED, IDC_RADIO_VIEW, IDC_RADIO_X, IDC_RADIO_Y, IDC_RADIO_Z, IDC_EDIT_ORIENTATIONPARM1, IDC_EDIT_ORIENTATIONPARM2, IDC_SLIDER_SPEEDFROM, IDC_EDIT_SPEEDFROM, IDC_EDIT_SPEEDTO, IDC_SLIDER_SPEEDTO, IDC_SLIDER_ROTATIONFROM, IDC_EDIT_ROTATIONFROM, IDC_EDIT_ROTATIONTO, IDC_SLIDER_ROTATIONTO, IDC_SLIDER_SIZEFROM, IDC_EDIT_SIZEFROM, IDC_EDIT_SIZETO, IDC_SLIDER_SIZETO, IDC_SLIDER_ASPECTFROM, IDC_EDIT_ASPECTFROM, IDC_EDIT_ASPECTTO, IDC_SLIDER_ASPECTTO, IDC_COMBO_CUSTOMPATH, IDC_CHECK_ENTITYCOLOR, }; const int StageIDCount = sizeof( StageEnableID ) / sizeof ( const int ); const int EditEnableID[] = { IDC_BUTTON_XDN, IDC_BUTTON_XUP, IDC_BUTTON_YUP, IDC_BUTTON_YDN, IDC_BUTTON_ZUP, IDC_BUTTON_ZDN, IDC_BUTTON_DROPEMITTER, IDC_BUTTON_VECTOR, IDC_BUTTON_BROWSECOLOR_ENTITY }; const int EditIDCount = sizeof ( EditEnableID ) / sizeof ( const int ); CDialogParticleEditor *g_ParticleDialog = NULL; /* ================ ParticleEditorInit ================ */ void ParticleEditorInit( const idDict *spawnArgs ) { if ( renderSystem->IsFullScreen() ) { common->Printf( "Cannot run the particle editor in fullscreen mode.\n" "Set r_fullscreen to 0 and vid_restart.\n" ); return; } if ( g_ParticleDialog == NULL ) { InitAfx(); g_ParticleDialog = new CDialogParticleEditor(); } if ( g_ParticleDialog->GetSafeHwnd() == NULL) { g_ParticleDialog->Create( IDD_DIALOG_PARTICLE_EDITOR ); /* // FIXME: restore position CRect rct; g_AFDialog->SetWindowPos( NULL, rct.left, rct.top, 0, 0, SWP_NOSIZE ); */ } idKeyInput::ClearStates(); g_ParticleDialog->ShowWindow( SW_SHOW ); g_ParticleDialog->SetFocus(); if ( spawnArgs ) { idStr str = spawnArgs->GetString( "model" ); str.StripFileExtension(); g_ParticleDialog->SelectParticle( str ); g_ParticleDialog->SetParticleVisualization( static_cast( CDialogParticleEditor::SELECTED ) ); } cvarSystem->SetCVarBool( "r_useCachedDynamicModels", false ); } /* ================ ParticleEditorRun ================ */ void ParticleEditorRun( void ) { #if _MSC_VER >= 1300 MSG *msg = AfxGetCurrentMessage(); // TODO Robert fix me!! #else MSG *msg = &m_msgCur; #endif while( ::PeekMessage(msg, NULL, NULL, NULL, PM_NOREMOVE) ) { // pump message if ( !AfxGetApp()->PumpMessage() ) { } } } /* ================ ParticleEditorShutdown ================ */ void ParticleEditorShutdown( void ) { delete g_ParticleDialog; g_ParticleDialog = NULL; } // CDialogParticleEditor dialog IMPLEMENT_DYNAMIC(CDialogParticleEditor, CDialog) CDialogParticleEditor::CDialogParticleEditor(CWnd* pParent /*=NULL*/) : CDialog(CDialogParticleEditor::IDD, pParent) , matName(_T("")) , animFrames(_T("")) , animRate(_T("")) , color(_T("")) , fadeColor(_T("")) , fadeIn(_T("")) , fadeOut(_T("")) , fadeFraction(_T("")) , count(_T("")) , time(_T("")) , timeOffset(_T("")) , deadTime(_T("")) , gravity(_T("")) , bunching(_T("")) , offset(_T("")) , xSize(_T("")) , ySize(_T("")) , zSize(_T("")) , ringOffset(_T("")) , directionParm(_T("")) , direction(0) , orientation(0) , distribution(0) , viewOrigin(_T("")) , speedFrom(_T("")) , speedTo(_T("")) , rotationFrom(_T("")) , rotationTo(_T("")) , sizeFrom(_T("")) , sizeTo(_T("")) , aspectFrom(_T("")) , aspectTo(_T("")) , customPath(_T("")) , customParms(_T("")) , trails(_T("")) , trailTime(_T("")) , worldGravity(TRUE) , entityColor(TRUE) , randomDistribution(TRUE) , initialAngle(_T("")) , boundsExpansion(_T("")) , customDesc(_T("")) , particleMode(FALSE) { visualization = TESTMODEL; mapModified = false; } CDialogParticleEditor::~CDialogParticleEditor() { } void CDialogParticleEditor::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT_DEPTHHACK, depthHack); DDX_Check(pDX, IDC_CHECK_WORLDGRAVITY, worldGravity); DDX_Check(pDX, IDC_CHECK_ENTITYCOLOR, entityColor); DDX_Control(pDX, IDC_COMBO_PARTICLES, comboParticle); DDX_Control(pDX, IDC_LIST_STAGES, listStages); DDX_Text(pDX, IDC_COMBO_CUSTOMPATH, customPath ); DDX_Text(pDX, IDC_EDIT_CUSTOMPARMS, customParms ); DDX_Text(pDX, IDC_EDIT_MATERIAL, matName); DDX_Text(pDX, IDC_EDIT_ANIMFRAMES, animFrames); DDX_Text(pDX, IDC_EDIT_ANIMRATE, animRate); DDX_Text(pDX, IDC_EDIT_COLOR, color); DDX_Text(pDX, IDC_EDIT_FADECOLOR, fadeColor); DDX_Text(pDX, IDC_EDIT_FADEIN, fadeIn); DDX_Text(pDX, IDC_EDIT_FADEOUT, fadeOut); DDX_Text(pDX, IDC_EDIT_FADEFRACTION, fadeFraction); DDX_Text(pDX, IDC_EDIT_COUNT, count); DDX_Text(pDX, IDC_EDIT_TIME, time); DDX_Text(pDX, IDC_EDIT_TIMEOFFSET, timeOffset); DDX_Text(pDX, IDC_EDIT_DEADTIME, deadTime); DDX_Text(pDX, IDC_EDIT_GRAVITY, gravity); DDX_Text(pDX, IDC_EDIT_BUNCHING, bunching); DDX_Text(pDX, IDC_EDIT_OFFSET, offset); DDX_Text(pDX, IDC_EDIT_XSIZE, xSize); DDX_Text(pDX, IDC_EDIT_YSIZE, ySize); DDX_Text(pDX, IDC_EDIT_ZSIZE, zSize); DDX_Text(pDX, IDC_EDIT_RINGOFFSET, ringOffset); DDX_Text(pDX, IDC_EDIT_CYCLES, cycles); DDX_Control(pDX, IDC_STATIC_DIRPARM, staticDirectionParm); DDX_Text(pDX, IDC_EDIT_DIRECTIONPARM, directionParm); DDX_Text(pDX, IDC_EDIT_SPEEDFROM, speedFrom); DDX_Text(pDX, IDC_EDIT_SPEEDTO, speedTo); DDX_Text(pDX, IDC_EDIT_ROTATIONFROM, rotationFrom); DDX_Text(pDX, IDC_EDIT_ROTATIONTO, rotationTo); DDX_Text(pDX, IDC_EDIT_SIZEFROM, sizeFrom); DDX_Text(pDX, IDC_EDIT_SIZETO, sizeTo); DDX_Text(pDX, IDC_EDIT_ASPECTFROM, aspectFrom); DDX_Text(pDX, IDC_EDIT_ASPECTTO, aspectTo); DDX_Text(pDX, IDC_EDIT_ORIENTATIONPARM1, trails); DDX_Text(pDX, IDC_EDIT_ORIENTATIONPARM2, trailTime); DDX_Check(pDX, IDC_CHECK_RANDOMDISTRIBUTION, randomDistribution); DDX_Text(pDX, IDC_EDIT_INITIALANGLE, initialAngle); DDX_Text(pDX, IDC_EDIT_BOUNDSEXPANSION, boundsExpansion); DDX_Text(pDX, IDC_STATIC_DESC, customDesc); DDX_Control(pDX, IDC_EDIT_RINGOFFSET, editRingOffset); DDX_Radio(pDX, IDC_RADIO_RECT, distribution); DDX_Radio(pDX, IDC_RADIO_CONE, direction); DDX_Radio(pDX, IDC_RADIO_VIEW, orientation); DDX_Control(pDX, IDC_SLIDER_BUNCHING, sliderBunching); DDX_Control(pDX, IDC_SLIDER_FADEIN, sliderFadeIn); DDX_Control(pDX, IDC_SLIDER_FADEOUT, sliderFadeOut); DDX_Control(pDX, IDC_SLIDER_FADEFRACTION, sliderFadeFraction); DDX_Control(pDX, IDC_SLIDER_COUNT, sliderCount); DDX_Control(pDX, IDC_SLIDER_TIME, sliderTime); DDX_Control(pDX, IDC_SLIDER_GRAVITY, sliderGravity); DDX_Control(pDX, IDC_SLIDER_SPEEDFROM, sliderSpeedFrom); DDX_Control(pDX, IDC_SLIDER_SPEEDTO, sliderSpeedTo); DDX_Control(pDX, IDC_SLIDER_ROTATIONFROM, sliderRotationFrom); DDX_Control(pDX, IDC_SLIDER_ROTATIONTO, sliderRotationTo); DDX_Control(pDX, IDC_SLIDER_SIZEFROM, sliderSizeFrom); DDX_Control(pDX, IDC_SLIDER_SIZETO, sliderSizeTo); DDX_Control(pDX, IDC_SLIDER_ASPECTFROM, sliderAspectFrom); DDX_Control(pDX, IDC_SLIDER_ASPECTTO, sliderAspectTo); DDX_Control(pDX, IDC_BUTTON_VECTOR, vectorControl); } BEGIN_MESSAGE_MAP(CDialogParticleEditor, CDialog) ON_BN_CLICKED(IDC_BUTTON_ADDSTAGE, OnBnClickedButtonAddstage) ON_BN_CLICKED(IDC_BUTTON_REMOVESTAGE, OnBnClickedButtonRemovestage) ON_BN_CLICKED(IDC_BUTTON_BROWSEMATERIAL, OnBnClickedButtonBrowsematerial) ON_BN_CLICKED(IDC_BUTTON_BROWSECOLOR, OnBnClickedButtonBrowsecolor) ON_BN_CLICKED(IDC_BUTTON_BROWSEFADECOLOR, OnBnClickedButtonBrowsefadecolor) ON_BN_CLICKED(IDC_BUTTON_BROWSECOLOR_ENTITY, OnBnClickedButtonBrowseEntitycolor) ON_BN_CLICKED(IDC_BUTTON_UPDATE, OnBnClickedButtonUpdate) ON_CBN_SELCHANGE(IDC_COMBO_PARTICLES, OnCbnSelchangeComboParticles) ON_CBN_SELCHANGE(IDC_COMBO_CUSTOMPATH, OnCbnSelchangeComboPath) ON_BN_CLICKED(IDC_RADIO_RECT, OnBnClickedRadioRect) ON_BN_CLICKED(IDC_RADIO_SPHERE, OnBnClickedRadioSphere) ON_BN_CLICKED(IDC_RADIO_CYLINDER, OnBnClickedRadioCylinder) ON_BN_CLICKED(IDC_RADIO_CONE, OnBnClickedRadioCone) ON_BN_CLICKED(IDC_RADIO_OUTWARD, OnBnClickedRadioOutward) ON_BN_CLICKED(IDC_RADIO_VIEW, OnBnClickedRadioView) ON_BN_CLICKED(IDC_RADIO_AIMED, OnBnClickedRadioAimed) ON_BN_CLICKED(IDC_RADIO_X, OnBnClickedRadioX) ON_BN_CLICKED(IDC_RADIO_Y, OnBnClickedRadioY) ON_BN_CLICKED(IDC_RADIO_Z, OnBnClickedRadioZ) ON_BN_CLICKED(IDC_BUTTON_HIDESTAGE, OnBnClickedButtonHidestage) ON_BN_CLICKED(IDC_BUTTON_SHOWSTAGE, OnBnClickedButtonShowstage) ON_BN_CLICKED(IDC_CHECK_WORLDGRAVITY, OnBnClickedWorldGravity) ON_BN_CLICKED(IDC_CHECK_ENTITYCOLOR, OnBnClickedEntityColor) ON_LBN_SELCHANGE(IDC_LIST_STAGES, OnLbnSelchangeListStages) ON_BN_CLICKED(IDC_BUTTON_NEW, OnBnClickedButtonNew) ON_BN_CLICKED(IDC_BUTTON_SAVE_PARTICLE, OnBnClickedButtonSave) ON_BN_CLICKED(IDC_BUTTON_SAVE_PARTICLE_AS, OnBnClickedButtonSaveAs) ON_BN_CLICKED(IDC_BUTTON_SAVE_PARTICLEENTITIES, OnBnClickedButtonSaveParticles) ON_BN_CLICKED(IDC_BUTTON_TESTMODEL, OnBnClickedTestModel) ON_BN_CLICKED(IDC_BUTTON_IMPACT, OnBnClickedImpact) ON_BN_CLICKED(IDC_BUTTON_MUZZLE, OnBnClickedMuzzle) ON_BN_CLICKED(IDC_BUTTON_FLIGHT, OnBnClickedFlight) ON_BN_CLICKED(IDC_BUTTON_SELECTED, OnBnClickedSelected) ON_BN_CLICKED(IDC_BUTTON_DOOM, OnBnClickedDoom) ON_BN_CLICKED(IDC_CHECK_EDITPARTICLEMODE, OnBnClickedParticleMode) ON_BN_CLICKED(IDC_BUTTON_DROPEMITTER, OnBtnDrop) ON_BN_CLICKED(IDC_BUTTON_YUP, OnBtnYup) ON_BN_CLICKED(IDC_BUTTON_YDN, OnBtnYdn) ON_BN_CLICKED(IDC_BUTTON_XDN, OnBtnXdn) ON_BN_CLICKED(IDC_BUTTON_XUP, OnBtnXup) ON_BN_CLICKED(IDC_BUTTON_ZUP, OnBtnZup) ON_BN_CLICKED(IDC_BUTTON_ZDN, OnBtnZdn) ON_WM_HSCROLL() END_MESSAGE_MAP() // CDialogParticleEditor message handlers void CDialogParticleEditor::OnBnClickedParticleMode() { particleMode = !particleMode; cvarSystem->SetCVarInteger( "g_editEntityMode", ( particleMode ) ? 4 : 0 ); EnableEditControls(); } void CDialogParticleEditor::OnBnClickedButtonSaveAs() { idDeclParticle *idp = GetCurParticle(); if ( idp == NULL ) { return; } DialogName dlg("New Particle"); if (dlg.DoModal() == IDOK) { if ( declManager->FindType( DECL_PARTICLE, dlg.m_strName, false ) ) { MessageBox( "Particle already exists!", "Particle exists", MB_OK ); return; } CFileDialog dlgSave( TRUE, "prt", NULL, OFN_CREATEPROMPT, "Particle Files (*.prt)|*.prt||All Files (*.*)|*.*||", AfxGetMainWnd() ); if ( dlgSave.DoModal() == IDOK ) { idStr fileName; fileName = fileSystem->OSPathToRelativePath( dlgSave.m_ofn.lpstrFile ); idDeclParticle *decl = dynamic_cast( declManager->CreateNewDecl( DECL_PARTICLE, dlg.m_strName, fileName ) ); if ( decl ) { decl->stages.DeleteContents( true ); decl->depthHack = idp->depthHack; for ( int i = 0; i < idp->stages.Num(); i++ ) { idParticleStage *stage = new idParticleStage(); *stage = *idp->stages[i]; decl->stages.Append( stage ); } EnumParticles(); int index = comboParticle.FindStringExact( -1, dlg.m_strName ); if ( index >= 0 ) { comboParticle.SetCurSel( index ); } OnBnClickedButtonSave(); OnCbnSelchangeComboParticles(); OnBnClickedButtonUpdate(); } } } } void CDialogParticleEditor::OnBnClickedButtonSaveParticles() { cmdSystem->BufferCommandText( CMD_EXEC_NOW, "saveParticles" ); CWnd *wnd = GetDlgItem( IDC_BUTTON_SAVE_PARTICLEENTITIES ); if ( wnd ) { wnd->EnableWindow( FALSE ); } } void CDialogParticleEditor::OnBnClickedButtonAddstage() { AddStage(); } void CDialogParticleEditor::OnBnClickedButtonRemovestage() { RemoveStage(); } void CDialogParticleEditor::OnBnClickedButtonBrowsematerial() { CPreviewDlg matDlg( this ); matDlg.SetMode(CPreviewDlg::MATERIALS, "particles" ); matDlg.SetDisablePreview( true ); if ( matDlg.DoModal() == IDOK ) { matName = matDlg.mediaName; DlgVarsToCurStage(); CurStageToDlgVars(); } } void CDialogParticleEditor::OnBnClickedButtonBrowsecolor() { int r, g, b; float ob; idParticleStage *ps = GetCurStage(); if ( ps == NULL ) { return; } r = ps->color.x * 255.0f; g = ps->color.y * 255.0f; b = ps->color.z * 255.0f; ob = 1.0f; if ( DoNewColor( &r, &g, &b, &ob ) ) { color.Format( "%f %f %f %f", (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, 1.0f ); DlgVarsToCurStage(); CurStageToDlgVars(); } } void CDialogParticleEditor::OnBnClickedButtonBrowseEntitycolor() { int r, g, b; float ob; idList list; idDict dict2; idStr str; list.SetNum( 128 ); int count = gameEdit->GetSelectedEntities( list.Ptr(), list.Num() ); list.SetNum( count ); if ( count ) { const idDict *dict = gameEdit->EntityGetSpawnArgs( list[0] ); if ( dict ) { idVec3 clr = dict->GetVector( "_color", "1 1 1" ); r = clr.x * 255.0f; g = clr.y * 255.0f; b = clr.z * 255.0f; ob = 1.0f; if ( DoNewColor( &r, &g, &b, &ob ) ) { for ( int i = 0; i < count; i++ ) { dict = gameEdit->EntityGetSpawnArgs( list[i] ); const char *name = dict->GetString( "name" ); idEntity *ent = gameEdit->FindEntity( name ); if ( ent ) { gameEdit->EntitySetColor( ent, idVec3( (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f ) ); str = va( "%f %f %f", (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f ); dict2.Clear(); dict2.Set( "_color", str ); gameEdit->EntityChangeSpawnArgs( ent, &dict2 ); gameEdit->MapSetEntityKeyVal( name, "_color", str ); } } } } CWnd *wnd = GetDlgItem( IDC_BUTTON_SAVE_PARTICLEENTITIES ); if ( wnd ) { wnd->EnableWindow( TRUE ); } } } void CDialogParticleEditor::OnBnClickedButtonBrowsefadecolor() { int r, g, b; float ob; idParticleStage *ps = GetCurStage(); if ( ps == NULL ) { return; } r = ps->fadeColor.x * 255.0f; g = ps->fadeColor.y * 255.0f; b = ps->fadeColor.z * 255.0f; ob = 1.0f; if ( DoNewColor( &r, &g, &b, &ob ) ) { fadeColor.Format( "%f %f %f %f", (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, 1.0f ); DlgVarsToCurStage(); CurStageToDlgVars(); } } void CDialogParticleEditor::OnBnClickedButtonUpdate() { UpdateData( TRUE ); DlgVarsToCurStage(); CurStageToDlgVars(); } void CDialogParticleEditor::SelectParticle( const char *name ) { int index = comboParticle.FindString( 0, name ); if ( index >= 0 ) { comboParticle.SetCurSel( index ); UpdateParticleData(); } } idDeclParticle *CDialogParticleEditor::GetCurParticle() { int sel = comboParticle.GetCurSel(); if ( sel == CB_ERR ) { return NULL; } int index = comboParticle.GetItemData( sel ); return static_cast( const_cast( declManager->DeclByIndex( DECL_PARTICLE, index ) ) ); } void CDialogParticleEditor::UpdateParticleData() { listStages.ResetContent(); idDeclParticle *idp = GetCurParticle(); if ( idp == NULL ) { return; } for ( int i = 0; i < idp->stages.Num(); i++ ) { int index = listStages.AddString( va( "stage %i", i ) ); if ( index >= 0 ) { listStages.SetItemData( index, i ); } } listStages.SetCurSel( 0 ); OnLbnSelchangeListStages(); CWnd *wnd = GetDlgItem( IDC_STATIC_INFILE ); if ( wnd ) { wnd->SetWindowText( va( "Particle file: %s", idp->GetFileName() ) ); } SetParticleView(); } void CDialogParticleEditor::OnCbnSelchangeComboParticles() { UpdateParticleData(); } void CDialogParticleEditor::OnCbnSelchangeComboPath() { DlgVarsToCurStage(); CurStageToDlgVars(); UpdateControlInfo(); } void CDialogParticleEditor::UpdateControlInfo() { CWnd *wnd = GetDlgItem( IDC_EDIT_RINGOFFSET ); if ( wnd ) { wnd->EnableWindow( distribution == 2 ); } wnd = GetDlgItem( IDC_STATIC_DIRPARM ); if ( wnd ) { wnd->SetWindowText( (direction == 0 ) ? "Angle" : "Upward Bias" ); } wnd = GetDlgItem( IDC_EDIT_ORIENTATIONPARM1 ); if ( wnd ) { wnd->EnableWindow( orientation == 1 ); } wnd = GetDlgItem( IDC_EDIT_ORIENTATIONPARM2 ); if ( wnd ) { wnd->EnableWindow( orientation == 1 ); } idParticleStage *ps = GetCurStage(); if ( ps == NULL ) { return; } sliderBunching.SetValuePos( ps->spawnBunching ); sliderFadeIn.SetValuePos( ps->fadeInFraction ); sliderFadeOut.SetValuePos( ps->fadeOutFraction ); sliderFadeFraction.SetValuePos( ps->fadeIndexFraction ); sliderCount.SetValuePos( ps->totalParticles ); sliderTime.SetValuePos( ps->particleLife ); sliderGravity.SetValuePos( ps->gravity ); sliderSpeedFrom.SetValuePos( ps->speed.from ); sliderSpeedTo.SetValuePos( ps->speed.to ); sliderRotationFrom.SetValuePos( ps->rotationSpeed.from ); sliderRotationTo.SetValuePos( ps->rotationSpeed.to ); sliderSizeFrom.SetValuePos( ps->size.from ); sliderSizeTo.SetValuePos( ps->size.to ); sliderAspectFrom.SetValuePos( ps->aspect.from ); sliderAspectTo.SetValuePos( ps->aspect.to ); } void CDialogParticleEditor::OnBnClickedRadioRect() { distribution = 0; DlgVarsToCurStage(); CurStageToDlgVars(); UpdateControlInfo(); } void CDialogParticleEditor::OnBnClickedRadioSphere() { distribution = 2; DlgVarsToCurStage(); CurStageToDlgVars(); UpdateControlInfo(); } void CDialogParticleEditor::OnBnClickedRadioCylinder() { distribution = 1; DlgVarsToCurStage(); CurStageToDlgVars(); UpdateControlInfo(); } void CDialogParticleEditor::OnBnClickedRadioCone() { direction = 0; DlgVarsToCurStage(); CurStageToDlgVars(); UpdateControlInfo(); } void CDialogParticleEditor::OnBnClickedRadioOutward() { direction = 1; DlgVarsToCurStage(); CurStageToDlgVars(); UpdateControlInfo(); } void CDialogParticleEditor::OnBnClickedRadioView() { orientation = 0; DlgVarsToCurStage(); CurStageToDlgVars(); UpdateControlInfo(); } void CDialogParticleEditor::OnBnClickedRadioAimed() { orientation = 1; DlgVarsToCurStage(); CurStageToDlgVars(); UpdateControlInfo(); } void CDialogParticleEditor::OnBnClickedRadioX() { orientation = 2; DlgVarsToCurStage(); CurStageToDlgVars(); UpdateControlInfo(); } void CDialogParticleEditor::OnBnClickedRadioY() { orientation = 3; DlgVarsToCurStage(); CurStageToDlgVars(); UpdateControlInfo(); } void CDialogParticleEditor::OnBnClickedRadioZ() { orientation = 4; DlgVarsToCurStage(); CurStageToDlgVars(); UpdateControlInfo(); } void CDialogParticleEditor::OnBnClickedDoom() { ::SetFocus(win32.hWnd); } void CDialogParticleEditor::OnBnClickedTestModel() { visualization = TESTMODEL; SetParticleView(); } void CDialogParticleEditor::OnBnClickedImpact() { visualization = IMPACT; SetParticleView(); } void CDialogParticleEditor::OnBnClickedMuzzle(){ visualization = MUZZLE; SetParticleView(); } void CDialogParticleEditor::OnBnClickedFlight() { visualization = FLIGHT; SetParticleView(); } void CDialogParticleEditor::OnBnClickedSelected() { visualization = SELECTED; SetParticleView(); } void CDialogParticleEditor::SetParticleVisualization( int i ) { visualization = i; SetParticleView(); } void CDialogParticleEditor::SetParticleView() { idDeclParticle *idp = GetCurParticle(); if ( idp == NULL ) { return; } cmdSystem->BufferCommandText( CMD_EXEC_NOW, "testmodel" ); idStr str; switch ( visualization ) { case TESTMODEL : str = idp->GetName(); str.SetFileExtension( ".prt" ); cmdSystem->BufferCommandText( CMD_EXEC_NOW, va("testmodel %s\n", str.c_str() ) ); break; case IMPACT : str = idp->GetName(); str.SetFileExtension( ".prt" ); cvarSystem->SetCVarInteger( "g_testParticle", TEST_PARTICLE_IMPACT ); cvarSystem->SetCVarString( "g_testParticleName", str ); break; case MUZZLE : str = idp->GetName(); str.SetFileExtension( ".prt" ); cvarSystem->SetCVarInteger( "g_testParticle", TEST_PARTICLE_MUZZLE ); cvarSystem->SetCVarString( "g_testParticleName", str ); break; case FLIGHT : str = idp->GetName(); str.SetFileExtension( ".prt" ); cvarSystem->SetCVarInteger( "g_testParticle", TEST_PARTICLE_FLIGHT ); cvarSystem->SetCVarString( "g_testParticleName", str ); break; case SELECTED : str = idp->GetName(); str.SetFileExtension( ".prt" ); cvarSystem->SetCVarInteger( "g_testParticle", TEST_PARTICLE_FLIGHT ); SetSelectedModel( str ); break; } } void CDialogParticleEditor::SetSelectedModel( const char *val ) { idList list; idMat3 axis; list.SetNum( 128 ); int count = gameEdit->GetSelectedEntities( list.Ptr(), list.Num() ); list.SetNum( count ); if ( count ) { for ( int i = 0; i < count; i++ ) { const idDict *dict = gameEdit->EntityGetSpawnArgs( list[i] ); if ( dict == NULL ) { continue; } const char *name = dict->GetString( "name" ); gameEdit->EntitySetModel( list[i], val ); gameEdit->EntityUpdateVisuals( list[i] ); gameEdit->EntityGetAxis( list[i], axis ); vectorControl.SetidAxis( axis ); gameEdit->MapSetEntityKeyVal( name, "model", val ); } CWnd *wnd = GetDlgItem( IDC_BUTTON_SAVE_PARTICLEENTITIES ); if ( wnd ) { wnd->EnableWindow( TRUE ); } } } void CDialogParticleEditor::OnBnClickedButtonHidestage() { HideStage(); } void CDialogParticleEditor::OnBnClickedButtonShowstage() { ShowStage(); } void CDialogParticleEditor::OnBnClickedWorldGravity() { worldGravity = !worldGravity; DlgVarsToCurStage(); CurStageToDlgVars(); } void CDialogParticleEditor::OnBnClickedEntityColor() { entityColor = !entityColor; DlgVarsToCurStage(); CurStageToDlgVars(); } void CDialogParticleEditor::AddStage() { idDeclParticle *idp = GetCurParticle(); if ( idp == NULL ) { return; } idParticleStage *stage = new idParticleStage; if ((GetAsyncKeyState(VK_CONTROL) & 0x8000)) { idParticleStage *source = GetCurStage(); if ( source == NULL ) { delete stage; return; } *stage = *source; } else { stage->Default(); } int newIndex = idp->stages.Append( stage ); int index = listStages.AddString( va( "stage %i", newIndex ) ); listStages.SetCurSel( index ); listStages.SetItemData( index, newIndex ); ShowCurrentStage(); EnableStageControls(); } void CDialogParticleEditor::RemoveStage() { idDeclParticle *idp = GetCurParticle(); if ( idp == NULL ) { return; } if ( MessageBox( "Are you sure you want to remove this stage?", "Remove Stage", MB_YESNO | MB_ICONQUESTION ) != IDYES ) { return; } int index = listStages.GetCurSel(); if ( index >= 0 ) { int newIndex = listStages.GetItemData( index ); if ( newIndex >= 0 && newIndex < idp->stages.Num() ) { idp->stages.RemoveIndex( newIndex ); index += ( index >= 1 ) ? -1 : 1; newIndex = comboParticle.FindStringExact( -1, idp->GetName() ); EnumParticles(); if ( newIndex >= 0 ) { comboParticle.SetCurSel( newIndex ); } OnCbnSelchangeComboParticles(); listStages.SetCurSel( index ); ShowCurrentStage(); } } EnableStageControls(); } void CDialogParticleEditor::ShowStage() { idParticleStage *ps = GetCurStage(); if ( ps == NULL ) { return; } ps->hidden = false; int index = listStages.GetCurSel(); int newIndex = listStages.GetItemData( index ); listStages.DeleteString ( index ); listStages.InsertString( index, va("stage %i", index ) ); listStages.SetItemData( index, newIndex ); listStages.SetCurSel( index ); EnableStageControls(); } void CDialogParticleEditor::HideStage() { idParticleStage *ps = GetCurStage(); if ( ps == NULL ) { return; } ps->hidden = true; int index = listStages.GetCurSel(); int newIndex = listStages.GetItemData( index ); listStages.DeleteString ( index ); listStages.InsertString( index, va("stage %i (H) ", index ) ); listStages.SetItemData( index, newIndex ); listStages.SetCurSel( index ); EnableStageControls(); } idParticleStage *CDialogParticleEditor::GetCurStage() { idDeclParticle *idp = GetCurParticle(); int sel = listStages.GetCurSel(); int index = listStages.GetItemData( sel ); if ( idp == NULL || sel == LB_ERR || index >= idp->stages.Num() ) { return NULL; } return idp->stages[index]; } void CDialogParticleEditor::ClearDlgVars() { matName = ""; animFrames = ""; animRate = ""; color = ""; fadeColor = ""; fadeIn = ""; fadeOut = ""; fadeFraction = ""; count = ""; time = ""; timeOffset = ""; deadTime = ""; gravity = ""; bunching = ""; offset = ""; xSize = ""; ySize = ""; zSize = ""; ringOffset = ""; directionParm = ""; direction = 1; orientation = 1; distribution = 1; speedFrom = ""; speedTo = ""; rotationFrom = ""; rotationTo = ""; sizeFrom = ""; sizeTo = ""; aspectFrom = ""; aspectTo = ""; customPath = ""; customParms = ""; trails = ""; trailTime = ""; worldGravity = FALSE; entityColor = FALSE; randomDistribution = TRUE; initialAngle = ""; customDesc = ""; UpdateData( FALSE ); } void CDialogParticleEditor::CurStageToDlgVars() { // go ahead and get the two system vars too idDeclParticle *idp = GetCurParticle(); if ( idp == NULL ) { return; } depthHack = va( "%.3f", idp->depthHack ); idParticleStage *ps = GetCurStage(); if ( ps == NULL ) { return; } matName = ps->material->GetName(); animFrames = va( "%i", ps->animationFrames ); animRate = va( "%i", ps->animationRate ); color = ps->color.ToString(); fadeColor = ps->fadeColor.ToString(); fadeIn = va( "%.3f", ps->fadeInFraction ); fadeOut = va( "%.3f", ps->fadeOutFraction ); fadeFraction = va( "%.3f", ps->fadeIndexFraction ); count = va( "%i", ps->totalParticles ); time = va( "%.3f", ps->particleLife ); timeOffset = va( "%.3f", ps->timeOffset ); deadTime = va( "%.3f", ps->deadTime ); gravity = va( "%.3f", ps->gravity ); bunching = va( "%.3f", ps->spawnBunching ); offset = ps->offset.ToString( 0 ); xSize = va( "%.3f", ps->distributionParms[0] ); ySize = va( "%.3f", ps->distributionParms[1] ); zSize = va( "%.3f", ps->distributionParms[2] ); ringOffset = va( "%.3f", ps->distributionParms[3] ); directionParm = va( "%.3f", ps->directionParms[0] ); direction = ps->directionType; orientation = ps->orientation; distribution = ps->distributionType; speedFrom = va( "%.3f", ps->speed.from ); speedTo = va( "%.3f", ps->speed.to ); rotationFrom = va( "%.3f", ps->rotationSpeed.from ); rotationTo = va( "%.3f", ps->rotationSpeed.to ); sizeFrom = va( "%.3f", ps->size.from ); sizeTo = va( "%.3f", ps->size.to ); aspectFrom = va( "%.3f", ps->aspect.from ); aspectTo = va( "%.3f", ps->aspect.to ); trails = va( "%f", ps->orientationParms[0] ); trailTime = va( "%.3f", ps->orientationParms[1] ); cycles = va( "%.3f", ps->cycles ); customPath = ps->GetCustomPathName(); customParms = ""; customDesc = ps->GetCustomPathDesc(); if ( ps->customPathType != PPATH_STANDARD ) { for ( int i = 0; i < ps->NumCustomPathParms(); i++ ) { customParms += va( "%.1f ", ps->customPathParms[i] ); } } worldGravity = ps->worldGravity; initialAngle = va( "%.3f", ps->initialAngle ); boundsExpansion = va( "%.3f", ps->boundsExpansion ); randomDistribution = ps->randomDistribution; entityColor = ps->entityColor; UpdateData( FALSE ); } void CDialogParticleEditor::DlgVarsToCurStage() { // go ahead and set the two system vars too idDeclParticle *idp = GetCurParticle(); if ( idp == NULL ) { return; } idp->depthHack = atof( depthHack ); idParticleStage *ps = GetCurStage(); if ( ps == NULL ) { return; } ps->material = declManager->FindMaterial( matName ); ps->animationFrames = atoi( animFrames ); ps->animationRate = atoi( animRate ); sscanf( color, "%f %f %f %f", &ps->color.x, &ps->color.y, &ps->color.z, &ps->color.w ); sscanf( fadeColor, "%f %f %f %f", &ps->fadeColor.x, &ps->fadeColor.y, &ps->fadeColor.z, &ps->fadeColor.w ); ps->fadeInFraction = atof( fadeIn ); ps->fadeOutFraction = atof( fadeOut ); ps->fadeIndexFraction = atof( fadeFraction ); ps->totalParticles = atoi( count ); ps->particleLife = atof( time ); ps->timeOffset = atof( timeOffset ); ps->deadTime = atof( deadTime ); ps->gravity = atof( gravity ); ps->spawnBunching = atof( bunching ); sscanf( offset, "%f %f %f", &ps->offset.x, &ps->offset.y, &ps->offset.z ); ps->distributionParms[0] = atof( xSize ); ps->distributionParms[1] = atof( ySize ); ps->distributionParms[2] = atof( zSize ); ps->distributionParms[3] = atof( ringOffset ); ps->directionParms[0] = atof( directionParm ); ps->directionType = static_cast( direction ); ps->orientation = static_cast( orientation ); ps->distributionType = static_cast( distribution ); ps->speed.from = atof( speedFrom ); ps->speed.to = atof( speedTo ); ps->rotationSpeed.from = atof( rotationFrom ); ps->rotationSpeed.to = atof( rotationTo ); ps->size.from = atof( sizeFrom ); ps->size.to = atof( sizeTo ); ps->aspect.from = atof( aspectFrom ); ps->aspect.to = atof( aspectTo ); ps->orientationParms[0] = atof( trails ); ps->orientationParms[1] = atof( trailTime ); ps->worldGravity = ( worldGravity == TRUE ); ps->cycles = atof( cycles ); ps->cycleMsec = ( ps->particleLife + ps->deadTime ) * 1000; sscanf( customParms, "%f %f %f %f %f %f %f %f", &ps->customPathParms[0], &ps->customPathParms[1], &ps->customPathParms[2], &ps->customPathParms[3], &ps->customPathParms[4], &ps->customPathParms[5], &ps->customPathParms[6], &ps->customPathParms[7] ); ps->SetCustomPathType( customPath ); ps->initialAngle = atof( initialAngle ); ps->boundsExpansion = atof( boundsExpansion ); ps->randomDistribution = ( randomDistribution != FALSE ); ps->entityColor = ( entityColor == TRUE ); } void CDialogParticleEditor::ShowCurrentStage() { ClearDlgVars(); idParticleStage *ps = GetCurStage(); if ( ps == NULL ) { return; } CurStageToDlgVars(); UpdateControlInfo(); } void CDialogParticleEditor::OnLbnSelchangeListStages() { ShowCurrentStage(); EnableStageControls(); } void CDialogParticleEditor::OnBnClickedButtonNew() { DialogName dlg("New Particle"); if (dlg.DoModal() == IDOK) { CFileDialog dlgSave( TRUE, "prt", NULL, OFN_CREATEPROMPT, "Particle Files (*.prt)|*.prt||All Files (*.*)|*.*||", AfxGetMainWnd() ); if ( dlgSave.DoModal() == IDOK ) { if ( declManager->FindType( DECL_PARTICLE, dlg.m_strName, false ) ) { MessageBox( "Particle already exists!", "Particle exists", MB_OK ); return; } idStr fileName; fileName = fileSystem->OSPathToRelativePath( dlgSave.m_ofn.lpstrFile ); idDecl *decl = declManager->CreateNewDecl( DECL_PARTICLE, dlg.m_strName, fileName ); if ( decl ) { if ( MessageBox( "Copy current particle?", "Copy current", MB_YESNO | MB_ICONQUESTION ) == IDYES ) { MessageBox( "Copy current particle not implemented yet.. Stay tuned" ); } EnumParticles(); int index = comboParticle.FindStringExact( -1, dlg.m_strName ); if ( index >= 0 ) { comboParticle.SetCurSel( index ); } OnBnClickedButtonSave(); OnCbnSelchangeComboParticles(); } } } } void CDialogParticleEditor::OnBnClickedButtonSave() { idDeclParticle *idp = GetCurParticle(); if ( idp == NULL ) { return; } if ( strstr( idp->GetFileName(), "implicit" ) ) { // defaulted, need to choose a file CFileDialog dlgSave( FALSE, "prt", NULL, OFN_OVERWRITEPROMPT, "Particle Files (*.prt)|*.prt||All Files (*.*)|*.*||", AfxGetMainWnd() ); if ( dlgSave.DoModal() == IDOK ) { idStr fileName; fileName = fileSystem->OSPathToRelativePath( dlgSave.m_ofn.lpstrFile ); idp->Save( fileName ); EnumParticles(); } } else { idp->Save(); } } void CDialogParticleEditor::EnumParticles() { CWaitCursor cursor; comboParticle.ResetContent(); for ( int i = 0; i < declManager->GetNumDecls( DECL_PARTICLE ); i++ ) { const idDecl *idp = declManager->DeclByIndex( DECL_PARTICLE, i ); int index = comboParticle.AddString( idp->GetName() ); if ( index >= 0 ) { comboParticle.SetItemData( index, i ); } } comboParticle.SetCurSel( 0 ); OnCbnSelchangeComboParticles(); } void CDialogParticleEditor::OnDestroy() { com_editors &= ~EDITOR_PARTICLE; return CDialog::OnDestroy(); } void VectorCallBack( idQuat rotation ) { if ( g_ParticleDialog && g_ParticleDialog->GetSafeHwnd() ) { g_ParticleDialog->SetVectorControlUpdate( rotation ); } } void CDialogParticleEditor::SetVectorControlUpdate( idQuat rotation ) { if ( particleMode ) { idList list; list.SetNum( 128 ); int count = gameEdit->GetSelectedEntities( list.Ptr(), list.Num() ); list.SetNum( count ); if ( count ) { for ( int i = 0; i < count; i++ ) { const idDict *dict = gameEdit->EntityGetSpawnArgs( list[i] ); if ( dict == NULL ) { continue; } const char *name = dict->GetString( "name" ); gameEdit->EntitySetAxis( list[i], rotation.ToMat3() ); gameEdit->EntityUpdateVisuals( list[i] ); gameEdit->MapSetEntityKeyVal( name, "rotation", rotation.ToMat3().ToString() ); } CWnd *wnd = GetDlgItem( IDC_BUTTON_SAVE_PARTICLEENTITIES ); if ( wnd ) { wnd->EnableWindow( TRUE ); } } } } BOOL CDialogParticleEditor::OnInitDialog() { com_editors |= EDITOR_PARTICLE; particleMode = ( cvarSystem->GetCVarInteger( "g_editEntityMode" ) == 4 ); mapModified = false; CDialog::OnInitDialog(); sliderBunching.SetRange( 0, 20 ); sliderBunching.SetValueRange( 0.0f, 1.0f ); sliderFadeIn.SetRange( 0, 20 ); sliderFadeIn.SetValueRange( 0.0f, 1.0f ); sliderFadeOut.SetRange( 0, 20 ); sliderFadeOut.SetValueRange( 0.0f, 1.0f ); sliderCount.SetRange( 0, 1024 ); sliderCount.SetValueRange( 0, 4096 ); sliderTime.SetRange( 0, 200 ); sliderTime.SetValueRange( 0.0f, 10.0f ); sliderGravity.SetRange( 0, 600 ); sliderGravity.SetValueRange( -300.0f, 300.0f ); sliderSpeedFrom.SetRange( 0, 600 ); sliderSpeedFrom.SetValueRange( -300.0f, 300.0f ); sliderSpeedTo.SetRange( 0, 600 ); sliderSpeedTo.SetValueRange( -300.0f, 300.0f ); sliderRotationFrom.SetRange( 0, 100 ); sliderRotationFrom.SetValueRange( 0.0f, 100.0f ); sliderRotationTo.SetRange( 0, 100 ); sliderRotationTo.SetValueRange( 0.0f, 100.0f ); sliderSizeFrom.SetRange( 0, 256 ); sliderSizeFrom.SetValueRange( 0.0f, 128.0f ); sliderSizeTo.SetRange( 0, 256 ); sliderSizeTo.SetValueRange( 0.0f, 128.0f ); sliderAspectFrom.SetRange( 0, 256 ); sliderAspectFrom.SetValueRange( 0.0f, 128.0f ); sliderAspectTo.SetRange( 0, 256 ); sliderAspectTo.SetValueRange( 0.0f, 128.0f ); sliderFadeFraction.SetRange( 0, 20 ); sliderFadeFraction.SetValueRange( 0.0f, 1.0f ); EnumParticles(); SetParticleView(); toolTipCtrl.Create( this ); toolTipCtrl.Activate( TRUE ); CWnd* wnd = GetWindow( GW_CHILD ); CString str; while ( wnd ) { if ( str.LoadString( wnd->GetDlgCtrlID() ) ) { toolTipCtrl.AddTool( wnd, str ); } wnd = wnd->GetWindow( GW_HWNDNEXT ); } wnd = GetDlgItem( IDC_BUTTON_SAVE_PARTICLEENTITIES ); if ( wnd ) { wnd->EnableWindow( FALSE ); } EnableEditControls(); vectorControl.SetVectorChangingCallback( VectorCallBack ); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CDialogParticleEditor::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar ) { CDialog::OnHScroll( nSBCode, nPos, pScrollBar ); CSliderCtrl *ctrl = dynamic_cast< CSliderCtrl* >( pScrollBar ); if ( !ctrl ) { return; } if ( ctrl == &sliderBunching ) { // handle bunching bunching = va( "%.3f", sliderBunching.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderFadeIn ) { fadeIn = va( "%.3f", sliderFadeIn.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderFadeOut ) { fadeOut = va( "%.3f", sliderFadeOut.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderFadeFraction ) { fadeFraction = va( "%.3f", sliderFadeFraction.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderCount ) { count = va( "%i", (int)sliderCount.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderTime ) { time = va( "%.3f", sliderTime.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderGravity ) { gravity = va( "%.3f", sliderGravity.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderSpeedFrom ) { speedFrom = va( "%.3f", sliderSpeedFrom.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderSpeedTo ) { speedTo = va( "%.3f", sliderSpeedTo.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderRotationFrom ) { rotationFrom = va( "%.3f", sliderRotationFrom.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderRotationTo ) { rotationTo = va( "%.3f", sliderRotationTo.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderSizeFrom ) { sizeFrom = va( "%.3f", sliderSizeFrom.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderSizeTo ) { sizeTo = va( "%.3f", sliderSizeTo.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderAspectFrom ) { aspectFrom = va( "%.3f", sliderAspectFrom.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } else if ( ctrl == &sliderAspectTo ) { aspectTo = va( "%.3f", sliderAspectTo.GetValue() ); DlgVarsToCurStage(); CurStageToDlgVars(); } } BOOL CDialogParticleEditor::PreTranslateMessage(MSG *pMsg) { if ( pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST ) { toolTipCtrl.RelayEvent( pMsg ); } return CDialog::PreTranslateMessage(pMsg); } void CDialogParticleEditor::EnableStageControls() { idParticleStage *stage = GetCurStage(); bool b = ( stage && stage->hidden ) ? false : true; for ( int i = 0; i < StageIDCount; i++ ) { CWnd *wnd = GetDlgItem( StageEnableID[ i ] ); if ( wnd ) { wnd->EnableWindow( b ); } } } void CDialogParticleEditor::EnableEditControls() { for ( int i = 0; i < EditIDCount; i++ ) { CWnd *wnd = GetDlgItem( EditEnableID[ i ] ); if ( wnd ) { wnd->EnableWindow( particleMode ); } } } void CDialogParticleEditor::UpdateSelectedOrigin( float x, float y, float z ) { idList list; idVec3 origin; idVec3 vec(x, y, z); list.SetNum( 128 ); int count = gameEdit->GetSelectedEntities( list.Ptr(), list.Num() ); list.SetNum( count ); if ( count ) { for ( int i = 0; i < count; i++ ) { const idDict *dict = gameEdit->EntityGetSpawnArgs( list[i] ); if ( dict == NULL ) { continue; } const char *name = dict->GetString( "name" ); gameEdit->EntityTranslate( list[i], vec ); gameEdit->EntityUpdateVisuals( list[i] ); gameEdit->MapEntityTranslate( name, vec ); } CWnd *wnd = GetDlgItem( IDC_BUTTON_SAVE_PARTICLEENTITIES ); if ( wnd ) { wnd->EnableWindow( TRUE ); } } } void CDialogParticleEditor::OnBtnYup() { UpdateSelectedOrigin(0, 8, 0); } void CDialogParticleEditor::OnBtnYdn() { UpdateSelectedOrigin(0, -8, 0); } void CDialogParticleEditor::OnBtnXdn() { UpdateSelectedOrigin(-8, 0, 0); } void CDialogParticleEditor::OnBtnXup() { UpdateSelectedOrigin(8, 0, 0); } void CDialogParticleEditor::OnBtnZup() { UpdateSelectedOrigin(0, 0, 8); } void CDialogParticleEditor::OnBtnZdn() { UpdateSelectedOrigin(0, 0, -8); } void CDialogParticleEditor::OnBtnDrop() { idStr classname; idStr key; idStr value; idVec3 org; idDict args; idAngles viewAngles; if ( !gameEdit->PlayerIsValid() ) { return; } gameEdit->PlayerGetViewAngles( viewAngles ); gameEdit->PlayerGetEyePosition( org ); org += idAngles( 0, viewAngles.yaw, 0 ).ToForward() * 80 + idVec3( 0, 0, 1 ); args.Set("origin", org.ToString()); args.Set("classname", "func_emitter"); args.Set("angle", va( "%f", viewAngles.yaw + 180 )); idDeclParticle *idp = GetCurParticle(); if ( idp == NULL ) { return; } idStr str = idp->GetName(); str.SetFileExtension( ".prt" ); args.Set("model", str); idStr name = gameEdit->GetUniqueEntityName( "func_emitter" ); bool nameValid = false; while (!nameValid) { DialogName dlg("Name Particle", this); dlg.m_strName = name; if (dlg.DoModal() == IDOK) { idEntity *gameEnt = gameEdit->FindEntity( dlg.m_strName ); if (gameEnt) { if (MessageBox("Please choose another name", "Duplicate Entity Name!", MB_OKCANCEL) == IDCANCEL) { return; } } else { nameValid = true; name = dlg.m_strName; } } } args.Set("name", name.c_str()); idEntity *ent = NULL; gameEdit->SpawnEntityDef( args, &ent ); if (ent) { gameEdit->EntityUpdateChangeableSpawnArgs( ent, NULL ); gameEdit->ClearEntitySelection(); gameEdit->AddSelectedEntity( ent ); } gameEdit->MapAddEntity( &args ); } void CDialogParticleEditor::OnOK() { // never return on OK as windows will map this at times when you don't want // ENTER closing the dialog // CDialog::OnOK(); }