summaryrefslogtreecommitdiffstats
path: root/tools/CreateSetChunk/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/CreateSetChunk/main.cpp')
-rw-r--r--tools/CreateSetChunk/main.cpp494
1 files changed, 494 insertions, 0 deletions
diff --git a/tools/CreateSetChunk/main.cpp b/tools/CreateSetChunk/main.cpp
new file mode 100644
index 0000000..62228a4
--- /dev/null
+++ b/tools/CreateSetChunk/main.cpp
@@ -0,0 +1,494 @@
+/*===========================================================================
+ File: main.cpp
+
+ This tool turns a greyscale image into a raw look up table.
+
+ Copyright (c) Radical Entertainment, Inc. All rights reserved.
+
+===========================================================================*/
+
+#include <stdio.h>
+#include <assert.h>
+#include <toollib.hpp>
+#include <dospath.hpp>
+#include <tlFrameControllerChunk16.hpp>
+#include <tlAnimationChunk.hpp>
+#include <atenum.hpp>
+#include <chunkids.hpp>
+
+#include "Param.hpp"
+#include <tlSetChunk.hpp>
+
+Parameters* Param;
+char outFile[P3DMAXNAME];
+
+struct TextureData
+{
+ TextureData() :
+ m_TextureID( 0 ),
+ m_NumIDs( 0 ),
+ m_ShaderID( 0 ),
+ m_AnimationChunk( 0 ),
+ m_ControllerChunk( 0 ),
+// m_MultiControllerChunk( 0 ),
+ m_pSetChunk( 0 ),
+ m_WritenOut( false ) {};
+ ~TextureData() { delete m_TextureID; } // Set chunk is deleted by the output chunk.
+ TLUID* m_TextureID; // List of texture chunks to put into set chunk.
+ int m_NumIDs; // Number in list. If number is negative then just the animation/controller chunk are removed and multicontroller modified.
+ TLUID m_ShaderID; // The shader this data is for.
+ TLUID m_AnimationChunk; // Texture animation chunk to remove.
+ TLUID m_ControllerChunk; // Texture frame controller chunk to remove.
+// TLUID m_MultiControllerChunk; // MultiController to remove texture frame controller from.
+ tlSetChunk* m_pSetChunk; // Set chunk which will be written to file.
+ bool m_WritenOut; // Has the set chunk been written out?
+};
+
+static const int TEXTURE_COLLECTION_SIZE = 256;
+static TextureData* g_TextureCollection[ TEXTURE_COLLECTION_SIZE ];
+static int g_TextureCollectionCount = 0;
+
+int main(int argc, char* argv[])
+{
+ Param = new Parameters(argc,argv);
+ bool sameFile = false; // Have we switched to a new output file.
+
+ tlDataChunk::RegisterDefaultChunks();
+
+ tlFile* output = 0;
+
+ for( int i = 0; i < TEXTURE_COLLECTION_SIZE; ++i )
+ {
+ g_TextureCollection[ i ] = 0;
+ }
+
+ if( Param->Files.Count() < 1 )
+ {
+ printf( "Must specify at least one input file.\n" );
+ exit( -1 );
+ }
+ if( Param->ShaderName == 0 )
+ {
+ printf( "Must specify the name of the shader with texture animation.\n" );
+ exit( -1 );
+ }
+
+ bool wildCardShader = false;
+ int shaderNameLen = strlen( Param->ShaderName );
+ if( Param->ShaderName[ shaderNameLen - 1 ] == '*' )
+ {
+ wildCardShader = true;
+ --shaderNameLen;
+ Param->ShaderName[ shaderNameLen ] = '\0';
+ }
+
+ // for each file on the command-line, do the following:
+ for(int curFile = 0; curFile < Param->Files.Count(); curFile++)
+ {
+ tlFile input(new tlFileByteStream(Param->Files[ curFile ], omREAD), tlFile::FROMFILE);
+ if(!input.IsOpen())
+ {
+ printf("Could not open %s\n", Param->Files[ curFile ]);
+ exit( -1 );
+ }
+ tlDataChunk* inChunk = new tlDataChunk( &input );
+
+ char outFileName[256];
+ if( output == 0 )
+ {
+ if( Param->OutputFile )
+ {
+ strcpy(outFileName, Param->OutputFile);
+ }
+ else
+ {
+ strcpy(outFileName, Param->Files[curFile]);
+ RemoveExtension(outFileName);
+ strcat(outFileName, ".p3d");
+ }
+ output = new tlFile(new tlFileByteStream(outFileName, omWRITE), tlFile::CHUNK32);
+ if( ( output == 0 ) || ( !output->IsOpen() ) )
+ {
+ printf("Could not open %s for writing\n", outFileName);
+ exit(-1);
+ }
+ sameFile = false;
+ }
+ for( int i = 0; i < g_TextureCollectionCount; ++i )
+ {
+ delete g_TextureCollection[ i ];
+ g_TextureCollection[ i ] = 0;
+ }
+
+ /*************************************************/
+ // First pass for input file, nose through the frame controllers.
+ // Go through all the sub-chunks of the input and look for shader name
+ //in heirarchy of texture frame controller.
+ int inChunkIndex;
+ for( inChunkIndex = 0; inChunkIndex < inChunk->SubChunkCount(); inChunkIndex++ )
+ {
+ tlDataChunk* sub = inChunk->GetSubChunk( inChunkIndex );
+ if( sub->ID() == Pure3D::Animation::FrameControllerData::FRAME_CONTROLLER )
+ {
+ // We have a frame controller...
+ tlFrameControllerChunk* controller = static_cast<tlFrameControllerChunk*>( sub );
+ if( controller->GetType() == Pure3DAnimationTypes::TEXTURE_TEX )
+ {
+ // and it's a texture controller. So check the hierarchy name.
+ bool foundShader = false;
+ const char* heirName = controller->HierarchyName();
+ if( wildCardShader )
+ {
+ foundShader = strncmp( heirName, Param->ShaderName, shaderNameLen ) == 0;
+ }
+ else
+ {
+ foundShader = strcmp( heirName, Param->ShaderName ) == 0;
+ }
+ if( foundShader )
+ {
+ // We found the shader so remember the texture animation data.
+ TextureData* texData = new TextureData();
+ if( texData == 0 )
+ {
+ printf( "Unable to allocate texture data.\n" );
+ exit( -1 );
+ }
+ texData->m_ShaderID = tlEntity::MakeUID( heirName );
+ texData->m_ControllerChunk = tlEntity::MakeUID( controller->GetName() );
+ texData->m_AnimationChunk = tlEntity::MakeUID( controller->AnimationName() );
+ // Look to see if we already have this shader.
+ //If we do, we'll just erase the controller and animation and modify the multicontroller.
+ //The first texData will be used to create the chunk set.
+ for( int i = 0; i < g_TextureCollectionCount; ++i )
+ {
+ if( g_TextureCollection[ i ]->m_ShaderID == texData->m_ShaderID )
+ {
+ texData->m_NumIDs = -1;
+ break;
+ }
+ }
+ g_TextureCollection[ g_TextureCollectionCount ] = texData;
+ ++g_TextureCollectionCount;
+ }
+ }
+ }
+ }
+ /*************************************************/
+ // Second pass. Now we look for the animation to go with all those texture frame controllers
+ //we found.
+ for( inChunkIndex = 0; inChunkIndex < inChunk->SubChunkCount(); inChunkIndex++ )
+ {
+ tlDataChunk* sub = inChunk->GetSubChunk( inChunkIndex );
+ // Is this an animation?
+ if( sub->ID() != Pure3D::Animation::AnimationData::ANIMATION )
+ {
+ // No, not interested.
+ continue;
+ }
+ tlAnimationChunk* anim = static_cast<tlAnimationChunk*>( sub );
+ // Is it a texture animation?
+ if( anim->GetAnimationType() != Pure3DAnimationTypes::TEXTURE_TEX )
+ {
+ // No, not interested.
+ continue;
+ }
+ // We've found a texture animation. Check if it's one we are looking for.
+ TLUID animID = tlEntity::MakeUID( anim->GetName() );
+ for( int i = 0; i < g_TextureCollectionCount; ++i )
+ {
+ if( ( g_TextureCollection[ i ]->m_NumIDs == 0 ) && ( g_TextureCollection[ i ]->m_AnimationChunk == animID ) )
+ {
+ // We've found the animation to match a frame controller. Let the mess begin.
+ TextureData* texData = g_TextureCollection[ i ]; // just for convience.
+ // Examine the sub chunks...there should be a goup list in there...
+ for( int subChunkIndex = 0; subChunkIndex < anim->SubChunkCount(); ++subChunkIndex )
+ {
+ tlDataChunk* animSub = anim->GetSubChunk( subChunkIndex );
+ if( animSub->ID() == Pure3D::Animation::AnimationData::GROUP_LIST )
+ {
+ // Found the group list. Now we'll nose around the groups...
+ tlAnimationGroupListChunk* groupList = static_cast<tlAnimationGroupListChunk*>( animSub );
+ for( int listChunkIndex = 0; listChunkIndex < groupList->SubChunkCount(); ++listChunkIndex )
+ {
+ // Look at all the channels in the groups in the group list.
+ tlDataChunk* listSub = groupList->GetSubChunk( listChunkIndex );
+ if( listSub->ID() == Pure3D::Animation::AnimationData::GROUP )
+ {
+ tlAnimationGroupChunk* group = static_cast<tlAnimationGroupChunk*>( listSub );
+ for( int channelIndex = 0; channelIndex < (int)group->GetNumChannels(); ++channelIndex )
+ {
+ int i;
+ // In the group (whew), look at all the channels.
+ // Is it an entity channel?
+ tlDataChunk* channelSub = group->GetSubChunk( channelIndex );
+ if( channelSub->ID() != Pure3D::Animation::ChannelData::ENTITY )
+ {
+ // No, not interested.
+ continue;
+ }
+ // Is the entity channel a texture?
+ tlEntityChannelChunk* entityChannel = static_cast<tlEntityChannelChunk*>( channelSub );
+ if( entityChannel->Param() != Pure3DAnimationTypes::TEXTURE_TEX )
+ {
+ // No, not interested.
+ continue;
+ }
+ // Okay we have the entity channel for a texture animation, now we
+ //record the texture names.
+ // We might end up allocating extra space for textures, but we'll
+ //leave the UIDs at zero at the end of the array.
+ texData->m_TextureID = new TLUID[ entityChannel->GetNumFrames() ];
+ if( texData->m_TextureID == 0 )
+ {
+ printf( "Unable to allocate texture array.\n" );
+ exit( -1 );
+ }
+ for( i = 0; i < (int)entityChannel->GetNumFrames(); ++i )
+ {
+ texData->m_TextureID[ i ] = 0;
+ }
+ // Get all the frame values.
+ char** values = entityChannel->GetValues();
+ for( i = 0; i < (int)entityChannel->GetNumFrames(); ++i )
+ {
+ TLUID textureID = tlEntity::MakeUID( values[ i ] );
+ // We have the texture tUID, look if it's a duplicate.
+ bool textureDup = false;
+ for( int j = 0; j < texData->m_NumIDs; ++j )
+ {
+ if( texData->m_TextureID[ j ] == textureID )
+ {
+ // this one is a duplicate, skip it.
+ textureDup = true;
+ break;
+ }
+ }
+ if( !textureDup )
+ {
+ // It's not a duplicate so remember it.
+ texData->m_TextureID[ texData->m_NumIDs ] = textureID;
+ ++texData->m_NumIDs;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ /*************************************************/
+ // Third pass, create the set chunks from the textures we got from those texture animations.
+ for( inChunkIndex = 0; inChunkIndex < inChunk->SubChunkCount(); inChunkIndex++ )
+ {
+ tlDataChunk* sub = inChunk->GetSubChunk( inChunkIndex );
+ if( sub->ID() == Pure3D::Texture::TEXTURE )
+ {
+ // We've found a texture, check to see if it's one of the textures we are looking for.
+ TextureData* texData = 0;
+ int textureIDIndex = 0;
+ TLUID textureID = tlEntity::MakeUID( sub->GetName() );
+ for( int i = 0; i < g_TextureCollectionCount; ++i )
+ {
+ texData = g_TextureCollection[ i ];
+ for( textureIDIndex = 0; textureIDIndex < texData->m_NumIDs; ++textureIDIndex )
+ {
+ if( textureID == texData->m_TextureID[ textureIDIndex ] )
+ {
+ if( texData->m_pSetChunk == 0 )
+ {
+ texData->m_pSetChunk = new tlSetChunk();
+ if( texData->m_pSetChunk == 0 )
+ {
+ printf( "Unable to create tlSetChunk.\n" );
+ exit( -1 );
+ }
+ }
+ if( textureIDIndex == 0 )
+ {
+ // This is the first texture in the set so we'll use the name for
+ //the set.
+ texData->m_pSetChunk->SetName( sub->GetName() );
+ }
+ texData->m_pSetChunk->AppendSubChunk( sub, 0 );
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /*************************************************/
+ // Forth pass, process the file. Copy all the chunks over,
+ //except the texture frame controllers, texture animations,
+ //and textures we've used. Also, modify the multicontrollers
+ //to exclude the texture frame controllers.
+ tlDataChunk* outChunk = new tlDataChunk;
+
+ if( Param->WriteHistory && !sameFile )
+ {
+ // put a history chunk in the output
+ // a history chunk shows what version of the tool
+ // was run on the file with what command-line
+ // parameters
+ outChunk->AppendSubChunk(Param->HistoryChunk());
+ sameFile = true;
+ }
+
+ if( outChunk == 0 )
+ {
+ printf( "Unable to create output chunk.\n" );
+ exit( -1 );
+ }
+ for( inChunkIndex = 0; inChunkIndex < inChunk->SubChunkCount(); inChunkIndex++ )
+ {
+ tlDataChunk* sub = inChunk->GetSubChunk( inChunkIndex );
+ if( sub->ID() == Pure3D::Texture::TEXTURE )
+ {
+ bool inAnySet = false;
+ for( int i = 0; i < g_TextureCollectionCount; ++i )
+ {
+ // Theorically a texture can go into multiple sets so go through them all.
+ bool found = false;
+ TextureData* texData = g_TextureCollection[ i ];
+ for( int j = 0; j < texData->m_NumIDs; ++j )
+ {
+ // Look to see if this texture is in this set.
+ if( tlEntity::MakeUID( sub->GetName() ) == texData->m_TextureID[ j ] )
+ {
+ found = true;
+ inAnySet = true;
+ break;
+ }
+ }
+ if( found && ( texData->m_NumIDs > 0 ) )
+ {
+ // This texture has gone into this set chunk. We'll write the
+ //set chunk out at this point so it's roughly in the same place in
+ //file to protect against load order dependency problems.
+ if( texData->m_WritenOut == false )
+ {
+ texData->m_pSetChunk->SetChildCount( texData->m_NumIDs );
+ outChunk->AppendSubChunk( texData->m_pSetChunk );
+ texData->m_WritenOut = true; // Only write it once.
+ }
+ }
+ }
+ if( !inAnySet )
+ {
+ // This isn't a texture we're interested in so write it out.
+ outChunk->AppendSubChunk( sub );
+ }
+ }
+ else if( sub->ID() == Pure3D::Animation::FrameControllerData::FRAME_CONTROLLER )
+ {
+ // This is a frame controller. If it's one we've used then don't include it.
+ bool found = false;
+ TLUID controllerID = tlEntity::MakeUID( sub->GetName() );
+ for( int i = 0; i < g_TextureCollectionCount; ++i )
+ {
+ if( controllerID == g_TextureCollection[ i ]->m_ControllerChunk )
+ {
+ found = true;
+ break;
+ }
+ }
+ if( !found )
+ {
+ outChunk->AppendSubChunk( sub );
+ }
+ }
+ else if( sub->ID() == Pure3D::Animation::AnimationData::ANIMATION )
+ {
+ // This is an animation. If it's one we've used then don't include it.
+ bool found = false;
+ TLUID animID = tlEntity::MakeUID( sub->GetName() );
+ for( int i = 0; i < g_TextureCollectionCount; ++i )
+ {
+ if( animID == g_TextureCollection[ i ]->m_AnimationChunk )
+ {
+ found = true;
+ break;
+ }
+ }
+ if( !found )
+ {
+ outChunk->AppendSubChunk( sub );
+ }
+ }
+ else if( sub->ID() == P3D_MULTI_CONTROLLER )
+ {
+ // This is a multicontroller. If a track references an framecontroller we
+ //used then exclude that track.
+ tlMultiControllerChunk16* multiCont = static_cast<tlMultiControllerChunk16*>( sub );
+ for( int subIndex = 0; subIndex < multiCont->SubChunkCount(); ++subIndex )
+ {
+ tlDataChunk* subChunk = multiCont->GetSubChunk( subIndex );
+ if( subChunk->ID() == P3D_MULTI_CONTROLLER_TRACKS )
+ {
+ tlMultiControllerTracksChunk16* tracks = static_cast<tlMultiControllerTracksChunk16*>( subChunk );
+ unsigned long numTracks = tracks->GetNumTracks();
+ tlMultiControllerTrackData* trackArray = tracks->GetTracks();
+ for( int i = 0; i < numTracks; ++i )
+ {
+ TLUID trackID = tlEntity::MakeUID( trackArray[ i ].name );
+ for( int j = 0; j < g_TextureCollectionCount; ++j )
+ {
+ if( trackID == g_TextureCollection[ j ]->m_ControllerChunk )
+ {
+ // Remove this track.
+ --numTracks;
+ tracks->SetNumTracks( numTracks );
+ multiCont->SetNumTracks( multiCont->GetNumTracks() - 1 );
+ if( i < numTracks )
+ {
+ trackArray[ i ] = trackArray[ numTracks ];
+ --i;
+ }
+ }
+ }
+ }
+ }
+ else if( subChunk->ID() == P3D_MULTI_CONTROLLER_TRACK )
+ {
+ tlMultiControllerTrackChunk16* track = static_cast<tlMultiControllerTrackChunk16*>( subChunk );
+ TLUID trackID = tlEntity::MakeUID( track->GetName() );
+ for( int i = 0; i < g_TextureCollectionCount; ++i )
+ {
+ if( trackID == g_TextureCollection[ i ]->m_ControllerChunk )
+ {
+ multiCont->RemoveSubChunk( subIndex );
+ multiCont->SetNumTracks( multiCont->GetNumTracks() - 1 );
+ }
+ }
+ }
+ }
+ outChunk->AppendSubChunk( sub );
+ }
+ else
+ {
+ outChunk->AppendSubChunk( sub );
+ }
+ }
+ outChunk->Write( output );
+ delete outChunk;
+ outChunk = 0;
+ if( Param->OutputFile == 0 )
+ {
+ // We have multiple output files so get rid of the
+ //the output file now.
+ delete output;
+ output = 0;
+ }
+ for( i = 0; i < g_TextureCollectionCount; ++i )
+ {
+ delete g_TextureCollection[ i ];
+ g_TextureCollection[ i ] = 0;
+ }
+ } // end of main for loop
+
+ delete Param;
+ return 0;
+}