Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. //studio.h takes care of all the other includes we need too
  2. #include "studio.h"
  3.  
  4. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  5. // This code requires the OrangeBox sdk
  6. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  7. ASSERT_INVARIANT( STUDIO_VERSION == 48 );
  8.  
  9. #define IDSTUDIOHEADER MAKEID( 'I', 'D', 'S', 'T' ) //Studiomodel ident
  10. #define RAD2DEG_INT( x ) (int)((RAD2DEG(x)) + 0.5f) //Rounds to nearest int
  11.  
  12. //Get a QC file name
  13. //Assumes input is from a studio model header (studiohdr_t->name)
  14. char *QC_GetName( char *in, char *append = ".qc" )
  15. {
  16.     static char out[128] = { 0 };
  17.  
  18.     //Strip any directory info and copy it
  19.     int tmp = 0; //this will be the postion of the last slash in the string (+1)
  20.     for( int i = strlen( in ); i > 0; --i )
  21.     {
  22.         if( in[i] == '\\' || in[i] == '/' )
  23.         {
  24.             tmp = ++i;
  25.             break;
  26.         }
  27.     }
  28.     memcpy( out, in+tmp, strlen(in)-tmp );
  29.  
  30.     out[strlen(out)-4] = 0; //remove .mdl
  31.     strcat( out, append ); //append .qc (default) or whatever the arg specifies
  32.     return out;
  33. }
  34.  
  35. void QC_DumpJigglebones( studiohdr_t *phdr )
  36. {
  37.     char *pszQc = QC_GetName( phdr->name, "_jiggles.qci" );
  38.     FILE *qcfile = fopen( pszQc, "w" ); //Will open in the current working directory of your command prompt
  39.  
  40.     //Dump it
  41.     for( int i = 0; i < phdr->numbones; ++i )
  42.     {
  43.         mstudiobone_t *pbone = phdr->pBone( i );
  44.         if( pbone->proctype == STUDIO_PROC_JIGGLE && pbone->procindex != 0 )
  45.         {
  46.             printf( "Jigglebone: %s ", pbone->pszName() );
  47.  
  48.             mstudiojigglebone_t *pjiggle = (mstudiojigglebone_t*)pbone->pProcedure();
  49.             fprintf( qcfile, "$jigglebone \"%s\" {\n", pbone->pszName() );
  50.  
  51.             if( pjiggle->flags & JIGGLE_IS_FLEXIBLE )
  52.             {
  53.                 printf( "- is_flexible " );
  54.                 fprintf( qcfile, "\tis_flexible {\n" );
  55.                 fprintf( qcfile, "\t\tyaw_stiffness %g\n", pjiggle->yawStiffness );
  56.                 fprintf( qcfile, "\t\tyaw_damping %g\n", pjiggle->yawDamping );
  57.                 fprintf( qcfile, "\t\tpitch_stiffness %g\n", pjiggle->pitchStiffness );
  58.                 fprintf( qcfile, "\t\tpitch_damping %g\n", pjiggle->pitchDamping );
  59.                 fprintf( qcfile, "\t\talong_stiffness %g\n", pjiggle->alongStiffness );
  60.                 fprintf( qcfile, "\t\talong_damping %g\n", pjiggle->alongDamping );
  61.                 fprintf( qcfile, "\t\tlength %g\n", pjiggle->length );
  62.                 fprintf( qcfile, "\t\ttip_mass %g\n", pjiggle->tipMass );
  63.  
  64.                 if( pjiggle->flags & JIGGLE_HAS_YAW_CONSTRAINT )
  65.                 {
  66.                     fprintf( qcfile, "\t\tyaw_constraint %i %i\n", RAD2DEG_INT( pjiggle->minYaw ), RAD2DEG_INT( pjiggle->maxYaw ) );
  67.                     fprintf( qcfile, "\t\tyaw_friction %g\n", pjiggle->yawFriction );
  68.                 }
  69.                
  70.                 if( pjiggle->flags & JIGGLE_HAS_ANGLE_CONSTRAINT )
  71.                 {
  72.                     fprintf( qcfile, "\t\tangle_constraint %i\n", RAD2DEG_INT( pjiggle->angleLimit ) );
  73.                 }
  74.                
  75.                 if( pjiggle->flags & JIGGLE_HAS_PITCH_CONSTRAINT )
  76.                 {
  77.                     fprintf( qcfile, "\t\tpitch_constraint %i %i\n", RAD2DEG_INT( pjiggle->minPitch ), RAD2DEG_INT( pjiggle->maxPitch ) );
  78.                     fprintf( qcfile, "\t\tpitch_friction %g\n", pjiggle->pitchFriction );
  79.                     fprintf( qcfile, "\t\tpitch_bounce %g\n", pjiggle->pitchBounce );
  80.                 }
  81.  
  82.                 fprintf( qcfile, "\t}\n" );
  83.             }
  84.  
  85.             if( pjiggle->flags & JIGGLE_IS_RIGID )
  86.             {
  87.                 printf( "- is_rigid " );
  88.                 fprintf( qcfile, "\tis_rigid {\n" );
  89.                 fprintf( qcfile, "\t\tlength %g\n", pjiggle->length );
  90.                 fprintf( qcfile, "\t\ttip_mass %g\n", pjiggle->tipMass );
  91.  
  92.                 if( pjiggle->flags & JIGGLE_HAS_YAW_CONSTRAINT )
  93.                 {
  94.                     fprintf( qcfile, "\t\tyaw_constraint %i %i\n", RAD2DEG_INT( pjiggle->minYaw ), RAD2DEG_INT( pjiggle->maxYaw ) );
  95.                     fprintf( qcfile, "\t\tyaw_friction %g\n", pjiggle->yawFriction );
  96.                 }
  97.                
  98.                 if( pjiggle->flags & JIGGLE_HAS_ANGLE_CONSTRAINT )
  99.                 {
  100.                     fprintf( qcfile, "\t\tangle_constraint %i\n", RAD2DEG_INT( pjiggle->angleLimit ) );
  101.                 }
  102.                
  103.                 if( pjiggle->flags & JIGGLE_HAS_PITCH_CONSTRAINT )
  104.                 {
  105.                     fprintf( qcfile, "\t\tpitch_constraint %i %i\n", RAD2DEG_INT( pjiggle->minPitch ), RAD2DEG_INT( pjiggle->maxPitch ) );
  106.                     fprintf( qcfile, "\t\tpitch_friction %g\n", pjiggle->pitchFriction );
  107.                     fprintf( qcfile, "\t\tpitch_bounce %g\n", pjiggle->pitchBounce );
  108.                 }
  109.  
  110.                 fprintf( qcfile, "\t}\n" );
  111.             }
  112.  
  113.             if( pjiggle->flags & JIGGLE_HAS_BASE_SPRING )
  114.             {
  115.                 printf( "- has_base_spring " );
  116.                 fprintf( qcfile, "\n\thas_base_spring {\n" );
  117.                 fprintf( qcfile, "\t\tbase_mass %g\n", pjiggle->baseMass );
  118.                 fprintf( qcfile, "\t\tstiffness %g\n", pjiggle->baseStiffness );
  119.                 fprintf( qcfile, "\t\tdamping %g\n", pjiggle->baseDamping );
  120.                 fprintf( qcfile, "\t\tleft_constraint %g %g\n", pjiggle->baseMinLeft, pjiggle->baseMaxLeft );
  121.                 fprintf( qcfile, "\t\tleft_friction %g\n", pjiggle->baseLeftFriction );
  122.                 fprintf( qcfile, "\t\tup_constraint %g %g\n", pjiggle->baseMinUp, pjiggle->baseMaxUp );
  123.                 fprintf( qcfile, "\t\tup_friction %g\n", pjiggle->baseUpFriction );
  124.                 fprintf( qcfile, "\t\tforward_constraint %g %g\n", pjiggle->baseMinUp, pjiggle->baseMaxUp );
  125.                 fprintf( qcfile, "\t\tforward_friction %g\n", pjiggle->baseUpFriction );
  126.                 fprintf( qcfile, "\t}\n" );
  127.             }
  128.             printf("\n");
  129.             fprintf( qcfile, "}\n\n" );
  130.         }
  131.     }
  132.     fclose( qcfile );
  133.  
  134.     printf( "Wrote %s\n", pszQc );
  135. }
  136.  
  137. int main( int argc, char *argv[] )
  138. {
  139.     if( argc != 2 )
  140.     {
  141.         printf( "Usage: jiggle_qcgen.exe modelfile.mdl\n" );
  142.         return 1;
  143.     }
  144.  
  145.     if( !strstr( argv[1], ".mdl" ) )
  146.     {
  147.         printf( "Specified file is not a model (*.mdl).\n" );
  148.         return 2;
  149.     }
  150.  
  151.     FILE *fp = fopen( argv[1], "rb" );
  152.     fseek( fp, 0, SEEK_END );
  153.     int len = ftell( fp );
  154.     rewind( fp );
  155.  
  156.     char *buffer = new char[len];
  157.     fread( buffer, 1, len, fp );
  158.     studiohdr_t *phdr = (studiohdr_t*)buffer;
  159.     fclose( fp );
  160.  
  161.     if( phdr->id != IDSTUDIOHEADER )
  162.     {
  163.         printf( "%s is not a studio model!\n", argv[1] );
  164.         delete[] buffer;
  165.         return 3;
  166.     }
  167.  
  168.     //Make sure it's an Orange box engine model, pre-OB models don't have jiggle bones.
  169.     if( phdr->version < 45 )
  170.     {
  171.         printf( "Version %i models do not have jigglebone data, exiting..\n", phdr->version );
  172.         delete[] buffer;
  173.         return 4;
  174.     }
  175.  
  176.     //Needs to be after the version check for obvious reasons.
  177.     Studio_ConvertStudioHdrToNewVersion( phdr );
  178.  
  179.     //iterate over all the bones to make sure at least one is jiggled first,
  180.     //so we don't create an empty qcfile.
  181.     for( int i = 0; i < phdr->numbones; ++i )
  182.     {
  183.         mstudiobone_t *pbone = phdr->pBone( i );
  184.         if( pbone->proctype == STUDIO_PROC_JIGGLE && pbone->procindex != 0 )
  185.         {
  186. #ifdef _DEBUG
  187.             printf( "Found at least one jigglebone, ending check loop..\n" );
  188. #endif
  189.             break; //Found at least one, build the file
  190.         }
  191.  
  192.         if( i < phdr->numbones-1 )
  193.         {
  194. #ifdef _DEBUG
  195.             printf( "Skip: %3i %3i  %s\n", i, phdr->numbones-1, pbone->pszName() );
  196. #endif
  197.             continue; //Skip until the last bone
  198.         }
  199.  
  200. #ifdef _DEBUG
  201.             printf( "End:  %3i %3i  %s\n", i, phdr->numbones-1, pbone->pszName() );
  202. #endif
  203.  
  204.         //None were found, get outta here
  205.         printf( "No bones contain jiggle info, exiting..\n" );
  206.         delete[] buffer;
  207.         return 5;
  208.     }
  209.  
  210.     //Build the qc file
  211.     QC_DumpJigglebones( phdr );
  212.  
  213.     phdr = NULL;
  214.     delete[] buffer;
  215.     return 0;
  216. }
  217.