]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/tools/af/DialogAFConstraintSpring.cpp
hello world
[icculus/iodoom3.git] / neo / tools / af / DialogAFConstraintSpring.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #include "../../sys/win32/rc/AFEditor_resource.h"
33
34 #include "DialogAF.h"
35 #include "DialogAFConstraint.h"
36 #include "DialogAFConstraintSpring.h"
37
38
39 // DialogAFConstraintSpring dialog
40
41 toolTip_t DialogAFConstraintSpring::toolTips[] = {
42         { IDC_RADIO_ANCHOR_JOINT, "use the position of a joint for the first anchor" },
43         { IDC_COMBO_ANCHOR_JOINT, "first anchor joint name" },
44         { IDC_RADIO_ANCHOR_COORDINATES, "use absolute coordinates for the first anchor" },
45         { IDC_EDIT_ANCHOR_X, "first anchor x-coordinate" },
46         { IDC_EDIT_ANCHOR_Y, "first anchor y-coordinate" },
47         { IDC_EDIT_ANCHOR_Z, "first anchor z-coordinate" },
48         { IDC_RADIO_ANCHOR2_JOINT, "use the position of a joint for the second anchor" },
49         { IDC_COMBO_ANCHOR2_JOINT, "second anchor joint name" },
50         { IDC_RADIO_ANCHOR2_COORDINATES, "use absolute coordinates for the second anchor" },
51         { IDC_EDIT_ANCHOR2_X, "second anchor x-coordinate" },
52         { IDC_EDIT_ANCHOR2_Y, "second anchor y-coordinate" },
53         { IDC_EDIT_ANCHOR2_Z, "second anchor z-coordinate" },
54         { IDC_EDIT_SPRING_STRETCH, "spring constant when stretched" },
55         { IDC_EDIT_SPRING_COMPRESS, "spring constant when compressed" },
56         { IDC_EDIT_SPRING_DAMPING, "spring damping" },
57         { IDC_EDIT_SPRING_REST_LENGTH, "rest length" },
58         { IDC_RADIO_SPRING_NO_MIN_LENGTH, "no minimum length" },
59         { IDC_RADIO_SPRING_MIN_LENGTH, "minimum length" },
60         { IDC_EDIT_SPRING_MIN_LENGTH, "minimum length" },
61         { IDC_RADIO_SPRING_NO_MAX_LENGTH, "no maximum length" },
62         { IDC_RADIO_SPRING_MAX_LENGTH, "maximum length" },
63         { IDC_EDIT_SPRING_MAX_LENGTH, "maximum length" },
64         { 0, NULL }
65 };
66
67 IMPLEMENT_DYNAMIC(DialogAFConstraintSpring, CDialog)
68
69 /*
70 ================
71 DialogAFConstraintSpring::DialogAFConstraintSpring
72 ================
73 */
74 DialogAFConstraintSpring::DialogAFConstraintSpring(CWnd* pParent /*=NULL*/)
75         : CDialog(DialogAFConstraintSpring::IDD, pParent)
76         , m_anchor_x(0)
77         , m_anchor_y(0)
78         , m_anchor_z(0)
79         , m_anchor2_x(0)
80         , m_anchor2_y(0)
81         , m_anchor2_z(0)
82         , m_stretch(0)
83         , m_compress(0)
84         , m_damping(0)
85         , m_restLength(0)
86         , m_minLength(0)
87         , m_maxLength(0)
88         , constraint(NULL)
89         , file(NULL)
90 {
91         Create( IDD_DIALOG_AF_CONSTRAINT_SPRING, pParent );
92         EnableToolTips( TRUE );
93 }
94
95 /*
96 ================
97 DialogAFConstraintSpring::~DialogAFConstraintSpring
98 ================
99 */
100 DialogAFConstraintSpring::~DialogAFConstraintSpring() {
101 }
102
103 /*
104 ================
105 DialogAFConstraintSpring::DoDataExchange
106 ================
107 */
108 void DialogAFConstraintSpring::DoDataExchange(CDataExchange* pDX) {
109         CDialog::DoDataExchange(pDX);
110         //{{AFX_DATA_MAP(DialogAFConstraintSpring)
111         DDX_Control(pDX, IDC_COMBO_ANCHOR_JOINT, m_comboAnchorJoint);
112         DDX_Control(pDX, IDC_COMBO_ANCHOR2_JOINT, m_comboAnchor2Joint);
113         DDX_Text(pDX, IDC_EDIT_ANCHOR_X, m_anchor_x);
114         DDX_Text(pDX, IDC_EDIT_ANCHOR_Y, m_anchor_y);
115         DDX_Text(pDX, IDC_EDIT_ANCHOR_Z, m_anchor_z);
116         DDX_Text(pDX, IDC_EDIT_ANCHOR2_X, m_anchor2_x);
117         DDX_Text(pDX, IDC_EDIT_ANCHOR2_Y, m_anchor2_y);
118         DDX_Text(pDX, IDC_EDIT_ANCHOR2_Z, m_anchor2_z);
119         DDX_Text(pDX, IDC_EDIT_SPRING_STRETCH, m_stretch);
120         DDX_Text(pDX, IDC_EDIT_SPRING_COMPRESS, m_compress);
121         DDX_Text(pDX, IDC_EDIT_SPRING_DAMPING, m_damping);
122         DDX_Text(pDX, IDC_EDIT_SPRING_REST_LENGTH, m_restLength);
123         DDX_Text(pDX, IDC_EDIT_SPRING_MIN_LENGTH, m_minLength);
124         DDX_Text(pDX, IDC_EDIT_SPRING_MAX_LENGTH, m_maxLength);
125         //}}AFX_DATA_MAP
126 }
127
128 /*
129 ================
130 DialogAFConstraintSpring::InitJointLists
131 ================
132 */
133 void DialogAFConstraintSpring::InitJointLists( void ) {
134         m_comboAnchorJoint.ResetContent();
135         m_comboAnchor2Joint.ResetContent();
136
137         if ( !file ) {
138                 return;
139         }
140
141         const idRenderModel *model = gameEdit->ANIM_GetModelFromName( file->model );
142         if ( !model ) {
143                 return;
144         }
145
146         int numJoints = model->NumJoints();
147         for ( int i = 0; i < numJoints; i++ ) {
148                 const char *jointName = model->GetJointName( (jointHandle_t) i );
149                 m_comboAnchorJoint.AddString( jointName );
150                 m_comboAnchor2Joint.AddString( jointName );
151         }
152 }
153
154 /*
155 ================
156 DialogAFConstraintSpring::LoadFile
157 ================
158 */
159 void DialogAFConstraintSpring::LoadFile( idDeclAF *af ) {
160         file = af;
161         constraint = NULL;
162         InitJointLists();
163 }
164
165 /*
166 ================
167 DialogAFConstraintSpring::SaveFile
168 ================
169 */
170 void DialogAFConstraintSpring::SaveFile( void ) {
171         SaveConstraint();
172 }
173
174 /*
175 ================
176 DialogAFConstraintSpring::LoadConstraint
177 ================
178 */
179 void DialogAFConstraintSpring::LoadConstraint( idDeclAF_Constraint *c ) {
180         int i;
181
182         constraint = c;
183
184         // load first anchor from the current idDeclAF_Constraint
185         SetSafeComboBoxSelection( &m_comboAnchorJoint, constraint->anchor.joint1.c_str(), -1 );
186         m_anchor_x = constraint->anchor.ToVec3().x;
187         m_anchor_y = constraint->anchor.ToVec3().y;
188         m_anchor_z = constraint->anchor.ToVec3().z;
189         if ( constraint->anchor.type == idAFVector::VEC_JOINT ) {
190                 i = IDC_RADIO_ANCHOR_JOINT;
191         }
192         else {
193                 i = IDC_RADIO_ANCHOR_COORDINATES;
194         }
195         CheckRadioButton( IDC_RADIO_ANCHOR_JOINT, IDC_RADIO_ANCHOR_COORDINATES, i );
196
197         // load second anchor from the current idDeclAF_Constraint
198         SetSafeComboBoxSelection( &m_comboAnchor2Joint, constraint->anchor2.joint1.c_str(), -1 );
199         m_anchor2_x = constraint->anchor2.ToVec3().x;
200         m_anchor2_y = constraint->anchor2.ToVec3().y;
201         m_anchor2_z = constraint->anchor2.ToVec3().z;
202         if ( constraint->anchor2.type == idAFVector::VEC_JOINT ) {
203                 i = IDC_RADIO_ANCHOR2_JOINT;
204         }
205         else {
206                 i = IDC_RADIO_ANCHOR2_COORDINATES;
207         }
208         CheckRadioButton( IDC_RADIO_ANCHOR2_JOINT, IDC_RADIO_ANCHOR2_COORDINATES, i );
209
210         // spring settings
211         m_stretch = constraint->stretch;
212         m_compress = constraint->compress;
213         m_damping = constraint->damping;
214         m_restLength = constraint->restLength;
215
216         // spring limits
217         if ( constraint->minLength > 0.0f ) {
218                 i = IDC_RADIO_SPRING_MIN_LENGTH;
219         }
220         else {
221                 i = IDC_RADIO_SPRING_NO_MIN_LENGTH;
222         }
223         CheckRadioButton( IDC_RADIO_SPRING_NO_MIN_LENGTH, IDC_RADIO_SPRING_MIN_LENGTH, i );
224         m_minLength = constraint->minLength;
225
226         if ( constraint->maxLength > 0.0f ) {
227                 i = IDC_RADIO_SPRING_MAX_LENGTH;
228         }
229         else {
230                 i = IDC_RADIO_SPRING_NO_MAX_LENGTH;
231         }
232         CheckRadioButton( IDC_RADIO_SPRING_NO_MAX_LENGTH, IDC_RADIO_SPRING_MAX_LENGTH, i );
233         m_maxLength = constraint->maxLength;
234
235         // update displayed values
236         UpdateData( FALSE );
237 }
238
239 /*
240 ================
241 DialogAFConstraintSpring::SaveConstraint
242 ================
243 */
244 void DialogAFConstraintSpring::SaveConstraint( void ) {
245         CString str;
246
247         if ( !file || !constraint ) {
248                 return;
249         }
250         UpdateData( TRUE );
251
252         // save first anchor to the current idDeclAF_Constraint
253         GetSafeComboBoxSelection( &m_comboAnchorJoint, str, -1 );
254         constraint->anchor.joint1 = str;
255         constraint->anchor.ToVec3().x = m_anchor_x;
256         constraint->anchor.ToVec3().y = m_anchor_y;
257         constraint->anchor.ToVec3().z = m_anchor_z;
258
259         // save second anchor to the current idDeclAF_Constraint
260         GetSafeComboBoxSelection( &m_comboAnchor2Joint, str, -1 );
261         constraint->anchor2.joint1 = str;
262         constraint->anchor2.ToVec3().x = m_anchor2_x;
263         constraint->anchor2.ToVec3().y = m_anchor2_y;
264         constraint->anchor2.ToVec3().z = m_anchor2_z;
265
266         // spring settings
267         constraint->stretch = m_stretch;
268         constraint->compress = m_compress;
269         constraint->damping = m_damping;
270         constraint->restLength = m_restLength;
271
272         // spring limits
273         constraint->minLength = m_minLength;
274         constraint->maxLength = m_maxLength;
275
276         AFDialogSetFileModified();
277 }
278
279 /*
280 ================
281 DialogAFConstraintSpring::UpdateFile
282 ================
283 */
284 void DialogAFConstraintSpring::UpdateFile( void ) {
285         SaveConstraint();
286         if ( file ) {
287                 gameEdit->AF_UpdateEntities( file->GetName() );
288         }
289 }
290
291 /*
292 ================
293 DialogAFConstraintSpring::OnToolHitTest
294 ================
295 */
296 int DialogAFConstraintSpring::OnToolHitTest( CPoint point, TOOLINFO* pTI ) const {
297         CDialog::OnToolHitTest( point, pTI );
298         return DefaultOnToolHitTest( toolTips, this, point, pTI );
299 }
300
301
302 BEGIN_MESSAGE_MAP(DialogAFConstraintSpring, CDialog)
303         ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
304         ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
305         ON_BN_CLICKED(IDC_RADIO_ANCHOR_JOINT, OnBnClickedRadioAnchorJoint)
306         ON_BN_CLICKED(IDC_RADIO_ANCHOR_COORDINATES, OnBnClickedRadioAnchorCoordinates)
307         ON_CBN_SELCHANGE(IDC_COMBO_ANCHOR_JOINT, OnCbnSelchangeComboAnchorJoint)
308         ON_EN_CHANGE(IDC_EDIT_ANCHOR_X, OnEnChangeEditAnchorX)
309         ON_EN_CHANGE(IDC_EDIT_ANCHOR_Y, OnEnChangeEditAnchorY)
310         ON_EN_CHANGE(IDC_EDIT_ANCHOR_Z, OnEnChangeEditAnchorZ)
311         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ANCHOR_X, OnDeltaposSpinAnchorX)
312         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ANCHOR_Y, OnDeltaposSpinAnchorY)
313         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ANCHOR_Z, OnDeltaposSpinAnchorZ)
314         ON_BN_CLICKED(IDC_RADIO_ANCHOR2_JOINT, OnBnClickedRadioAnchor2Joint)
315         ON_BN_CLICKED(IDC_RADIO_ANCHOR2_COORDINATES, OnBnClickedRadioAnchor2Coordinates)
316         ON_CBN_SELCHANGE(IDC_COMBO_ANCHOR2_JOINT, OnCbnSelchangeComboAnchor2Joint)
317         ON_EN_CHANGE(IDC_EDIT_ANCHOR2_X, OnEnChangeEditAnchor2X)
318         ON_EN_CHANGE(IDC_EDIT_ANCHOR2_Y, OnEnChangeEditAnchor2Y)
319         ON_EN_CHANGE(IDC_EDIT_ANCHOR2_Z, OnEnChangeEditAnchor2Z)
320         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ANCHOR2_X, OnDeltaposSpinAnchor2X)
321         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ANCHOR2_Y, OnDeltaposSpinAnchor2Y)
322         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ANCHOR2_Z, OnDeltaposSpinAnchor2Z)
323         ON_EN_CHANGE(IDC_EDIT_SPRING_STRETCH, OnEnChangeEditSpringStretch)
324         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_SPRING_STRETCH, OnDeltaposSpinSpringStretch)
325         ON_EN_CHANGE(IDC_EDIT_SPRING_COMPRESS, OnEnChangeEditSpringCompress)
326         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_SPRING_COMPRESS, OnDeltaposSpinSpringCompress)
327         ON_EN_CHANGE(IDC_EDIT_SPRING_DAMPING, OnEnChangeEditSpringDamping)
328         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_SPRING_DAMPING, OnDeltaposSpinSpringDamping)
329         ON_EN_CHANGE(IDC_EDIT_SPRING_REST_LENGTH, OnEnChangeEditSpringRestLength)
330         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_SPRING_REST_LENGTH, OnDeltaposSpinSpringRestLength)
331         ON_BN_CLICKED(IDC_RADIO_SPRING_NO_MIN_LENGTH, OnBnClickedRadioLimitNoMinLength)
332         ON_BN_CLICKED(IDC_RADIO_SPRING_MIN_LENGTH, OnBnClickedRadioLimitMinLength)
333         ON_EN_CHANGE(IDC_EDIT_SPRING_MIN_LENGTH, OnEnChangeEditLimitMinLength)
334         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_SPRING_MIN_LENGTH, OnDeltaposSpinLimitMinLength)
335         ON_BN_CLICKED(IDC_RADIO_SPRING_NO_MAX_LENGTH, OnBnClickedRadioLimitNoMaxLength)
336         ON_BN_CLICKED(IDC_RADIO_SPRING_MAX_LENGTH, OnBnClickedRadioLimitMaxLength)
337         ON_EN_CHANGE(IDC_EDIT_SPRING_MAX_LENGTH, OnEnChangeEditLimitMaxLength)
338         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_SPRING_MAX_LENGTH, OnDeltaposSpinLimitMaxLength)
339 END_MESSAGE_MAP()
340
341
342 // DialogAFConstraintSpring message handlers
343
344 BOOL DialogAFConstraintSpring::OnToolTipNotify( UINT id, NMHDR *pNMHDR, LRESULT *pResult ) {
345         return DefaultOnToolTipNotify( toolTips, id, pNMHDR, pResult );
346 }
347
348 void DialogAFConstraintSpring::OnBnClickedRadioAnchorJoint() {
349         if ( IsDlgButtonChecked( IDC_RADIO_ANCHOR_JOINT ) ) {
350                 if ( constraint ) {
351                         constraint->anchor.type = idAFVector::VEC_JOINT;
352                         UpdateFile();
353                 }
354         }
355 }
356
357 void DialogAFConstraintSpring::OnBnClickedRadioAnchorCoordinates() {
358         if ( IsDlgButtonChecked( IDC_RADIO_ANCHOR_COORDINATES ) ) {
359                 if ( constraint ) {
360                         constraint->anchor.type = idAFVector::VEC_COORDS;
361                         UpdateFile();
362                 }
363         }
364 }
365
366 void DialogAFConstraintSpring::OnCbnSelchangeComboAnchorJoint() {
367         UpdateFile();
368 }
369
370 void DialogAFConstraintSpring::OnEnChangeEditAnchorX() {
371         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_X ) ) ) {
372                 UpdateFile();
373         }
374         else {
375                 EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_X ) );
376         }
377 }
378
379 void DialogAFConstraintSpring::OnEnChangeEditAnchorY() {
380         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_Y ) ) ) {
381                 UpdateFile();
382         }
383         else {
384                 EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_Y ) );
385         }
386 }
387
388 void DialogAFConstraintSpring::OnEnChangeEditAnchorZ() {
389         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_Z ) ) ) {
390                 UpdateFile();
391         }
392         else {
393                 EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_Z ) );
394         }
395 }
396
397 void DialogAFConstraintSpring::OnDeltaposSpinAnchorX(NMHDR *pNMHDR, LRESULT *pResult) {
398         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
399         if ( pNMUpDown->iDelta < 0 ) {
400                 m_anchor_x += 1.0f;
401         }
402         else {
403                 m_anchor_x -= 1.0f;
404         }
405         UpdateData( FALSE );
406         UpdateFile();
407         *pResult = 0;
408 }
409
410 void DialogAFConstraintSpring::OnDeltaposSpinAnchorY(NMHDR *pNMHDR, LRESULT *pResult) {
411         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
412         if ( pNMUpDown->iDelta < 0 ) {
413                 m_anchor_y += 1.0f;
414         }
415         else {
416                 m_anchor_y -= 1.0f;
417         }
418         UpdateData( FALSE );
419         UpdateFile();
420         *pResult = 0;
421 }
422
423 void DialogAFConstraintSpring::OnDeltaposSpinAnchorZ(NMHDR *pNMHDR, LRESULT *pResult) {
424         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
425         if ( pNMUpDown->iDelta < 0 ) {
426                 m_anchor_z += 1.0f;
427         }
428         else {
429                 m_anchor_z -= 1.0f;
430         }
431         UpdateData( FALSE );
432         UpdateFile();
433         *pResult = 0;
434 }
435
436 void DialogAFConstraintSpring::OnBnClickedRadioAnchor2Joint() {
437         if ( IsDlgButtonChecked( IDC_RADIO_ANCHOR2_JOINT ) ) {
438                 if ( constraint ) {
439                         constraint->anchor2.type = idAFVector::VEC_JOINT;
440                         UpdateFile();
441                 }
442         }
443 }
444
445 void DialogAFConstraintSpring::OnBnClickedRadioAnchor2Coordinates() {
446         if ( IsDlgButtonChecked( IDC_RADIO_ANCHOR2_COORDINATES ) ) {
447                 if ( constraint ) {
448                         constraint->anchor2.type = idAFVector::VEC_COORDS;
449                         UpdateFile();
450                 }
451         }
452 }
453
454 void DialogAFConstraintSpring::OnCbnSelchangeComboAnchor2Joint() {
455         UpdateFile();
456 }
457
458 void DialogAFConstraintSpring::OnEnChangeEditAnchor2X() {
459         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR2_X ) ) ) {
460                 UpdateFile();
461         }
462         else {
463                 EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR2_X ) );
464         }
465 }
466
467 void DialogAFConstraintSpring::OnEnChangeEditAnchor2Y() {
468         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR2_Y ) ) ) {
469                 UpdateFile();
470         }
471         else {
472                 EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR2_Y ) );
473         }
474 }
475
476 void DialogAFConstraintSpring::OnEnChangeEditAnchor2Z() {
477         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR2_Z ) ) ) {
478                 UpdateFile();
479         }
480         else {
481                 EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR2_Z ) );
482         }
483 }
484
485 void DialogAFConstraintSpring::OnDeltaposSpinAnchor2X(NMHDR *pNMHDR, LRESULT *pResult) {
486         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
487         if ( pNMUpDown->iDelta < 0 ) {
488                 m_anchor2_x += 1.0f;
489         }
490         else {
491                 m_anchor2_x -= 1.0f;
492         }
493         UpdateData( FALSE );
494         UpdateFile();
495         *pResult = 0;
496 }
497
498 void DialogAFConstraintSpring::OnDeltaposSpinAnchor2Y(NMHDR *pNMHDR, LRESULT *pResult) {
499         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
500         if ( pNMUpDown->iDelta < 0 ) {
501                 m_anchor2_y += 1.0f;
502         }
503         else {
504                 m_anchor2_y -= 1.0f;
505         }
506         UpdateData( FALSE );
507         UpdateFile();
508         *pResult = 0;
509 }
510
511 void DialogAFConstraintSpring::OnDeltaposSpinAnchor2Z(NMHDR *pNMHDR, LRESULT *pResult) {
512         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
513         if ( pNMUpDown->iDelta < 0 ) {
514                 m_anchor2_z += 1.0f;
515         }
516         else {
517                 m_anchor2_z -= 1.0f;
518         }
519         UpdateData( FALSE );
520         UpdateFile();
521         *pResult = 0;
522 }
523
524 void DialogAFConstraintSpring::OnEnChangeEditSpringStretch() {
525         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_SPRING_STRETCH ) ) ) {
526                 UpdateFile();
527         }
528         else {
529                 EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_SPRING_STRETCH ) );
530         }
531 }
532
533 void DialogAFConstraintSpring::OnDeltaposSpinSpringStretch(NMHDR *pNMHDR, LRESULT *pResult) {
534         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
535         m_stretch = EditSpinFloat( (CEdit *)GetDlgItem( IDC_EDIT_SPRING_STRETCH ), pNMUpDown->iDelta < 0 );
536         UpdateFile();
537         *pResult = 0;
538 }
539
540 void DialogAFConstraintSpring::OnEnChangeEditSpringCompress() {
541         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_SPRING_COMPRESS ) ) ) {
542                 UpdateFile();
543         }
544         else {
545                 EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_SPRING_COMPRESS ) );
546         }
547 }
548
549 void DialogAFConstraintSpring::OnDeltaposSpinSpringCompress(NMHDR *pNMHDR, LRESULT *pResult) {
550         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
551         m_compress = EditSpinFloat( (CEdit *)GetDlgItem( IDC_EDIT_SPRING_COMPRESS ), pNMUpDown->iDelta < 0 );
552         UpdateFile();
553         *pResult = 0;
554 }
555
556 void DialogAFConstraintSpring::OnEnChangeEditSpringDamping() {
557         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_SPRING_DAMPING ) ) ) {
558                 UpdateFile();
559         }
560         else {
561                 EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_SPRING_DAMPING ) );
562         }
563 }
564
565 void DialogAFConstraintSpring::OnDeltaposSpinSpringDamping(NMHDR *pNMHDR, LRESULT *pResult) {
566         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
567         m_damping = EditSpinFloat( (CEdit *)GetDlgItem( IDC_EDIT_SPRING_DAMPING ), pNMUpDown->iDelta < 0 );
568         UpdateFile();
569         *pResult = 0;
570 }
571
572 void DialogAFConstraintSpring::OnEnChangeEditSpringRestLength() {
573         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_SPRING_REST_LENGTH ) ) ) {
574                 UpdateFile();
575         }
576         else {
577                 EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_SPRING_REST_LENGTH ) );
578         }
579 }
580
581 void DialogAFConstraintSpring::OnDeltaposSpinSpringRestLength(NMHDR *pNMHDR, LRESULT *pResult) {
582         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
583         if ( pNMUpDown->iDelta < 0 ) {
584                 m_restLength += 1.0f;
585         }
586         else {
587                 m_restLength -= 1.0f;
588         }
589         UpdateData( FALSE );
590         UpdateFile();
591         *pResult = 0;
592 }
593
594 void DialogAFConstraintSpring::OnBnClickedRadioLimitNoMinLength() {
595         if ( IsDlgButtonChecked( IDC_RADIO_SPRING_NO_MIN_LENGTH ) ) {
596                 if ( constraint ) {
597                         constraint->minLength = 0.0f;
598                         UpdateFile();
599                 }
600         }
601 }
602
603 void DialogAFConstraintSpring::OnBnClickedRadioLimitMinLength() {
604         // do nothing
605 }
606
607 void DialogAFConstraintSpring::OnEnChangeEditLimitMinLength() {
608         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_SPRING_MIN_LENGTH ) ) ) {
609                 UpdateFile();
610         }
611         else {
612                 EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_SPRING_MIN_LENGTH ) );
613         }
614 }
615
616 void DialogAFConstraintSpring::OnDeltaposSpinLimitMinLength(NMHDR *pNMHDR, LRESULT *pResult) {
617         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
618         if ( pNMUpDown->iDelta < 0 ) {
619                 m_minLength += 1.0f;
620         }
621         else {
622                 m_minLength -= 1.0f;
623         }
624         UpdateData( FALSE );
625         UpdateFile();
626         *pResult = 0;
627 }
628
629 void DialogAFConstraintSpring::OnBnClickedRadioLimitNoMaxLength() {
630         if ( IsDlgButtonChecked( IDC_RADIO_SPRING_NO_MAX_LENGTH ) ) {
631                 if ( constraint ) {
632                         constraint->maxLength = 0.0f;
633                         UpdateFile();
634                 }
635         }
636 }
637
638 void DialogAFConstraintSpring::OnBnClickedRadioLimitMaxLength() {
639         // do nothing
640 }
641
642 void DialogAFConstraintSpring::OnEnChangeEditLimitMaxLength() {
643         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_SPRING_MAX_LENGTH ) ) ) {
644                 UpdateFile();
645         }
646         else {
647                 EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_SPRING_MAX_LENGTH ) );
648         }
649 }
650
651 void DialogAFConstraintSpring::OnDeltaposSpinLimitMaxLength(NMHDR *pNMHDR, LRESULT *pResult) {
652         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
653         if ( pNMUpDown->iDelta < 0 ) {
654                 m_maxLength += 1.0f;
655         }
656         else {
657                 m_maxLength -= 1.0f;
658         }
659         UpdateData( FALSE );
660         UpdateFile();
661         *pResult = 0;
662 }