]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/tools/af/DialogAFConstraintUniversal.cpp
hello world
[icculus/iodoom3.git] / neo / tools / af / DialogAFConstraintUniversal.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 "DialogAFConstraintUniversal.h"
37
38
39 // DialogAFConstraintUniversal dialog
40
41 toolTip_t DialogAFConstraintUniversal::toolTips[] = {
42         { IDC_RADIO_ANCHOR_JOINT, "use the position of a joint for the anchor" },
43         { IDC_COMBO_ANCHOR_JOINT, "anchor joint name" },
44         { IDC_RADIO_ANCHOR_COORDINATES, "use absolute coordinates for the anchor" },
45         { IDC_EDIT_ANCHOR_X, "anchor x-coordinate" },
46         { IDC_EDIT_ANCHOR_Y, "anchor y-coordinate" },
47         { IDC_EDIT_ANCHOR_Z, "anchor z-coordinate" },
48         { IDC_RADIO_UNIVERSAL_BONE_SHAFT1, "use a bone for the first shaft" },
49         { IDC_RADIO_UNIVERSAL_ANGLES_SHAFT1, "use angles to set the orientation of the first shaft" },
50         { IDC_COMBO_UNIVERSAL_JOINT1_SHAFT1, "bone start joint" },
51         { IDC_COMBO_UNIVERSAL_JOINT2_SHAFT1, "bone end joint" },
52         { IDC_EDIT_UNIVERSAL_PITCH_SHAFT1, "pitch angle" },
53         { IDC_EDIT_UNIVERSAL_YAW_SHAFT1, "yaw angle" },
54         { IDC_RADIO_UNIVERSAL_BONE_SHAFT2, "use a bone for the second shaft" },
55         { IDC_RADIO_UNIVERSAL_ANGLES_SHAFT2, "use angles to set the orientation of the second shaft" },
56         { IDC_COMBO_UNIVERSAL_JOINT1_SHAFT2, "bone start joint" },
57         { IDC_COMBO_UNIVERSAL_JOINT2_SHAFT2, "bone end joint" },
58         { IDC_EDIT_UNIVERSAL_PITCH_SHAFT2, "pitch angle" },
59         { IDC_EDIT_UNIVERSAL_YAW_SHAFT2, "yaw angle" },
60         { IDC_RADIO_UNIVERSAL_LIMIT_NONE, "no joint limit" },
61         { IDC_RADIO_UNIVERSAL_LIMIT_CONE, "cone shaped joint limit" },
62         { IDC_RADIO_UNIVERSAL_LIMIT_PYRAMID, "pyramid shaped joint limit" },
63         { IDC_RADIO_UNIVERSAL_LIMIT_BONE, "use a bone for the limit orientation" },
64         { IDC_RADIO_UNIVERSAL_LIMIT_ANGLES, "use angles for the limit orientation" },
65         { IDC_COMBO_UNIVERSAL_LIMIT_JOINT1, "bone start joint" },
66         { IDC_COMBO_UNIVERSAL_LIMIT_JOINT2, "bone end joint" },
67         { IDC_EDIT_UNIVERSAL_LIMIT_PITCH, "pitch angle" },
68         { IDC_EDIT_UNIVERSAL_LIMIT_YAW, "yaw angle" },
69         { IDC_EDIT_UNIVERSAL_LIMIT_ROLL, "roll angle" },
70         { IDC_EDIT_UNIVERSAL_LIMIT_CONE_ANGLE, "cone angle" },
71         { IDC_EDIT_UNIVERSAL_LIMIT_PYRAMID_ANGLE1, "first pyramid angle" },
72         { IDC_EDIT_UNIVERSAL_LIMIT_PYRAMID_ANGLE2, "second pyramid angle" },
73         { 0, NULL }
74 };
75
76 IMPLEMENT_DYNAMIC(DialogAFConstraintUniversal, CDialog)
77
78 /*
79 ================
80 DialogAFConstraintUniversal::DialogAFConstraintUniversal
81 ================
82 */
83 DialogAFConstraintUniversal::DialogAFConstraintUniversal(CWnd* pParent /*=NULL*/)
84         : CDialog(DialogAFConstraintUniversal::IDD, pParent)
85         , m_anchor_x(0)
86         , m_anchor_y(0)
87         , m_anchor_z(0)
88         , m_pitchShaft1(0)
89         , m_yawShaft1(0)
90         , m_pitchShaft2(0)
91         , m_yawShaft2(0)
92         , m_coneAngle(30.0f)
93         , m_pyramidAngle1(30.0f)
94         , m_pyramidAngle2(30.0f)
95         , m_limitPitch(0)
96         , m_limitYaw(0)
97         , m_limitRoll(0)
98         , constraint(NULL)
99         , file(NULL)
100 {
101         Create( IDD_DIALOG_AF_CONSTRAINT_UNIVERSAL, pParent );
102         EnableToolTips( TRUE );
103 }
104
105 /*
106 ================
107 DialogAFConstraintUniversal::~DialogAFConstraintUniversal
108 ================
109 */
110 DialogAFConstraintUniversal::~DialogAFConstraintUniversal() {
111 }
112
113 /*
114 ================
115 DialogAFConstraintUniversal::DoDataExchange
116 ================
117 */
118 void DialogAFConstraintUniversal::DoDataExchange(CDataExchange* pDX) {
119         CDialog::DoDataExchange(pDX);
120         //{{AFX_DATA_MAP(DialogAFConstraintUniversal)
121         DDX_Control(pDX, IDC_COMBO_ANCHOR_JOINT, m_comboAnchorJoint);
122         DDX_Text(pDX, IDC_EDIT_ANCHOR_X, m_anchor_x);
123         DDX_Text(pDX, IDC_EDIT_ANCHOR_Y, m_anchor_y);
124         DDX_Text(pDX, IDC_EDIT_ANCHOR_Z, m_anchor_z);
125         DDX_Control(pDX, IDC_COMBO_UNIVERSAL_JOINT1_SHAFT1, m_comboJoint1Shaft1);
126         DDX_Control(pDX, IDC_COMBO_UNIVERSAL_JOINT2_SHAFT1, m_comboJoint2Shaft1);
127         DDX_Text(pDX, IDC_EDIT_UNIVERSAL_PITCH_SHAFT1, m_pitchShaft1);
128         DDX_Text(pDX, IDC_EDIT_UNIVERSAL_YAW_SHAFT1, m_yawShaft1);
129         DDX_Control(pDX, IDC_COMBO_UNIVERSAL_JOINT1_SHAFT2, m_comboJoint1Shaft2);
130         DDX_Control(pDX, IDC_COMBO_UNIVERSAL_JOINT2_SHAFT2, m_comboJoint2Shaft2);
131         DDX_Text(pDX, IDC_EDIT_UNIVERSAL_PITCH_SHAFT2, m_pitchShaft2);
132         DDX_Text(pDX, IDC_EDIT_UNIVERSAL_YAW_SHAFT2, m_yawShaft2);
133         DDX_Text(pDX, IDC_EDIT_UNIVERSAL_LIMIT_CONE_ANGLE, m_coneAngle);
134         DDX_Text(pDX, IDC_EDIT_UNIVERSAL_LIMIT_PYRAMID_ANGLE1, m_pyramidAngle1);
135         DDX_Text(pDX, IDC_EDIT_UNIVERSAL_LIMIT_PYRAMID_ANGLE2, m_pyramidAngle2);
136         DDX_Control(pDX, IDC_COMBO_UNIVERSAL_LIMIT_JOINT1, m_comboLimitJoint1);
137         DDX_Control(pDX, IDC_COMBO_UNIVERSAL_LIMIT_JOINT2, m_comboLimitJoint2);
138         DDX_Text(pDX, IDC_EDIT_UNIVERSAL_LIMIT_PITCH, m_limitPitch);
139         DDX_Text(pDX, IDC_EDIT_UNIVERSAL_LIMIT_YAW, m_limitYaw);
140         DDX_Text(pDX, IDC_EDIT_UNIVERSAL_LIMIT_ROLL, m_limitRoll);
141         //}}AFX_DATA_MAP
142 }
143
144 /*
145 ================
146 DialogAFConstraintUniversal::InitJointLists
147 ================
148 */
149 void DialogAFConstraintUniversal::InitJointLists( void ) {
150         m_comboAnchorJoint.ResetContent();
151         m_comboJoint1Shaft1.ResetContent();
152         m_comboJoint2Shaft1.ResetContent();
153         m_comboJoint1Shaft2.ResetContent();
154         m_comboJoint2Shaft2.ResetContent();
155         m_comboLimitJoint1.ResetContent();
156         m_comboLimitJoint2.ResetContent();
157
158         if ( !file ) {
159                 return;
160         }
161
162         const idRenderModel *model = gameEdit->ANIM_GetModelFromName( file->model );
163         if ( !model ) {
164                 return;
165         }
166
167         int numJoints = model->NumJoints();
168         for ( int i = 0; i < numJoints; i++ ) {
169                 const char *jointName = model->GetJointName( (jointHandle_t) i );
170                 m_comboAnchorJoint.AddString( jointName );
171                 m_comboJoint1Shaft1.AddString( jointName );
172                 m_comboJoint2Shaft1.AddString( jointName );
173                 m_comboJoint1Shaft2.AddString( jointName );
174                 m_comboJoint2Shaft2.AddString( jointName );
175                 m_comboLimitJoint1.AddString( jointName );
176                 m_comboLimitJoint2.AddString( jointName );
177         }
178 }
179
180 /*
181 ================
182 DialogAFConstraintUniversal::LoadFile
183 ================
184 */
185 void DialogAFConstraintUniversal::LoadFile( idDeclAF *af ) {
186         file = af;
187         constraint = NULL;
188         InitJointLists();
189 }
190
191 /*
192 ================
193 DialogAFConstraintUniversal::SaveFile
194 ================
195 */
196 void DialogAFConstraintUniversal::SaveFile( void ) {
197         SaveConstraint();
198 }
199
200 /*
201 ================
202 DialogAFConstraintUniversal::LoadConstraint
203 ================
204 */
205 void DialogAFConstraintUniversal::LoadConstraint( idDeclAF_Constraint *c ) {
206         int i, s1, s2;
207         idAngles angles;
208         idMat3 mat;
209
210         constraint = c;
211
212         // anchor
213         SetSafeComboBoxSelection( &m_comboAnchorJoint, constraint->anchor.joint1.c_str(), -1 );
214         m_anchor_x = constraint->anchor.ToVec3().x;
215         m_anchor_y = constraint->anchor.ToVec3().y;
216         m_anchor_z = constraint->anchor.ToVec3().z;
217         if ( constraint->anchor.type == idAFVector::VEC_JOINT ) {
218                 i = IDC_RADIO_ANCHOR_JOINT;
219         }
220         else {
221                 i = IDC_RADIO_ANCHOR_COORDINATES;
222         }
223         CheckRadioButton( IDC_RADIO_ANCHOR_JOINT, IDC_RADIO_ANCHOR_COORDINATES, i );
224
225         // shaft 1
226         s1 = SetSafeComboBoxSelection( &m_comboJoint1Shaft1, constraint->shaft[0].joint1.c_str(), -1 );
227         s2 = SetSafeComboBoxSelection( &m_comboJoint2Shaft1, constraint->shaft[0].joint2.c_str(), s1 );
228         angles = constraint->shaft[0].ToVec3().ToAngles();
229         m_pitchShaft1 = angles.pitch;
230         m_yawShaft1 = angles.yaw;
231         if ( constraint->shaft[0].type == idAFVector::VEC_BONEDIR ) {
232                 i = IDC_RADIO_UNIVERSAL_BONE_SHAFT1;
233         }
234         else {
235                 i = IDC_RADIO_UNIVERSAL_ANGLES_SHAFT1;
236                 constraint->shaft[0].type = idAFVector::VEC_COORDS;
237         }
238         CheckRadioButton( IDC_RADIO_UNIVERSAL_BONE_SHAFT1, IDC_RADIO_UNIVERSAL_ANGLES_SHAFT1, i );
239
240         // shaft 2
241         s1 = SetSafeComboBoxSelection( &m_comboJoint1Shaft2, constraint->shaft[1].joint1.c_str(), -1 );
242         s2 = SetSafeComboBoxSelection( &m_comboJoint2Shaft2, constraint->shaft[1].joint2.c_str(), s1 );
243         angles = constraint->shaft[1].ToVec3().ToAngles();
244         m_pitchShaft2 = angles.pitch;
245         m_yawShaft2 = angles.yaw;
246         if ( constraint->shaft[1].type == idAFVector::VEC_BONEDIR ) {
247                 i = IDC_RADIO_UNIVERSAL_BONE_SHAFT2;
248         }
249         else {
250                 i = IDC_RADIO_UNIVERSAL_ANGLES_SHAFT2;
251                 constraint->shaft[1].type = idAFVector::VEC_COORDS;
252         }
253         CheckRadioButton( IDC_RADIO_UNIVERSAL_BONE_SHAFT2, IDC_RADIO_UNIVERSAL_ANGLES_SHAFT2, i );
254
255         // limit
256         if ( constraint->limit == idDeclAF_Constraint::LIMIT_CONE ) {
257                 i = IDC_RADIO_UNIVERSAL_LIMIT_CONE;
258         }
259         else if ( constraint->limit == idDeclAF_Constraint::LIMIT_PYRAMID ) {
260                 i = IDC_RADIO_UNIVERSAL_LIMIT_PYRAMID;
261         }
262         else {
263                 i = IDC_RADIO_UNIVERSAL_LIMIT_NONE;
264         }
265         CheckRadioButton( IDC_RADIO_UNIVERSAL_LIMIT_NONE, IDC_RADIO_UNIVERSAL_LIMIT_PYRAMID, i );
266
267         m_coneAngle = constraint->limitAngles[0];
268         m_pyramidAngle1 = constraint->limitAngles[0];
269         m_pyramidAngle2 = constraint->limitAngles[1];
270         m_limitRoll = constraint->limitAngles[2];
271         angles = constraint->limitAxis.ToVec3().ToAngles();
272         m_limitPitch = angles.pitch;
273         m_limitYaw = angles.yaw;
274
275         if ( constraint->limitAxis.type == idAFVector::VEC_BONEDIR ) {
276                 i = IDC_RADIO_UNIVERSAL_LIMIT_BONE;
277         }
278         else {
279                 i = IDC_RADIO_UNIVERSAL_LIMIT_ANGLES;
280         }
281         CheckRadioButton( IDC_RADIO_UNIVERSAL_LIMIT_BONE, IDC_RADIO_UNIVERSAL_LIMIT_ANGLES, i );
282         s1 = SetSafeComboBoxSelection( &m_comboLimitJoint1, constraint->limitAxis.joint1.c_str(), -1 );
283         s2 = SetSafeComboBoxSelection( &m_comboLimitJoint2, constraint->limitAxis.joint2.c_str(), s1 );
284
285         // update displayed values
286         UpdateData( FALSE );
287 }
288
289 /*
290 ================
291 DialogAFConstraintUniversal::SaveConstraint
292 ================
293 */
294 void DialogAFConstraintUniversal::SaveConstraint( void ) {
295         int s1, s2;
296         CString str;
297         idAngles angles;
298         idMat3 mat;
299
300         if ( !file || !constraint ) {
301                 return;
302         }
303         UpdateData( TRUE );
304
305         // anchor
306         GetSafeComboBoxSelection( &m_comboAnchorJoint, str, -1 );
307         constraint->anchor.joint1 = str;
308         constraint->anchor.ToVec3().x = m_anchor_x;
309         constraint->anchor.ToVec3().y = m_anchor_y;
310         constraint->anchor.ToVec3().z = m_anchor_z;
311
312         // shaft 1
313         if ( constraint->shaft[0].type == idAFVector::VEC_BONEDIR ) {
314                 s1 = GetSafeComboBoxSelection( &m_comboJoint1Shaft1, str, -1 );
315                 constraint->shaft[0].joint1 = str;
316                 s2 = GetSafeComboBoxSelection( &m_comboJoint2Shaft1, str, s1 );
317                 constraint->shaft[0].joint2 = str;
318         }
319         else {
320                 constraint->shaft[0].ToVec3() = idAngles( m_pitchShaft1, m_yawShaft1, 0.0f ).ToForward();
321         }
322
323         // shaft 2
324         if ( constraint->shaft[1].type == idAFVector::VEC_BONEDIR ) {
325                 s1 = GetSafeComboBoxSelection( &m_comboJoint1Shaft2, str, -1 );
326                 constraint->shaft[1].joint1 = str;
327                 s2 = GetSafeComboBoxSelection( &m_comboJoint2Shaft2, str, s1 );
328                 constraint->shaft[1].joint2 = str;
329         }
330         else {
331                 constraint->shaft[1].ToVec3() = idAngles( m_pitchShaft2, m_yawShaft2, 0.0f ).ToForward();
332         }
333
334         // limit
335         if ( constraint->limit == idDeclAF_Constraint::LIMIT_CONE ) {
336                 constraint->limitAngles[0] = m_coneAngle;
337         }
338         else {
339                 constraint->limitAngles[0] = m_pyramidAngle1;
340         }
341         constraint->limitAngles[1] = m_pyramidAngle2;
342         constraint->limitAngles[2] = m_limitRoll;
343         angles.pitch = m_limitPitch;
344         angles.yaw = m_limitYaw;
345         angles.roll = 0.0f;
346         constraint->limitAxis.ToVec3() = angles.ToForward();
347         s1 = GetSafeComboBoxSelection( &m_comboLimitJoint1, str, -1 );
348         constraint->limitAxis.joint1 = str;
349         s2 = GetSafeComboBoxSelection( &m_comboLimitJoint2, str, s1 );
350         constraint->limitAxis.joint2 = str;
351
352         AFDialogSetFileModified();
353 }
354
355 /*
356 ================
357 DialogAFConstraintUniversal::UpdateFile
358 ================
359 */
360 void DialogAFConstraintUniversal::UpdateFile( void ) {
361         SaveConstraint();
362         if ( file ) {
363                 gameEdit->AF_UpdateEntities( file->GetName() );
364         }
365 }
366
367 /*
368 ================
369 DialogAFConstraintUniversal::OnToolHitTest
370 ================
371 */
372 int DialogAFConstraintUniversal::OnToolHitTest( CPoint point, TOOLINFO* pTI ) const {
373         CDialog::OnToolHitTest( point, pTI );
374         return DefaultOnToolHitTest( toolTips, this, point, pTI );
375 }
376
377
378 BEGIN_MESSAGE_MAP(DialogAFConstraintUniversal, CDialog)
379         ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
380         ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
381         ON_BN_CLICKED(IDC_RADIO_ANCHOR_JOINT, OnBnClickedRadioAnchorJoint)
382         ON_BN_CLICKED(IDC_RADIO_ANCHOR_COORDINATES, OnBnClickedRadioAnchorCoordinates)
383         ON_CBN_SELCHANGE(IDC_COMBO_ANCHOR_JOINT, OnCbnSelchangeComboAnchorJoint)
384         ON_EN_CHANGE(IDC_EDIT_ANCHOR_X, OnEnChangeEditAnchorX)
385         ON_EN_CHANGE(IDC_EDIT_ANCHOR_Y, OnEnChangeEditAnchorY)
386         ON_EN_CHANGE(IDC_EDIT_ANCHOR_Z, OnEnChangeEditAnchorZ)
387         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ANCHOR_X, OnDeltaposSpinAnchorX)
388         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ANCHOR_Y, OnDeltaposSpinAnchorY)
389         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ANCHOR_Z, OnDeltaposSpinAnchorZ)
390         ON_BN_CLICKED(IDC_RADIO_UNIVERSAL_BONE_SHAFT1, OnBnClickedRadioUniversalBoneShaft1)
391         ON_BN_CLICKED(IDC_RADIO_UNIVERSAL_ANGLES_SHAFT1, OnBnClickedRadioUniversalAnglesShaft1)
392         ON_CBN_SELCHANGE(IDC_COMBO_UNIVERSAL_JOINT1_SHAFT1, OnCbnSelchangeComboUniversalJoint1Shaft1)
393         ON_CBN_SELCHANGE(IDC_COMBO_UNIVERSAL_JOINT2_SHAFT1, OnCbnSelchangeComboUniversalJoint2Shaft1)
394         ON_EN_CHANGE(IDC_EDIT_UNIVERSAL_PITCH_SHAFT1, OnEnChangeEditUniversalPitchShaft1)
395         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_UNIVERSAL_PITCH_SHAFT1, OnDeltaposSpinUniversalPitchShaft1)
396         ON_EN_CHANGE(IDC_EDIT_UNIVERSAL_YAW_SHAFT1, OnEnChangeEditUniversalYawShaft1)
397         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_UNIVERSAL_YAW_SHAFT1, OnDeltaposSpinUniversalYawShaft1)
398         ON_BN_CLICKED(IDC_RADIO_UNIVERSAL_BONE_SHAFT2, OnBnClickedRadioUniversalBoneShaft2)
399         ON_BN_CLICKED(IDC_RADIO_UNIVERSAL_ANGLES_SHAFT2, OnBnClickedRadioUniversalAnglesShaft2)
400         ON_CBN_SELCHANGE(IDC_COMBO_UNIVERSAL_JOINT1_SHAFT2, OnCbnSelchangeComboUniversalJoint1Shaft2)
401         ON_CBN_SELCHANGE(IDC_COMBO_UNIVERSAL_JOINT2_SHAFT2, OnCbnSelchangeComboUniversalJoint2Shaft2)
402         ON_EN_CHANGE(IDC_EDIT_UNIVERSAL_PITCH_SHAFT2, OnEnChangeEditUniversalPitchShaft2)
403         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_UNIVERSAL_PITCH_SHAFT2, OnDeltaposSpinUniversalPitchShaft2)
404         ON_EN_CHANGE(IDC_EDIT_UNIVERSAL_YAW_SHAFT2, OnEnChangeEditUniversalYawShaft2)
405         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_UNIVERSAL_YAW_SHAFT2, OnDeltaposSpinUniversalYawShaft2)
406         ON_BN_CLICKED(IDC_RADIO_UNIVERSAL_LIMIT_NONE, OnBnClickedRadioUniversalLimitNone)
407         ON_BN_CLICKED(IDC_RADIO_UNIVERSAL_LIMIT_CONE, OnBnClickedRadioUniversalLimitCone)
408         ON_BN_CLICKED(IDC_RADIO_UNIVERSAL_LIMIT_PYRAMID, OnBnClickedRadioUniversalLimitPyramid)
409         ON_EN_CHANGE(IDC_EDIT_UNIVERSAL_LIMIT_CONE_ANGLE, OnEnChangeEditUniversalLimitConeAngle)
410         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_UNIVERSAL_LIMIT_CONE_ANGLE, OnDeltaposSpinUniversalLimitConeAngle)
411         ON_EN_CHANGE(IDC_EDIT_UNIVERSAL_LIMIT_PYRAMID_ANGLE1, OnEnChangeEditUniversalLimitPyramidAngle1)
412         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_UNIVERSAL_LIMIT_PYRAMID_ANGLE1, OnDeltaposSpinUniversalLimitPyramidAngle1)
413         ON_EN_CHANGE(IDC_EDIT_UNIVERSAL_LIMIT_PYRAMID_ANGLE2, OnEnChangeEditUniversalLimitPyramidAngle2)
414         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_UNIVERSAL_LIMIT_PYRAMID_ANGLE2, OnDeltaposSpinUniversalLimitPyramidAngle2)
415         ON_EN_CHANGE(IDC_EDIT_UNIVERSAL_LIMIT_ROLL, OnEnChangeEditUniversalLimitRoll)
416         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_UNIVERSAL_LIMIT_ROLL, OnDeltaposSpinUniversalLimitRoll)
417         ON_BN_CLICKED(IDC_RADIO_UNIVERSAL_LIMIT_BONE, OnBnClickedRadioUniversalLimitBone)
418         ON_BN_CLICKED(IDC_RADIO_UNIVERSAL_LIMIT_ANGLES, OnBnClickedRadioUniversalLimitAngles)
419         ON_CBN_SELCHANGE(IDC_COMBO_UNIVERSAL_LIMIT_JOINT1, OnCbnSelchangeComboUniversalLimitJoint1)
420         ON_CBN_SELCHANGE(IDC_COMBO_UNIVERSAL_LIMIT_JOINT2, OnCbnSelchangeComboUniversalLimitJoint2)
421         ON_EN_CHANGE(IDC_EDIT_UNIVERSAL_LIMIT_PITCH, OnEnChangeEditUniversalLimitPitch)
422         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_UNIVERSAL_LIMIT_PITCH, OnDeltaposSpinUniversalLimitPitch)
423         ON_EN_CHANGE(IDC_EDIT_UNIVERSAL_LIMIT_YAW, OnEnChangeEditUniversalLimitYaw)
424         ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_UNIVERSAL_LIMIT_YAW, OnDeltaposSpinUniversalLimitYaw)
425 END_MESSAGE_MAP()
426
427
428 // DialogAFConstraintUniversal message handlers
429
430 BOOL DialogAFConstraintUniversal::OnToolTipNotify( UINT id, NMHDR *pNMHDR, LRESULT *pResult ) {
431         return DefaultOnToolTipNotify( toolTips, id, pNMHDR, pResult );
432 }
433
434 void DialogAFConstraintUniversal::OnBnClickedRadioAnchorJoint() {
435         if ( IsDlgButtonChecked( IDC_RADIO_ANCHOR_JOINT ) ) {
436                 if ( constraint ) {
437                         constraint->anchor.type = idAFVector::VEC_JOINT;
438                         UpdateFile();
439                 }
440         }
441 }
442
443 void DialogAFConstraintUniversal::OnBnClickedRadioAnchorCoordinates() {
444         if ( IsDlgButtonChecked( IDC_RADIO_ANCHOR_COORDINATES ) ) {
445                 if ( constraint ) {
446                         constraint->anchor.type = idAFVector::VEC_COORDS;
447                         UpdateFile();
448                 }
449         }
450 }
451
452 void DialogAFConstraintUniversal::OnCbnSelchangeComboAnchorJoint() {
453         UpdateFile();
454 }
455
456 void DialogAFConstraintUniversal::OnEnChangeEditAnchorX() {
457         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_X ) ) ) {
458                 UpdateFile();
459         }
460         else {
461                 m_anchor_x = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_X ) );
462         }
463 }
464
465 void DialogAFConstraintUniversal::OnEnChangeEditAnchorY() {
466         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_Y ) ) ) {
467                 UpdateFile();
468         }
469         else {
470                 m_anchor_y = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_Y ) );
471         }
472 }
473
474 void DialogAFConstraintUniversal::OnEnChangeEditAnchorZ() {
475         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_Z ) ) ) {
476                 UpdateFile();
477         }
478         else {
479                 m_anchor_z = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_Z ) );
480         }
481 }
482
483 void DialogAFConstraintUniversal::OnDeltaposSpinAnchorX(NMHDR *pNMHDR, LRESULT *pResult) {
484         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
485         if ( pNMUpDown->iDelta < 0 ) {
486                 m_anchor_x += 1.0f;
487         }
488         else {
489                 m_anchor_x -= 1.0f;
490         }
491         UpdateData( FALSE );
492         UpdateFile();
493         *pResult = 0;
494 }
495
496 void DialogAFConstraintUniversal::OnDeltaposSpinAnchorY(NMHDR *pNMHDR, LRESULT *pResult) {
497         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
498         if ( pNMUpDown->iDelta < 0 ) {
499                 m_anchor_y += 1.0f;
500         }
501         else {
502                 m_anchor_y -= 1.0f;
503         }
504         UpdateData( FALSE );
505         UpdateFile();
506         *pResult = 0;
507 }
508
509 void DialogAFConstraintUniversal::OnDeltaposSpinAnchorZ(NMHDR *pNMHDR, LRESULT *pResult) {
510         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
511         if ( pNMUpDown->iDelta < 0 ) {
512                 m_anchor_z += 1.0f;
513         }
514         else {
515                 m_anchor_z -= 1.0f;
516         }
517         UpdateData( FALSE );
518         UpdateFile();
519         *pResult = 0;
520 }
521
522 void DialogAFConstraintUniversal::OnBnClickedRadioUniversalBoneShaft1() {
523         if ( IsDlgButtonChecked( IDC_RADIO_UNIVERSAL_BONE_SHAFT1 ) ) {
524                 if ( constraint ) {
525                         constraint->shaft[0].type = idAFVector::VEC_BONEDIR;
526                         UpdateFile();
527                 }
528         }
529 }
530
531 void DialogAFConstraintUniversal::OnBnClickedRadioUniversalAnglesShaft1() {
532         if ( IsDlgButtonChecked( IDC_RADIO_UNIVERSAL_ANGLES_SHAFT1 ) ) {
533                 if ( constraint ) {
534                         constraint->shaft[0].type = idAFVector::VEC_COORDS;
535                         UpdateFile();
536                 }
537         }
538 }
539
540 void DialogAFConstraintUniversal::OnCbnSelchangeComboUniversalJoint1Shaft1() {
541         CString str;
542         GetSafeComboBoxSelection( &m_comboJoint1Shaft1, str, -1 );
543         UnsetSafeComboBoxSelection( &m_comboJoint2Shaft1, str );
544         UpdateFile();
545 }
546
547 void DialogAFConstraintUniversal::OnCbnSelchangeComboUniversalJoint2Shaft1() {
548         CString str;
549         GetSafeComboBoxSelection( &m_comboJoint2Shaft1, str, -1 );
550         UnsetSafeComboBoxSelection( &m_comboJoint1Shaft1, str );
551         UpdateFile();
552 }
553
554 void DialogAFConstraintUniversal::OnEnChangeEditUniversalPitchShaft1() {
555         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_PITCH_SHAFT1 ) ) ) {
556                 UpdateFile();
557         }
558         else {
559                 m_pitchShaft1 = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_PITCH_SHAFT1 ) );
560         }
561 }
562
563 void DialogAFConstraintUniversal::OnDeltaposSpinUniversalPitchShaft1(NMHDR *pNMHDR, LRESULT *pResult) {
564         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
565         if ( pNMUpDown->iDelta < 0 ) {
566                 m_pitchShaft1 += 1.0f;
567         }
568         else {
569                 m_pitchShaft1 -= 1.0f;
570         }
571         UpdateData( FALSE );
572         UpdateFile();
573         *pResult = 0;
574 }
575
576 void DialogAFConstraintUniversal::OnEnChangeEditUniversalYawShaft1() {
577         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_YAW_SHAFT1 ) ) ) {
578                 UpdateFile();
579         }
580         else {
581                 m_yawShaft1 = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_YAW_SHAFT1 ) );
582         }
583 }
584
585 void DialogAFConstraintUniversal::OnDeltaposSpinUniversalYawShaft1(NMHDR *pNMHDR, LRESULT *pResult) {
586         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
587         if ( pNMUpDown->iDelta < 0 ) {
588                 m_yawShaft1 += 1.0f;
589         }
590         else {
591                 m_yawShaft1 -= 1.0f;
592         }
593         UpdateData( FALSE );
594         UpdateFile();
595         *pResult = 0;
596 }
597
598 void DialogAFConstraintUniversal::OnBnClickedRadioUniversalBoneShaft2() {
599         if ( IsDlgButtonChecked( IDC_RADIO_UNIVERSAL_BONE_SHAFT2 ) ) {
600                 if ( constraint ) {
601                         constraint->shaft[1].type = idAFVector::VEC_BONEDIR;
602                         UpdateFile();
603                 }
604         }
605 }
606
607 void DialogAFConstraintUniversal::OnBnClickedRadioUniversalAnglesShaft2() {
608         if ( IsDlgButtonChecked( IDC_RADIO_UNIVERSAL_ANGLES_SHAFT2 ) ) {
609                 if ( constraint ) {
610                         constraint->shaft[1].type = idAFVector::VEC_COORDS;
611                         UpdateFile();
612                 }
613         }
614 }
615
616 void DialogAFConstraintUniversal::OnCbnSelchangeComboUniversalJoint1Shaft2() {
617         CString str;
618         GetSafeComboBoxSelection( &m_comboJoint1Shaft2, str, -1 );
619         UnsetSafeComboBoxSelection( &m_comboJoint2Shaft2, str );
620         UpdateFile();
621 }
622
623 void DialogAFConstraintUniversal::OnCbnSelchangeComboUniversalJoint2Shaft2() {
624         CString str;
625         GetSafeComboBoxSelection( &m_comboJoint2Shaft2, str, -1 );
626         UnsetSafeComboBoxSelection( &m_comboJoint1Shaft2, str );
627         UpdateFile();
628 }
629
630 void DialogAFConstraintUniversal::OnEnChangeEditUniversalPitchShaft2() {
631         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_PITCH_SHAFT2 ) ) ) {
632                 UpdateFile();
633         }
634         else {
635                 m_pitchShaft2 = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_PITCH_SHAFT2 ) );
636         }
637 }
638
639 void DialogAFConstraintUniversal::OnDeltaposSpinUniversalPitchShaft2(NMHDR *pNMHDR, LRESULT *pResult) {
640         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
641         if ( pNMUpDown->iDelta < 0 ) {
642                 m_pitchShaft2 += 1.0f;
643         }
644         else {
645                 m_pitchShaft2 -= 1.0f;
646         }
647         UpdateData( FALSE );
648         UpdateFile();
649         *pResult = 0;
650 }
651
652 void DialogAFConstraintUniversal::OnEnChangeEditUniversalYawShaft2() {
653         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_YAW_SHAFT2 ) ) ) {
654                 UpdateFile();
655         }
656         else {
657                 m_yawShaft2 = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_YAW_SHAFT2 ) );
658         }
659 }
660
661 void DialogAFConstraintUniversal::OnDeltaposSpinUniversalYawShaft2(NMHDR *pNMHDR, LRESULT *pResult) {
662         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
663         if ( pNMUpDown->iDelta < 0 ) {
664                 m_yawShaft2 += 1.0f;
665         }
666         else {
667                 m_yawShaft2 -= 1.0f;
668         }
669         UpdateData( FALSE );
670         UpdateFile();
671         *pResult = 0;
672 }
673
674 void DialogAFConstraintUniversal::OnBnClickedRadioUniversalLimitNone() {
675         if ( IsDlgButtonChecked( IDC_RADIO_UNIVERSAL_LIMIT_NONE ) ) {
676                 if ( constraint ) {
677                         constraint->limit = idDeclAF_Constraint::LIMIT_NONE;
678                         UpdateFile();
679                 }
680         }
681 }
682
683 void DialogAFConstraintUniversal::OnBnClickedRadioUniversalLimitCone() {
684         if ( IsDlgButtonChecked( IDC_RADIO_UNIVERSAL_LIMIT_CONE ) ) {
685                 if ( constraint ) {
686                         constraint->limit = idDeclAF_Constraint::LIMIT_CONE;
687                         UpdateFile();
688                 }
689         }
690 }
691
692 void DialogAFConstraintUniversal::OnBnClickedRadioUniversalLimitPyramid() {
693         if ( IsDlgButtonChecked( IDC_RADIO_UNIVERSAL_LIMIT_PYRAMID ) ) {
694                 if ( constraint ) {
695                         constraint->limit = idDeclAF_Constraint::LIMIT_PYRAMID;
696                         UpdateFile();
697                 }
698         }
699 }
700
701 void DialogAFConstraintUniversal::OnEnChangeEditUniversalLimitConeAngle() {
702         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_LIMIT_CONE_ANGLE ) ) ) {
703                 UpdateFile();
704         }
705         else {
706                 m_coneAngle = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_LIMIT_CONE_ANGLE ), false );
707         }
708 }
709
710 void DialogAFConstraintUniversal::OnDeltaposSpinUniversalLimitConeAngle(NMHDR *pNMHDR, LRESULT *pResult) {
711         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
712         if ( pNMUpDown->iDelta < 0 ) {
713                 m_coneAngle += 1.0f;
714         }
715         else if ( m_coneAngle > 0.0f ) {
716                 m_coneAngle -= 1.0f;
717         }
718         UpdateData( FALSE );
719         UpdateFile();
720         *pResult = 0;
721 }
722
723 void DialogAFConstraintUniversal::OnEnChangeEditUniversalLimitPyramidAngle1() {
724         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_LIMIT_PYRAMID_ANGLE1 ) ) ) {
725                 UpdateFile();
726         }
727         else {
728                 m_pyramidAngle1 = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_LIMIT_PYRAMID_ANGLE1 ), false );
729         }
730 }
731
732 void DialogAFConstraintUniversal::OnDeltaposSpinUniversalLimitPyramidAngle1(NMHDR *pNMHDR, LRESULT *pResult) {
733         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
734         if ( pNMUpDown->iDelta < 0 ) {
735                 m_pyramidAngle1 += 1.0f;
736         }
737         else if ( m_pyramidAngle1 > 0.0f ) {
738                 m_pyramidAngle1 -= 1.0f;
739         }
740         UpdateData( FALSE );
741         UpdateFile();
742         *pResult = 0;
743 }
744
745 void DialogAFConstraintUniversal::OnEnChangeEditUniversalLimitPyramidAngle2() {
746         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_LIMIT_PYRAMID_ANGLE2 ) ) ) {
747                 UpdateFile();
748         }
749         else {
750                 m_pyramidAngle2 = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_LIMIT_PYRAMID_ANGLE2 ), false );
751         }
752 }
753
754 void DialogAFConstraintUniversal::OnDeltaposSpinUniversalLimitPyramidAngle2(NMHDR *pNMHDR, LRESULT *pResult) {
755         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
756         if ( pNMUpDown->iDelta < 0 ) {
757                 m_pyramidAngle2 += 1.0f;
758         }
759         else if ( m_pyramidAngle2 > 0.0f ) {
760                 m_pyramidAngle2 -= 1.0f;
761         }
762         UpdateData( FALSE );
763         UpdateFile();
764         *pResult = 0;
765 }
766
767 void DialogAFConstraintUniversal::OnEnChangeEditUniversalLimitRoll() {
768         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_LIMIT_ROLL ) ) ) {
769                 UpdateFile();
770         }
771         else {
772                 m_limitRoll = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_LIMIT_ROLL ) );
773         }
774 }
775
776 void DialogAFConstraintUniversal::OnDeltaposSpinUniversalLimitRoll(NMHDR *pNMHDR, LRESULT *pResult) {
777         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
778         if ( pNMUpDown->iDelta < 0 ) {
779                 m_limitRoll += 1.0f;
780         }
781         else {
782                 m_limitRoll -= 1.0f;
783         }
784         UpdateData( FALSE );
785         UpdateFile();
786         *pResult = 0;
787 }
788
789 void DialogAFConstraintUniversal::OnBnClickedRadioUniversalLimitBone() {
790         if ( IsDlgButtonChecked( IDC_RADIO_UNIVERSAL_LIMIT_BONE ) ) {
791                 if ( constraint ) {
792                         constraint->limitAxis.type = idAFVector::VEC_BONEDIR;
793                         UpdateFile();
794                 }
795         }
796 }
797
798 void DialogAFConstraintUniversal::OnBnClickedRadioUniversalLimitAngles() {
799         if ( IsDlgButtonChecked( IDC_RADIO_UNIVERSAL_LIMIT_ANGLES ) ) {
800                 if ( constraint ) {
801                         constraint->limitAxis.type = idAFVector::VEC_COORDS;
802                         UpdateFile();
803                 }
804         }
805 }
806
807 void DialogAFConstraintUniversal::OnCbnSelchangeComboUniversalLimitJoint1() {
808         CString str;
809         GetSafeComboBoxSelection( &m_comboLimitJoint1, str, -1 );
810         UnsetSafeComboBoxSelection( &m_comboLimitJoint2, str );
811         UpdateFile();
812 }
813
814 void DialogAFConstraintUniversal::OnCbnSelchangeComboUniversalLimitJoint2() {
815         CString str;
816         GetSafeComboBoxSelection( &m_comboLimitJoint2, str, -1 );
817         UnsetSafeComboBoxSelection( &m_comboLimitJoint1, str );
818         UpdateFile();
819 }
820
821 void DialogAFConstraintUniversal::OnEnChangeEditUniversalLimitPitch() {
822         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_LIMIT_PITCH ) ) ) {
823                 UpdateFile();
824         }
825         else {
826                 m_limitPitch = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_LIMIT_PITCH ) );
827         }
828 }
829
830 void DialogAFConstraintUniversal::OnDeltaposSpinUniversalLimitPitch(NMHDR *pNMHDR, LRESULT *pResult) {
831         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
832         if ( pNMUpDown->iDelta < 0 ) {
833                 m_limitPitch += 1.0f;
834         }
835         else {
836                 m_limitPitch -= 1.0f;
837         }
838         UpdateData( FALSE );
839         UpdateFile();
840         *pResult = 0;
841 }
842
843 void DialogAFConstraintUniversal::OnEnChangeEditUniversalLimitYaw() {
844         if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_LIMIT_YAW ) ) ) {
845                 UpdateFile();
846         }
847         else {
848                 m_limitYaw = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_UNIVERSAL_LIMIT_YAW ) );
849         }
850 }
851
852 void DialogAFConstraintUniversal::OnDeltaposSpinUniversalLimitYaw(NMHDR *pNMHDR, LRESULT *pResult) {
853         LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
854         if ( pNMUpDown->iDelta < 0 ) {
855                 m_limitYaw += 1.0f;
856         }
857         else {
858                 m_limitYaw -= 1.0f;
859         }
860         UpdateData( FALSE );
861         UpdateFile();
862         *pResult = 0;
863 }