reman3/Rayman_X/cpa/Appli/ModExp/ModExp.cpp

681 lines
15 KiB
C++

/**********************************************************************
DESCRIPTION: .MOD file export
CREATED BY: Boujemaa
**********************************************************************/
#include "StdAfx.h"
#include "resource.h"
#include "ModExp.h"
#include "modobject.h"
HINSTANCE hInstance;
int controlsInit = FALSE;
CModExport* g_Eporter = NULL;
TCHAR* GetString(int id)
{
static TCHAR stBuf[ERROR_MSG_MAX_LEN];
if (hInstance)
return LoadString(hInstance, id, stBuf, ERROR_MSG_MAX_LEN) ? stBuf : NULL;
return NULL;
}
static int Alert(int s1, int s2 = IDS_MODEXP, int option = MB_OK) {
return MessageBox(g_Eporter->m_Gi->GetMAXHWnd(), GetString(s1), GetString(s2), option);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved) {
// Hang on to this DLL's instance handle.
hInstance = hinstDLL;
if ( !controlsInit ) {
controlsInit = TRUE;
// Initialize 3ds Max's custom controls
InitCustomControls(hInstance);
// Initialize Windows controls
InitCommonControls();
}
return(TRUE);
}
static CModExpClassDesc _ModExpDesc;
__declspec( dllexport ) const TCHAR * LibDescription() {
return GetString(IDS_MODEXPDLL);
}
__declspec( dllexport ) int
LibNumberClasses()
{
return 1;
}
__declspec( dllexport ) ClassDesc *
LibClassDesc(int i)
{
switch(i) {
case 0: return &_ModExpDesc; break;
default: return 0; break;
}
}
// Return version so can detect obsolete DLLs
__declspec( dllexport ) ULONG LibVersion()
{
return VERSION_3DSMAX;
}
inline const TCHAR* CModExpClassDesc::Category()
{
return GetString(IDS_SCENEEXPORT);
}
inline SClass_ID CModExpClassDesc::SuperClassID()
{
return SCENE_EXPORT_CLASS_ID;
}
inline Class_ID CModExpClassDesc::ClassID()
{
return Class_ID(0x7d285801, 0x3c7b4aaa);
}
inline const TCHAR * CModExpClassDesc::ClassName()
{
return GetString(IDS_UBIMOD);
}
inline int CModExpClassDesc::IsPublic()
{
return 1;
}
inline void * CModExpClassDesc::Create(BOOL loading)
{
g_Eporter = new CModExport;
return g_Eporter;
}
CModExport::CModExport()
{
m_exportSelected = 0;
m_showPrompts = 1;
m_Gi = NULL;
m_ei = NULL;
}
CModExport::~CModExport()
{
}
int CModExport::GetExportOptions(DWORD _options, BOOL _suppressPrompts)
{
m_showPrompts = _suppressPrompts ? FALSE : TRUE;
m_exportSelected = (_options & SCENE_EXPORT_SELECTED) ? TRUE : FALSE;
return 1;
}
int CModExport::DumpHeader(WorkFile &modFile, BOOL _isSpo)
{
char currentCmd[MAX_MOD_COMMAND_LEN];
{
modFile.OutLine("; (c) Ubi Casablanca");
}
{
char filename[MAX_FILE_NAME];
_splitpath(modFile.GetFileName(), NULL, NULL, filename, NULL);
if (_isSpo)
{
strcat(filename, ".SPO");
sprintf(currentCmd, ";.SPO (graphic Module) : %s", filename);
}
else
{
strcat(filename, ".MOD");
sprintf(currentCmd, ";.MOD (graphic Module) : %s", filename);
}
modFile.SetShortfName(filename);
modFile.OutLine(currentCmd);
}
{
assert(m_Gi != NULL);
sprintf(currentCmd, ";Generated from file %s", m_Gi->GetCurFileName());
modFile.OutLine(currentCmd);
}
{
struct tm *newtime;
time_t aclock;
time( &aclock ); // Get time in seconds
newtime = localtime( &aclock ); // Convert time to struct tm form
/* Print local time as a string */
sprintf( currentCmd, ";Creation date : %s", asctime( newtime ) );
modFile.OutLine(currentCmd);
}
/*
;Version directive, the version number is stored in file result 0
$SetCurrentFileDouble(0,"5.20")
;Unit directive, the unit is stored in file result 1
;And correspond to the value of one unit exprimed in meter
$SetCurrentFileDouble(1,1)
*/
modFile.OutLine(";Version directive, the version number is stored in file result 0");
modFile.OutLine("$SetCurrentFileDouble(0,\"5.20\")\n");
modFile.OutLine(";Unit directive, the unit is stored in file result 1");
modFile.OutLine(";And correspond to the value of one unit exprimed in meter");
modFile.OutLine("$SetCurrentFileDouble(1,1)\n");
return 1;
}
int CModExport::DumpData(WorkFile &_modFile,WorkFile &_spoFile)
{
// Make sure there are nodes we're interested in!
// Ask the scene to enumerate all its nodes so we can determine if there are any we can use
SceneEnumProc myScene(g_Eporter->m_Gi->GetTime());
m_ei->theScene->EnumTree(&myScene);
// Any useful nodes?
if(myScene.Count() == 0)
{
if(m_showPrompts)
Alert(IDS_NODATATOEXPORT);
return 1;
}
myScene.DumpGeoms(_modFile);
myScene.DumpMtls(_modFile);
myScene.DumpRoot(_spoFile);
return 1;
}
int CModExport::ExportFile(const TCHAR *_filename)
{
TSTR LvlName;
TSTR LvlPath;
SplitFilename((TSTR)_filename, &LvlPath, &LvlName, NULL);
strcat(LvlPath, "\\");
strcat(LvlPath, LvlName);
strcat(LvlPath, ".SPO");
WorkFile modFile(_filename,"wt");
WorkFile spoFile(LvlPath,"wt");
DumpHeader(modFile);
DumpHeader(spoFile, true);
DumpData(modFile,spoFile);
return 1;
}
int CModExport::DoExport(const TCHAR *filename,ExpInterface *ei,Interface *gi, BOOL suppressPrompts, DWORD options)
{
int result;
m_Gi = gi;
m_ei = ei;
result = GetExportOptions(options, suppressPrompts);
if (!result)
return 0;
result = ExportFile(filename);
return result;
}
void CModExport::ShowAbout(HWND hWnd)
{
// Optional
}
unsigned int CModExport::Version()
{
// Version number * 100 (i.e. v3.01 = 301)
return 100;
}
int CModExport::ExtCount()
{
return 1;
}
const TCHAR * CModExport::Ext(int n)
{ // Extensions supported for import/export modules
switch(n) {
case 0:
return _T("MOD");
}
return _T("");
}
const TCHAR * CModExport::LongDesc()
{ // Long ASCII description (i.e. "Targa 2.0 Image File")
return GetString(IDS_MODSCENEFILE);
}
const TCHAR * CModExport::ShortDesc()
{ // Short ASCII description (i.e. "Targa")
return GetString(IDS_MODFILE);
}
const TCHAR * CModExport::AuthorName()
{ // ASCII Author name
return GetString(IDS_UBICASA);
}
const TCHAR * CModExport::OtherMessage1()
{ // Other message #1
return _T("");
}
const TCHAR * CModExport::OtherMessage2()
{ // Other message #2
return _T("");
}
const TCHAR * CModExport::CopyrightMessage()
{ // ASCII Copyright message
return GetString(IDS_COPYRIGHT_UBI);
}
void WorkFile::OutLine(char* _txtLine)
{
fprintf(stream, "%s\n", _txtLine);
}
SceneEnumProc::SceneEnumProc(TimeValue time)
{
m_time = time;
m_count = 0;
m_root = new CSuperObject(NULL);
}
SceneEnumProc::~SceneEnumProc()
{
m_GeomList.clear();
m_MatList.clear();
delete m_root;
}
int SceneEnumProc::callback(INode *node)
{
if(g_Eporter->m_exportSelected && node->Selected() == FALSE)
return TREE_CONTINUE;
Append(node);
return TREE_CONTINUE;
}
void SceneEnumProc::Append(INode *_node)
{
if (_node->IsRootNode())
return;
// find parent
INode * Parentnode = _node->GetParentNode();
CSuperObject *ParentSpo;
if (Parentnode->IsRootNode())
ParentSpo = m_root;
else
ParentSpo = m_root->findSpo(Parentnode);
if (ParentSpo == NULL)
{
ParentSpo = m_root;
}
if (ParentSpo == m_root)
{
char NodeName[MAX_NAME_OBJ];
strcpy(NodeName,_node->GetName());
strlwr(NodeName);
if ((NodeName[0] != 's') ||
(NodeName[1] != 'c') ||
(NodeName[2] != 't'))
{
// object not linked to any dumy
assert(0);
return;
}
}
// create sop
CSuperObject *NewSpo = new CSuperObject(_node);
ParentSpo->AddNode(NewSpo);
Object *obj = _node->EvalWorldState(m_time).obj;
if (obj->CanConvertToType(triObjectClassID))
{
m_GeomList.push_back(NewSpo);
m_count ++;
}
}
void SceneEnumProc::AppendMat(Mtl *_mtl)
{
std::list <Mtl *>::iterator Iter;
for ( Iter = m_MatList.begin( ); Iter != m_MatList.end( ); Iter++ )
{
Mtl *current = *Iter;
if (current == _mtl)
{
return;
}
}
m_MatList.push_back(_mtl);
}
void SceneEnumProc::DumpGeoms(WorkFile &modFile)
{
std::list <CSuperObject *>::iterator Iter;
for ( Iter = m_GeomList.begin( ); Iter != m_GeomList.end( ); Iter++ )
{
DumpOneGeom(modFile, *Iter);
}
}
void SceneEnumProc::DumpRoot(WorkFile &_spoFile)
{
m_root->DumpSpo(_spoFile, m_time);
}
void SceneEnumProc::DumpMtls(WorkFile &modFile)
{
std::list <Mtl*>::iterator Iter;
for ( Iter = m_MatList.begin( ); Iter != m_MatList.end( ); Iter++ )
{
DumpOneMtl(modFile, *Iter);
}
}
void SceneEnumProc::DumpOneGeom(WorkFile &modFile, CSuperObject *_node)
{
char currentCmd[MAX_MOD_COMMAND_LEN];
int i = 0;
std::vector <CModElem*>::iterator IterElem;
std::vector <CFace>::iterator IterFace;
std::vector <CUV>::iterator IterUV;
CModObject curObj(_node->m_maxNode, m_time);
if (!curObj.m_ValidObj)
return;
int nbrElems = 0;
for ( IterElem = curObj.m_elements.begin( ); IterElem != curObj.m_elements.end( ); IterElem++ )
{
CModElem* elem = *IterElem;
if (elem->m_Faces.size() != 0)
{
SceneEnumProc::AppendMat(elem->m_material);
nbrElems++;
}
}
// set spo link
sprintf(currentCmd, "Geometric(\"%s^Geometric:%s\")", modFile.GetShortfName(), curObj.m_name);
_node->SetGeomLink(currentCmd);
// geom
sprintf(currentCmd, "{Geometric:%s(%d,0,%d)", curObj.m_name, curObj.m_nbrVrtx, nbrElems);
modFile.OutLine(currentCmd);
// vertxs
for (i = 0; i < curObj.m_Vertxs.size(); i++)
{
sprintf(currentCmd, "\tAddVertex(%d,\"%g\",\"%g\",\"%g\",\"%g\",\"%g\",\"%g\",0,0,0)",
i,
curObj.m_Vertxs[i].x, curObj.m_Vertxs[i].y, curObj.m_Vertxs[i].z,
curObj.m_Vertxs[i].nx, curObj.m_Vertxs[i].ny, curObj.m_Vertxs[i].nz);
modFile.OutLine(currentCmd);
}
// Geomelem
i=0;
for ( IterElem = curObj.m_elements.begin( ); IterElem != curObj.m_elements.end( ); IterElem++ )
{
CModElem* elem = *IterElem;
if (elem->m_Faces.size() != 0)
{
sprintf(currentCmd, "\tAddElement(%d,IndexedTriangles,\"*^ElementIndexedTriangles:%s_%s\")",i, curObj.m_name, elem->m_name);
modFile.OutLine(currentCmd);
i++;
}
}
modFile.OutLine("}");
// elems
for ( IterElem = curObj.m_elements.begin( ); IterElem != curObj.m_elements.end( ); IterElem++ )
{
CModElem* elem = *IterElem;
if (elem->m_Faces.size() != 0)
{
sprintf(currentCmd, "{ElementIndexedTriangles:%s_%s(%d,%d)", curObj.m_name, elem->m_name,elem->m_Faces.size(),elem->m_UVs.size());
modFile.OutLine(currentCmd);
sprintf(currentCmd, "\tMaterial(\"*^Material:%s\")", elem->m_name);
modFile.OutLine(currentCmd);
i = 0;
for (IterFace = elem->m_Faces.begin(); IterFace != elem->m_Faces.end(); IterFace++)
{
CFace* face =&(*IterFace);
sprintf(currentCmd, "\tAddFaceUV(%d,%d,%d,%d,\"%g\",\"%g\",\"%g\",%d,%d,%d)",
i,
face->I, face->J,face->K,
face->nx, face->ny,face->nz,
face->IUV, face->JUV,face->KUV);
modFile.OutLine(currentCmd);
i++;
}
i = 0;
for (IterUV = elem->m_UVs.begin(); IterUV != elem->m_UVs.end(); IterUV++)
{
CUV* uv =&(*IterUV);
sprintf(currentCmd, "\tAddUV(%d,\"%g\",\"%g\")", i, uv->U, uv->V);
modFile.OutLine(currentCmd);
i++;
}
modFile.OutLine("}");
}
}
}
void SceneEnumProc::DumpOneMtl(WorkFile &modFile, Mtl *_mtl)
{
char currentCmd[MAX_MOD_COMMAND_LEN];
sprintf(currentCmd, "{Material:%s", _mtl->GetName());
modFile.OutLine(currentCmd);
sprintf(currentCmd, "\tType(Gouraud)");
modFile.OutLine(currentCmd);
sprintf(currentCmd, "\tAmbientColor(\"%g\",\"%g\",\"%g\")", _mtl->GetAmbient().r, _mtl->GetAmbient().g, _mtl->GetAmbient().b);
modFile.OutLine(currentCmd);
sprintf(currentCmd, "\tDiffuseColor(\"%g\",\"%g\",\"%g\")", _mtl->GetDiffuse().r, _mtl->GetDiffuse().g, _mtl->GetDiffuse().b);
modFile.OutLine(currentCmd);
sprintf(currentCmd, "\tSpecularColor(\"%g\",\"%g\",\"%g\",\"%g\")", _mtl->GetSpecular().r, _mtl->GetSpecular().g, _mtl->GetSpecular().b, _mtl->GetShinStr());
modFile.OutLine(currentCmd);
{
BitmapTex *tx = (BitmapTex*)_mtl->GetSubTexmap(ID_DI);//ID_DI : diffuse
char filename[MAX_FILE_NAME];
char ext[5];
_splitpath((char*)(tx->GetMapName()), NULL, NULL, filename, ext);
sprintf(currentCmd, "\tTexture(\"%s%s\")",filename, ext);
modFile.OutLine(currentCmd);
}
{
if (((StdMat *)_mtl)->GetTwoSided())
sprintf(currentCmd, "\tBackface(OFF)");
else
sprintf(currentCmd, "\tBackface(ON)");
modFile.OutLine(currentCmd);
}
modFile.OutLine("}");
}
void CSuperObject::AddNode(CSuperObject *_node)
{
m_childs.push_back(_node);
_node->m_Parent = this;
}
CSuperObject::CSuperObject(INode *_node)
{
if (_node != NULL)
{
sprintf(m_name, "SPO_%s", _node->GetName());
}
else
strcpy(m_name, "Root");
m_maxNode = _node;
m_GeomLink = NULL;
m_Parent = NULL;
}
CSuperObject::~CSuperObject()
{
std::list <CSuperObject*>::iterator Iter;
for ( Iter = m_childs.begin( ); Iter != m_childs.end( ); Iter++ )
{
CSuperObject *spo = *Iter;
delete spo;
}
m_childs.clear();
if (m_GeomLink)
delete m_GeomLink;
}
void CSuperObject::SetGeomLink(char* _GeomLink)
{
if (m_GeomLink == NULL)
m_GeomLink = new char[MAX_MOD_COMMAND_LEN];
strcpy(m_GeomLink, _GeomLink);
}
char* CSuperObject::GetGeomLink()
{
return m_GeomLink;
}
CSuperObject* CSuperObject::findSpo(INode *_node)
{
if (m_maxNode == _node)
return this;
else
{
std::list <CSuperObject*>::iterator Iter;
for ( Iter = m_childs.begin( ); Iter != m_childs.end( ); Iter++ )
{
CSuperObject *spo = *Iter;
CSuperObject *retSpo = spo->findSpo(_node);
if (retSpo != NULL)
return retSpo;
}
}
return NULL;
}
void CSuperObject::DumpSpo(WorkFile &_spoFile, TimeValue _time)
{
char currentCmd[MAX_MOD_COMMAND_LEN];
std::list <CSuperObject*>::iterator Iter;
// dump obj
sprintf(currentCmd, "{SuperObject:%s", m_name);
_spoFile.OutLine(currentCmd);
sprintf(currentCmd, "\tPutMatrix(\"*^Matrix:%s\")", m_name);
_spoFile.OutLine(currentCmd);
if (GetGeomLink())
{
sprintf(currentCmd, "\t%s", GetGeomLink());
_spoFile.OutLine(currentCmd);
}
for ( Iter = m_childs.begin( ); Iter != m_childs.end( ); Iter++ )
{
CSuperObject *spo = *Iter;
sprintf(currentCmd, "\tAddChild(\"*^SuperObject:%s\")", spo->m_name);
_spoFile.OutLine(currentCmd);
}
_spoFile.OutLine("}\n");
// dump matrix
sprintf(currentCmd, "{Matrix:%s", m_name);
_spoFile.OutLine(currentCmd);
Matrix3 NodMat;
GetLocalMatrix(NodMat, _time);
Point3 pos = NodMat.GetTrans();
sprintf(currentCmd, "\tMatrixTranslation(\"%g\",\"%g\",\"%g\")", pos.x, pos.y, pos.z);
_spoFile.OutLine(currentCmd);
/*
Quat quat = node->GetObjOffsetRot();
Matrix3 RotMat;
quat.MakeMatrix(RotMat);
ScaleValue scaleValue = node->GetObjOffsetScale();
*/
_spoFile.OutLine("}\n");
// dump childs
for ( Iter = m_childs.begin( ); Iter != m_childs.end( ); Iter++ )
{
CSuperObject *spo = *Iter;
spo->DumpSpo(_spoFile, _time);
}
}
void CSuperObject::GetLocalMatrix(Matrix3 &_NodMat, TimeValue _time)
{
if (m_maxNode != NULL)
{
_NodMat = m_maxNode->GetNodeTM(_time);
}
else
{
_NodMat = Matrix3(true);
}
if ((m_Parent != NULL) && (m_Parent->m_maxNode != NULL))
{
Matrix3 temp = _NodMat;
Matrix3 ip = Inverse(m_Parent->m_maxNode->GetNodeTM(_time));
_NodMat = ip * temp;
}
}