void XsiExp::DumpPosKeys( INode * node, int indentLevel) { Control * cont = node->GetTMController()->GetPositionController(); IKeyControl * ikc = GetKeyControlInterface(cont); INode * parent = node->GetParentNode(); if (!cont || !parent || (parent && parent->IsRootNode()) || !ikc) { // no controller or root node return; } int numKeys = ikc->GetNumKeys(); if (numKeys <= 1) { return; } Object * obj = node->EvalWorldState(0).obj; BOOL isBone = obj && obj->ClassID() == Class_ID(BONE_CLASS_ID, 0) ? TRUE : FALSE; // anim keys header TSTR indent = GetIndent(indentLevel); fprintf(pStream,"%s\tSI_AnimationKey {\n", indent.data()); fprintf(pStream,"%s\t\t2;\n", indent.data()); // 2 means position keys fprintf(pStream,"%s\t\t%d;\n", indent.data(), numKeys); int t, delta = GetTicksPerFrame(); Matrix3 matrix; for (int i = 0; i < numKeys; i++) { // get the key's time if (cont->ClassID() == Class_ID(TCBINTERP_POSITION_CLASS_ID, 0)) { ITCBRotKey key; ikc->GetKey(i, &key); t = key.time; } else if (cont->ClassID() == Class_ID(HYBRIDINTERP_POSITION_CLASS_ID, 0)) { IBezQuatKey key; ikc->GetKey(i, &key); t = key.time; } else if (cont->ClassID() == Class_ID(LININTERP_POSITION_CLASS_ID, 0)) { ILinRotKey key; ikc->GetKey(i, &key); t = key.time; } // sample the node's matrix matrix = node->GetNodeTM(t) * Inverse(node->GetParentTM(t)); if (!isBone) { matrix = matrix * topMatrix; } Point3 pos = matrix.GetRow(3); fprintf(pStream, "%s\t\t%d; 3; %.6f, %.6f, %.6f;;%s\n", indent.data(), t / delta, pos.x, pos.z, -pos.y, i == numKeys - 1 ? ";\n" : ","); } // anim keys close fprintf(pStream,"%s\t}\n\n", indent.data()); }
void KeyTest() { int i, numKeys; INode * n; Control * c; Quat newQuat, prevQuat; IKeyControl* ikeys; ITCBPoint3Key tcbPosKey; ITCBRotKey tcbRotKey; ITCBScaleKey tcbScaleKey; IBezPoint3Key bezPosKey; IBezQuatKey bezRotKey; IBezScaleKey bezScaleKey; ILinPoint3Key linPosKey; ILinRotKey linRotKey; ILinScaleKey linScaleKey; // Get the first node in the selection set if (!CMaxEnv::singleton().m_pInterace->GetSelNodeCount()) return; n = CMaxEnv::singleton().m_pInterace->GetSelNode(0); // --- Process the position keys --- c = n->GetTMController()->GetPositionController(); ikeys = GetKeyControlInterface(c); if (!ikeys) { // No interface available to access the keys... // Just sample the controller to get the position // data at each key... SampleController(n, c); return; } numKeys = ikeys->GetNumKeys(); DebugPrint(_T("\nThere are %d position key(s)"), numKeys); if (c->ClassID() == Class_ID(TCBINTERP_POSITION_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &tcbPosKey); //DebugPrint(_T("\nTCB Position Key: %d=(%.1f, %.1f, %.1f)"), // i, tcbPosKey.val.x, tcbPosKey.val.y, tcbPosKey.val.z); } } else if (c->ClassID() == Class_ID(HYBRIDINTERP_POSITION_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &bezPosKey); //DebugPrint(_T("\nBezier Position Key: %d=(%.1f, %.1f, %.1f)"), // i, bezPosKey.val.x, bezPosKey.val.y, bezPosKey.val.z); } } else if (c->ClassID() == Class_ID(LININTERP_POSITION_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &linPosKey); //DebugPrint(_T("\nLinear Position Key: %d=(%.1f, %.1f, %.1f)"), // i, linPosKey.val.x, linPosKey.val.y, linPosKey.val.z); } } // --- Process the rotation keys --- c = n->GetTMController()->GetRotationController(); ikeys = GetKeyControlInterface(c); if (!ikeys) return; numKeys = ikeys->GetNumKeys(); //DebugPrint(_T("\nThere are %d rotation key(s)"), numKeys); if (c->ClassID() == Class_ID(TCBINTERP_ROTATION_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &tcbRotKey); newQuat = QFromAngAxis(tcbRotKey.val.angle, tcbRotKey.val.axis); if (i) newQuat = prevQuat * newQuat; prevQuat = newQuat; //DebugPrint(_T("\nTCB Rotation Key: %d=(%.1f, %.1f, %.1f, %.1f)"), // i, newQuat.x, newQuat.y, newQuat.z, newQuat.w); } } else if (c->ClassID() == Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &bezRotKey); newQuat = bezRotKey.val; if (i) newQuat = prevQuat * newQuat; prevQuat = newQuat; //DebugPrint(_T("\nBezier Rotation Key: %d=(%.1f, %.1f, %.1f, %.1f)"), // i, newQuat.x, newQuat.y, newQuat.z, newQuat.w); } } else if (c->ClassID() == Class_ID(LININTERP_ROTATION_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &linRotKey); newQuat = linRotKey.val; if (i) newQuat = prevQuat * newQuat; prevQuat = newQuat; //DebugPrint(_T("\nLinear Rotation Key: %d=(%.1f, %.1f, %.1f, %.1f)"), // i, newQuat.x, newQuat.y, newQuat.z, newQuat.w); } } // --- Process the scale keys --- c = n->GetTMController()->GetScaleController(); ikeys = GetKeyControlInterface(c); if (!ikeys) return; numKeys = ikeys->GetNumKeys(); //DebugPrint(_T("\nThere are %d scale key(s)"), numKeys); if (c->ClassID() == Class_ID(TCBINTERP_SCALE_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &tcbScaleKey); //DebugPrint(_T("\nTCB Scale Key: %2d=(%.1f, %.1f, %.1f)"), // i, tcbScaleKey.val.s.x, tcbScaleKey.val.s.y, // tcbScaleKey.val.s.z); } } else if (c->ClassID() == Class_ID(HYBRIDINTERP_SCALE_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &bezScaleKey); //DebugPrint(_T("\nBezier Scale Key: %2d=(%.1f, %.1f, %.1f)"), // i, bezScaleKey.val.s.x, bezScaleKey.val.s.y, // bezScaleKey.val.s.z); } } else if (c->ClassID() == Class_ID(LININTERP_SCALE_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &linScaleKey); DebugPrint(_T("\nLinear Scale Key: %2d=(%.1f, %.1f, %.1f)"), i, linScaleKey.val.s.x, linScaleKey.val.s.y, linScaleKey.val.s.z); } } }
void bgAnimMax::DumpFloatKeys(Control* pControl, bgMesh* pMesh) { if (!pControl) return; int i; bgAnimTrack Anim; IKeyControl *ikc = NULL; ikc = GetKeyControlInterface(pControl); if (ikc && pControl->ClassID() == Class_ID(TCBINTERP_FLOAT_CLASS_ID, 0)) { for (i = 0; i < ikc->GetNumKeys(); i++) { ITCBFloatKey key; ikc->GetKey(i, &key); Anim.iTick = key.time; Anim.vValue.x = key.val; pMesh->AlpTrack.push_back(Anim); } } else if (ikc && pControl->ClassID() == Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID, 0)) { for (i = 0; i < ikc->GetNumKeys(); i++) { IBezFloatKey key; ikc->GetKey(i, &key); Anim.iTick = key.time; Anim.vValue.x = key.val; pMesh->AlpTrack.push_back(Anim); } } else if (ikc && pControl->ClassID() == Class_ID(LININTERP_FLOAT_CLASS_ID, 0)) { for (i = 0; i < ikc->GetNumKeys(); i++) { ILinFloatKey key; ikc->GetKey(i, &key); Anim.iTick = key.time; Anim.vValue.x = key.val; pMesh->AlpTrack.push_back(Anim); } } else { TSTR name; pControl->GetClassName(name); if (pControl->IsAnimated()) { float value; Interval range; Interval animRange = m_p3DMax->GetAnimRange(); TimeValue t = pControl->GetTimeRange(TIMERANGE_ALL).Start(); while (animRange.InInterval(t)) { range = FOREVER; pControl->GetValue(t, &value, range); t = range.Start(); Anim.iTick = t; Anim.vValue.x = value; pMesh->AlpTrack.push_back(Anim); if (range.End() > pControl->GetTimeRange(TIMERANGE_ALL).End()) { break; } else { t = (range.End() / GetTicksPerFrame()) * GetTicksPerFrame(); } } } } }
//BOOL TbsAnimObj::IsKnownController(Control* cont) //{ // ulong partA, partB; // // if (!cont) // return FALSE; // ////Listed below are the first ULONG of the 8 byte ID. ////The second ULONG is 0 for all built-in classes (unless noted otherwise). ////For example a Class_ID for a TriObject would read: ////Class_ID(TRIOBJ_CLASS_ID, 0); ////Note that only built-in classes should have the second ULONG equal to 0. ////All plug-in developers should use both ULONGs. // // // // ClassID는 두개의 ULONG변수로 구성되며 내장된 클래스들은 모두 두번째 // // 변수는 0의 값을 갖고 있다. // // 단, 개발자의 플로그인은 두번째 값을 갖게 된다. // partA = cont->ClassID().PartA(); // partB = cont->ClassID().PartB(); // // if (partB != 0x00) // return FALSE; // // switch (partA) { // case TCBINTERP_POSITION_CLASS_ID: // case TCBINTERP_ROTATION_CLASS_ID: // case TCBINTERP_SCALE_CLASS_ID: // case HYBRIDINTERP_POSITION_CLASS_ID: // case HYBRIDINTERP_ROTATION_CLASS_ID: // case HYBRIDINTERP_SCALE_CLASS_ID: // case LININTERP_POSITION_CLASS_ID: // case LININTERP_ROTATION_CLASS_ID: // case LININTERP_SCALE_CLASS_ID: // return TRUE; // } // // return FALSE; //} void TbsAnimObj::DumpFloatKeys(Control* cont, TMesh* pMesh) { if (!cont) return; int i; IKeyControl *ikc = NULL; ikc = GetKeyControlInterface(cont); TAnimTrack Anim; // TCB float if (ikc && cont->ClassID() == Class_ID(TCBINTERP_FLOAT_CLASS_ID, 0)) { for (i=0; i<ikc->GetNumKeys(); i++) { ITCBFloatKey key; ikc->GetKey(i, &key); Anim.iTick = key.time; Anim.vValue.x = key.val; pMesh->m_VisTrack.push_back( Anim ); } } // Bezier float else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID, 0)) { for (i=0; i<ikc->GetNumKeys(); i++) { IBezFloatKey key; ikc->GetKey(i, &key); Anim.iTick = key.time; Anim.vValue.x = key.val; pMesh->m_VisTrack.push_back( Anim ); } } else if (ikc && cont->ClassID() == Class_ID(LININTERP_FLOAT_CLASS_ID, 0)) { for (i=0; i<ikc->GetNumKeys(); i++) { ILinFloatKey key; ikc->GetKey(i, &key); Anim.iTick = key.time; Anim.vValue.x = key.val; pMesh->m_VisTrack.push_back( Anim ); } } else { TSTR name; cont->GetClassName(name); // If it is animated at all... if (cont->IsAnimated()) { // Get the range of the controller animation Interval range; // Get range of full animation Interval animRange = m_p3dsMax->GetAnimRange(); TimeValue t = cont->GetTimeRange(TIMERANGE_ALL).Start(); float value; // While we are inside the animation... while (animRange.InInterval(t)) { // Sample the controller range = FOREVER; cont->GetValue(t, &value, range); // Set time to start of controller validity interval t = range.Start(); Anim.iTick = t; Anim.vValue.x = value; pMesh->m_VisTrack.push_back( Anim ); if (range.End() > cont->GetTimeRange(TIMERANGE_ALL).End()) { break; } else { //t = (range.End()/GetTicksPerFrame()+GetKeyFrameStep()) * GetTicksPerFrame(); t = (range.End()/GetTicksPerFrame()) * GetTicksPerFrame(); } } } } }
void RandKeysUtil::Apply() { BOOL timeMode = iu->GetMajorMode()==TVMODE_EDITTIME; BOOL fcurveMode = iu->GetMajorMode()==TVMODE_EDITFCURVE; Interval iv = iu->GetTimeSelection(); if (!doTime && !doVal) return; theHold.Begin(); // Turn animation on SuspendAnimate(); AnimateOn(); for (int i=0; i<iu->GetNumTracks(); i++) { if ((timeMode||fcurveMode) && !iu->IsSelected(i)) continue; // Get Interfaces Animatable *anim = iu->GetAnim(i); Animatable *client = iu->GetClient(i); int subNum = iu->GetSubNum(i); Control *cont = GetControlInterface(anim); IKeyControl *ikc = GetKeyControlInterface(anim); IKey *key = GetKeyPointer(anim->SuperClassID(),anim->ClassID()); if (!ikc || !cont || !key) continue; if (fcurveMode && !anim->IsCurveSelected()) continue; // Get the param dim float min = negVal, max = posVal; ParamDimension *dim = client->GetParamDimension(subNum); if (dim) { min = dim->UnConvert(min); max = dim->UnConvert(max); } for (int j=0; j<ikc->GetNumKeys(); j++) { // Get the key data ikc->GetKey(j,key); // Check if it's selected if (timeMode && !iv.InInterval(key->time)) continue; if (!timeMode && !(key->flags&IKEY_SELECTED)) continue; // Randomize time if (doTime) { key->time = (int)CompRand( float(key->time-negTime), float(key->time+posTime)); ikc->SetKey(j,key); } } if (doTime) ikc->SortKeys(); for (j=0; j<ikc->GetNumKeys(); j++) { // Get the key data ikc->GetKey(j,key); // Check if it's selected if (timeMode && !iv.InInterval(key->time)) continue; if (!timeMode && !(key->flags&IKEY_SELECTED)) continue; // Randomize value if (doVal) { Point3 pt, ang; Point4 p4; float f; Quat q; ScaleValue s; BOOL doX, doY, doZ, doW; doX = doY = doZ = doW = TRUE; if (!fcurveMode) { if (!(key->flags&IKEY_XSEL)) doX = FALSE; if (!(key->flags&IKEY_YSEL)) doY = FALSE; if (!(key->flags&IKEY_ZSEL)) doZ = FALSE; if (!(key->flags&IKEY_WSEL)) doW = FALSE; } switch (anim->SuperClassID()) { case CTRL_FLOAT_CLASS_ID: cont->GetValue(key->time,&f,FOREVER); f = CompRand(f-min,f+max); cont->SetValue(key->time,&f); break; case CTRL_POSITION_CLASS_ID: case CTRL_POINT3_CLASS_ID: cont->GetValue(key->time,&pt,FOREVER); if (doX) pt.x = CompRand(pt.x-min,pt.x+max); if (doY) pt.y = CompRand(pt.y-min,pt.y+max); if (doZ) pt.z = CompRand(pt.z-min,pt.z+max); cont->SetValue(key->time,&pt); break; case CTRL_POINT4_CLASS_ID: cont->GetValue(key->time,&p4,FOREVER); if (doX) p4.x = CompRand(p4.x-min,p4.x+max); if (doY) p4.y = CompRand(p4.y-min,p4.y+max); if (doZ) p4.z = CompRand(p4.z-min,p4.z+max); if (doW) p4.w = CompRand(p4.w-min,p4.w+max); cont->SetValue(key->time,&p4); break; case CTRL_ROTATION_CLASS_ID: cont->GetValue(key->time,&q,FOREVER); QuatToEuler(q, ang); ang.x = CompRand(ang.x-min,ang.x+max); ang.y = CompRand(ang.y-min,ang.y+max); ang.z = CompRand(ang.z-min,ang.z+max); EulerToQuat(ang,q); cont->SetValue(key->time,&q); break; case CTRL_SCALE_CLASS_ID: cont->GetValue(key->time,&s,FOREVER); if (doX) s.s.x = CompRand(s.s.x-min,s.s.x+max); if (doY) s.s.y = CompRand(s.s.y-min,s.s.y+max); if (doZ) s.s.z = CompRand(s.s.z-min,s.s.z+max); cont->SetValue(key->time,&s); break; } } } } ResumeAnimate(); theHold.Accept(GetString(IDS_RB_RANDOMIZEKEYS)); ip->RedrawViews(ip->GetTime()); }