//===========================================================================// // File: falltool.cpp // Project: MechWarrior 4 // Contents: Plugin to modify mech falling animations //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 05/26/99 jkyle Initial coding, //---------------------------------------------------------------------------// // Copyright (C) 1999, Fasa Interactive, Inc. // All Rights reserved worldwide // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //===========================================================================// #include "stdafx.h" #ifdef STRICT // Already defined by stdafx, #undef STRICT // so we avoid warning linking msg #endif #ifdef _MBCS // The same as above #undef _MBCS #endif #include "FallTool.hpp" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ////////////////////////////////////////////////////////////////////// // ProtoTypes int NegateKeys(Control *pControl,int key_number = 0); int SwapKeys(Control *pCtrl1,Control *pCtrl2,int key_number = 0); ////////////////////////////////////////////////////////////////////// // Global Variables FallToolPanel g_fallToolPanel; //////////////////////////////////////////////////////////////////////////////// // FallToolPanel Dialog Procedure to handle User and System Interactions static BOOL CALLBACK FallToolPanelProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); switch (msg) { case WM_INITDIALOG: //Panel's extra initialization g_fallToolPanel.Init(hWnd); break; case WM_DESTROY: //Panel's extra destruction g_fallToolPanel.Destroy(hWnd); break; case WM_COMMAND : switch (LOWORD(wParam)) { //Handle Panel's controls case IDC_ABOUT: { CAbout dlg; dlg.DoModal(); break;} case IDC_FALLTOOL_FALLLEFT: { // Spec is reversed g_fallToolPanel.m_iFallType = FallToolPanel::FALL_RIGHT; break; } case IDC_FALLTOOL_FALLRIGHT: { g_fallToolPanel.m_iFallType = FallToolPanel::FALL_LEFT; break; } case IDC_FALLTOOL_FALLBACK: { g_fallToolPanel.m_iFallType = FallToolPanel::FALL_BACK; break; } case IDC_FALLTOOL_EXECUTE: { g_fallToolPanel.ExecuteFallTool(); break; } } break; //////////////////////////////////////////////////////////////////////// //The following lines are not necessary for MAX2 Plugins case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_MOUSEMOVE: g_fallToolPanel.m_ip->RollupMouseMessage(hWnd, msg, wParam, lParam); break; //////////////////////////////////////////////////////////////////////// default: return FALSE; } return TRUE; } //////////////////////////////////////////////////////////////////////////////// // Display the Plugin's Panel void FallToolPanel::BeginEditParams(Interface* ip, IUtil* iu) { m_ip = ip; //Get the Plugin's Interface m_iu = iu; //Get the Utility Plugin's Interface //Display the plugin's Rollup Dialog AFX_MANAGE_STATE(AfxGetStaticModuleState()); HINSTANCE loc_hInstance = AfxGetResourceHandle (); m_hPanel = m_ip->AddRollupPage(loc_hInstance, MAKEINTRESOURCE(IDD_FALLTOOL_PANEL), FallToolPanelProc, GetString(IDS_FALLTOOL_NAME),0); } //////////////////////////////////////////////////////////////////////////////// // Free the Plugins' Panel void FallToolPanel::EndEditParams(Interface *ip, IUtil *iu) { m_iu = NULL; m_ip = NULL; //Remove the Rollup Dialog ip->DeleteRollupPage(m_hPanel); m_hPanel = NULL; } //////////////////////////////////////////////////////////////////////////////// // Panel Initialization callback void FallToolPanel::Init(HWND hWnd) { SendDlgItemMessage(hWnd, IDC_FALLTOOL_FALLLEFT, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); } //////////////////////////////////////////////////////////////////////////////// // Panel Destruction callback void FallToolPanel::Destroy(HWND hWnd) { } //////////////////////////////////////////////////////////////////////////////// // Execute the fall tool int FallToolPanel::ExecuteFallTool() { INode *pjoint_VEL = m_ip->GetINodeByName("joint_VEL"); INode *pjoint_ROOT = m_ip->GetINodeByName("joint_ROOT"); INode *phandle_lfoot = m_ip->GetINodeByName("handle_lfoot"); INode *phandle_rfoot = m_ip->GetINodeByName("handle_rfoot"); // Make sure we have all of these nodes, or else the model will mess up pretty bad if (pjoint_VEL && pjoint_ROOT && phandle_lfoot && phandle_rfoot) { // Adjust pjoint_VEL if (TRUE) { // Adjust the joint_VEL node if (Control *pControl = pjoint_VEL->GetTMController()) { // Adjust the position controllers if (Control *pPosControl = pControl->GetPositionController()) { // Adjust the XPosition Controller Control *pXControl = NULL; if (pXControl = pPosControl->GetXController()) { if (IKeyControl *pKeyControl = GetKeyControlInterface(pXControl)) { if (pKeyControl->GetNumKeys()<1) return -1; switch (m_iFallType) { case FALL_LEFT: { break; } case FALL_RIGHT: { break; } case FALL_BACK: { NegateKeys(pXControl); break; } } } } // Adjust the YPosition Controller if (Control *pYControl = pPosControl->GetYController()) { if (IKeyControl *pKeyControl = GetKeyControlInterface(pYControl)) { switch (m_iFallType) { case FALL_RIGHT: { SwapKeys(pYControl,pXControl); NegateKeys(pXControl); NegateKeys(pYControl); break; } case FALL_LEFT: { SwapKeys(pYControl,pXControl); // Fall through to negate key } case FALL_BACK: { NegateKeys(pYControl); break; } } } } } // Adjust the rotation controllers if (Control *pRotControl = pControl->GetRotationController()) { // Adjust the ZRotation Controller if (Control *pZControl = pRotControl->GetZController()) { if (IKeyControl *pKeyControl = GetKeyControlInterface(pZControl)) { float rot = (float)M_PI; switch (m_iFallType) { case FALL_RIGHT: { rot *= -1.0; } case FALL_LEFT: { rot /= -2.0; // Fall through to FALL_BACK } case FALL_BACK: { IBezFloatKey key; key.time = 0; //key.flags = IKEY_ZSEL; key.val = 0; key.intan = 0; key.outtan = 0; pKeyControl->AppendKey(&key); Interval iv = m_ip->GetAnimRange(); key.time = iv.End(); key.val = rot; pKeyControl->AppendKey(&key); pKeyControl->SortKeys(); break; } } } } } } } // Adjust the foot nodes - same for both feet if (TRUE) { int foot = 2; do { foot--; Control *pControl= NULL; if (1==foot) pControl = phandle_lfoot->GetTMController(); else pControl = phandle_rfoot->GetTMController(); if (pControl) { if (Control *pPosControl = pControl->GetPositionController()) { //Adjust the XPosition Control *pXControl; if (pXControl = pPosControl->GetXController()) { if (IKeyControl *pKeyControl = GetKeyControlInterface(pXControl)) { switch (m_iFallType) { case FALL_LEFT: { break; } case FALL_RIGHT: { break; } case FALL_BACK: { NegateKeys(pXControl,1); break; } } } } //Adjust the YPosition if (Control *pYControl = pPosControl->GetYController()) { if (IKeyControl *pKeyControl = GetKeyControlInterface(pYControl)) { switch (m_iFallType) { case FALL_RIGHT: { NegateKeys(pYControl,1); } case FALL_LEFT: { // Fall through to negate Y in FALL_BACK SwapKeys(pYControl,pXControl,1); } case FALL_BACK: { if (m_iFallType != FALL_RIGHT) NegateKeys(pYControl,1); break; } } } } } if (Control *pRotControl = pControl->GetRotationController()) { //Adjust the ZRotation Controller if (Control *pZControl = pRotControl->GetZController()) { if (IKeyControl *pKeyControl = GetKeyControlInterface(pZControl)) { float rot = (float)M_PI; switch (m_iFallType) { case FALL_LEFT: { rot *= -1.0; } case FALL_RIGHT: { rot /= 2.0; // Fall through to FALL_BACK } case FALL_BACK: { IBezFloatKey key; int i; pKeyControl->GetKey(i = (pKeyControl->GetNumKeys()-1),&key); key.val += rot; pKeyControl->SetKey(i,&key); break; } } } } } } } while (foot); } return 0; } return -1; } int NegateKeys(Control *pControl,int key_number) { int MaxKeys; IKeyControl *ikc = GetKeyControlInterface(pControl); Class_ID id = pControl->ClassID(); MaxKeys=ikc->GetNumKeys(); for(;key_numberGetKey(key_number, &key); key.val=key.val*-1; ikc->SetKey(key_number, &key); } else if (id == Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID,0)) { IBezFloatKey key; ikc->GetKey(key_number, &key); key.val*=-1; key.intan*=-1; key.outtan*=-1; ikc->SetKey(key_number, &key); } else if (id == Class_ID(TCBINTERP_FLOAT_CLASS_ID,0)) { ITCBFloatKey key; ikc->GetKey(key_number, &key); key.val*=-1; ikc->SetKey(key_number, &key); } else if (id == Class_ID(LININTERP_POSITION_CLASS_ID,0)) { ILinPoint3Key key; ikc->GetKey(key_number, &key); key.val.x*=-1; key.val.y*=-1; key.val.z*=-1; ikc->SetKey(key_number, &key); } else if (id == Class_ID(HYBRIDINTERP_POSITION_CLASS_ID,0)) { IBezPoint3Key key; ikc->GetKey(key_number, &key); key.val.x*=-1; key.intan.x*=-1; key.outtan.x*=-1; key.val.y*=-1; key.intan.y*=-1; key.outtan.y*=-1; key.val.z*=-1; key.intan.z*=-1; key.outtan.z*=-1; ikc->SetKey(key_number, &key); } else if (id == Class_ID(TCBINTERP_POSITION_CLASS_ID,0)) { ITCBPoint3Key key; ikc->GetKey(key_number, &key); key.val.x*=-1; key.val.y*=-1; key.val.z*=-1; ikc->SetKey(key_number, &key); } else if (id == Class_ID(LININTERP_ROTATION_CLASS_ID,0)) { ILinRotKey key; ikc->GetKey(key_number, &key); key.val.w*=-1; ikc->SetKey(key_number, &key); } else if (id == Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID,0)) { IBezQuatKey key; ikc->GetKey(key_number, &key); key.val.w*=-1; ikc->SetKey(key_number, &key); } else if (id == Class_ID(TCBINTERP_ROTATION_CLASS_ID,0)) { ITCBRotKey key; ikc->GetKey(key_number, &key); key.val.angle*=-1; ikc->SetKey(key_number, &key); } else if (id == Class_ID(HYBRIDINTERP_POINT3_CLASS_ID,0)) { IBezPoint3Key key; ikc->GetKey(key_number, &key); key.val.x*=-1; key.val.y*=-1; key.val.z*=-1; ikc->SetKey(key_number, &key); } else if (id == Class_ID(TCBINTERP_POINT3_CLASS_ID,0)) { ITCBPoint3Key key; ikc->GetKey(key_number, &key); key.val.x*=-1; key.val.y*=-1; key.val.z*=-1; ikc->SetKey(key_number, &key); } } // end of for i return MaxKeys; } static int SwapKeys(Control *pCtrl1,Control *pCtrl2,int key_number) { if (!(pCtrl1 && pCtrl2)) { return 0; } // Only swap same IDs Class_ID id; if ((id = pCtrl1->ClassID()) != pCtrl2->ClassID()) return 1; IKeyControl *pKey1 = GetKeyControlInterface(pCtrl1); IKeyControl *pKey2 = GetKeyControlInterface(pCtrl2); int MaxKeys1 = pKey1->GetNumKeys(); int MaxKeys2 = pKey2->GetNumKeys(); // First copy all the keys, then delete them from both controls, then append them back if (id == Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID,0)) { IBezFloatKey *keyarr = new IBezFloatKey[MaxKeys1-key_number]; for (int i=key_number;iGetKey(i,&keyarr[i-key_number]); } pKey1->SetNumKeys(key_number); for (i=key_number;iGetKey(i,&key); pKey1->AppendKey(&key); } pKey2->SetNumKeys(key_number); for (i=0;i<(MaxKeys1-key_number);i++) { IBezFloatKey key; pKey2->AppendKey(&keyarr[i]); } delete keyarr; pKey1->SortKeys(); pKey2->SortKeys(); } return 0; }