
// Milkshape Exporter
// bkenwright@xbdev.net

// cl /LD msRawB.cpp msRawB.def

// Few notes:
// The first two letters of our exporter dll, must be 'ms'...so for example 
// you can have msMyCool.dll, myRawXBDEV.dll etc.
// You usually need a 'def' (definition) file for visual studio, as it uses 
// __stdcall, so it decorates the exported function name...by using 
// a def file, you stop this!


#include <string.h> // Needed for strcpy(..)
#include <stdio.h>  // for fopen and fprint etc



// msRawB.def
/*
LIBRARY "msRawB"

EXPORTS
   CreatePlugIn
*/


//--------------------------------------------------------------------------


/**********************************************************************
 *
 * Constants
 *
 **********************************************************************/

#define MS_MAX_NAME             32
#define MS_MAX_PATH             256



/**********************************************************************
 *
 * Types
 *
 **********************************************************************/
#pragma pack(1)

#ifndef byte
typedef unsigned char byte;
#endif /* byte */

#ifndef word
typedef unsigned short word;
#endif /* word */

typedef float   msVec4[4];
typedef float   msVec3[3];
typedef float   msVec2[2];

/* msFlag */
typedef enum {
    eSelected = 1, eSelected2 = 2, eHidden = 4, eDirty = 8, 
		eAveraged = 16, eUnused = 32
} msFlag;

/* msVertex */
typedef struct msVertex
{
    byte        nFlags;
    msVec3      Vertex;
    float       u, v;
    char        nBoneIndex;
} msVertex;

/* msTriangle */
typedef struct
{
    word        nFlags;
    word        nVertexIndices[3];
    word        nNormalIndices[3];
    msVec3      Normal;
    byte        nSmoothingGroup;
} msTriangle;

/* msMesh */
typedef struct msMesh
{
    byte        nFlags;
    char        szName[MS_MAX_NAME];
    char        nMaterialIndex;
    
    word        nNumVertices;
    word        nNumAllocedVertices;
    msVertex*   pVertices;

    word        nNumNormals;
    word        nNumAllocedNormals;
    msVec3*     pNormals;

    word        nNumTriangles;
    word        nNumAllocedTriangles;
    msTriangle* pTriangles;
} msMesh;

/* msMaterial */
typedef struct msMaterial
{
    int         nFlags;
    char        szName[MS_MAX_NAME];
    msVec4      Ambient;
    msVec4      Diffuse;
    msVec4      Specular;
    msVec4      Emissive;
    float       fShininess;
    float       fTransparency;
    char        szDiffuseTexture[MS_MAX_PATH];
    char        szAlphaTexture[MS_MAX_PATH];
    int         nName;
} msMaterial;

/* msPositionKey */
typedef struct msPositionKey
{
    float       fTime;
    msVec3      Position;
} msPositionKey;

/* msRotationKey */
typedef struct msRotationKey
{
    float   fTime;
    msVec3  Rotation;
} msRotationKey;

/* msBone */
typedef struct msBone
{
    int             nFlags;
    char            szName[MS_MAX_NAME];
    char            szParentName[MS_MAX_NAME];
    msVec3          Position;
    msVec3          Rotation;

    int             nNumPositionKeys;
    int             nNumAllocedPositionKeys;
    msPositionKey*  pPositionKeys;

    int             nNumRotationKeys;
    int             nNumAllocedRotationKeys;
    msRotationKey*  pRotationKeys;
} msBone;

/* msModel */
typedef struct msModel
{
    int         nNumMeshes;
    int         nNumAllocedMeshes;
    msMesh*     pMeshes;

    int         nNumMaterials;
    int         nNumAllocedMaterials;
    msMaterial* pMaterials;

    int         nNumBones;
    int         nNumAllocedBones;
    msBone*     pBones;

    int         nFrame;
    int         nTotalFrames;

    msVec3      Position;
    msVec3      Rotation;
} msModel;

#pragma pack()

// ----------------------------------------------------------------------------


class cMsPlugIn
{
public:
    enum
    {
        eTypeImport  = 1,
        eTypeExport  = 2,
        eTypeTool    = 3,
	eTypeEdit    = 4,
	eTypeVertex  = 5,
	eTypeFace    = 6,
	eTypeAnimate = 7
    };

public:
    cMsPlugIn () {};
    virtual ~cMsPlugIn () {};

public:
    virtual int             GetType () = 0;
    virtual const char *    GetTitle () = 0;
    virtual int             Execute (msModel* pModel) = 0;
};



// -----------------------------------------------------------------------


class MyPlugin : public cMsPlugIn
{
public:
   MyPlugin()
   {
      strcpy(szTitle, "www.xbdev.net - Custom Raw Exporter");
   }

   virtual ~MyPlugin() { }

   // Do we want an exporter or a tool?..hmmm, well we decide that here
   int GetType()
   {
      return cMsPlugIn::eTypeExport;
   }

   const char *GetTitle()
   {
      return szTitle;
   }

   int Execute(msModel *);

private:
   char szTitle[64];
};


int MyPlugin::Execute( msModel * pModel )
{
   if (!pModel) return -1;

    // Export our data from here on

    // Default File Location is C drive, with a default name of "raw.txt"
    char szFile[] = "C:\\raw.txt";
    FILE *file = fopen (szFile, "wt");
    if (!file)
        return -1;

    int nNumMeshes = pModel->nNumMeshes;
    fprintf(file, "nNumMeshes %d\n", nNumMeshes);

    msMesh * pMeshes = pModel->pMeshes;
    for(int i=0; i<nNumMeshes; i++)
    {
       fprintf(file, "Mesh: %d\n", i);

       fprintf(file, "szName: %s\n", pMeshes[i].szName);
       fprintf(file, "nNumVertices: %d\n",pMeshes[i].nNumVertices);

       for(int j=0; j< pMeshes[i].nNumVertices; j++)
       {
          msVertex * pVertices = pMeshes[i].pVertices;
          fprintf(file, "x:%f, y:%f, z:%f\n", 
               pVertices->Vertex[0], 
               pVertices->Vertex[1], 
               pVertices->Vertex[2] );
          
       }//End inner for loop
    }//End outer for loop
    

    fclose(file);

    // We should destroy pModel here as well
    return 0;
}



cMsPlugIn *CreatePlugIn()
{
   return new MyPlugin;
}

