#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 "OptimizeKeyframe.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif OptimizeKeyframePanel g_optimizeKeyframePanel; CCriticalSection g_threadLock; ThreadData g_threadInfo; //////////////////////////////////////////////////////////////////////////////// // PlugPanel Dialog Procedure to handle User and System Interactions static BOOL CALLBACK OptimizeKeyframePanelProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); switch (msg) { case WM_INITDIALOG: //Panel's extra initialization g_optimizeKeyframePanel.Init(hWnd); break; case WM_DESTROY: //Panel's extra destruction g_optimizeKeyframePanel.Destroy(hWnd); break; case WM_COMMAND : switch (LOWORD(wParam)) { //Handle Panel's controls case IDC_ABOUT: { CAbout dlg; dlg.DoModal(); break; } case IDC_OPTIMIZE: { g_optimizeKeyframePanel.Optimize(); break; } } break; //////////////////////////////////////////////////////////////////////// //The following lines are not necessary for MAX2 Plugins case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_MOUSEMOVE: g_optimizeKeyframePanel.m_ip->RollupMouseMessage(hWnd, msg, wParam, lParam); break; //////////////////////////////////////////////////////////////////////// default: return FALSE; } return TRUE; } //////////////////////////////////////////////////////////////////////////////// // Display the Plugin's Panel void OptimizeKeyframePanel::BeginEditParams(Interface* ip, IUtil* iu) { m_ip = ip; //Get the Plugin's Interface m_iu = iu; //Get the Utility Plugin's Interface AFX_MANAGE_STATE(AfxGetStaticModuleState()); HINSTANCE loc_hInstance = AfxGetResourceHandle (); //Display the plugin's Rollup Dialog m_hPanel = m_ip->AddRollupPage(loc_hInstance, MAKEINTRESOURCE(IDD_OPT_PANEL), OptimizeKeyframePanelProc, GetString(IDS_OPTIMIZEKEY_NAME),0); } //////////////////////////////////////////////////////////////////////////////// // Free the Plugins' Panel void OptimizeKeyframePanel::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 OptimizeKeyframePanel::Init(HWND hWnd) { } //////////////////////////////////////////////////////////////////////////////// // Panel Destruction callback void OptimizeKeyframePanel::Destroy(HWND hWnd) { } //////////////////////////////////////////////////////////////////////////////// // Called when the Optimize Button is pushed void OptimizeKeyframePanel::Optimize() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); JointEditDialog dialog(m_ip->GetRootNode(), m_ip); if (dialog.DoModal() == IDOK) { // now optimize... int total_nodes = JointEditDialog::CountChildren(m_ip->GetRootNode()); int current_node = 0; theHold.SuperBegin(); LPVOID arg = NULL; m_ip->ProgressStart(_T("Optimizing Joints"), TRUE, fn, arg); OptimizeAnimation(m_ip->GetRootNode(), current_node, total_nodes, &dialog); m_ip->ProgressEnd(); // Close out the undo theHold.SuperAccept("Replicate"); } } //////////////////////////////////////////////////////////////////////////////// void OptimizeKeyframePanel::OptimizeAnimation(INode *copy_node, int ¤t_node, int total_nodes, JointEditDialog *dialog) { Control *position_control = NULL; Control *rotation_control = NULL; Control *tm_controller = copy_node->GetTMController(); if (tm_controller != NULL) { position_control = tm_controller->GetPositionController(); rotation_control = tm_controller->GetRotationController(); JointPreference *pref = dialog->GetJointPrefrence(copy_node); Verify(pref != NULL); int include_joint = true; if (pref->m_excludeJoint == JointPreference::ExcludeJoint) { include_joint = false; } if (pref->m_excludeJoint == JointPreference::AutoJoint) { if(dialog->NodeAnimated(copy_node)) { include_joint = false; } } if (include_joint) { if (pref->m_optimizeRotation) { if (rotation_control != NULL) { int num_keys = rotation_control->NumKeys(); if (num_keys > 0) { TimeValue start = rotation_control->GetKeyTime(0); TimeValue end = rotation_control->GetKeyTime(num_keys-1); if (pref->m_rotationRange) { start = (TimeValue)pref->m_rotationSampleStartFrame * GetTicksPerFrame(); end = (TimeValue)pref->m_rotationSampleEndFrame * GetTicksPerFrame(); } Interval range; start = (rotation_control->GetKeyTime(0) > start) ? rotation_control->GetKeyTime(0):start; end = (rotation_control->GetKeyTime(num_keys-1) < end) ? rotation_control->GetKeyTime(num_keys-1):end; // adjust the optimization to not include the last frame... tehehehehehe if ((end - GetTicksPerFrame()) > start) { end -= GetTicksPerFrame(); } range.Set(start , end); OptKeyReduceStatus rot_progress; ApplyKeyReduction_MW4( rotation_control, range, pref->m_rotationThreshold * Stuff::Radians_Per_Degree, GetTicksPerFrame(), &rot_progress ); } } } if (pref->m_optimizeTranslation) { if (position_control != NULL) { int num_keys = position_control->NumKeys(); if (num_keys > 0) { TimeValue start = position_control->GetKeyTime(0); TimeValue end = position_control->GetKeyTime(num_keys-1); if (pref->m_translationRange) { start = (TimeValue)pref->m_translationSampleStartFrame * GetTicksPerFrame(); end = (TimeValue)pref->m_translationSampleEndFrame * GetTicksPerFrame(); } Interval range; start = (position_control->GetKeyTime(0) > start) ? position_control->GetKeyTime(0):start; end = (position_control->GetKeyTime(num_keys-1) < end) ? position_control->GetKeyTime(num_keys-1):end; // adjust the optimization to not include the last frame... tehehehehehe if ((end - GetTicksPerFrame()) > start) { end -= GetTicksPerFrame(); } range.Set(start , end); OptKeyReduceStatus tran_progress; ApplyKeyReduction_MW4( position_control, range, pref->m_translationThreshold, GetTicksPerFrame(), &tran_progress ); } } } } } ++current_node; int total_done = (int)(((float)current_node/(float)total_nodes)*100.0f); m_ip->ProgressUpdate(total_done); for (int i = 0; i < copy_node->NumberOfChildren(); i++) { INode *child_node = copy_node->GetChildNode(i); assert(child_node != NULL); OptimizeAnimation(child_node, current_node, total_nodes, dialog); } return; }