// 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()); } }
// 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()); } }
int dump_mtlchunk(ushort tag,FILE *stream,void *data) { long chunkptr,chunkbase,curpos,chunksize; Color_f *cf; Color_24 *c24; Interface14 *iface= GetCOREInterface14(); UINT codePage = iface->DefaultTextSaveCodePage(); TSTR tName; CStr cName ; Mmtllist *ml; // Mliblist *mlb; chunkbase=ftell(stream); WRTERR(&tag,2); chunkptr=ftell(stream); /* Save file ptr for chunk size */ WRTERR(&chunkptr,4); switch(tag) { case MLIBMAGIC: switch(libtype) { case 0: // if(mlib) // { // mlb=mlib; // while(mlb) // { // savemtl= &mlb->material; // if(dump_mtlchunk(MAT_ENTRY,stream,NULL)==0) // return(0); // mlb=mlb->next; // } // } break; case 1: if(mmtl) { // tag_used_mmtls(); // for our purposes, they're ALL used ml=mmtl; while(ml) { // if(ml->flags & MMTLUSED) { savemtl= &ml->material; if(dump_mtlchunk(MAT_ENTRY,stream,NULL)==0) return(0); } ml=ml->next; } } break; } break; case MAT_ENTRY: case MATMAGIC: { if(dump_mtlchunk(MAT_NAME,stream,savemtl->name)==0) return(0); if(dump_mtlchunk(MAT_AMBIENT,stream,&savemtl->amb)==0) return(0); if(dump_mtlchunk(MAT_DIFFUSE,stream,&savemtl->diff)==0) return(0); if(dump_mtlchunk(MAT_SPECULAR,stream,&savemtl->spec)==0)return(0); if(dump_mtlchunk(MAT_SHININESS,stream,NULL)==0) return(0); if(dump_mtlchunk(MAT_SHIN2PCT,stream,NULL)==0) return(0); if(dump_mtlchunk(MAT_TRANSPARENCY,stream,NULL)==0) return(0); if(dump_mtlchunk(MAT_XPFALL,stream,NULL)==0) return(0); if(dump_mtlchunk(MAT_REFBLUR,stream,NULL)==0) return(0); if(dump_mtlchunk(MAT_SHADING,stream,NULL)==0) return(0); if(dump_mtlchunk(MAT_SELF_ILPCT,stream,NULL)==0) return(0); if(savemtl->use&MATUSE_XPFALL) { if(dump_mtlchunk(MAT_USE_XPFALL,stream,NULL)==0) return(0); } if(savemtl->use&MATUSE_REFBLUR) { if(dump_mtlchunk(MAT_USE_REFBLUR,stream,NULL)==0) return(0); } if(savemtl->flags & MF_TWOSIDE) { if(dump_mtlchunk(MAT_TWO_SIDE,stream,NULL)==0) return(0); } if(savemtl->flags & MF_ADDITIVE) { if(dump_mtlchunk(MAT_ADDITIVE,stream,NULL)==0) return(0); } if(savemtl->flags & MF_WIRE) { if(dump_mtlchunk(MAT_WIRE,stream,NULL)==0) return(0); } if(savemtl->flags & MF_FACEMAP) { if(dump_mtlchunk(MAT_FACEMAP,stream,NULL)==0) return(0); } if(savemtl->flags & MF_XPFALLIN) { if(dump_mtlchunk(MAT_XPFALLIN,stream,NULL)==0) return(0); } if(savemtl->flags & MF_PHONGSOFT) { if(dump_mtlchunk(MAT_PHONGSOFT,stream,NULL)==0) return(0); } if(savemtl->flags & MF_WIREABS) { if(dump_mtlchunk(MAT_WIREABS,stream,NULL)==0) return(0); } if(dump_mtlchunk(MAT_WIRESIZE,stream,&savemtl->wiresize)==0) return(0); /* Save out any texture maps, masks, sxp's */ for (int k=0; k<NMAPTYPES; k++) { Mapping *mp = savemtl->map[k]; if (mp==NULL) continue; if (mp->use) { DMP_MATCHUNK(map_chunks[k],NULL); if (k!=Nrefl) { if (isSXPMap(&mp->map)) DMP_MATCHUNK(map_sxp_chunks[k],mp->map.p.tex.sxp_data); } if (mp->mask.name[0]!=0) { DMP_MATCHUNK(mask_chunks[k],NULL); if (isSXPMap(&mp->mask)) DMP_MATCHUNK(mask_sxp_chunks[k],mp->mask.p.tex.sxp_data); } } } /* dump auto-cubic chunk */ { Mapping *rm = savemtl->map[Nrefl]; if (rm&&rm->use&&rm->map.p.ref.acb.flags & AC_ON) DMP_MATCHUNK(MAT_ACUBIC,&rm->map.p.ref.acb); } if (savemtl->appdata) if(dump_mtlchunk(APP_DATA,stream,savemtl->appdata)==0) return(0); } break; case APP_DATA: { ULONG *plong = (ULONG *)data; WRTERR(&plong[1],plong[0]); } break; case MAT_AMBIENT: case MAT_DIFFUSE: case MAT_SPECULAR: if (gammaMgr.enable) { Color_24 gc; c24 = (Color_24 *)data; gc.r = gammaMgr.file_in_gamtab[c24->r]; gc.g = gammaMgr.file_in_gamtab[c24->g]; gc.b = gammaMgr.file_in_gamtab[c24->b]; if(dump_mtlchunk(COLOR_24,stream,&gc)==0) return(0); if(dump_mtlchunk(LIN_COLOR_24,stream,data)==0)return(0); } else { if(dump_mtlchunk(COLOR_24,stream,data)==0) return(0); } break; case MAT_SHININESS: if(dump_mtlchunk(INT_PERCENTAGE,stream,&savemtl->shininess)==0) return(0); break; case MAT_SHIN2PCT: if(dump_mtlchunk(INT_PERCENTAGE,stream,&savemtl->shin2pct)==0) return(0); break; case MAT_SHIN3PCT: if(dump_mtlchunk(INT_PERCENTAGE,stream,&savemtl->shin3pct)==0) return(0); break; case MAT_TRANSPARENCY: if(dump_mtlchunk(INT_PERCENTAGE,stream,&savemtl->transparency)==0) return(0); break; case MAT_XPFALL: if(dump_mtlchunk(INT_PERCENTAGE,stream,&savemtl->xpfall)==0) return(0); break; case MAT_REFBLUR: if(dump_mtlchunk(INT_PERCENTAGE,stream,&savemtl->refblur)==0) return(0); break; case MAT_SELF_ILPCT: if(dump_mtlchunk(INT_PERCENTAGE,stream,&savemtl->selfipct)==0) return(0); break; case MAT_SHADING: WRTERR(&savemtl->shading,2); break; case MAT_TEXMAP: if (!dmp_map(stream,Ntex)) return(0); break; case MAT_TEX2MAP: if (!dmp_map(stream,Ntex2)) return(0); break; case MAT_OPACMAP: if (!dmp_map(stream,Nopac)) return(0); break; case MAT_BUMPMAP: if (!dmp_map(stream,Nbump)) return(0); break; case MAT_SPECMAP: if (!dmp_map(stream,Nspec)) return(0); break; case MAT_SHINMAP: if (!dmp_map(stream,Nshin)) return(0); break; case MAT_SELFIMAP: if (!dmp_map(stream,Nselfi)) return(0); break; case MAT_REFLMAP: if (!dmp_map(stream,Nrefl)) return(0); break; case MAT_TEXMASK: if (!dmp_mask(stream,Ntex)) return(0); break; case MAT_TEX2MASK: if (!dmp_mask(stream,Ntex2)) return(0); break; case MAT_OPACMASK: if (!dmp_mask(stream,Nopac)) return(0); break; case MAT_BUMPMASK: if (!dmp_mask(stream,Nbump)) return(0); break; case MAT_SPECMASK: if (!dmp_mask(stream,Nspec)) return(0); break; case MAT_SHINMASK: if (!dmp_mask(stream,Nshin)) return(0); break; case MAT_SELFIMASK:if (!dmp_mask(stream,Nselfi)) return(0); break; case MAT_REFLMASK: if (!dmp_mask(stream,Nrefl)) return(0); break; case MAT_MAP_TILING: WRTERR(data,2); break; case MAT_MAP_TEXBLUR: case MAT_MAP_USCALE: case MAT_MAP_VSCALE: case MAT_MAP_UOFFSET: case MAT_MAP_VOFFSET: WRTERR(data,4); break; case MAT_MAP_COL1: case MAT_MAP_COL2: case MAT_MAP_RCOL: case MAT_MAP_GCOL: case MAT_MAP_BCOL: c24=(Color_24 *)data; WRTERR(c24,3); break; case MAT_MAP_ANG: { MapParams *mp = (MapParams *)data; float ang,dang; ang = (float)atan2(mp->ang_sin,mp->ang_cos); dang = RadToDeg(ang); #if 0 printf("Saving MAT_MAP_ANG sin = %.4f , cos = %.4f, ang = %.4f \n", mp->ang_sin, mp->ang_cos, ang); #endif WRTERR(&dang,4); } break; case COLOR_F: cf=(Color_f *)data; WRTERR(cf,12); break; case COLOR_24: c24=(Color_24 *)data; WRTERR(c24,3); break; case LIN_COLOR_24: c24 = (Color_24 *)data; WRTERR(c24,3); break; case MAT_NAME: /* Simple strings */ tName = (TCHAR *)data; cName = tName.ToCP(codePage).data(); if(cName.Length()>16) cName.Resize(16); WRTERR(cName.data(),(size_t)( cName.Length()+1)); break; case MAT_MAPNAME: tName = (TCHAR *)data; // convert to 8.3 filename format EightDotThreeName( tName, false ); cName = tName.ToCP(codePage).data(); if(cName.Length()>12) cName.Resize(12); WRTERR( cName.data(),(size_t)( cName.Length()+1)); break; case MAT_BUMP_PERCENT: case INT_PERCENTAGE: WRTERR(data,2); break; case MAT_WIRESIZE: WRTERR(data,4); break; case MAT_TWO_SIDE: case MAT_SUPERSMP: case MAT_ADDITIVE: case MAT_WIRE: case MAT_FACEMAP: case MAT_XPFALLIN: case MAT_USE_XPFALL: case MAT_USE_REFBLUR: case MAT_PHONGSOFT: case MAT_WIREABS: case DUMMY: break; case MAT_ACUBIC: { AutoCubicParams *ac = (AutoCubicParams *)data; WRTERR(&ac->shade,1); WRTERR(&ac->aalevel,1); WRTERR(&ac->flags,2); WRTERR(&ac->size,4); WRTERR(&ac->nth,4); } break; case MAT_SXP_TEXT_DATA: case MAT_SXP_TEXT2_DATA: case MAT_SXP_OPAC_DATA: case MAT_SXP_BUMP_DATA: case MAT_SXP_SPEC_DATA: case MAT_SXP_SHIN_DATA: case MAT_SXP_SELFI_DATA: case MAT_SXP_TEXT_MASKDATA: case MAT_SXP_TEXT2_MASKDATA: case MAT_SXP_OPAC_MASKDATA: case MAT_SXP_BUMP_MASKDATA: case MAT_SXP_SPEC_MASKDATA: case MAT_SXP_SHIN_MASKDATA: case MAT_SXP_SELFI_MASKDATA: case MAT_SXP_REFL_MASKDATA: { ULONG *plong = (ULONG *)data; if (plong!=NULL) WRTERR(&plong[1],plong[0]); } break; } /* Save file ptr */ curpos=ftell(stream); /* Point back to chunk size location */ fseek(stream,chunkptr,SEEK_SET); /* Calc & write chunk size */ chunksize=curpos-chunkbase; WRTERR(&chunksize,4); /* Point back to file end */ fseek(stream,curpos,SEEK_SET); return(1); }