/* MultiGen Creator Peo File Exporter. Created by Badger 2/10/00 */ #include #include #include #include #include #include #include "mgapiall.h" #include "resource.h" #define BLANK_BYTE 171 static FILE *fd; static int currentVertex; static int totalVertices; static int totalNormals; static int totalPolys; long nameOffset; int lastChildOffset; typedef struct { char names[200][50]; int numOfNames; int offset; } namestruct; typedef struct { char identifier[8]; int version; int nameoffset; // file name offset int filesize; int localsize; int nPublicMaterials; int nLocalMaterials; int oPublicMaterials; int oLocalMaterials; int nPolygonObjects; } header; typedef struct { int nameoffset; unsigned char ambient[4]; unsigned char diffuse[4]; unsigned char specular[4]; float kAlpha; // not used int textureOffset; unsigned short flags; char numOfIllumColors; char textureRegistered; //internal int textureNameRegistered; // internal } materialentry; typedef struct { int NormalIndex; unsigned short iV0; unsigned short iV1; unsigned short iV2; unsigned short MaterialIndex; float s0; float t0; float s1; float t1; float s2; float t2; unsigned short flags; unsigned short reserved;// two reserved bytes; } polyentry; typedef struct { float x; float y; float z; int normalIndex; } vertexentry; typedef struct { float x; float y; float z; int reserved; // 4 reserved bytes } normalentry; typedef struct { int nameoffset; char nodename[30]; char flags; // some sort of object flag, 1 byte unsigned short crcname; // 16bit crc of name; int nPolygons; int vertexOffset; int normalOffset; int polylistOffset; int pMother; int pDaughter; int pSister; float localMatrix[16]; int numOfVertices; int numOfNormals; vertexentry vertexList[1000]; normalentry normalList[1000]; polyentry *polyList[1000]; } polyobject; typedef struct { int numOfPolys; int numOfMaterials; int numOfPolyObjects; header Header; polyobject polyObjects[50]; materialentry *materials[50]; namestruct nameRecord; } main_struct_; static main_struct_ *mainStruct; static namestruct writtenNames; /*============================================================================*\ GUI Functions \*============================================================================*/ static int addToMaterialNames( char *string ) { int i; for (i=0; inameRecord.numOfNames; i++ ) { if ( !strcmp( string, mainStruct->nameRecord.names[i] )) return( i ); } strcpy( mainStruct->nameRecord.names[mainStruct->nameRecord.numOfNames], string ); mainStruct->nameRecord.numOfNames++; return( mainStruct->nameRecord.numOfNames-1 ); } static int writeName( char *string ) { long oldPosition = ftell( fd ); long newPosition = 0; int i; for (i=0; inumOfMaterials; i++ ) // find if already present { if ( ( mainStruct->materials[i]->ambient[0] == Mat.ambient[0] ) && ( mainStruct->materials[i]->ambient[1] == Mat.ambient[1] ) && ( mainStruct->materials[i]->ambient[2] == Mat.ambient[2] ) && ( mainStruct->materials[i]->diffuse[0] == Mat.diffuse[0] ) && ( mainStruct->materials[i]->diffuse[1] == Mat.diffuse[1] ) && ( mainStruct->materials[i]->diffuse[2] == Mat.diffuse[2] ) && ( mainStruct->materials[i]->specular[0] == Mat.specular[0] ) && ( mainStruct->materials[i]->specular[1] == Mat.specular[1] ) && ( mainStruct->materials[i]->specular[2] == Mat.specular[2] ) && ( mainStruct->materials[i]->textureOffset == Mat.textureOffset ) && ( mainStruct->materials[i]->flags == Mat.flags )) { current = i; } } if ( current == -1 ) // add new entry { mgSendMessage ( MMSG_STATUS, " creating new material %d %d", mainStruct->numOfMaterials, Mat.textureOffset ); mainStruct->materials[mainStruct->numOfMaterials] = (materialentry*) mgMalloc ( sizeof(materialentry) ); mainStruct->materials[mainStruct->numOfMaterials]->ambient[0] = Mat.ambient[0]; mainStruct->materials[mainStruct->numOfMaterials]->ambient[1] = Mat.ambient[1]; mainStruct->materials[mainStruct->numOfMaterials]->ambient[2] = Mat.ambient[2]; mainStruct->materials[mainStruct->numOfMaterials]->diffuse[0] = Mat.diffuse[0]; mainStruct->materials[mainStruct->numOfMaterials]->diffuse[1] = Mat.diffuse[1]; mainStruct->materials[mainStruct->numOfMaterials]->diffuse[2] = Mat.diffuse[2]; mainStruct->materials[mainStruct->numOfMaterials]->specular[0] = Mat.specular[0]; mainStruct->materials[mainStruct->numOfMaterials]->specular[1] = Mat.specular[1]; mainStruct->materials[mainStruct->numOfMaterials]->specular[2] = Mat.specular[2]; mainStruct->materials[mainStruct->numOfMaterials]->textureOffset = Mat.textureOffset; mainStruct->materials[mainStruct->numOfMaterials]->flags = Mat.flags; index = mainStruct->numOfMaterials; mainStruct->numOfMaterials++; } else index = current; return( index ); } static int addToNormalList( normalentry Norm, polyobject *PO ) { int i = 0; int index = 0; int current = -1; for ( i=0; inumOfNormals; i++ ) // find if already present { if (( PO->normalList[i].x == Norm.x ) && ( PO->normalList[i].y == Norm.y ) && ( PO->normalList[i].z == Norm.z )) current = i; } if ( current == -1 ) // add new entry { PO->numOfNormals++; PO->normalList[PO->numOfNormals-1].x = Norm.x; PO->normalList[PO->numOfNormals-1].y = Norm.y; PO->normalList[PO->numOfNormals-1].z = Norm.z; index = PO->numOfNormals-1; totalNormals++; } else index = current; return( index ); } static int addToVertexList( vertexentry Vert, polyobject *PO ) { int i = 0; int index = 0; int current = -1; for ( i=0; inumOfVertices; i++ ) // find if already present { if (( PO->vertexList[i].x == Vert.x ) && ( PO->vertexList[i].y == Vert.y ) && ( PO->vertexList[i].z == Vert.z )) current = i; } if ( current == -1 ) // add new entry { PO->numOfVertices++; PO->vertexList[PO->numOfVertices-1].x = Vert.x; PO->vertexList[PO->numOfVertices-1].y = Vert.y; PO->vertexList[PO->numOfVertices-1].z = Vert.z; PO->vertexList[PO->numOfVertices-1].normalIndex = Vert.normalIndex; index = PO->numOfVertices-1; totalVertices++; } else index = current; return( index ); } static void computeFaceNormals( void ) { float tempvec[3]; normalentry facenormal; int i, j; polyentry *poly; vertexentry *v1, *v2, *v3; float dist; for ( i=0; inumOfPolyObjects; i++ ) { for ( j=0; jpolyObjects[i].nPolygons; j++ ) { poly = mainStruct->polyObjects[i].polyList[j]; v1 = &mainStruct->polyObjects[i].vertexList[poly->iV0]; v2 = &mainStruct->polyObjects[i].vertexList[poly->iV1]; v3 = &mainStruct->polyObjects[i].vertexList[poly->iV2]; tempvec[0] = v1->x + v2->x + v3->x; tempvec[1] = v1->y + v2->y + v3->y; tempvec[2] = v1->z + v2->z + v3->z; dist = (float)sqrt(( tempvec[0]*tempvec[0] )+( tempvec[1]*tempvec[1] )+( tempvec[2]*tempvec[2] )); facenormal.x = tempvec[0]/dist; facenormal.y = tempvec[1]/dist; facenormal.z = tempvec[2]/dist; poly->NormalIndex = addToNormalList( facenormal, &mainStruct->polyObjects[i] ); } } } static void readFltVertex( mgrec* rec ) { polyobject *PO; polyentry *PE; vertexentry VE; normalentry NE; mgcoord3d pnt1; int index; float heading, pitch, roll; float u_coord, v_coord; u_coord = 0; v_coord = 0; PO = &mainStruct->polyObjects[ mainStruct->numOfPolyObjects-1 ]; PE = PO->polyList[PO->nPolygons-1]; mgGetCoord3d ( rec, fltCoord3d, &pnt1.x, &pnt1.y, &pnt1.z ); mgGetVector ( rec, fltVNormal, &heading, &pitch, &roll ); mgGetAttList( rec, fltVU, &u_coord, fltVV, &v_coord, MG_NULL ); NE.x = heading; NE.y = pitch; NE.z = roll; v_coord = v_coord*-1.0f; // VE.normalIndex = addToNormalList( NE, PO ); VE.normalIndex = 0; VE.x = (float)pnt1.x; VE.y = (float)pnt1.y; VE.z = (float)pnt1.z; if ( currentVertex == 0 ) { PE->iV0 = addToVertexList( VE, PO ); PE->s0 = u_coord; PE->t0 = v_coord; currentVertex++; index = PE->iV0; } else if ( currentVertex == 1 ) { PE->iV1 = addToVertexList( VE, PO ); PE->s1 = u_coord; PE->t1 = v_coord; currentVertex++; index = PE->iV1; } else if ( currentVertex == 2 ) { PE->iV2 = addToVertexList( VE, PO ); PE->s2 = u_coord; PE->t2 = v_coord; currentVertex++; index = PE->iV2; } // mgSendMessage ( MMSG_STATUS, " U coord %f V coord %f ", u_coord, v_coord ); // mgSendMessage ( MMSG_STATUS, "Finished Vertex %s %lf %lf %lf index %d", // mgGetName(rec), VE.x, VE.y, VE.z, index); // mgSendMessage ( MMSG_STATUS, "Finished Normal %s %lf %lf %lf index %d", // mgGetName(rec), heading, pitch, roll, VE.normalIndex ); } static void readFltPolygon( mgrec* rec, mgrec* db_rec ) { polyobject *PO; polyentry *PE; short polyTexture; char *tname; char *pos; materialentry Mat; int pcolor; short r, g, b; float pintens; char drawtype; PO = &mainStruct->polyObjects[ mainStruct->numOfPolyObjects-1 ]; PO->nPolygons++; PO->polyList[PO->nPolygons-1] = (polyentry*) mgMalloc ( sizeof(polyentry) ); if ( PO->polyList[PO->nPolygons-1] == NULL ) { mgSendMessage ( MMSG_STATUS, "polygon entry not allocated" ); return; } PE = PO->polyList[PO->nPolygons-1]; mgGetAttList( rec, fltPolyTexture, &polyTexture, fltPolyPrimeColor, &pcolor, fltPolyPrimeIntensity, &pintens, fltPolyDrawType, &drawtype, MG_NULL ); tname = mgGetTextureName(db_rec, polyTexture); mgIndex2RGB ( db_rec, pcolor, pintens, &r, &g, &b ); pos = strrchr( tname, '.' ); if ( pos != NULL ) *pos = 0; pos = strrchr( tname, '/' ); if ( pos != NULL ) tname = pos+1; // mgSendMessage ( MMSG_STATUS, "texture is %hd name %s", polyTexture, tname ); // mgSendMessage ( MMSG_STATUS, "color is %hd %hd %hd ", r, g, b ); Mat.ambient[0] = r; Mat.ambient[1] = g; Mat.ambient[2] = b; Mat.ambient[3] = 0; Mat.diffuse[0] = r; Mat.diffuse[1] = g; Mat.diffuse[2] = b; Mat.diffuse[3] = 0; Mat.specular[0] = 0; Mat.specular[1] = 0; Mat.specular[2] = 0; Mat.specular[3] = 0; Mat.textureOffset = addToMaterialNames( tname ); Mat.flags = 0; if ( drawtype == 1 ) Mat.flags = 8; // two sided polys // mgSendMessage ( MMSG_STATUS, "material is %d", Mat.flags ); PE->flags = 0; PE->iV0 = 0; PE->iV1 = 0; PE->iV2 = 0; PE->MaterialIndex = addToMaterialList( Mat, PO ); PE->NormalIndex = 0; PE->s0 = 0.0f; PE->t0 = 0.0f; PE->s1 = 0.0f; PE->t1 = 0.0f; PE->s2 = 0.0f; PE->t2 = 0.0f; PE->reserved = 0; currentVertex = 0; totalPolys++; } static void readFltObject( mgrec* rec ) { polyobject *PO; mgrec* xForm; mgxfllcode xType; mgmatrix matrix; PO = &mainStruct->polyObjects[ mainStruct->numOfPolyObjects ]; strcpy( PO->nodename, mgGetName(rec) ); PO->nameoffset = 1026; PO->flags = 2; PO->nPolygons = 0; PO->vertexOffset = 0; PO->normalOffset = 0; PO->polylistOffset = 0; PO->numOfVertices = 0; PO->numOfNormals = 0; PO->pMother = 0; PO->pDaughter = 0; PO->pSister = 0; PO->localMatrix[0] = 1.0f; PO->localMatrix[1] = 0.0f; PO->localMatrix[2] = 0.0f; PO->localMatrix[3] = 0.0f; PO->localMatrix[4] = 0.0f; PO->localMatrix[5] = 1.0f; PO->localMatrix[6] = 0.0f; PO->localMatrix[7] = 0.0f; PO->localMatrix[8] = 0.0f; PO->localMatrix[9] = 0.0f; PO->localMatrix[10] = 1.0f; PO->localMatrix[11] = 0.0f; PO->localMatrix[12] = 0.0f; PO->localMatrix[13] = 0.0f; PO->localMatrix[14] = 0.0f; PO->localMatrix[15] = 1.0f; if ( mgHasXform ( rec ) ) { xForm = mgGetXform ( rec ); xType = mgGetXformType ( xForm ); xType = mgGetXformType ( xForm ); if ( xType == MXLL_PUT ) { mgSendMessage ( MMSG_STATUS, "Obj \"%s\" has put matrix ", mgGetName(rec) ); mgGetAttBuf ( rec, fltMatrix, &matrix ); // mgSendMessage ( MMSG_STATUS, "Obj \"%s\" m0 %lf m1 %lf m2 %lf", // mgGetName(rec), matrix[0], matrix[1], matrix[2] ); PO->localMatrix[0] = (float)matrix[0]; PO->localMatrix[1] = (float)matrix[1]; PO->localMatrix[2] = (float)matrix[2]; PO->localMatrix[3] = (float)matrix[3]; PO->localMatrix[4] = (float)matrix[4]; PO->localMatrix[5] = (float)matrix[5]; PO->localMatrix[6] = (float)matrix[6]; PO->localMatrix[7] = (float)matrix[7]; PO->localMatrix[8] = (float)matrix[8]; PO->localMatrix[9] = (float)matrix[9]; PO->localMatrix[10] = (float)matrix[10]; PO->localMatrix[11] = (float)matrix[11]; PO->localMatrix[12] = (float)matrix[12]; PO->localMatrix[13] = (float)matrix[13]; PO->localMatrix[14] = (float)matrix[14]; PO->localMatrix[15] = (float)matrix[15]; } } if ( mainStruct->numOfPolyObjects == 1 ) mainStruct->polyObjects[ mainStruct->numOfPolyObjects-1 ].pDaughter = 180; if ( mainStruct->numOfPolyObjects > 0 ) PO->pMother = 68; if ( mainStruct->numOfPolyObjects > 1 ) mainStruct->polyObjects[ mainStruct->numOfPolyObjects-1 ].pSister = 68+(112*mainStruct->numOfPolyObjects); mainStruct->numOfPolyObjects++; mgSendMessage ( MMSG_STATUS, "Loaded Obj \"%s\"", mgGetName(rec) ); } static mgbool preVisitEachNode( mgrec* db_rec, mgrec* par_rec, mgrec* rec, void* id ) { char *name; name = mgGetName( rec ); if ( mgIsCode( rec, fltObject ) ) { readFltObject( rec ); } else if ( mgIsCode( rec, fltPolygon ) ) { readFltPolygon( rec, db_rec ); } else if ( mgIsCode( rec, fltVertex ) ) { readFltVertex( rec ); } mgFree( name ); return( MG_TRUE ); } static void writeNormalList( void ) { int i, j; long position = 0; for ( i=0; inumOfPolyObjects; i++ ) { position = ftell( fd ); mainStruct->polyObjects[i].normalOffset = position; for (j=0; jpolyObjects[i].numOfNormals; j++ ) fwrite( &mainStruct->polyObjects[i].normalList[j], sizeof( normalentry ), 1, fd ); } mgSendMessage ( MMSG_STATUS, "Written Normals " ); } static void writeVertexList( void ) { int i, j; long position = 0; vertexentry *entry; for ( i=0; inumOfPolyObjects; i++ ) { position = ftell( fd ); mainStruct->polyObjects[i].vertexOffset = position; for (j=0; jpolyObjects[i].numOfVertices; j++ ) { entry = &mainStruct->polyObjects[i].vertexList[j]; fwrite( entry, sizeof( vertexentry ), 1, fd ); } } mgSendMessage ( MMSG_STATUS, "Written Vertices " ); } static void writeMaterials( void ) { int i; mainStruct->Header.oPublicMaterials = ftell( fd ); mainStruct->Header.oLocalMaterials = ftell( fd ); for ( i=0; inumOfMaterials; i++ ) { /* mainStruct->materials[i] = (materialentry*) mgMalloc ( sizeof(materialentry) ); mainStruct->materials[i]->ambient[0] = 50; mainStruct->materials[i]->ambient[1] = 50; mainStruct->materials[i]->ambient[2] = 50; mainStruct->materials[i]->ambient[3] = 0; mainStruct->materials[i]->diffuse[0] = 200; mainStruct->materials[i]->diffuse[1] = 200; mainStruct->materials[i]->diffuse[2] = 200; mainStruct->materials[i]->diffuse[3] = 0; mainStruct->materials[i]->specular[0] = 0; mainStruct->materials[i]->specular[1] = 0; mainStruct->materials[i]->specular[2] = 0; mainStruct->materials[i]->specular[3] = 0; mainStruct->materials[i]->kAlpha = 0.0f; mainStruct->materials[i]->textureOffset; mainStruct->materials[i]->flags = 0; */ mgSendMessage ( MMSG_STATUS, "ambient out %hd %hd %hd %hd", mainStruct->materials[i]->ambient[0], mainStruct->materials[i]->ambient[1], mainStruct->materials[i]->ambient[2], mainStruct->materials[i]->ambient[3]); mainStruct->materials[i]->textureOffset = writeName( mainStruct->nameRecord.names[mainStruct->materials[i]->textureOffset] ); fwrite( mainStruct->materials[i], sizeof( materialentry ), 1, fd ); } } static void writePolygon( polyentry *poly ) { fwrite( poly, sizeof( polyentry ), 1, fd ); } static void writePolygons( void ) { int i, j; long position = 0; for ( i=0; inumOfPolyObjects; i++ ) { position = ftell( fd ); mainStruct->polyObjects[i].polylistOffset = position; for ( j=0; jpolyObjects[i].nPolygons; j++ ) writePolygon( mainStruct->polyObjects[i].polyList[j] ); } mgSendMessage ( MMSG_STATUS, "Written Polygons " ); } static void writePolygonObjects( void ) { int i, j; for ( i=0; inumOfPolyObjects; i++ ) { mainStruct->polyObjects[i].nameoffset = writeName( mainStruct->polyObjects[i].nodename ); _putw( mainStruct->polyObjects[i].nameoffset, fd ); fputc( 0, fd ); // internal use 4 bytes fputc( 0, fd ); fputc( 0, fd ); fputc( 0, fd ); _putw( mainStruct->polyObjects[i].numOfVertices, fd ); _putw( mainStruct->polyObjects[i].numOfNormals, fd ); // face normals _putw( 0, fd ); // vertex normals _putw( mainStruct->polyObjects[i].nPolygons, fd ); _putw( mainStruct->polyObjects[i].vertexOffset, fd ); _putw( mainStruct->polyObjects[i].normalOffset, fd ); _putw( mainStruct->polyObjects[i].polylistOffset, fd ); _putw( mainStruct->polyObjects[i].pMother, fd ); _putw( mainStruct->polyObjects[i].pDaughter, fd ); _putw( mainStruct->polyObjects[i].pSister, fd ); for (j=0; j<16; j++ ) fwrite( &mainStruct->polyObjects[i].localMatrix[j], sizeof(float), 1, fd ); mgSendMessage ( MMSG_STATUS, "Written Polygonobject \"%d\"", mainStruct->polyObjects[i].numOfVertices); } } static void writeHeader( void ) { int i = 0; mainStruct->Header.identifier[0] = 'R'; mainStruct->Header.identifier[1] = 'M'; mainStruct->Header.identifier[2] = 'F'; mainStruct->Header.identifier[3] = '9'; mainStruct->Header.identifier[4] = '9'; mainStruct->Header.identifier[5] = 'b'; mainStruct->Header.identifier[6] = 'a'; mainStruct->Header.identifier[7] = 0; mainStruct->Header.version = 1026; mainStruct->Header.nameoffset = 0; mainStruct->Header.filesize = nameOffset; mainStruct->Header.localsize = 0; mainStruct->Header.nPublicMaterials = mainStruct->numOfMaterials; mainStruct->Header.nLocalMaterials = 0; mainStruct->Header.nPolygonObjects = mainStruct->numOfPolyObjects; fputc( mainStruct->Header.identifier[0], fd ); fputc( mainStruct->Header.identifier[1], fd ); fputc( mainStruct->Header.identifier[2], fd ); fputc( mainStruct->Header.identifier[3], fd ); fputc( mainStruct->Header.identifier[4], fd ); fputc( mainStruct->Header.identifier[5], fd ); fputc( mainStruct->Header.identifier[6], fd ); fputc( mainStruct->Header.identifier[7], fd ); _putw( mainStruct->Header.version, fd ); _putw( mainStruct->Header.nameoffset, fd ); _putw( mainStruct->Header.filesize, fd ); _putw( mainStruct->Header.localsize, fd ); _putw( mainStruct->Header.nPublicMaterials, fd ); _putw( mainStruct->Header.nLocalMaterials, fd ); _putw( mainStruct->Header.oPublicMaterials, fd ); _putw( mainStruct->Header.oLocalMaterials, fd ); _putw( mainStruct->Header.nPolygonObjects, fd ); for (i=0; i<24; i++ ) fputc( BLANK_BYTE, fd ); mgSendMessage ( MMSG_STATUS, "Written Header " ); } static mgstatus StartWritePeo ( mgplugintool pluginTool, void *userData, void *callData ) { mgexportercallbackrec* cbData = (mgexportercallbackrec*) callData; mgresource resource = (mgresource) userData; mgrec* db = mgGetActivationDb (cbData->toolActivation); char *filename = cbData->fileName; mainStruct = (main_struct_*) mgMalloc ( sizeof(main_struct_) ); if ( mainStruct == NULL ) { mgSendError ( pluginTool, "mainStruct not allocated" ); return(MSTAT_OK); } mainStruct->numOfPolys = 0; mainStruct->numOfMaterials = 0; mainStruct->numOfPolyObjects = 0; mainStruct->nameRecord.numOfNames = 0; writtenNames.numOfNames = 0; totalVertices = 0; totalNormals = 0; totalPolys = 0; lastChildOffset = 0; if ( ( fd = fopen ( filename, "wb" ) ) == NULL ) { mgSendError ( pluginTool, "Cannot create \"%s\"", filename ); return(MSTAT_OK); } mgWalk( db, preVisitEachNode, MG_NULL, MG_NULL, MWALK_VERTEX ); computeFaceNormals(); nameOffset = 68+(112*mainStruct->numOfPolyObjects)+ (16*totalVertices)+(16*totalNormals)+(40*totalPolys)+(32*mainStruct->numOfMaterials); // skip bytes for the rest of the file header+numObjects*objsize fseek( fd, (68+(112*mainStruct->numOfPolyObjects)), SEEK_SET ); mgSendMessage ( MMSG_STATUS, "begin verts at \"%ld\"", ftell( fd )); writeVertexList(); mgSendMessage ( MMSG_STATUS, "begin normals at \"%ld\"", ftell( fd )); writeNormalList(); mgSendMessage ( MMSG_STATUS, "begin polygons at \"%ld\"", ftell( fd )); writePolygons(); mgSendMessage ( MMSG_STATUS, "end polygons at \"%ld\"", ftell( fd )); writeMaterials(); mgSendMessage ( MMSG_STATUS, "end materials at \"%ld\"", ftell( fd )); fseek( fd, 68, SEEK_SET ); mgSendMessage ( MMSG_STATUS, "begin poly object at \"%ld\"", ftell( fd )); writePolygonObjects(); mgSendMessage ( MMSG_STATUS, "end poly object at \"%ld\"", ftell( fd )); fseek( fd, 0, SEEK_SET ); mgSendMessage ( MMSG_STATUS, "Setting position at \"%ld\"", ftell( fd )); // dont forget to get the filesize writeHeader(); fclose( fd ); mgSendMessage ( MMSG_STATUS, "Written file <%s>", filename); return (MSTAT_OK); } mgbool InitWritePeo ( mgplugin plugin, mgresource resource, int* argc, char* argv [] ) { mgplugintool pluginTool; pluginTool = mgRegisterExporter ( plugin, "Write Peo", StartWritePeo, MG_NULL, MTA_VERSION, "1.0", MTA_FILTER, "*.peo", MTA_FILETYPE, "Homeworld Peo Files", MG_NULL ); return ( pluginTool ? MG_TRUE : MG_FALSE ); } void ExitWritePeo ( mgplugin plugin ) { }