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 "../../sys/win32/rc/AFEditor_resource.h"
35 #include "DialogAFName.h"
36 #include "DialogAFConstraint.h"
37 #include "DialogAFConstraintFixed.h"
38 #include "DialogAFConstraintBallAndSocket.h"
39 #include "DialogAFConstraintUniversal.h"
40 #include "DialogAFConstraintHinge.h"
41 #include "DialogAFConstraintSlider.h"
42 #include "DialogAFConstraintSpring.h"
44 #ifdef ID_DEBUG_MEMORY
52 declAFConstraintType_t type;
56 c_type_t constraintTypes[] = {
57 { DECLAF_CONSTRAINT_FIXED, "fixed" },
58 { DECLAF_CONSTRAINT_BALLANDSOCKETJOINT, "ball and socket" },
59 { DECLAF_CONSTRAINT_UNIVERSALJOINT, "universal" },
60 { DECLAF_CONSTRAINT_HINGE, "hinge" },
61 { DECLAF_CONSTRAINT_SLIDER, "slider" },
62 { DECLAF_CONSTRAINT_SPRING, "spring" },
63 { DECLAF_CONSTRAINT_INVALID, NULL }
67 const char *ConstraintTypeToString( declAFConstraintType_t type ) {
68 for ( int i = 0; constraintTypes[i].name; i++ ) {
69 if ( constraintTypes[i].type == type ) {
70 return constraintTypes[i].name;
76 declAFConstraintType_t StringToConstraintType( const char *str ) {
77 for ( int i = 0; constraintTypes[i].name; i++ ) {
78 if ( idStr::Icmp( constraintTypes[i].name, str ) == 0 ) {
79 return constraintTypes[i].type;
82 return DECLAF_CONSTRAINT_INVALID;
86 // DialogAFConstraint dialog
88 toolTip_t DialogAFConstraint::toolTips[] = {
89 { IDC_COMBO_CONSTRAINTS, "select contraint for editing" },
90 { IDC_BUTTON_NEWCONSTRAINT, "create a new constraint" },
91 { IDC_BUTTON_RENAMECONSTRAINT, "rename the selected constraint" },
92 { IDC_BUTTON_DELETECONSTRAINT, "delete the selected constraint" },
93 { IDC_COMBO_CONSTRAINT_TYPE, "constraint type" },
94 { IDC_COMBO_CONSTRAINT_BODY1, "first constrained body" },
95 { IDC_COMBO_CONSTRAINT_BODY2, "second constrained body" },
96 { IDC_EDIT_CONSTRAINT_FRICTION, "constraint friction" },
100 IMPLEMENT_DYNAMIC(DialogAFConstraint, CDialog)
104 DialogAFConstraint::DialogAFConstraint
107 DialogAFConstraint::DialogAFConstraint( CWnd* pParent /*=NULL*/ )
108 : CDialog(DialogAFConstraint::IDD, pParent)
112 , constraintDlg(NULL)
114 Create( IDD_DIALOG_AF_CONSTRAINT, pParent );
115 EnableToolTips( TRUE );
120 DialogAFConstraint::~DialogAFConstraint
123 DialogAFConstraint::~DialogAFConstraint() {
128 DialogAFConstraint::DoDataExchange
131 void DialogAFConstraint::DoDataExchange( CDataExchange* pDX ) {
132 CDialog::DoDataExchange(pDX);
133 //{{AFX_DATA_MAP(DialogAFConstraint)
134 DDX_Control(pDX, IDC_COMBO_CONSTRAINTS, m_comboConstraintList);
135 DDX_Control(pDX, IDC_COMBO_CONSTRAINT_TYPE, m_comboConstraintType);
136 DDX_Control(pDX, IDC_COMBO_CONSTRAINT_BODY1, m_comboBody1List);
137 DDX_Control(pDX, IDC_COMBO_CONSTRAINT_BODY2, m_comboBody2List);
138 DDX_Text(pDX, IDC_EDIT_CONSTRAINT_FRICTION, m_friction);
144 DialogAFConstraint::InitConstraintList
147 void DialogAFConstraint::InitConstraintList( void ) {
150 m_comboConstraintList.ResetContent();
154 for ( int i = 0; i < file->constraints.Num(); i++ ) {
155 m_comboConstraintList.AddString( file->constraints[i]->name.c_str() );
157 if ( m_comboConstraintList.GetCount() != 0 ) {
158 m_comboConstraintList.SetCurSel( 0 );
159 m_comboConstraintList.GetLBText( 0, str );
160 LoadConstraint( str );
166 DialogAFConstraint::InitConstraintTypeDlg
169 void DialogAFConstraint::InitConstraintTypeDlg( void ) {
173 if ( !file || !constraint ) {
179 if ( constraintDlg ) {
180 constraintDlg->ShowWindow( SW_HIDE );
183 GetSafeComboBoxSelection( &m_comboConstraintType, str, -1 );
184 switch( StringToConstraintType( str ) ) {
185 case DECLAF_CONSTRAINT_FIXED:
186 fixedDlg->LoadConstraint( constraint );
187 constraintDlg = fixedDlg;
189 case DECLAF_CONSTRAINT_BALLANDSOCKETJOINT:
190 ballAndSocketDlg->LoadConstraint( constraint );
191 constraintDlg = ballAndSocketDlg;
193 case DECLAF_CONSTRAINT_UNIVERSALJOINT:
194 universalDlg->LoadConstraint( constraint );
195 constraintDlg = universalDlg;
197 case DECLAF_CONSTRAINT_HINGE:
198 hingeDlg->LoadConstraint( constraint );
199 constraintDlg = hingeDlg;
201 case DECLAF_CONSTRAINT_SLIDER:
202 sliderDlg->LoadConstraint( constraint );
203 constraintDlg = sliderDlg;
205 case DECLAF_CONSTRAINT_SPRING:
206 springDlg->LoadConstraint( constraint );
207 constraintDlg = springDlg;
211 if ( constraintDlg ) {
212 constraintDlg->ShowWindow( SW_SHOW );
213 constraintDlg->GetWindowRect( &rect );
214 constraintDlg->MoveWindow( 0, 117, rect.right - rect.left, rect.bottom - rect.top );
220 DialogAFConstraint::InitBodyLists
223 void DialogAFConstraint::InitBodyLists( void ) {
224 m_comboBody1List.ResetContent();
225 m_comboBody2List.ResetContent();
229 for ( int i = 0; i < file->bodies.Num(); i++ ) {
230 m_comboBody1List.AddString( file->bodies[i]->name );
231 m_comboBody2List.AddString( file->bodies[i]->name );
233 // the second body may also be the world
234 m_comboBody2List.AddString( "world" ); // FIXME: we currently assume this is the last body in the list
239 DialogAFConstraint::InitNewRenameDeleteButtons
242 void DialogAFConstraint::InitNewRenameDeleteButtons( void ) {
243 if ( file && file->bodies.Num() >= 1 ) {
244 GetDlgItem( IDC_BUTTON_NEWCONSTRAINT )->EnableWindow( true );
247 GetDlgItem( IDC_BUTTON_NEWCONSTRAINT )->EnableWindow( false );
250 if ( file && m_comboConstraintList.GetCount() >= 1 ) {
251 GetDlgItem( IDC_BUTTON_RENAMECONSTRAINT )->EnableWindow( true );
252 GetDlgItem( IDC_BUTTON_DELETECONSTRAINT )->EnableWindow( true );
255 GetDlgItem( IDC_BUTTON_RENAMECONSTRAINT )->EnableWindow( false );
256 GetDlgItem( IDC_BUTTON_DELETECONSTRAINT )->EnableWindow( false );
262 DialogAFConstraint::LoadFile
265 void DialogAFConstraint::LoadFile( idDeclAF *af ) {
268 ballAndSocketDlg->LoadFile( af );
269 universalDlg->LoadFile( af );
270 hingeDlg->LoadFile( af );
271 sliderDlg->LoadFile( af );
272 springDlg->LoadFile( af );
274 InitConstraintList();
275 InitNewRenameDeleteButtons();
280 DialogAFConstraint::SaveFile
283 void DialogAFConstraint::SaveFile( void ) {
289 DialogAFConstraint::LoadConstraint
292 void DialogAFConstraint::LoadConstraint( const char *name ) {
298 for ( i = 0; i < file->constraints.Num(); i++ ) {
299 if ( file->constraints[i]->name.Icmp( name ) == 0 ) {
303 if ( i >= file->constraints.Num() ) {
306 constraint = file->constraints[i];
308 // load the constraint type from the current idDeclAF_Constraint
309 SetSafeComboBoxSelection( &m_comboConstraintType, ConstraintTypeToString( constraint->type ), -1 );
311 // load constrained bodies from the current idDeclAF_Constraint
312 s1 = SetSafeComboBoxSelection( &m_comboBody1List, constraint->body1.c_str(), -1 );
313 s2 = SetSafeComboBoxSelection( &m_comboBody2List, constraint->body2.c_str(), s1 );
315 // load friction from the current idDeclAF_Constraint
316 m_friction = constraint->friction;
318 // update displayed values
321 InitConstraintTypeDlg();
323 if ( GetStyle() & WS_VISIBLE ) {
324 // highlight the current constraint ingame
325 cvarSystem->SetCVarString( "af_highlightConstraint", name );
331 DialogAFConstraint::SaveConstraint
334 void DialogAFConstraint::SaveConstraint( void ) {
338 if ( !file || !constraint ) {
343 // save constraint type to the current idDeclAF_Constraint
344 GetSafeComboBoxSelection( &m_comboConstraintType, str, -1 );
345 constraint->type = StringToConstraintType( str );
347 // save constrained bodies to the current idDeclAF_Constraint
348 s1 = GetSafeComboBoxSelection( &m_comboBody1List, str, -1 );
349 constraint->body1 = str;
350 s2 = GetSafeComboBoxSelection( &m_comboBody2List, str, s1 );
351 constraint->body2 = str;
353 // save friction to the current idDeclAF_Constraint
354 constraint->friction = m_friction;
356 AFDialogSetFileModified();
361 DialogAFConstraint::UpdateFile
364 void DialogAFConstraint::UpdateFile( void ) {
367 gameEdit->AF_UpdateEntities( file->GetName() );
373 DialogAFConstraint::OnInitDialog
376 BOOL DialogAFConstraint::OnInitDialog() {
378 CDialog::OnInitDialog();
380 // initialize the constraint types
381 m_comboConstraintType.ResetContent();
382 for ( int i = 0; constraintTypes[i].name; i++ ) {
383 m_comboConstraintType.AddString( constraintTypes[i].name );
386 fixedDlg = new DialogAFConstraintFixed( this );
387 fixedDlg->ShowWindow( SW_HIDE );
389 ballAndSocketDlg = new DialogAFConstraintBallAndSocket( this );
390 ballAndSocketDlg->ShowWindow( SW_HIDE );
392 universalDlg = new DialogAFConstraintUniversal( this );
393 universalDlg->ShowWindow( SW_HIDE );
395 hingeDlg = new DialogAFConstraintHinge( this );
396 hingeDlg->ShowWindow( SW_HIDE );
398 sliderDlg = new DialogAFConstraintSlider( this );
399 sliderDlg->ShowWindow( SW_HIDE );
401 springDlg = new DialogAFConstraintSpring( this );
402 springDlg->ShowWindow( SW_HIDE );
404 constraintDlg = NULL;
406 InitNewRenameDeleteButtons();
408 return TRUE; // return TRUE unless you set the focus to a control
409 // EXCEPTION: OCX Property Pages should return FALSE
414 DialogAFConstraint::OnToolHitTest
417 int DialogAFConstraint::OnToolHitTest( CPoint point, TOOLINFO* pTI ) const {
418 CDialog::OnToolHitTest( point, pTI );
419 return DefaultOnToolHitTest( toolTips, this, point, pTI );
422 BEGIN_MESSAGE_MAP(DialogAFConstraint, CDialog)
423 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
424 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
426 ON_CBN_SELCHANGE(IDC_COMBO_CONSTRAINTS, OnCbnSelchangeComboConstraints)
427 ON_CBN_SELCHANGE(IDC_COMBO_CONSTRAINT_TYPE, OnCbnSelchangeComboConstraintType)
428 ON_CBN_SELCHANGE(IDC_COMBO_CONSTRAINT_BODY1, OnCbnSelchangeComboConstraintBody1)
429 ON_CBN_SELCHANGE(IDC_COMBO_CONSTRAINT_BODY2, OnCbnSelchangeComboConstraintBody2)
430 ON_EN_CHANGE(IDC_EDIT_CONSTRAINT_FRICTION, OnEnChangeEditConstraintFriction)
431 ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_CONSTRAINT_FRICTION, OnDeltaposSpinConstraintFriction)
432 ON_BN_CLICKED(IDC_BUTTON_NEWCONSTRAINT, OnBnClickedButtonNewconstraint)
433 ON_BN_CLICKED(IDC_BUTTON_RENAMECONSTRAINT, OnBnClickedButtonRenameconstraint)
434 ON_BN_CLICKED(IDC_BUTTON_DELETECONSTRAINT, OnBnClickedButtonDeleteconstraint)
438 // DialogAFConstraint message handlers
440 BOOL DialogAFConstraint::OnToolTipNotify( UINT id, NMHDR *pNMHDR, LRESULT *pResult ) {
441 return DefaultOnToolTipNotify( toolTips, id, pNMHDR, pResult );
444 void DialogAFConstraint::OnShowWindow( BOOL bShow, UINT nStatus ) {
445 if ( bShow && constraint ) {
446 cvarSystem->SetCVarString( "af_highlightConstraint", constraint->name.c_str() );
448 cvarSystem->SetCVarString( "af_highlightConstraint", "" );
450 CDialog::OnShowWindow( bShow, nStatus );
453 void DialogAFConstraint::OnCbnSelchangeComboConstraints() {
456 GetSafeComboBoxSelection( &m_comboConstraintList, str, -1 );
457 LoadConstraint( str );
460 void DialogAFConstraint::OnBnClickedButtonNewconstraint() {
461 DialogAFName nameDlg;
464 nameDlg.SetComboBox( &m_comboConstraintList );
465 if ( nameDlg.DoModal() == IDOK ) {
466 nameDlg.GetName( str );
467 // create new constraint
468 file->NewConstraint( str );
469 m_comboConstraintList.SetCurSel( m_comboConstraintList.AddString( str ) );
470 LoadConstraint( str );
471 gameEdit->AF_UpdateEntities( file->GetName() );
472 AFDialogSetFileModified();
474 InitNewRenameDeleteButtons();
477 void DialogAFConstraint::OnBnClickedButtonRenameconstraint() {
479 CString name, newName;
480 DialogAFName nameDlg;
482 if ( !file || !constraint ) {
486 i = m_comboConstraintList.GetCurSel();
488 m_comboConstraintList.GetLBText( i, name );
489 nameDlg.SetName( name );
490 nameDlg.SetComboBox( &m_comboConstraintList );
491 if ( nameDlg.DoModal() == IDOK ) {
492 nameDlg.GetName( newName );
493 // rename constraint;
494 file->RenameConstraint( name, newName );
495 m_comboConstraintList.DeleteString( i );
496 m_comboConstraintList.SetCurSel( m_comboConstraintList.AddString( newName ) );
497 LoadConstraint( newName );
498 gameEdit->AF_UpdateEntities( file->GetName() );
499 AFDialogSetFileModified();
504 void DialogAFConstraint::OnBnClickedButtonDeleteconstraint() {
508 if ( !file || !constraint ) {
512 i = m_comboConstraintList.GetCurSel();
514 if ( MessageBox( "Are you sure you want to delete this constraint ?", "Delete Constraint", MB_YESNO | MB_ICONQUESTION ) == IDYES ) {
515 m_comboConstraintList.GetLBText( i, str );
516 // delete current constraint
517 file->DeleteConstraint( str );
519 m_comboConstraintList.DeleteString( i );
520 OnCbnSelchangeComboConstraints();
521 gameEdit->AF_UpdateEntities( file->GetName() );
522 AFDialogSetFileModified();
525 InitNewRenameDeleteButtons();
528 void DialogAFConstraint::OnCbnSelchangeComboConstraintType() {
529 InitConstraintTypeDlg();
533 void DialogAFConstraint::OnCbnSelchangeComboConstraintBody1() {
535 GetSafeComboBoxSelection( &m_comboBody1List, str, -1 );
536 UnsetSafeComboBoxSelection( &m_comboBody2List, str );
540 void DialogAFConstraint::OnCbnSelchangeComboConstraintBody2() {
542 GetSafeComboBoxSelection( &m_comboBody2List, str, -1 );
543 UnsetSafeComboBoxSelection( &m_comboBody1List, str );
547 void DialogAFConstraint::OnEnChangeEditConstraintFriction() {
548 if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_CONSTRAINT_FRICTION ) ) ) {
552 EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_CONSTRAINT_FRICTION ), false );
556 void DialogAFConstraint::OnDeltaposSpinConstraintFriction(NMHDR *pNMHDR, LRESULT *pResult) {
557 LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
558 m_friction = EditSpinFloat( (CEdit *)GetDlgItem( IDC_EDIT_CONSTRAINT_FRICTION ), pNMUpDown->iDelta < 0 );