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 "DialogAFConstraint.h"
36 #include "DialogAFConstraintHinge.h"
39 // DialogAFConstraintHinge dialog
41 toolTip_t DialogAFConstraintHinge::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_HINGE_AXIS_BONE, "use a bone for the hinge axis" },
49 { IDC_RADIO_HINGE_AXIS_ANGLES, "use angles to set the orientation of the hinge axis" },
50 { IDC_COMBO_HINGE_AXIS_JOINT1, "bone start joint" },
51 { IDC_COMBO_HINGE_AXIS_JOINT2, "bone end joint" },
52 { IDC_EDIT_HINGE_AXIS_PITCH, "pitch angle" },
53 { IDC_EDIT_HINGE_AXIS_YAW, "yaw angle" },
54 { IDC_RADIO_HINGE_LIMIT_NONE, "no limit" },
55 { IDC_RADIO_HINGE_LIMIT_ANGLES, "angle limit" },
56 { IDC_EDIT_HINGE_LIMIT_ANGLE1, "limit orientation" },
57 { IDC_EDIT_HINGE_LIMIT_ANGLE2, "limit width" },
58 { IDC_EDIT_HINGE_LIMIT_ANGLE3, "limit angle" },
62 IMPLEMENT_DYNAMIC(DialogAFConstraintHinge, CDialog)
66 DialogAFConstraintHinge::DialogAFConstraintHinge
69 DialogAFConstraintHinge::DialogAFConstraintHinge(CWnd* pParent /*=NULL*/)
70 : CDialog(DialogAFConstraintHinge::IDD, pParent)
77 , m_limitAngle2(30.0f)
82 Create( IDD_DIALOG_AF_CONSTRAINT_HINGE, pParent );
83 EnableToolTips( TRUE );
88 DialogAFConstraintHinge::~DialogAFConstraintHinge
91 DialogAFConstraintHinge::~DialogAFConstraintHinge() {
96 DialogAFConstraintHinge::DoDataExchange
99 void DialogAFConstraintHinge::DoDataExchange(CDataExchange* pDX) {
100 CDialog::DoDataExchange(pDX);
101 //{{AFX_DATA_MAP(DialogAFConstraintHinge)
102 DDX_Control(pDX, IDC_COMBO_ANCHOR_JOINT, m_comboAnchorJoint);
103 DDX_Text(pDX, IDC_EDIT_ANCHOR_X, m_anchor_x);
104 DDX_Text(pDX, IDC_EDIT_ANCHOR_Y, m_anchor_y);
105 DDX_Text(pDX, IDC_EDIT_ANCHOR_Z, m_anchor_z);
106 DDX_Control(pDX, IDC_COMBO_HINGE_AXIS_JOINT1, m_comboAxisJoint1);
107 DDX_Control(pDX, IDC_COMBO_HINGE_AXIS_JOINT2, m_comboAxisJoint2);
108 DDX_Text(pDX, IDC_EDIT_HINGE_AXIS_PITCH, m_axisPitch);
109 DDX_Text(pDX, IDC_EDIT_HINGE_AXIS_YAW, m_axisYaw);
110 DDX_Text(pDX, IDC_EDIT_HINGE_LIMIT_ANGLE1, m_limitAngle1);
111 DDX_Text(pDX, IDC_EDIT_HINGE_LIMIT_ANGLE2, m_limitAngle2);
112 DDX_Text(pDX, IDC_EDIT_HINGE_LIMIT_ANGLE3, m_limitAngle3);
118 DialogAFConstraintHinge::InitJointLists
121 void DialogAFConstraintHinge::InitJointLists( void ) {
122 m_comboAnchorJoint.ResetContent();
123 m_comboAxisJoint1.ResetContent();
124 m_comboAxisJoint2.ResetContent();
130 const idRenderModel *model = gameEdit->ANIM_GetModelFromName( file->model );
135 int numJoints = model->NumJoints();
136 for ( int i = 0; i < numJoints; i++ ) {
137 const char *jointName = model->GetJointName( (jointHandle_t) i );
138 m_comboAnchorJoint.AddString( jointName );
139 m_comboAxisJoint1.AddString( jointName );
140 m_comboAxisJoint2.AddString( jointName );
146 DialogAFConstraintHinge::LoadFile
149 void DialogAFConstraintHinge::LoadFile( idDeclAF *af ) {
157 DialogAFConstraintHinge::SaveFile
160 void DialogAFConstraintHinge::SaveFile( void ) {
166 DialogAFConstraintHinge::LoadConstraint
169 void DialogAFConstraintHinge::LoadConstraint( idDeclAF_Constraint *c ) {
175 // load anchor from the current idDeclAF_Constraint
176 SetSafeComboBoxSelection( &m_comboAnchorJoint, constraint->anchor.joint1.c_str(), -1 );
177 m_anchor_x = constraint->anchor.ToVec3().x;
178 m_anchor_y = constraint->anchor.ToVec3().y;
179 m_anchor_z = constraint->anchor.ToVec3().z;
180 if ( constraint->anchor.type == idAFVector::VEC_JOINT ) {
181 i = IDC_RADIO_ANCHOR_JOINT;
184 i = IDC_RADIO_ANCHOR_COORDINATES;
186 CheckRadioButton( IDC_RADIO_ANCHOR_JOINT, IDC_RADIO_ANCHOR_COORDINATES, i );
189 s1 = SetSafeComboBoxSelection( &m_comboAxisJoint1, constraint->axis.joint1.c_str(), -1 );
190 s2 = SetSafeComboBoxSelection( &m_comboAxisJoint2, constraint->axis.joint2.c_str(), s1 );
191 angles = constraint->axis.ToVec3().ToAngles();
192 m_axisPitch = angles.pitch;
193 m_axisYaw = angles.yaw;
194 if ( constraint->axis.type == idAFVector::VEC_BONEDIR ) {
195 i = IDC_RADIO_HINGE_AXIS_BONE;
198 i = IDC_RADIO_HINGE_AXIS_ANGLES;
199 constraint->axis.type = idAFVector::VEC_COORDS;
201 CheckRadioButton( IDC_RADIO_HINGE_AXIS_BONE, IDC_RADIO_HINGE_AXIS_ANGLES, i );
204 if ( constraint->limit == idDeclAF_Constraint::LIMIT_CONE ) {
205 i = IDC_RADIO_HINGE_LIMIT_ANGLES;
208 i = IDC_RADIO_HINGE_LIMIT_NONE;
210 CheckRadioButton( IDC_RADIO_HINGE_LIMIT_NONE, IDC_RADIO_HINGE_LIMIT_ANGLES, i );
211 m_limitAngle1 = constraint->limitAngles[0];
212 m_limitAngle2 = constraint->limitAngles[1];
213 m_limitAngle3 = constraint->limitAngles[2];
215 // update displayed values
221 DialogAFConstraintHinge::SaveConstraint
224 void DialogAFConstraintHinge::SaveConstraint( void ) {
228 if ( !file || !constraint ) {
233 // save anchor to the current idDeclAF_Constraint
234 GetSafeComboBoxSelection( &m_comboAnchorJoint, str, -1 );
235 constraint->anchor.joint1 = str;
236 constraint->anchor.ToVec3().x = m_anchor_x;
237 constraint->anchor.ToVec3().y = m_anchor_y;
238 constraint->anchor.ToVec3().z = m_anchor_z;
241 if ( constraint->axis.type == idAFVector::VEC_BONEDIR ) {
242 s1 = GetSafeComboBoxSelection( &m_comboAxisJoint1, str, -1 );
243 constraint->axis.joint1 = str;
244 s2 = GetSafeComboBoxSelection( &m_comboAxisJoint2, str, s1 );
245 constraint->axis.joint2 = str;
248 constraint->axis.ToVec3() = idAngles( m_axisPitch, m_axisYaw, 0.0f ).ToForward();
252 constraint->limitAngles[0] = m_limitAngle1;
253 constraint->limitAngles[1] = m_limitAngle2;
254 constraint->limitAngles[2] = m_limitAngle3;
256 AFDialogSetFileModified();
261 DialogAFConstraintHinge::UpdateFile
264 void DialogAFConstraintHinge::UpdateFile( void ) {
267 gameEdit->AF_UpdateEntities( file->GetName() );
273 DialogAFConstraintHinge::OnToolHitTest
276 int DialogAFConstraintHinge::OnToolHitTest( CPoint point, TOOLINFO* pTI ) const {
277 CDialog::OnToolHitTest( point, pTI );
278 return DefaultOnToolHitTest( toolTips, this, point, pTI );
282 BEGIN_MESSAGE_MAP(DialogAFConstraintHinge, CDialog)
283 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
284 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
285 ON_BN_CLICKED(IDC_RADIO_ANCHOR_JOINT, OnBnClickedRadioAnchorJoint)
286 ON_BN_CLICKED(IDC_RADIO_ANCHOR_COORDINATES, OnBnClickedRadioAnchorCoordinates)
287 ON_CBN_SELCHANGE(IDC_COMBO_ANCHOR_JOINT, OnCbnSelchangeComboAnchorJoint)
288 ON_EN_CHANGE(IDC_EDIT_ANCHOR_X, OnEnChangeEditAnchorX)
289 ON_EN_CHANGE(IDC_EDIT_ANCHOR_Y, OnEnChangeEditAnchorY)
290 ON_EN_CHANGE(IDC_EDIT_ANCHOR_Z, OnEnChangeEditAnchorZ)
291 ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ANCHOR_X, OnDeltaposSpinAnchorX)
292 ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ANCHOR_Y, OnDeltaposSpinAnchorY)
293 ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ANCHOR_Z, OnDeltaposSpinAnchorZ)
294 ON_BN_CLICKED(IDC_RADIO_HINGE_AXIS_BONE, OnBnClickedRadioHingeAxisBone)
295 ON_BN_CLICKED(IDC_RADIO_HINGE_AXIS_ANGLES, OnBnClickedRadioHingeAxisAngles)
296 ON_CBN_SELCHANGE(IDC_COMBO_HINGE_AXIS_JOINT1, OnCbnSelchangeComboHingeAxisJoint1)
297 ON_CBN_SELCHANGE(IDC_COMBO_HINGE_AXIS_JOINT2, OnCbnSelchangeComboHingeAxisJoint2)
298 ON_EN_CHANGE(IDC_EDIT_HINGE_AXIS_PITCH, OnEnChangeEditHingeAxisPitch)
299 ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_HINGE_AXIS_PITCH, OnDeltaposSpinHingeAxisPitch)
300 ON_EN_CHANGE(IDC_EDIT_HINGE_AXIS_YAW, OnEnChangeEditHingeAxisYaw)
301 ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_HINGE_AXIS_YAW, OnDeltaposSpinHingeAxisYaw)
302 ON_BN_CLICKED(IDC_RADIO_HINGE_LIMIT_NONE, OnBnClickedRadioHingeLimitNone)
303 ON_BN_CLICKED(IDC_RADIO_HINGE_LIMIT_ANGLES, OnBnClickedRadioHingeLimitAngles)
304 ON_EN_CHANGE(IDC_EDIT_HINGE_LIMIT_ANGLE1, OnEnChangeEditHingeLimitAngle1)
305 ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_HINGE_LIMIT_ANGLE1, OnDeltaposSpinHingeLimitAngle1)
306 ON_EN_CHANGE(IDC_EDIT_HINGE_LIMIT_ANGLE2, OnEnChangeEditHingeLimitAngle2)
307 ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_HINGE_LIMIT_ANGLE2, OnDeltaposSpinHingeLimitAngle2)
308 ON_EN_CHANGE(IDC_EDIT_HINGE_LIMIT_ANGLE3, OnEnChangeEditHingeLimitAngle3)
309 ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_HINGE_LIMIT_ANGLE3, OnDeltaposSpinHingeLimitAngle3)
313 // DialogAFConstraintHinge message handlers
315 BOOL DialogAFConstraintHinge::OnToolTipNotify( UINT id, NMHDR *pNMHDR, LRESULT *pResult ) {
316 return DefaultOnToolTipNotify( toolTips, id, pNMHDR, pResult );
319 void DialogAFConstraintHinge::OnBnClickedRadioAnchorJoint() {
320 if ( IsDlgButtonChecked( IDC_RADIO_ANCHOR_JOINT ) ) {
322 constraint->anchor.type = idAFVector::VEC_JOINT;
328 void DialogAFConstraintHinge::OnBnClickedRadioAnchorCoordinates() {
329 if ( IsDlgButtonChecked( IDC_RADIO_ANCHOR_COORDINATES ) ) {
331 constraint->anchor.type = idAFVector::VEC_COORDS;
337 void DialogAFConstraintHinge::OnCbnSelchangeComboAnchorJoint() {
341 void DialogAFConstraintHinge::OnEnChangeEditAnchorX() {
342 if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_X ) ) ) {
346 m_anchor_x = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_X ) );
350 void DialogAFConstraintHinge::OnEnChangeEditAnchorY() {
351 if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_Y ) ) ) {
355 m_anchor_y = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_Y ) );
359 void DialogAFConstraintHinge::OnEnChangeEditAnchorZ() {
360 if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_Z ) ) ) {
364 m_anchor_z = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_ANCHOR_Z ) );
368 void DialogAFConstraintHinge::OnDeltaposSpinAnchorX(NMHDR *pNMHDR, LRESULT *pResult) {
369 LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
370 if ( pNMUpDown->iDelta < 0 ) {
381 void DialogAFConstraintHinge::OnDeltaposSpinAnchorY(NMHDR *pNMHDR, LRESULT *pResult) {
382 LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
383 if ( pNMUpDown->iDelta < 0 ) {
394 void DialogAFConstraintHinge::OnDeltaposSpinAnchorZ(NMHDR *pNMHDR, LRESULT *pResult) {
395 LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
396 if ( pNMUpDown->iDelta < 0 ) {
407 void DialogAFConstraintHinge::OnBnClickedRadioHingeAxisBone() {
408 if ( IsDlgButtonChecked( IDC_RADIO_HINGE_AXIS_BONE ) ) {
410 constraint->axis.type = idAFVector::VEC_BONEDIR;
416 void DialogAFConstraintHinge::OnBnClickedRadioHingeAxisAngles() {
417 if ( IsDlgButtonChecked( IDC_RADIO_HINGE_AXIS_ANGLES ) ) {
419 constraint->axis.type = idAFVector::VEC_COORDS;
425 void DialogAFConstraintHinge::OnCbnSelchangeComboHingeAxisJoint1() {
427 GetSafeComboBoxSelection( &m_comboAxisJoint1, str, -1 );
428 UnsetSafeComboBoxSelection( &m_comboAxisJoint2, str );
432 void DialogAFConstraintHinge::OnCbnSelchangeComboHingeAxisJoint2() {
434 GetSafeComboBoxSelection( &m_comboAxisJoint2, str, -1 );
435 UnsetSafeComboBoxSelection( &m_comboAxisJoint1, str );
439 void DialogAFConstraintHinge::OnEnChangeEditHingeAxisPitch() {
440 if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_HINGE_AXIS_PITCH ) ) ) {
444 m_axisPitch = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_HINGE_AXIS_PITCH ) );
448 void DialogAFConstraintHinge::OnDeltaposSpinHingeAxisPitch(NMHDR *pNMHDR, LRESULT *pResult) {
449 LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
450 if ( pNMUpDown->iDelta < 0 ) {
461 void DialogAFConstraintHinge::OnEnChangeEditHingeAxisYaw() {
462 if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_HINGE_AXIS_YAW ) ) ) {
466 m_axisYaw = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_HINGE_AXIS_YAW ) );
470 void DialogAFConstraintHinge::OnDeltaposSpinHingeAxisYaw(NMHDR *pNMHDR, LRESULT *pResult) {
471 LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
472 if ( pNMUpDown->iDelta < 0 ) {
483 void DialogAFConstraintHinge::OnBnClickedRadioHingeLimitNone() {
484 if ( IsDlgButtonChecked( IDC_RADIO_HINGE_LIMIT_NONE ) ) {
486 constraint->limit = idDeclAF_Constraint::LIMIT_NONE;
492 void DialogAFConstraintHinge::OnBnClickedRadioHingeLimitAngles() {
493 if ( IsDlgButtonChecked( IDC_RADIO_HINGE_LIMIT_ANGLES ) ) {
495 constraint->limit = idDeclAF_Constraint::LIMIT_CONE;
501 void DialogAFConstraintHinge::OnEnChangeEditHingeLimitAngle1() {
502 if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_HINGE_LIMIT_ANGLE1 ) ) ) {
506 m_limitAngle1 = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_HINGE_LIMIT_ANGLE1 ) );
510 void DialogAFConstraintHinge::OnDeltaposSpinHingeLimitAngle1(NMHDR *pNMHDR, LRESULT *pResult) {
511 LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
512 if ( pNMUpDown->iDelta < 0 ) {
513 m_limitAngle1 += 1.0f;
516 m_limitAngle1 -= 1.0f;
523 void DialogAFConstraintHinge::OnEnChangeEditHingeLimitAngle2() {
524 if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_HINGE_LIMIT_ANGLE2 ) ) ) {
528 m_limitAngle2 = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_HINGE_LIMIT_ANGLE2 ), false );
532 void DialogAFConstraintHinge::OnDeltaposSpinHingeLimitAngle2(NMHDR *pNMHDR, LRESULT *pResult) {
533 LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
534 if ( pNMUpDown->iDelta < 0 ) {
535 m_limitAngle2 += 1.0f;
537 else if ( m_limitAngle2 > 0.0f ) {
538 m_limitAngle2 -= 1.0f;
545 void DialogAFConstraintHinge::OnEnChangeEditHingeLimitAngle3() {
546 if ( EditControlEnterHit( (CEdit *) GetDlgItem( IDC_EDIT_HINGE_LIMIT_ANGLE3 ) ) ) {
550 m_limitAngle3 = EditVerifyFloat( (CEdit *) GetDlgItem( IDC_EDIT_HINGE_LIMIT_ANGLE3 ) );
554 void DialogAFConstraintHinge::OnDeltaposSpinHingeLimitAngle3(NMHDR *pNMHDR, LRESULT *pResult) {
555 LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
556 if ( pNMUpDown->iDelta < 0 ) {
557 m_limitAngle3 += 1.0f;
560 m_limitAngle3 -= 1.0f;