void XsiExp::WriteConfig() { TSTR filename = GetCfgFilename(); FILE* cfgStream; cfgStream = fopen(filename, "wb"); if (!cfgStream) { return; } // Write CFG version _putw(CFG_VERSION, cfgStream); fputc(GetIncludeAnim(), cfgStream); fputc(GetIncludeVertexColors(), cfgStream); fputc(GetAlwaysSample(), cfgStream); _putw(GetMeshFrameStep(), cfgStream); _putw(GetKeyFrameStep(), cfgStream); _putw(GetPrecision(), cfgStream); fclose(cfgStream); }
// Output float keys if this is a known float controller that // supports key operations. Otherwise we will sample the controller // once for each frame to get the value. void AsciiExp::DumpFloatKeys(Control* cont, int indentLevel) { if (!cont) return; int i; TSTR indent = GetIndent(indentLevel); IKeyControl *ikc = NULL; // If the user wants us to always sample, we will ignore the KeyControlInterface if (!GetAlwaysSample()) ikc = GetKeyControlInterface(cont); // TCB float if (ikc && cont->ClassID() == Class_ID(TCBINTERP_FLOAT_CLASS_ID, 0)) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_FLOAT_TCB); for (i=0; i<ikc->GetNumKeys(); i++) { ITCBFloatKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s"), indent.data(), ID_TCB_FLOAT_KEY, key.time, Format(key.val)); _ftprintf(pStream, _T("\t%s\t%s\t%s\t%s\t%s\n"), Format(key.tens), Format(key.cont), Format(key.bias), Format(key.easeIn), Format(key.easeOut)); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } // Bezier float else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID, 0)) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_FLOAT_BEZIER); for (i=0; i<ikc->GetNumKeys(); i++) { IBezFloatKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s"), indent.data(), ID_BEZIER_FLOAT_KEY, key.time, Format(key.val)); _ftprintf(pStream, _T("\t%s\t%s\t%d\n"), Format(key.intan), Format(key.outtan), key.flags); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } else if (ikc && cont->ClassID() == Class_ID(LININTERP_FLOAT_CLASS_ID, 0)) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_FLOAT_LINEAR); for (i=0; i<ikc->GetNumKeys(); i++) { ILinFloatKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s\n"), indent.data(), ID_FLOAT_KEY, key.time, Format(key.val)); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } else { // Unknown controller, no key interface or sample on demand - // This might be a procedural controller or something else we // don't know about. The last resort is to get the value from the // controller at every n frames. TSTR name; cont->GetClassName(name); TSTR className = FixupName(name); Interface14 *iface = GetCOREInterface14(); UINT codepage = iface-> DefaultTextSaveCodePage(true); const char* className_locale = className.ToCP(codepage); _ftprintf(pStream, _T("%s\t\t%s \"%hs\" {\n"), indent.data(), ID_CONTROL_FLOAT_SAMPLE, className_locale); // 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 = ip->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(); // Output the sample _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s\n"), indent.data(), ID_FLOAT_KEY, t, Format(value)); // If the end of the controller validity is beyond the // range of the animation if (range.End() > cont->GetTimeRange(TIMERANGE_ALL).End()) { break; } else { t = (range.End()/GetTicksPerFrame()+GetKeyFrameStep()) * GetTicksPerFrame(); } } } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } }
// Get hold of the transform controllers for the node... void AsciiExp::ExportAnimKeys(INode* node, int indentLevel) { TSTR indent = GetIndent(indentLevel); BOOL bPosAnim; BOOL bRotAnim; BOOL bScaleAnim; BOOL bDoKeys = FALSE; // We can only export keys if all TM controllers are "known" to us. // The reason for that is that some controllers control more than what // they should. Consider a path position controller, if you turn on // follow and banking, this position controller will also control // rotation. If a node that had a path position controller also had a // TCB rotation controller, the TCB keys would not describe the whole // rotation of the node. // For that reason we will only export keys if all controllers // position, rotation and scale are linear, hybrid (bezier) or tcb. if (!GetAlwaysSample()) { Control* pC = node->GetTMController()->GetPositionController(); Control* rC = node->GetTMController()->GetRotationController(); Control* sC = node->GetTMController()->GetScaleController(); if (IsKnownController(pC) && IsKnownController(rC) && IsKnownController(sC)) { bDoKeys = TRUE; } } Interface14 *iface = GetCOREInterface14(); UINT codepage = iface-> DefaultTextSaveCodePage(true); TSTR nodeName = FixupName(node->GetName()); const char* nodeName_locale = nodeName.ToCP(codepage); if (bDoKeys) { // Only dump the track header if any of the controllers have keys if (node->GetTMController()->GetPositionController()->NumKeys() || node->GetTMController()->GetRotationController()->NumKeys() || node->GetTMController()->GetScaleController()->NumKeys()) { _ftprintf(pStream, _T("%s\t%s {\n"), indent.data(), ID_TM_ANIMATION); _ftprintf(pStream, _T("%s\t\t%s \"%hs\"\n"), indent.data(), ID_NODE_NAME, nodeName_locale); DumpPosKeys(node->GetTMController()->GetPositionController(), indentLevel); DumpRotKeys(node->GetTMController()->GetRotationController(), indentLevel); DumpScaleKeys(node->GetTMController()->GetScaleController(), indentLevel); _ftprintf(pStream, _T("%s\t}\n"), indent.data()); } } else if (CheckForAnimation(node, bPosAnim, bRotAnim, bScaleAnim)) { _ftprintf(pStream, _T("%s\t%s {\n"), indent.data(), ID_TM_ANIMATION); _ftprintf(pStream, _T("%s\t\t%s \"%hs\"\n"), indent.data(), ID_NODE_NAME, nodeName_locale); if (bPosAnim) { DumpPosSample(node, indentLevel); } if (bRotAnim) { DumpRotSample(node, indentLevel); } if (bScaleAnim) { DumpScaleSample(node, indentLevel); } _ftprintf(pStream, _T("%s\t}\n"), indent.data()); } }
// Get hold of the transform controllers for the node... void XsiExp::ExportAnimKeys( INode * node, int & animHit) { // Targets are actually geomobjects, but we will export them // from the camera and light objects, so we skip them here. // Object * obj = node->EvalWorldState(GetStaticFrame()).obj; if (!obj || obj->ClassID() == Class_ID( TARGET_CLASS_ID, 0)) { return; } TSTR indent = GetIndent(1); BOOL bPosAnim, bRotAnim, bScaleAnim, bDoKeys = FALSE; TCHAR * name = FixupName( node->GetName()); BOOL isBone = obj->ClassID() == Class_ID(BONE_CLASS_ID, 0) ? TRUE : FALSE; if (isBone) { // bone anims get passed to children if (!node->GetParentNode() || node->GetParentNode()->IsRootNode()) { // can't anim top bone return; } node = node->GetParentNode(); } // We can only export keys if all TM controllers are "known" to us. // The reason for that is that some controllers control more than what // they should. Consider a path position controller, if you turn on // follow and banking, this position controller will also control // rotation. If a node that had a path position controller also had a // TCB rotation controller, the TCB keys would not describe the whole // rotation of the node. // For that reason we will only export keys if all controllers // position, rotation and scale are linear, hybrid (bezier) or tcb. if (!GetAlwaysSample()) { Control* pC = node->GetTMController()->GetPositionController(); Control* rC = node->GetTMController()->GetRotationController(); Control* sC = node->GetTMController()->GetScaleController(); if (IsKnownController(pC) && IsKnownController(rC) && IsKnownController(sC)) { bDoKeys = TRUE; } } if (bDoKeys) { // Only dump the track header if any of the controllers have keys if (node->GetTMController()->GetPositionController()->NumKeys() > 1 || node->GetTMController()->GetRotationController()->NumKeys() > 1 || node->GetTMController()->GetScaleController()->NumKeys() > 1) { if (!animHit) { fprintf(pStream,"AnimationSet {\n"); animHit = TRUE; } fprintf(pStream,"%sAnimation anim-%s {\n", indent.data(), name ); indent = GetIndent(2); fprintf(pStream,"%s{frm-%s}\n", indent.data(), name ); DumpRotKeys( node, 1); DumpPosKeys( node, 1); DumpScaleKeys( node, 1); indent = GetIndent(1); fprintf(pStream,"%s}\n\n", indent.data()); } } else if (CheckForAnimation(node, bPosAnim, bRotAnim, bScaleAnim)) { if (!animHit) { fprintf(pStream,"AnimationSet {\n"); animHit = TRUE; } fprintf(pStream,"%sAnimation anim-%s {\n", indent.data(), name ); indent = GetIndent(2); fprintf(pStream,"%s{frm-%s}\n", indent.data(), name ); DumpRotKeys( node, 1); DumpPosKeys( node, 1); DumpScaleKeys( node, 1); fprintf(pStream,"%s}\n", indent.data()); } }