2534 lines
80 KiB
C++
2534 lines
80 KiB
C++
//**************************************************************************
|
|
//* Max2Nmo.cpp - Virtools File Exporter
|
|
//*
|
|
//* Romain Sididris - Copyright (c) Virtools 2000
|
|
//*
|
|
//* (Based on Ascii File Exporter source code
|
|
//* By Christer Janson
|
|
//* Kinetix Development
|
|
//* Copyright (c) Kinetix 1997, All Rights Reserved. )
|
|
//*
|
|
//* This module contains the DLL startup functions
|
|
//*
|
|
//***************************************************************************
|
|
#include "Precomp.h"
|
|
#include "Max2Nmo.h"
|
|
#include "float.h"
|
|
|
|
|
|
#ifdef _USESCRIPTS_
|
|
#include "PropertiesEvaluator.h"
|
|
#include "Special Parameter Registration.h"
|
|
#include "Special Parameter Registration2.h"
|
|
#endif
|
|
|
|
#ifdef CK_LIB
|
|
#include "CKLibIncludes.h"
|
|
#endif
|
|
|
|
HINSTANCE hInstance;
|
|
int controlsInit = FALSE;
|
|
BOOL VirtoolsPluginsParsed = FALSE;
|
|
|
|
static BOOL exportSelected;
|
|
|
|
#define MAX2NMO_CLASS_ID Class_ID(0x2dee0760, 0x75462793)
|
|
|
|
//---------------------------------------
|
|
// Character Studio 3.12 headers are not
|
|
// compatible with previous version need to
|
|
// add a version check !
|
|
//
|
|
// In Version 4.2 of 3dsMax we automatically consider that we use Character studio 3.2
|
|
BOOL g_CharacterStudio312;
|
|
|
|
|
|
|
|
//----------------------------------------
|
|
//--------------- Add MAXScript Function
|
|
|
|
|
|
#include "MAXScrpt.h"
|
|
#include "definsfn.h"
|
|
|
|
def_visible_primitive( Export2NMO,"export2nmo");
|
|
|
|
Value *Export2NMO_cf( Value** arg_list, int count )
|
|
{
|
|
int CmdArgCnt=46;
|
|
if(count<3)
|
|
{
|
|
|
|
TSTR usage;
|
|
mprintf(_T("export2Nmo: Invalid Argument Count. Wanted %d and got only %d.\n"),CmdArgCnt, count);
|
|
|
|
//The Max Script command arguments try to match the file save format... new arguments being add at the end
|
|
usage.append( _T("usage: export2Nmo\n"));
|
|
/*00*/ usage.append( _T("[string filename]\n"));
|
|
/*01*/ usage.append( _T("[BOOL onlySelected]\n"));
|
|
/*02*/ usage.append( _T("[int exportAs]\n"));
|
|
/*03*/ usage.append( _T("[BOOL convertToSkin]\n"));
|
|
/*04*/ usage.append( _T("[BOOL storeOnlyTextureFileName]\n"));
|
|
/*05*/ usage.append( _T("[BOOL unitIsMeter]\n"));
|
|
/*06*/ usage.append( _T("[int reportLevel]\n"));
|
|
/*07*/ usage.append( _T("[int samplingStepForDeformables]\n"));
|
|
/*08*/ usage.append( _T("[int samplingStepForKeyFrames]\n"));
|
|
/*09*/ usage.append( _T("[string characterName]\n"));
|
|
/*10*/ usage.append( _T("[string animationName]\n"));
|
|
/*11*/ usage.append( _T("[BOOL groupToPlace]\n"));
|
|
/*12*/ usage.append( _T("[BOOL saveBipedGeom]\n"));
|
|
/*13*/ usage.append( _T("[int compressionLevel]\n"));
|
|
/*14*/ usage.append( _T("[BOOL alignAnimOnZ]\n"));
|
|
/*15*/ usage.append( _T("[BOOL reduceRedondantKeys]\n"));
|
|
/*16*/ usage.append( _T("[BOOL shellMaterialExportBoth]\n"));
|
|
/*17*/ usage.append( _T("[BOOL ignore1KeyAnimation]\n"));
|
|
/*18*/ usage.append( _T("[BOOL exportAnimation]\n"));
|
|
/*19*/ usage.append( _T("[float reduceKeysThreshold]\n"));
|
|
/*20*/ usage.append( _T("[BOOL forceAllUVs]\n"));
|
|
/*21*/ usage.append( _T("[BOOL splitMesh]\n"));
|
|
/*22*/ usage.append( _T("[BOOL LOD]\n"));
|
|
/*23*/ usage.append( _T("[BOOL splinesAsDummies]\n"));
|
|
/*24*/ usage.append( _T("[BOOL exportAlphaMap]\n"));
|
|
/*25*/ usage.append( _T("[BOOL usePower2]\n"));
|
|
/*26*/ usage.append( _T("[BOOL force1x1Ratio]\n"));
|
|
/*27*/ usage.append( _T("[int resizeMethod (NearestPowerOfTwo=0, LowerPowerOfTwo=1, HigherPowerOfTwo=2)]\n"));
|
|
/*28*/ usage.append( _T("[BOOL deactivateMeshChannels]\n"));
|
|
/*29*/ usage.append( _T("[BOOL hideHelpers]\n"));
|
|
/*30*/ usage.append( _T("[BOOL DASIAnimation]\n"));
|
|
/*31*/ usage.append( _T("[BOOL DASIMesh]\n"));
|
|
/*32*/ usage.append( _T("[BOOL DASIMaterial]\n"));
|
|
/*33*/ usage.append( _T("[BOOL DASITexture]\n"));
|
|
/*34*/ usage.append( _T("[string startingCameraName]\n"));
|
|
/*35*/ usage.append( _T("[BOOL SelectionAsGroup]\n")); //??????????????? was not saved
|
|
/*36*/ usage.append( _T("[BOOL ReadChannels]\n"));
|
|
/*37*/ usage.append( _T("[string ReadChannelsFilename]\n"));
|
|
/*38*/ usage.append( _T("[BOOL ReportToFile]\n"));
|
|
/*39*/ usage.append( _T("[string ReportFilename]\n"));
|
|
/*40*/ usage.append( _T("[BOOL ExportBlendShapes]\n"));
|
|
/*41*/ usage.append( _T("[BOOL ExportBlendShapeAnims]\n"));
|
|
/*42*/ usage.append( _T("[BOOL IncludeBlendShapesInMorphController]\n"));
|
|
/*43*/ usage.append( _T("[BOOL reduceRedondantBlendShapesKeys]\n"));
|
|
/*44*/ usage.append( _T("[float reduceBlendShapesKeysThreshold]\n"));
|
|
/*45*/ usage.append( _T("[int samplingStepForBlendShapes]\n"));
|
|
mprintf(usage);
|
|
|
|
return ∅
|
|
}
|
|
|
|
|
|
|
|
int i=-1;
|
|
|
|
// "filename"
|
|
++i;
|
|
char *fileName = arg_list[i]->to_string();//00
|
|
|
|
// retrieve the extension of the file
|
|
char fileExt[5];
|
|
if(strlen(fileName) > 4)
|
|
memcpy(fileExt, fileName + strlen(fileName) -4, 5);
|
|
else
|
|
fileExt[0] = 0;
|
|
|
|
if(stricmp(fileExt, ".nmo") &&
|
|
stricmp(fileExt, ".cmo") &&
|
|
stricmp(fileExt, ".vmo")) {
|
|
mprintf(_T("export2Nmo: Invalid File Extension Type! (Waiting for .nmo, .cmo or .vmo)"));
|
|
return ∅
|
|
}
|
|
|
|
ClassDesc *aed = GetAsciiExpDesc();
|
|
Max2Nmo *exp = (Max2Nmo *)aed->Create();
|
|
|
|
// [BOOL onlySelected]
|
|
++i;
|
|
BOOL exportSelected = arg_list[i]->to_bool();//01
|
|
|
|
// [int exportAs]
|
|
++i;
|
|
int exportAs = arg_list[i]->to_int();//02
|
|
|
|
//if the max script user use an invalid number... use a default value
|
|
if( exportAs<1 || exportAs>4)
|
|
exportAs = 1;
|
|
|
|
if(stricmp(fileExt, ".nmo") == 0 && exportAs == 4) {
|
|
MessageBox(NULL, "Cannot export As Level in NMO !\nSwitching automatically to Export As Objects.", "Max2Nmo", MB_OK);
|
|
exportAs = 1;
|
|
}
|
|
else if(stricmp(fileExt, ".nmo") && exportAs != 4) {
|
|
MessageBox(NULL, "Can only export As Level in CMO or VMO !\nSwitching automatically to Export As Level.", "Max2Nmo", MB_OK);
|
|
exportAs = 4;
|
|
}
|
|
|
|
exp->SetExportAsObjects( exportAs==1 );
|
|
exp->SetExportAsCharacter( exportAs==2 );
|
|
exp->SetExportAsAnimationOnly( exportAs==3 );
|
|
exp->SetExportAsLevel( exportAs==4 );
|
|
|
|
|
|
#define READ_BOOL_PARAM( fct ) ++i; if(i<count) exp->fct( arg_list[i]->to_bool() );
|
|
#define READ_INT_PARAM( fct ) ++i; if(i<count) exp->fct( arg_list[i]->to_int() );
|
|
#define READ_STRING_PARAM( fct )++i; if(i<count) exp->fct( arg_list[i]->to_string() );
|
|
#define READ_FLOAT_PARAM( fct ) ++i; if(i<count) exp->fct( arg_list[i]->to_float() );
|
|
|
|
READ_BOOL_PARAM( SetConvertPhysiqueToSkin );//03
|
|
READ_BOOL_PARAM( SetStoreOnlyFilenames );
|
|
READ_BOOL_PARAM( SetRescaleScene );
|
|
READ_INT_PARAM( SetReportLevel );
|
|
READ_INT_PARAM( SetMeshFrameStep );
|
|
READ_INT_PARAM( SetKeyFrameStep );
|
|
READ_STRING_PARAM( SetCharacterName );
|
|
READ_STRING_PARAM( SetAnimationName ); //10
|
|
READ_BOOL_PARAM( SetGroupAsPlace );
|
|
READ_BOOL_PARAM( SetSaveBipedGeom );
|
|
READ_INT_PARAM( SetCompressionLevel );
|
|
READ_BOOL_PARAM( SetbAlignAnimOnZ );
|
|
READ_BOOL_PARAM( SetReduceRedondantKeys );
|
|
READ_BOOL_PARAM( SetShellMaterialAsSingle );
|
|
READ_BOOL_PARAM( SetIgnore1Keyanimation );
|
|
READ_BOOL_PARAM( SetExportAnimation );
|
|
READ_FLOAT_PARAM( SetKeysThreshold ); //20
|
|
|
|
READ_BOOL_PARAM( SetForceAllUVs );
|
|
READ_BOOL_PARAM( SetSplitMesh );
|
|
READ_BOOL_PARAM( SetLOD );
|
|
READ_BOOL_PARAM( SetSplinesAsDummies );
|
|
READ_BOOL_PARAM( SetExportAlphaMap );
|
|
READ_BOOL_PARAM( SetUsePower2 );
|
|
READ_BOOL_PARAM( SetForce1x1Ratio );
|
|
READ_INT_PARAM( SetForce1x1RatioMethod );
|
|
READ_BOOL_PARAM( SetDeactivateMeshChannels );
|
|
READ_BOOL_PARAM( SetHideHelpers );
|
|
READ_BOOL_PARAM( SetDASIAnimation ); //30
|
|
READ_BOOL_PARAM( SetDASIMesh );
|
|
READ_BOOL_PARAM( SetDASIMaterial );
|
|
READ_BOOL_PARAM( SetDASITexture );
|
|
READ_STRING_PARAM( SetStartingCamera );
|
|
READ_BOOL_PARAM( SetSelectionAsGroup ); //36
|
|
READ_BOOL_PARAM( SetReadChannels );
|
|
READ_STRING_PARAM( SetReadChannelsFilename ); //38
|
|
READ_BOOL_PARAM( SetReport );
|
|
READ_STRING_PARAM( SetReportFilename ); //40
|
|
READ_BOOL_PARAM( SetExportBlendShapes ); //41
|
|
READ_BOOL_PARAM( SetExportBlendShapeAnims ); //42
|
|
READ_BOOL_PARAM( SetIncludeBlendShapesInMorphController ); //42
|
|
READ_BOOL_PARAM( SetReduceRedondantBlendShapesKeys ); // 43
|
|
READ_FLOAT_PARAM( SetBlendShapesKeysThreshold ); // 44
|
|
READ_INT_PARAM( SetBlendShapesStep ); // 45
|
|
//--- Really Do Export
|
|
exp->SetShowProgressionBar( FALSE );
|
|
exp->ReallyDoExport( fileName, MAXScript_interface, exportSelected );
|
|
|
|
delete exp;
|
|
|
|
return &ok;
|
|
}
|
|
//----------------------------------------
|
|
|
|
#ifdef _USESCRIPTS_
|
|
#undef new
|
|
#undef delete
|
|
|
|
//----------------------------------------
|
|
//--------------- Add Virtools Tool Button
|
|
#include "Maxscrpt\Parser.h"
|
|
#include "utilapi.h"
|
|
|
|
#define VIRTOOLSTOOL_CLASS_ID Class_ID(0x6c7e7fe9,0x379a5550)
|
|
|
|
class VirtoolsTool : public UtilityObj {
|
|
public:
|
|
XString m_ExportFileName;
|
|
|
|
public:
|
|
VirtoolsTool();
|
|
~VirtoolsTool();
|
|
|
|
void BeginEditParams(Interface *ip,IUtil *iu);
|
|
void EndEditParams(Interface *ip,IUtil *iu);
|
|
void DeleteThis() {}
|
|
};
|
|
|
|
static VirtoolsTool theVirtoolsTool;
|
|
|
|
class VirtoolsToolClassDesc:public ClassDesc {
|
|
public:
|
|
int IsPublic() {return 1;}
|
|
void * Create(BOOL loading = FALSE) {return &theVirtoolsTool;}
|
|
const TCHAR * ClassName() {return _T("Virtools Exporter");}
|
|
SClass_ID SuperClassID() {return UTILITY_CLASS_ID;}
|
|
Class_ID ClassID() {return VIRTOOLSTOOL_CLASS_ID;}
|
|
const TCHAR* Category() {return _T("");}
|
|
};
|
|
|
|
static VirtoolsToolClassDesc VirtoolsToolDesc;
|
|
ClassDesc* GetVirtoolsToolDesc(){ return &VirtoolsToolDesc; }
|
|
|
|
VirtoolsTool::VirtoolsTool(){
|
|
m_ExportFileName = "";
|
|
}
|
|
|
|
VirtoolsTool::~VirtoolsTool(){
|
|
}
|
|
|
|
void VirtoolsTool::BeginEditParams(Interface *ip,IUtil *iu)
|
|
{
|
|
CharStream *out = thread_local(current_stdout);
|
|
Parser *parser = new Parser (out);
|
|
|
|
// First instruction to know where we came from
|
|
XString initInst("global alreadyGivenFileName = ");
|
|
StringStream *initSource = new StringStream;
|
|
if( m_ExportFileName.Length() ){
|
|
initSource->init( (initInst + "\"" + m_ExportFileName + "\"").Str() );
|
|
} else {
|
|
initSource->init( (initInst + "undefined").Str() );
|
|
}
|
|
Value *code = parser->compile( initSource );
|
|
Value *result = code->eval();
|
|
delete initSource;
|
|
|
|
XString maxScriptDir(ip->GetDir(APP_SCRIPTS_DIR));
|
|
FileStream *source = (new FileStream)->open( (maxScriptDir + "\\CKInstScripts\\VirtoolsUtility.ms").Str() , "rt");
|
|
|
|
BOOL quiet=TRUE;
|
|
|
|
if (!quiet)
|
|
source->log_to(out);
|
|
|
|
// loop through file compiling and evaluating all expressions
|
|
try
|
|
{
|
|
//source->flush_whitespace();
|
|
while (!source->at_eos())
|
|
{
|
|
code = parser->compile(source);
|
|
result = code->eval();
|
|
if (!quiet)
|
|
result->print();
|
|
//source->flush_whitespace();
|
|
}
|
|
source->close();
|
|
}
|
|
catch (...)
|
|
{
|
|
// catch any errors and tell what file we are in if any
|
|
out->printf("Error occurred in file: ");
|
|
source->sprin1(out);
|
|
out->printf("\n");
|
|
//throw;
|
|
}
|
|
|
|
/*
|
|
code = parser->compile_all(source);
|
|
result = code->eval();
|
|
|
|
source->close();
|
|
*/
|
|
delete parser;
|
|
|
|
m_ExportFileName = "";
|
|
|
|
}
|
|
|
|
void VirtoolsTool::EndEditParams(Interface *ip,IUtil *iu)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------
|
|
|
|
#endif //_USESCRIPTS_
|
|
|
|
BOOL GetVersionInfo(char *file,DWORD& Version1,DWORD& Version2,DWORD& Version3,DWORD& Version4)
|
|
{
|
|
DWORD dwVerHnd;
|
|
DWORD dwVerInfoSize;
|
|
long resMOld = 327680;
|
|
int ret = -1;
|
|
|
|
dwVerInfoSize = GetFileVersionInfoSize(file, &dwVerHnd);
|
|
if (dwVerInfoSize){
|
|
// If we were able to get the information, process it:
|
|
HANDLE hMem;
|
|
LPVOID lpvMem;
|
|
BOOL fRet;
|
|
UINT cchVer = 0;
|
|
VS_FIXEDFILEINFO *vInfo;
|
|
|
|
hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
|
|
lpvMem = GlobalLock(hMem);
|
|
GetFileVersionInfo(file, dwVerHnd, dwVerInfoSize, lpvMem);
|
|
|
|
fRet = VerQueryValue(lpvMem, TEXT("\\"),
|
|
(LPVOID*)&vInfo, &cchVer);
|
|
if (fRet && cchVer && vInfo) {
|
|
vInfo->dwFileVersionMS;
|
|
vInfo->dwFileVersionLS;
|
|
|
|
Version1 = HIWORD(vInfo->dwFileVersionMS);
|
|
Version2 = LOWORD(vInfo->dwFileVersionMS);
|
|
Version3 = HIWORD(vInfo->dwFileVersionLS);
|
|
Version4 = LOWORD(vInfo->dwFileVersionLS);
|
|
}
|
|
|
|
GlobalUnlock(hMem);
|
|
GlobalFree(hMem);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved)
|
|
{
|
|
hInstance = hinstDLL;
|
|
|
|
// Initialize the custom controls. This should be done only once.
|
|
if (!controlsInit) {
|
|
controlsInit = TRUE;
|
|
InitCustomControls(hInstance);
|
|
InitCommonControls();
|
|
|
|
//#pragma NOTE(__FILE__LINE__"Initialisation CK")
|
|
DWORD fpu = VxGetFPUControlWord();
|
|
CKStartUp(hinstDLL);
|
|
if (VxGetFPUControlWord()!=fpu)
|
|
_control87(_CW_DEFAULT, 0xfffff);
|
|
}
|
|
switch(fdwReason) {
|
|
case DLL_PROCESS_DETACH: CKShutdown();
|
|
default: return TRUE;
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
//-------- Presentation of functions to Max
|
|
//--------
|
|
__declspec( dllexport ) const TCHAR* LibDescription()
|
|
{
|
|
return GetString(IDS_LIBDESCRIPTION);
|
|
}
|
|
|
|
__declspec( dllexport ) int LibNumberClasses()
|
|
{
|
|
#ifdef _USESCRIPTS_
|
|
return 2;
|
|
#else
|
|
return 1;
|
|
#endif
|
|
}
|
|
|
|
__declspec( dllexport ) ClassDesc* LibClassDesc(int i)
|
|
{
|
|
switch(i) {
|
|
case 0: return GetAsciiExpDesc();
|
|
#ifdef _USESCRIPTS_
|
|
case 1: return GetVirtoolsToolDesc();
|
|
#endif
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
__declspec( dllexport ) ULONG LibVersion()
|
|
{
|
|
return VERSION_3DSMAX;
|
|
}
|
|
|
|
// Let the plug-in register itself for deferred loading
|
|
__declspec( dllexport ) ULONG CanAutoDefer()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
static CKContext *g_VirtoolsContext = NULL;
|
|
|
|
class AsciiExpClassDesc:public ClassDesc {
|
|
public:
|
|
int IsPublic() { return 1; }
|
|
void* Create(BOOL loading = FALSE) { return new Max2Nmo; }
|
|
const TCHAR* ClassName() { return GetString(IDS_ASCIIEXP); }
|
|
SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
|
|
Class_ID ClassID() { return MAX2NMO_CLASS_ID; }
|
|
const TCHAR* Category() { return GetString(IDS_CATEGORY); }
|
|
|
|
~AsciiExpClassDesc(){
|
|
CKCloseContext(g_VirtoolsContext);
|
|
g_VirtoolsContext = NULL;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
static AsciiExpClassDesc AsciiExpDesc;
|
|
|
|
ClassDesc* GetAsciiExpDesc()
|
|
{
|
|
return &AsciiExpDesc;
|
|
}
|
|
|
|
TCHAR *GetString(int id)
|
|
{
|
|
static TCHAR buf[256];
|
|
|
|
if (hInstance)
|
|
return LoadString(hInstance, id, buf, sizeof(buf)) ? buf : NULL;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
Max2Nmo::Max2Nmo()
|
|
{
|
|
// These are the default values that will be active when
|
|
// the exporter is ran the first time.
|
|
// After the first session these options are sticky.
|
|
InitDefaultValues();
|
|
}
|
|
|
|
Max2Nmo::~Max2Nmo()
|
|
{
|
|
}
|
|
|
|
void Max2Nmo::InitDefaultValues()
|
|
{
|
|
bShowProgressionBar = TRUE;
|
|
bExportAsObjects = TRUE;
|
|
bReduceRedondantKeys = TRUE;
|
|
bExportAsCharacter = FALSE;
|
|
bExportAsAnimationOnly = FALSE;
|
|
bExportAsLevel = FALSE;
|
|
bConvertPhysiqueToSkin = TRUE;
|
|
bStoreOnlyTextureFilenames = FALSE;
|
|
bRescaleScene = FALSE;
|
|
bGroupAsPlace = FALSE;
|
|
bSelectionAsGroup = FALSE;
|
|
szCharacterName = "Character";
|
|
szAnimationName = "Animation";
|
|
nMeshFrameStep = 3;
|
|
nKeyFrameStep = 3;
|
|
nCompressionLevel = 0;
|
|
nReportLevel = 0;
|
|
GroupIndent = 0;
|
|
bSaveBipedGeom = FALSE;
|
|
bAlignAnimOnZ = FALSE;
|
|
|
|
VirtoolsExporter = NULL;
|
|
VirtoolsContext = NULL;
|
|
bShellMaterialExportBoth = FALSE;
|
|
bIgnore1KeyAnimation = TRUE;
|
|
|
|
ReportBufferPos = 0;
|
|
|
|
m_RescaleFactor = 1.0;
|
|
|
|
bExportAnimation =TRUE;
|
|
bForceSkinToMorph =FALSE;
|
|
fKeysThreshold =TRUE;
|
|
bForceAllUVs =FALSE;
|
|
bSplitMesh =FALSE;
|
|
bLOD =FALSE;
|
|
bSplinesAsDummies =FALSE;
|
|
bExportAlphaMap =FALSE;
|
|
bUsePower2 =FALSE;
|
|
bForce1x1Ratio =FALSE;
|
|
nForce1x1RatioMethod =eNearestPowerOfTwo;
|
|
bDeactivateMeshChannels =FALSE;
|
|
bHideHelpers =FALSE;
|
|
bDASIAnimation =FALSE;
|
|
bDASIMesh =FALSE;
|
|
bDASIMaterial =FALSE;
|
|
bDASITexture =FALSE;
|
|
sStartingCamera ="Camera01";
|
|
bReadChannels =FALSE;
|
|
szReadChannelsFilename ="MyChannels.txt";
|
|
bReport =FALSE;
|
|
szReportFilename ="Report.txt";
|
|
|
|
VirtoolsExporter = NULL;
|
|
VirtoolsContext = NULL;
|
|
|
|
bAlphaRef = TRUE;
|
|
iAlphaRefValue = 1;
|
|
|
|
bExportBlendShapes = FALSE;
|
|
bExportBlendShapeAnims = FALSE;
|
|
bIncludeBlendShapesInMorphController = TRUE;
|
|
bReduceRedondantBlendShapesKeys = FALSE;
|
|
bReduceRedondantBlendShapesKeys = TRUE;
|
|
fBlendShapesKeysThreshold = 0.1f;
|
|
nBlendShapesStep = 3;
|
|
}
|
|
|
|
void Max2Nmo::UpdateInterface(HWND hWnd)
|
|
{
|
|
Max2Nmo* exp = this;
|
|
ISpinnerControl *spin;
|
|
|
|
// retrieve the extension of the file
|
|
XString sfileName = exp->GetExportFileName();
|
|
const char* fileName = sfileName.CStr();
|
|
char fileExt[5];
|
|
|
|
if(strlen(fileName) > 4)
|
|
memcpy(fileExt, fileName + strlen(fileName)-4, 5);
|
|
else
|
|
fileExt[0] = 0;
|
|
|
|
// ensure Export As mode is compatible with output file type
|
|
if(stricmp(fileExt, ".nmo") == 0 && exp->GetExportAsLevel()) {
|
|
// if NMO, avoid to Export As Level
|
|
exp->SetExportAsObjects(true);
|
|
exp->SetExportAsCharacter(false);
|
|
exp->SetExportAsAnimationOnly(false);
|
|
exp->SetExportAsLevel(false);
|
|
}
|
|
else if(stricmp(fileExt, ".nmo")) {
|
|
// if not an NMO, force to Export As Level
|
|
exp->SetExportAsObjects(false);
|
|
exp->SetExportAsCharacter(false);
|
|
exp->SetExportAsAnimationOnly(false);
|
|
exp->SetExportAsLevel(true);
|
|
}
|
|
|
|
|
|
// check Export Type
|
|
int RadioToEnable = IDC_RADIOEXPORTASOBJECTS;
|
|
if (exp->GetExportAsLevel()) {
|
|
RadioToEnable=IDC_RADIOEXPORTASLEVEL;
|
|
EnableWindow(GetDlgItem(hWnd, IDC_RADIOEXPORTASOBJECTS), false);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_RADIOEXPORTASCHARACTER), false);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_RADIOEXPORTASANIMATION), false);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_RADIOEXPORTASLEVEL), true);
|
|
}
|
|
else {
|
|
if (exp->GetExportAsObjects())
|
|
RadioToEnable=IDC_RADIOEXPORTASOBJECTS;
|
|
else if (exp->GetExportAsCharacter())
|
|
RadioToEnable=IDC_RADIOEXPORTASCHARACTER;
|
|
else if (exp->GetExportAsAnimationOnly())
|
|
RadioToEnable=IDC_RADIOEXPORTASANIMATION;
|
|
EnableWindow(GetDlgItem(hWnd, IDC_RADIOEXPORTASOBJECTS), true);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_RADIOEXPORTASCHARACTER), true);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_RADIOEXPORTASANIMATION), true);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_RADIOEXPORTASLEVEL), false);
|
|
}
|
|
|
|
CheckRadioButton(hWnd, IDC_RADIOEXPORTASOBJECTS, IDC_RADIOEXPORTASLEVEL, RadioToEnable);
|
|
|
|
CheckDlgButton(hWnd, IDC_CHECKSTOREFILENAMES, exp->GetStoreOnlyFilenames());
|
|
CheckDlgButton(hWnd, IDC_CHECKRESCALESCENE, exp->GetRescaleScene());
|
|
CheckDlgButton(hWnd, IDC_CHECKGROUPASPLACE, exp->GetGroupAsPlace());
|
|
CheckDlgButton(hWnd, IDC_CHECKBIPEDMESH, exp->GetSaveBipedGeom());
|
|
CheckDlgButton(hWnd, IDC_CHECKALIGNANIMATIONS, exp->GetAlignAnimOnZ());
|
|
CheckDlgButton(hWnd, IDC_CHECKREDUCEREDOUNDANTKEYS, exp->ReduceRedondantKeys());
|
|
CheckDlgButton(hWnd, IDC_CHECKSHELLMATERIALASSINGLE, exp->GetShellMaterialExportBoth());
|
|
|
|
CheckDlgButton(hWnd, IDC_CHECKEXPORTANIMATION , exp->GetExportAnimation());
|
|
CheckDlgButton(hWnd, IDC_CHECK_FORCESKINTOMORPH , exp->GetForceSkinToMorph());
|
|
CheckDlgButton(hWnd, IDC_CHECKFORCEUVS , exp->GetForceAllUVs());
|
|
CheckDlgButton(hWnd, IDC_CHECKLOD , exp->GetLOD() );
|
|
CheckDlgButton(hWnd, IDC_CHECKSPLINESASDUMMIES , exp->GetSplinesAsDummies());
|
|
CheckDlgButton(hWnd, IDC_CHECKSPLITMESH , exp->GetSplitMesh());
|
|
CheckDlgButton(hWnd, IDC_CHECKALPHAMAP , exp->GetExportAlphaMap());
|
|
CheckDlgButton(hWnd, IDC_CHECKPOWER2 , exp->GetUsePower2());
|
|
CheckDlgButton(hWnd, IDC_CHECKFORCERATIO , exp->GetForce1x1Ratio());
|
|
CheckDlgButton(hWnd, IDC_CHECKDEACTIVATEMESHCHANNELS , exp->GetDeactivateMeshChannels());
|
|
CheckDlgButton(hWnd, IDC_CHECKHIDEHELPERS , exp->GetHideHelpers());
|
|
CheckDlgButton(hWnd, IDC_CHECKCHANNELSETTINGS , exp->GetReadChannels());
|
|
CheckDlgButton(hWnd, IDC_CHECKREPORT , exp->GetReport());
|
|
|
|
//alpha ref
|
|
//CheckDlgButton(hWnd, IDC_ALPHAREF_CHECK , exp->GetAlphaRef());
|
|
if (!exp->GetAlphaRef())
|
|
{
|
|
EnableWindow(GetDlgItem(hWnd,IDC_ALPHAREF_STEP),FALSE);
|
|
EnableWindow(GetDlgItem(hWnd,IDC_ALPHAREF_STEP_SPIN),FALSE);
|
|
}
|
|
|
|
// Blend shapes
|
|
CheckDlgButton(hWnd, IDC_EXPORTBLENDSHAPES , exp->GetExportBlendShapes());
|
|
CheckDlgButton(hWnd, IDC_EXPORTBLENDSHAPEANIMS , exp->GetExportBlendShapeAnims());
|
|
CheckDlgButton(hWnd, IDC_INCLUDEBLENDSHAPESINMORPHCONTROLLER, exp->GetIncludeBlendShapesInMorphController());
|
|
CheckDlgButton(hWnd, IDC_CHECKREDUCEREDOUNDANTKEYS_BLENDSHAPES, exp->GetReduceRedondantBlendShapesKeys());
|
|
|
|
//PostExport Settings fo Detect and Share identical...
|
|
//will be remove in BEExport
|
|
CheckDlgButton(hWnd, IDC_CHECKDASIANIMATION , exp->GetDASIAnimation());
|
|
CheckDlgButton(hWnd, IDC_CHECKDASIMESH , exp->GetDASIMesh());
|
|
CheckDlgButton(hWnd, IDC_CHECKDASIMATERIAL , exp->GetDASIMaterial());
|
|
CheckDlgButton(hWnd, IDC_CHECKDASITEXTURE , exp->GetDASITexture());
|
|
|
|
//Force1x1RatioMethod: To acces the combobox, we use standard Win32 messages
|
|
HWND combo=GetDlgItem(hWnd, IDC_COMBOFORCERATIOMETHOD);
|
|
SendMessage( combo , CB_ADDSTRING, 0, (LPARAM) (LPCTSTR) "Nearest Power of 2");
|
|
SendMessage( combo , CB_ADDSTRING, 0, (LPARAM) (LPCTSTR) "Lower Power of 2");
|
|
SendMessage( combo , CB_ADDSTRING, 0, (LPARAM) (LPCTSTR) "Higher Power of 2");
|
|
SendMessage( combo , CB_SETCURSEL , exp->GetForce1x1RatioMethod(), 0);
|
|
|
|
//IDC_COMBOREPORTLEVEL: Report Level can be None, Low, Medium or High (0,1,2,3)
|
|
combo=GetDlgItem(hWnd, IDC_COMBOREPORTLEVEL);
|
|
SendMessage( combo , CB_ADDSTRING, 0, (LPARAM) (LPCTSTR) "None");
|
|
SendMessage( combo , CB_ADDSTRING, 0, (LPARAM) (LPCTSTR) "Steps");
|
|
SendMessage( combo , CB_ADDSTRING, 0, (LPARAM) (LPCTSTR) "Detailed steps");
|
|
SendMessage( combo , CB_ADDSTRING, 0, (LPARAM) (LPCTSTR) "Verbose");
|
|
SendMessage( combo , CB_SETCURSEL , exp->GetReportLevel(), 0);
|
|
|
|
CheckRadioButton(hWnd, IDC_RADIOSKIN, IDC_RADIOMORPH,
|
|
exp->GetConvertPhysiqueToSkin() ? IDC_RADIOSKIN : IDC_RADIOMORPH);
|
|
|
|
CheckDlgButton(hWnd, IDC_CHECK_IGNORE1KEYANIMATION, exp->GetIgnore1KeyAnimation());
|
|
|
|
|
|
|
|
// Setup the spinner controls for the controller key sample rate
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_CONT_STEP_SPIN));
|
|
spin->LinkToEdit(GetDlgItem(hWnd,IDC_CONT_STEP), EDITTYPE_INT );
|
|
spin->SetLimits(1, 100, TRUE);
|
|
spin->SetScale(1.0f);
|
|
spin->SetValue(exp->GetKeyFrameStep() ,FALSE);
|
|
ReleaseISpinner(spin);
|
|
|
|
|
|
|
|
// Setup the spinner controls for the compression level
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_CONT_COMPRESSIONSPIN));
|
|
spin->LinkToEdit(GetDlgItem(hWnd,IDC_CONT_COMPRESSION), EDITTYPE_INT );
|
|
spin->SetLimits(0, 9, TRUE);
|
|
spin->SetScale(1.0f);
|
|
spin->SetValue(exp->GetCompressionLevel() ,FALSE);
|
|
ReleaseISpinner(spin);
|
|
|
|
// Setup the spinner controls for alpharef
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_ALPHAREF_STEP_SPIN));
|
|
spin->LinkToEdit(GetDlgItem(hWnd,IDC_ALPHAREF_STEP), EDITTYPE_INT );
|
|
spin->SetLimits(0, 255, TRUE);
|
|
spin->SetScale(1.0f);
|
|
if (exp->GetAlphaRef())
|
|
spin->SetValue(exp->GetAlphaRefValue() ,FALSE);
|
|
else
|
|
spin->SetValue(1 ,FALSE);
|
|
ReleaseISpinner(spin);
|
|
|
|
// Setup the spinner controls for the mesh definition sample rate
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_MESH_STEP_SPIN));
|
|
spin->LinkToEdit(GetDlgItem(hWnd,IDC_MESH_STEP), EDITTYPE_INT );
|
|
spin->SetLimits(1, 100, TRUE);
|
|
spin->SetScale(1.0f);
|
|
spin->SetValue(exp->GetMeshFrameStep() ,FALSE);
|
|
ReleaseISpinner(spin);
|
|
|
|
// Setup the spinner controls for the Animation Reduce Keys Threshold
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_KEYSTHRESHOLDSPIN));
|
|
spin->LinkToEdit(GetDlgItem(hWnd,IDC_KEYSTHRESHOLD), EDITTYPE_FLOAT );
|
|
spin->SetLimits(0.0f, 100.0f, TRUE);
|
|
spin->SetScale(0.0001f);
|
|
spin->SetValue(exp->GetKeysThreshold() ,FALSE);
|
|
ReleaseISpinner(spin);
|
|
|
|
// Setup the spinner controls for the Animation Reduce Blend Shapes Keys Threshold
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_KEYSTHRESHOLDSPIN_BLENDSHAPES));
|
|
spin->LinkToEdit(GetDlgItem(hWnd,IDC_KEYSTHRESHOLD_BLENDSHAPES), EDITTYPE_FLOAT );
|
|
spin->SetLimits(0.0f, 1.0f, TRUE);
|
|
spin->SetScale(0.0001f);
|
|
spin->SetValue(exp->GetBlendShapesKeysThreshold() ,FALSE);
|
|
ReleaseISpinner(spin);
|
|
|
|
// Setup the spinner controls for the blend shape weights anims sampling step
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_BLENDSHAPES_STEP_SPIN));
|
|
spin->LinkToEdit(GetDlgItem(hWnd,IDC_BLENDSHAPES_STEP), EDITTYPE_INT );
|
|
spin->SetLimits(1, 100, TRUE);
|
|
spin->SetScale(1.0f);
|
|
spin->SetValue(exp->GetBlendShapesStep() ,FALSE);
|
|
ReleaseISpinner(spin);
|
|
|
|
|
|
|
|
SetWindowText(GetDlgItem(hWnd, IDC_EDITCHARACTERNAME),exp->GetCharacterName());
|
|
SetWindowText(GetDlgItem(hWnd, IDC_EDITANIMATIONNAME),exp->GetAnimationName());
|
|
SetWindowText(GetDlgItem(hWnd, IDC_EDITSTARTINGCAMERA),exp->GetStartingCamera());
|
|
SetWindowText(GetDlgItem(hWnd, IDC_EDITREADCHANNELSFILENAME),exp->GetReadChannelsFilename());
|
|
SetWindowText(GetDlgItem(hWnd, IDC_EDITREPORTFILENAME),exp->GetReportFilename());
|
|
|
|
//Setup ToolTips
|
|
exp->UIToolTips(hWnd);
|
|
|
|
//Set the state of all controls based on all values.
|
|
exp->UIUpdate(hWnd);
|
|
}
|
|
|
|
int Max2Nmo::ExtCount()
|
|
{
|
|
return 3;
|
|
}
|
|
|
|
const TCHAR * Max2Nmo::Ext(int n)
|
|
{
|
|
switch(n) {
|
|
case 0:
|
|
return _T("Nmo");
|
|
case 1:
|
|
return _T("Vmo");
|
|
case 2:
|
|
return _T("Cmo");
|
|
}
|
|
return _T("");
|
|
}
|
|
|
|
const TCHAR * Max2Nmo::LongDesc()
|
|
{
|
|
return GetString(IDS_LONGDESC);
|
|
}
|
|
|
|
const TCHAR * Max2Nmo::ShortDesc()
|
|
{
|
|
return GetString(IDS_SHORTDESC);
|
|
}
|
|
|
|
const TCHAR * Max2Nmo::AuthorName()
|
|
{
|
|
return _T("Romain Sididris, Francisco Cabrita and Guillaume Laferriere");
|
|
}
|
|
|
|
const TCHAR * Max2Nmo::CopyrightMessage()
|
|
{
|
|
return GetString(IDS_COPYRIGHT);
|
|
}
|
|
|
|
const TCHAR * Max2Nmo::OtherMessage1()
|
|
{
|
|
return _T("");
|
|
}
|
|
|
|
const TCHAR * Max2Nmo::OtherMessage2()
|
|
{
|
|
return _T("");
|
|
}
|
|
|
|
unsigned int Max2Nmo::Version()
|
|
{
|
|
return 100;
|
|
}
|
|
|
|
static BOOL CALLBACK AboutBoxDlgProc(HWND hWnd, UINT msg,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (msg) {
|
|
case WM_INITDIALOG:
|
|
CenterWindow(hWnd, GetParent(hWnd));
|
|
break;
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDOK:
|
|
EndDialog(hWnd, 1);
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void Max2Nmo::ShowAbout(HWND hWnd)
|
|
{
|
|
DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, AboutBoxDlgProc, 0);
|
|
}
|
|
|
|
static BOOL CALLBACK ReportDlgProc(HWND hWnd, UINT msg,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
Max2Nmo *exp = (Max2Nmo*)GetWindowLong(hWnd,GWL_USERDATA);
|
|
switch (msg) {
|
|
case WM_INITDIALOG: {
|
|
exp = (Max2Nmo*)lParam;
|
|
SetWindowLong(hWnd,GWL_USERDATA,lParam);
|
|
CenterWindow(hWnd, GetParent(hWnd));
|
|
SetDlgItemText(hWnd,IDC_EDITREPORT,(const char*)exp->ReportBuffer.Begin());
|
|
break;
|
|
}
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDOK: {
|
|
EndDialog(hWnd, 1);
|
|
break;
|
|
} break;
|
|
}
|
|
default: return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Dialog proc
|
|
static BOOL CALLBACK ExportDlgProc(HWND hWnd, UINT msg,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
Interval animRange;
|
|
ISpinnerControl *spin;
|
|
char* CPtr;
|
|
TCHAR CBuf[512];
|
|
int ret;
|
|
|
|
Max2Nmo *exp = (Max2Nmo*)GetWindowLong(hWnd,GWL_USERDATA);
|
|
switch (msg) {
|
|
case WM_INITDIALOG: {
|
|
exp = (Max2Nmo*)lParam;
|
|
SetWindowLong(hWnd,GWL_USERDATA,lParam);
|
|
CenterWindow(hWnd, GetParent(hWnd));
|
|
exp->UpdateInterface(hWnd);
|
|
break;
|
|
}
|
|
case CC_SPINNER_CHANGE:
|
|
spin = (ISpinnerControl*)lParam;
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDC_BUTTON_GETCHANNELFILE:
|
|
CPtr=(char*)exp->UIGetFilename(hWnd, CBuf, sizeof(CBuf), "*.TXT", FALSE);
|
|
if(CPtr){
|
|
exp->SetReadChannelsFilename(XString(CPtr).Str());
|
|
SetWindowText(GetDlgItem(hWnd, IDC_EDITREADCHANNELSFILENAME),exp->GetReadChannelsFilename());
|
|
}
|
|
break;
|
|
|
|
case IDC_BUTTON_GETREPORTFILE:
|
|
CPtr=(char*)exp->UIGetFilename(hWnd, CBuf, sizeof(CBuf));
|
|
if(CPtr){
|
|
exp->SetReportFilename(XString(CPtr).Str());
|
|
SetWindowText(GetDlgItem(hWnd, IDC_EDITREPORTFILENAME),exp->GetReportFilename());
|
|
}
|
|
break;
|
|
|
|
case IDC_DEFAULT:
|
|
{
|
|
exp->InitDefaultValues();
|
|
exp->UpdateInterface(hWnd);
|
|
}
|
|
break;
|
|
/*
|
|
case IDC_ALPHAREF_CHECK:
|
|
{
|
|
UINT res = IsDlgButtonChecked(hWnd, IDC_ALPHAREF_CHECK);
|
|
EnableWindow(GetDlgItem(hWnd,IDC_ALPHAREF_STEP),res);
|
|
EnableWindow(GetDlgItem(hWnd,IDC_ALPHAREF_STEP_SPIN),res);
|
|
exp->SetAlphaRef(TRUE);
|
|
if (!res)
|
|
{
|
|
ISpinnerControl* spin = GetISpinner(GetDlgItem(hWnd, IDC_ALPHAREF_STEP_SPIN));
|
|
//spin->SetValue(255);
|
|
exp->SetAlphaRef(FALSE);
|
|
//exp->SetAlphaRefValue(255);
|
|
}
|
|
}
|
|
break;
|
|
*/
|
|
case IDC_CHECKCHANNELSETTINGS:
|
|
case IDC_RADIOEXPORTASANIMATION:
|
|
case IDC_RADIOEXPORTASOBJECTS:
|
|
case IDC_RADIOEXPORTASCHARACTER:
|
|
case IDC_RADIOEXPORTASLEVEL:
|
|
case IDC_CHECKEXPORTANIMATION:
|
|
case IDC_CHECK_FORCESKINTOMORPH:
|
|
case IDC_CHECKSTOREFILENAMES:
|
|
case IDC_CHECKFORCEUVS:
|
|
case IDC_CHECKPOWER2:
|
|
case IDC_CHECKREPORT:
|
|
case IDC_EXPORTBLENDSHAPES:
|
|
case IDC_EXPORTBLENDSHAPEANIMS:
|
|
exp->UIUpdate(hWnd);
|
|
break;
|
|
|
|
case IDOK: {
|
|
exp->SetExportAsAnimationOnly(IsDlgButtonChecked(hWnd, IDC_RADIOEXPORTASANIMATION));
|
|
exp->SetExportAsCharacter(IsDlgButtonChecked(hWnd, IDC_RADIOEXPORTASCHARACTER));
|
|
exp->SetExportAsObjects(IsDlgButtonChecked(hWnd, IDC_RADIOEXPORTASOBJECTS));
|
|
exp->SetExportAsLevel(IsDlgButtonChecked(hWnd, IDC_RADIOEXPORTASLEVEL));
|
|
exp->SetConvertPhysiqueToSkin(IsDlgButtonChecked(hWnd, IDC_RADIOSKIN));
|
|
exp->SetRescaleScene(IsDlgButtonChecked(hWnd, IDC_CHECKRESCALESCENE));
|
|
exp->SetGroupAsPlace(IsDlgButtonChecked(hWnd, IDC_CHECKGROUPASPLACE));
|
|
exp->SetSaveBipedGeom(IsDlgButtonChecked(hWnd, IDC_CHECKBIPEDMESH));
|
|
exp->SetbAlignAnimOnZ(IsDlgButtonChecked(hWnd, IDC_CHECKALIGNANIMATIONS));
|
|
exp->SetStoreOnlyFilenames(IsDlgButtonChecked(hWnd, IDC_CHECKSTOREFILENAMES));
|
|
exp->SetReduceRedondantKeys(IsDlgButtonChecked(hWnd, IDC_CHECKREDUCEREDOUNDANTKEYS));
|
|
exp->SetShellMaterialAsSingle(IsDlgButtonChecked(hWnd, IDC_CHECKSHELLMATERIALASSINGLE));
|
|
exp->SetIgnore1Keyanimation(IsDlgButtonChecked(hWnd, IDC_CHECK_IGNORE1KEYANIMATION));
|
|
|
|
exp->SetExportAnimation(IsDlgButtonChecked(hWnd, IDC_CHECKEXPORTANIMATION));
|
|
exp->SetForceSkinToMorph(IsDlgButtonChecked(hWnd, IDC_CHECK_FORCESKINTOMORPH));
|
|
exp->SetForceAllUVs(IsDlgButtonChecked(hWnd, IDC_CHECKFORCEUVS));
|
|
exp->SetLOD(IsDlgButtonChecked(hWnd, IDC_CHECKLOD));
|
|
exp->SetSplinesAsDummies(IsDlgButtonChecked(hWnd, IDC_CHECKSPLINESASDUMMIES));
|
|
exp->SetSplitMesh(IsDlgButtonChecked(hWnd, IDC_CHECKSPLITMESH));
|
|
exp->SetExportAlphaMap(IsDlgButtonChecked(hWnd, IDC_CHECKALPHAMAP));
|
|
exp->SetUsePower2(IsDlgButtonChecked(hWnd, IDC_CHECKPOWER2));
|
|
exp->SetForce1x1Ratio(IsDlgButtonChecked(hWnd, IDC_CHECKFORCERATIO));
|
|
exp->SetDeactivateMeshChannels( IsDlgButtonChecked(hWnd, IDC_CHECKDEACTIVATEMESHCHANNELS) );
|
|
exp->SetHideHelpers( IsDlgButtonChecked(hWnd, IDC_CHECKHIDEHELPERS) );
|
|
exp->SetReadChannels( IsDlgButtonChecked(hWnd, IDC_CHECKCHANNELSETTINGS) );
|
|
exp->SetReport( IsDlgButtonChecked(hWnd, IDC_CHECKREPORT) );
|
|
|
|
exp->SetDASIAnimation(IsDlgButtonChecked(hWnd, IDC_CHECKDASIANIMATION));
|
|
exp->SetDASIMesh(IsDlgButtonChecked(hWnd, IDC_CHECKDASIMESH));
|
|
exp->SetDASIMaterial(IsDlgButtonChecked(hWnd, IDC_CHECKDASIMATERIAL));
|
|
exp->SetDASITexture(IsDlgButtonChecked(hWnd, IDC_CHECKDASITEXTURE));
|
|
|
|
// blend shapes
|
|
exp->SetExportBlendShapes(IsDlgButtonChecked(hWnd, IDC_EXPORTBLENDSHAPES));
|
|
exp->SetExportBlendShapeAnims(IsDlgButtonChecked(hWnd, IDC_EXPORTBLENDSHAPEANIMS));
|
|
exp->SetIncludeBlendShapesInMorphController(IsDlgButtonChecked(hWnd, IDC_INCLUDEBLENDSHAPESINMORPHCONTROLLER));
|
|
exp->SetReduceRedondantBlendShapesKeys(IsDlgButtonChecked(hWnd, IDC_CHECKREDUCEREDOUNDANTKEYS_BLENDSHAPES));
|
|
//exp->SetAlphaRef(IsDlgButtonChecked(hWnd, IDC_ALPHAREF_CHECK));
|
|
|
|
char TempString[512];
|
|
GetDlgItemText(hWnd,IDC_EDITANIMATIONNAME,TempString,512); exp->SetAnimationName(TempString);
|
|
GetDlgItemText(hWnd,IDC_EDITCHARACTERNAME,TempString,512); exp->SetCharacterName(TempString);
|
|
GetDlgItemText(hWnd,IDC_EDITSTARTINGCAMERA,TempString,512); exp->SetStartingCamera(TempString);
|
|
GetDlgItemText(hWnd,IDC_EDITREADCHANNELSFILENAME,TempString,512); exp->SetReadChannelsFilename(TempString);
|
|
GetDlgItemText(hWnd,IDC_EDITREPORTFILENAME,TempString,512); exp->SetReportFilename(TempString);
|
|
|
|
exp->SetForce1x1RatioMethod( (int) SendMessage( GetDlgItem(hWnd, IDC_COMBOFORCERATIOMETHOD) , CB_GETCURSEL , 0, 0));
|
|
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_CONT_STEP_SPIN));
|
|
exp->SetKeyFrameStep(spin->GetIVal());
|
|
ReleaseISpinner(spin);
|
|
|
|
ret=SendMessage(GetDlgItem(hWnd, IDC_COMBOREPORTLEVEL), CB_GETCURSEL,0,0);
|
|
if(ret==CB_ERR) ret=0;
|
|
exp->SetReportLevel(ret);
|
|
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_CONT_COMPRESSIONSPIN));
|
|
exp->SetCompressionLevel(spin->GetIVal());
|
|
ReleaseISpinner(spin);
|
|
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_ALPHAREF_STEP_SPIN));
|
|
exp->SetAlphaRefValue(spin->GetIVal());
|
|
ReleaseISpinner(spin);
|
|
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_MESH_STEP_SPIN));
|
|
exp->SetMeshFrameStep(spin->GetIVal());
|
|
ReleaseISpinner(spin);
|
|
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_KEYSTHRESHOLDSPIN));
|
|
exp->SetKeysThreshold( spin->GetFVal() );
|
|
ReleaseISpinner(spin);
|
|
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_KEYSTHRESHOLDSPIN_BLENDSHAPES));
|
|
exp->SetBlendShapesKeysThreshold( spin->GetFVal() );
|
|
ReleaseISpinner(spin);
|
|
|
|
spin = GetISpinner(GetDlgItem(hWnd, IDC_BLENDSHAPES_STEP_SPIN));
|
|
exp->SetBlendShapesStep(spin->GetIVal());
|
|
ReleaseISpinner(spin);
|
|
|
|
EndDialog(hWnd, 1);
|
|
break;
|
|
}
|
|
case IDCANCEL:
|
|
EndDialog(hWnd, 0);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// Dummy function for progress bar
|
|
DWORD WINAPI fn(LPVOID arg)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
// Start the exporter!
|
|
// This is the real entrypoint to the exporter. After the user has selected
|
|
// the filename (and he's prompted for overwrite etc.) this method is called.
|
|
int Max2Nmo::DoExport(const TCHAR *name,ExpInterface *ei,Interface *inf, BOOL suppressPrompts, DWORD options)
|
|
{
|
|
// Grab the interface pointer.
|
|
ip = inf;
|
|
|
|
#ifdef _USESCRIPTS_
|
|
if( name ){
|
|
theVirtoolsTool.m_ExportFileName = name;
|
|
for( int a=0 ; a<theVirtoolsTool.m_ExportFileName.Length() ; ++a ){
|
|
if( theVirtoolsTool.m_ExportFileName[a] == '\\' ){
|
|
theVirtoolsTool.m_ExportFileName[a] = '/';
|
|
}
|
|
}
|
|
} else {
|
|
theVirtoolsTool.m_ExportFileName = "";
|
|
}
|
|
|
|
theVirtoolsTool.BeginEditParams( inf, NULL );
|
|
|
|
return 1;
|
|
|
|
#else
|
|
|
|
// store the export file name, which will be accessed
|
|
// by the options dialog
|
|
m_ExportFileName = name;
|
|
|
|
// Get the options the user selected the last time
|
|
ReadConfig();
|
|
|
|
if (!suppressPrompts) {
|
|
// Prompt the user with our dialogbox, and get all the options.
|
|
if (!DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_MAX2NMOEXPORT_DLG),
|
|
ip->GetMAXHWnd(), ExportDlgProc, (LPARAM)this)) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// Araya: don't force this for max script command, but only for the dialog version
|
|
this->bForceAllUVs=true;
|
|
|
|
SetShowProgressionBar( TRUE );
|
|
int res = ReallyDoExport( name, ip, (options&SCENE_EXPORT_SELECTED)? TRUE:FALSE );
|
|
|
|
return res;
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
// This method do the export job, and suppose all the parameters
|
|
// has correctly been set (by the export UI, or with MAXScript)
|
|
int Max2Nmo::ReallyDoExport( const TCHAR *name, Interface *inf, BOOL sel )
|
|
{
|
|
ip = inf;
|
|
exportSelected = sel;
|
|
|
|
m_ExportFileName = name;
|
|
|
|
// Virtools Engine initialization
|
|
if (!VirtoolsPluginsParsed) {
|
|
|
|
#ifndef MAX42
|
|
//------ Check the version of Physique installed...
|
|
g_CharacterStudio312 = FALSE;
|
|
// Parse every plugin dir to find Physique Version !
|
|
DWORD Version1,Version2,Version3,Version4;
|
|
for (int k=0;k<ip->GetPlugInEntryCount();k++) {
|
|
XString Path = ip->GetPlugInDir(k);
|
|
Path << "Physique.dlm";
|
|
if (GetVersionInfo(Path.Str(),Version1,Version2,Version3,Version4)) {
|
|
#ifdef MAX4
|
|
// For Max 4 incompatibility starts at version 3.0.2
|
|
if ((Version1 >= 3) && ( Version2 >= 1) && ( Version3 >= 2)) {
|
|
g_CharacterStudio312 = TRUE;
|
|
}
|
|
#else
|
|
// For Max 3 incompatibility starts at version 3.0.2
|
|
if ((Version1 >= 3) && ( Version2 >= 0) && ( Version3 >= 2)) {
|
|
g_CharacterStudio312 = TRUE;
|
|
}
|
|
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
//-------------------------------------------------------
|
|
|
|
#ifdef CK_LIB
|
|
// Register static plugins that we use...
|
|
CKPluginManager* pm = CKGetPluginManager();
|
|
|
|
// NULL Rasterizer
|
|
RegisterRenderEngine(pm);
|
|
|
|
// Image Plugins
|
|
RegisterImageReader(pm);
|
|
RegisterAVIReader(pm);
|
|
RegisterPNGReader(pm);
|
|
RegisterJPGReader(pm);
|
|
RegisterDDSReader(pm);
|
|
RegisterTIFFReader(pm);
|
|
|
|
//--- Mesh Modifier Static
|
|
RegisterMeshesBehaviors(pm);
|
|
|
|
#else
|
|
for (int j=0;j<ip->GetPlugInEntryCount();j++)
|
|
CKGetPluginManager()->ParsePlugins(ip->GetPlugInDir(j));
|
|
#endif
|
|
VirtoolsPluginsParsed = TRUE;
|
|
}
|
|
|
|
if( !g_VirtoolsContext ){
|
|
if (CKCreateContext(&VirtoolsContext,ip->GetMAXHWnd(),0) != CK_OK)
|
|
{
|
|
MessageBox(NULL, "CK Initialisation Problems", "Max2Nmo", MB_OK);
|
|
return 1;
|
|
}
|
|
|
|
VirtoolsContext->GetVariableManager()->SetStringValue("Globals/StartingFlags","Disable Sound,Disable Input");
|
|
|
|
//-- Add Max Bitmap path to Virtools PathManager
|
|
int BitmapPathCount = TheManager->GetMapDirCount();
|
|
for(int i=0;i<BitmapPathCount;i++) {
|
|
VirtoolsContext->GetPathManager()->AddPath(BITMAP_PATH_IDX,XString(TheManager->GetMapDir(i)));
|
|
}
|
|
|
|
RegisterAllSpecialParameters();
|
|
|
|
g_VirtoolsContext = VirtoolsContext;
|
|
|
|
} else {
|
|
|
|
VirtoolsContext = g_VirtoolsContext;
|
|
}
|
|
|
|
|
|
|
|
// Virtools Exporter context creation
|
|
VirtoolsExporter = new Export2Virtools(VirtoolsContext, TRUE);
|
|
//Start Log to file... all Report call are also redirected to the same file Ge2Virtools uses as log.
|
|
if(GetReport())
|
|
{
|
|
m_ReportGeLog= new GeFileLog( GetReportFilename() );
|
|
if( m_ReportGeLog->InitLog() == FALSE){
|
|
delete m_ReportGeLog;
|
|
m_ReportGeLog=NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_ReportGeLog=NULL;
|
|
}
|
|
VirtoolsExporter->m_FileLog=m_ReportGeLog;
|
|
|
|
// Rescale Scene to 1 unit = 1 meter if asked
|
|
if (GetRescaleScene()) {
|
|
RescaleScene();
|
|
Report(REPORT_HLEVEL,"Scene rescaled to 1 unit = 1 meter\r\n");
|
|
}
|
|
|
|
// First we write out a file header with global information.
|
|
Interval range = ip->GetAnimRange();
|
|
m_StartFrame = (float)range.Start();
|
|
m_EndFrame = (float)range.End();
|
|
m_InvFrameRate = 1.0f/(float)GetTicksPerFrame();
|
|
|
|
|
|
// Startup the progress bar.
|
|
this->SetShowProgressionBar(TRUE);
|
|
if( GetShowProgressionBar() ){
|
|
ip->ProgressStart(GetString(IDS_PROGRESS_MSG), TRUE, fn, NULL);
|
|
}
|
|
|
|
// Get a total node count by traversing the scene
|
|
// We don't really need to do this, but it doesn't take long, and
|
|
// it is nice to have an accurate progress bar.
|
|
nTotalNodeCount = 0;
|
|
nCurNode = 0;
|
|
PreProcess(ip->GetRootNode(), nTotalNodeCount);
|
|
|
|
//-- Get the Level Settings
|
|
if( this->GetExportAsLevel() ){
|
|
Report(REPORT_HLEVEL,"---------Exporting Environment and Atmosphere Settings----------\r\n");
|
|
ExportLevelSettings();
|
|
}
|
|
|
|
//-- Export list of material definitions
|
|
Report(REPORT_HLEVEL,"---------Exporting materials----------\r\n");
|
|
ExportMaterialList();
|
|
|
|
Report(REPORT_HLEVEL,"\r\n");
|
|
Report(REPORT_HLEVEL,"-----------Exporting objects-----------\r\n");
|
|
// Call our node enumerator.
|
|
// The nodeEnum function will recurse into itself and
|
|
// export each object found in the scene.
|
|
ip->SetCancel(FALSE);//set cancel to false.
|
|
int numChildren = ip->GetRootNode()->NumberOfChildren();
|
|
for (int idx=0; idx<numChildren; idx++) {
|
|
if (ip->GetCancel()){//Give some feed back if it is cancel
|
|
Report(REPORT_HLEVEL,"Canceled by user at object %d\r\n",idx);
|
|
break;
|
|
}
|
|
nodeEnum(ip->GetRootNode()->GetChildNode(idx));
|
|
}
|
|
|
|
Report(REPORT_HLEVEL,"\r\n");
|
|
Report(REPORT_HLEVEL,"------ Exporting animated meshes ------\r\n");
|
|
|
|
//-- Check if there are animated meshes (morph, skin, physique)
|
|
PostProcess(ip->GetRootNode());
|
|
|
|
//--Remove unused channel materials
|
|
if( this->GetForceAllUVs() ){
|
|
|
|
for(int i=0; i< MAX_UVCHANNEL_COUNT; i++){
|
|
if(UsedChannels[i]== false || i==0){
|
|
CKMaterial* m=VirtoolsExporter->GetMaterialByKey((void*)(i+1));
|
|
if(m!=NULL)
|
|
VirtoolsExporter->DestroyObject(m,(void*)(i+1) );
|
|
}
|
|
}
|
|
}
|
|
// We're done. Finish the progress bar.
|
|
if( GetShowProgressionBar() ){
|
|
ip->ProgressEnd();
|
|
}
|
|
|
|
|
|
// Write the current options to be used next time around.
|
|
WriteConfig();
|
|
|
|
|
|
// Finish creating appropriate objects
|
|
|
|
///// What is this ?!?!?!?
|
|
///// it created a global animation ... see swap-meet post
|
|
///// http://www.theswapmeet-forum.com/viewtopic.php?t=5204&highlight=&sid=511000f9f2c4421d2db0a2ca10a0e991
|
|
/////
|
|
CKKeyedAnimation* GlobalAnim = VirtoolsExporter->CreateGlobalAnimation(GetAnimationName());
|
|
GlobalAnim->SetLength(FrameTime(m_EndFrame));
|
|
|
|
if (GetExportAsCharacter()) {
|
|
Report(REPORT_HLEVEL,"\r\n");
|
|
Report(REPORT_HLEVEL,"Creating character : %s\r\n",GetCharacterName());
|
|
VirtoolsExporter->CreateCharacter(GetCharacterName());
|
|
}
|
|
|
|
|
|
if (GetStoreOnlyFilenames())
|
|
VirtoolsContext->SetGlobalImagesSaveOptions(CKTEXTURE_EXTERNAL);
|
|
else
|
|
VirtoolsContext->SetGlobalImagesSaveOptions(CKTEXTURE_RAWDATA);
|
|
|
|
|
|
//Activate or deactivate Split Mesh Algorithm
|
|
VirtoolsExporter->SetSplitMesh( this->GetSplitMesh()==TRUE );
|
|
|
|
// Generate the final list containing all the CKObjects
|
|
CKFile* VirtoolsFile = VirtoolsContext->CreateCKFile();
|
|
m_VirtoolsObjects = CreateCKObjectArray();
|
|
|
|
VirtoolsExporter->GenerateObjects(m_VirtoolsObjects,GetExportAsAnimationOnly(), GetExportAsLevel() );
|
|
|
|
|
|
// Create Groups for Named Selection Sets
|
|
if( GetSelectionAsGroup() ){
|
|
Report(REPORT_HLEVEL,"\r\n");
|
|
Report(REPORT_HLEVEL,"----------- Exporting Named Selections -----------\r\n");
|
|
int namedSelCount = ip->GetNumNamedSelSets();
|
|
for( int a=0 ; a<namedSelCount ; ++a ){
|
|
CKGroup *grp = (CKGroup *)VirtoolsContext->CreateObject( CKCID_GROUP, ip->GetNamedSelSetName(a) );
|
|
if( !grp ) continue;
|
|
|
|
int selObjCount = ip->GetNamedSelSetItemCount(a);
|
|
for( int b=0 ; b<selObjCount ; ++b ){
|
|
INode *selNode = ip->GetNamedSelSetItem( a, b);
|
|
CK3dEntity *selEnt = VirtoolsExporter->GetEntityByKey( selNode );
|
|
if( !selEnt ){
|
|
selEnt = VirtoolsExporter->GetLightByKey( selNode );
|
|
if( !selEnt ){
|
|
selEnt = VirtoolsExporter->GetCameraByKey( selNode );
|
|
}
|
|
}
|
|
if( selEnt ){
|
|
grp->AddObject( selEnt );
|
|
}
|
|
}
|
|
|
|
if( grp->GetObjectCount() ){
|
|
m_VirtoolsObjects->InsertFront( grp );
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef _USESCRIPTS_
|
|
Report(REPORT_HLEVEL,"\r\n");
|
|
Report(REPORT_HLEVEL,"----------- Evaluating User Defined Properties -----------\r\n");
|
|
// Call our node user defined properties evaluator.
|
|
// The nodeEnum function will recurse into itself and
|
|
// evaluate each user defined properties
|
|
for( idx=0; idx<numChildren; idx++) {
|
|
if (ip->GetCancel())
|
|
break;
|
|
evaluateNodeUserDefinedProperties( ip->GetRootNode()->GetChildNode(idx) );
|
|
}
|
|
|
|
// If some scripts has been added
|
|
// we must create a Level
|
|
int behCount = VirtoolsContext->GetObjectsCountByClassID( CKCID_BEHAVIOR );
|
|
if( behCount ){
|
|
|
|
// create a level
|
|
CKLevel *level = (CKLevel *)VirtoolsContext->CreateObject( CKCID_LEVEL );
|
|
CKScene* LevelScene = level->GetLevelScene();
|
|
VirtoolsContext->SetCurrentLevel(level);
|
|
|
|
// add all objects to this level
|
|
for( m_VirtoolsObjects->Reset() ; !m_VirtoolsObjects->EndOfList() ; ){
|
|
CKObject *tmpObj = m_VirtoolsObjects->GetData( VirtoolsContext );
|
|
|
|
// if their was already a scene or a level remove it
|
|
if (CKIsChildClassOf(tmpObj,CKCID_SCENE) || CKIsChildClassOf(tmpObj,CKCID_LEVEL)) {
|
|
m_VirtoolsObjects->RemoveAt();
|
|
|
|
// if it isn't a level (or scene)
|
|
} else {
|
|
|
|
DWORD SceneFlags = 0;
|
|
CKSceneObject* ScnObj = NULL;
|
|
|
|
// if the object is attached to a scene
|
|
if (CKIsChildClassOf(tmpObj,CKCID_SCENEOBJECT)) {
|
|
ScnObj = (CKSceneObject*)tmpObj;
|
|
CKScene *Scene = ScnObj->GetSceneIn(0);
|
|
|
|
if (Scene && Scene!=LevelScene) {
|
|
// get the scripts activation states
|
|
SceneFlags = Scene->GetObjectFlags(ScnObj);
|
|
}
|
|
}
|
|
|
|
// add object to the created level
|
|
level->AddObject( tmpObj );
|
|
|
|
if (SceneFlags) {
|
|
// put scripts activation states
|
|
LevelScene->SetObjectFlags( ScnObj, (CK_SCENEOBJECT_FLAGS)SceneFlags);
|
|
}
|
|
|
|
m_VirtoolsObjects->Next();
|
|
}
|
|
}
|
|
|
|
// add the created level to the list of objects to be saved
|
|
// only for the web player (because it has no level and it need one)
|
|
// but don't save the level if it's supposed to be loaded by some
|
|
// application (like Dev) that already has a level (because it won't be loaded).
|
|
//
|
|
// if we save without level, the scripts activation states will be saved
|
|
// into a special chunk
|
|
|
|
XString fileName = name;
|
|
CKPathSplitter splitter( fileName.Str() );
|
|
char *fileNameExtension = splitter.GetExtension();
|
|
if( strcmp(fileNameExtension, ".nmo") ){ // save the level only for ".cmo" and ".vmo"
|
|
m_VirtoolsObjects->InsertFront( level );
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
//--- Set Compression Level
|
|
if( GetCompressionLevel() ){
|
|
VirtoolsContext->SetFileWriteMode( CKFILE_WHOLECOMPRESSED );
|
|
VirtoolsContext->SetCompressionLevel( GetCompressionLevel() );
|
|
} else {
|
|
VirtoolsContext->SetFileWriteMode( CKFILE_UNCOMPRESSED );
|
|
}
|
|
|
|
//---- Normalizing root anim Y orientation aligning it with the Z world
|
|
if ((GetExportAsCharacter() || GetExportAsAnimationOnly()) && GetAlignAnimOnZ()) {
|
|
CK_ID* pid = VirtoolsContext->GetObjectsListByClassID(CKCID_KEYEDANIMATION);
|
|
CKKeyedAnimation* ka = (CKKeyedAnimation*) VirtoolsContext->GetObject(*pid);
|
|
|
|
if (ka) {
|
|
CKObjectAnimation* oa = ka->GetAnimation(ka->GetRootEntity()) ;
|
|
if (oa) {
|
|
CKAnimController* rctrl = oa->GetRotationController();
|
|
int rkeycount=0;
|
|
if (rctrl && (rkeycount=rctrl->GetKeyCount())) {
|
|
VxQuaternion diffy,first,dest;
|
|
CKRotationKey* rotkey = NULL;
|
|
VxMatrix or0;
|
|
|
|
rotkey = (CKRotationKey*) rctrl->GetKey(0);
|
|
first = rotkey->GetRotation();
|
|
first.ToMatrix(or0);
|
|
VxVector dir0(or0[0][2],or0[1][2],or0[2][2]);
|
|
dir0.y = 0.0f;
|
|
dir0.Normalize();
|
|
float dot = DotProduct(dir0,VxVector::axisZ());
|
|
if (dot>1.0f)
|
|
dot = 1.0f;
|
|
if (dot<-1.0f)
|
|
dot = -1.0f;
|
|
float angle = acosf(dot);
|
|
if (!_isnan(angle)) {
|
|
diffy.FromRotation(VxVector(0.0f,1.0f,0.0f),-(PI/2 - angle));
|
|
for (int ki = 0; ki<rkeycount;ki++) {
|
|
rotkey = (CKRotationKey*) rctrl->GetKey(ki);
|
|
dest = rotkey->GetRotation();
|
|
dest.Multiply(diffy);
|
|
dest.Normalize();
|
|
rotkey->SetRotation(dest);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//---PostProcess
|
|
|
|
Report(REPORT_HLEVEL,"\n---------- Post Process ------------\n");
|
|
if( this->m_RescaleFactor!= 1.0f)
|
|
VirtoolsExporter->RescaleScene(m_RescaleFactor);
|
|
|
|
if( this->GetUsePower2() )
|
|
VirtoolsExporter->ForceTextureResize( (ETextureResizeMethod) GetForce1x1RatioMethod(), GetForce1x1Ratio()==TRUE );
|
|
|
|
if( this->GetDASITexture() )
|
|
VirtoolsExporter->DASITexturesGlobal();
|
|
|
|
if( this->GetDASIMaterial() )
|
|
VirtoolsExporter->DASIMaterialsGlobal();
|
|
|
|
if( this->GetDASIMesh() )
|
|
VirtoolsExporter->DASIMeshesGlobal();
|
|
|
|
if( this->GetDASIAnimation() )
|
|
VirtoolsExporter->DASIAnimationsGlobal();
|
|
|
|
if( this->GetLOD() )
|
|
VirtoolsExporter->FindNamedLODGlobal("LOD",1);
|
|
|
|
if( this->GetReadChannels() )
|
|
VirtoolsExporter->ReadChannels( (CKSTRING)this->GetReadChannelsFilename() );
|
|
|
|
if(this->GetIgnore1KeyAnimation() )
|
|
VirtoolsExporter->RemoveSingleKeyAnimation( VirtoolsExporter->GetGlobalAnimation() );
|
|
|
|
if( this->ReduceRedondantKeys() )
|
|
VirtoolsExporter->ReduceAnimKeys( VirtoolsExporter->GetGlobalAnimation(), this->GetKeysThreshold(), 1, eFileSize );
|
|
|
|
if( this->GetReduceRedondantBlendShapesKeys() )
|
|
VirtoolsExporter->ReduceAnimBlendShapesKeys( VirtoolsExporter->GetGlobalAnimation(), this->GetBlendShapesKeysThreshold(), 1, eFileSize );
|
|
|
|
// Comment Thomas Bucher - 03/08/2006
|
|
//
|
|
// The helpers are already hidden in export.cpp l.509
|
|
// The AutoHideHierarchyGlobal does not do what it is supposed
|
|
// to do... it should be removed.
|
|
//if( this->GetHideHelpers() )
|
|
// VirtoolsExporter->AutoHideHierarchyGlobal();
|
|
|
|
// Write the file to hard drive
|
|
CKERROR err = VirtoolsFile->StartSave((char *)name);
|
|
if (err==CK_OK) {
|
|
VirtoolsFile->SaveObjects(m_VirtoolsObjects);
|
|
err = VirtoolsFile->EndSave();
|
|
}
|
|
if (err==CK_OK) {
|
|
Report(REPORT_HLEVEL,"\r\n");
|
|
Report(REPORT_HLEVEL,"File saved succesfully\r\n");
|
|
} else {
|
|
Report(REPORT_HLEVEL,"\r\n");
|
|
Report(REPORT_HLEVEL,"Error while saving file: %s\r\n",CKErrorToString(err));
|
|
}
|
|
|
|
|
|
if (GetReportLevel())
|
|
if (!DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_REPORT),
|
|
ip->GetMAXHWnd(), ReportDlgProc, (LPARAM)this)) {
|
|
return 1;
|
|
}
|
|
|
|
|
|
// Clean Up
|
|
DeleteCKObjectArray(m_VirtoolsObjects);
|
|
m_VirtoolsObjects = NULL;
|
|
VirtoolsContext->DeleteCKFile(VirtoolsFile);
|
|
|
|
|
|
if( m_ReportGeLog ){
|
|
m_ReportGeLog->CloseLog();
|
|
delete m_ReportGeLog;
|
|
m_ReportGeLog=NULL;
|
|
}
|
|
|
|
delete VirtoolsExporter;
|
|
VirtoolsExporter = NULL;
|
|
|
|
VirtoolsContext->ClearAll();
|
|
|
|
return 1;
|
|
}
|
|
|
|
////////////////////////////////////
|
|
// Register All Special Parameters
|
|
////////////////////////////////////
|
|
BOOL Max2Nmo::RegisterAllSpecialParameters() {
|
|
|
|
CKParameterManager* pm = VirtoolsContext->GetParameterManager();
|
|
//Need to add the LOD Attribute
|
|
#ifdef _USESCRIPTS_
|
|
RegisterSpecialParameters( pm );
|
|
RegisterSpecialParameters2( pm );
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL Max2Nmo::SupportsOptions(int ext, DWORD options) {
|
|
//assert(ext == 0);
|
|
return(options == SCENE_EXPORT_SELECTED) ? TRUE : FALSE;
|
|
}
|
|
|
|
#ifdef _USESCRIPTS_
|
|
|
|
// This method parse all the nodes (recursivly), and evaluates
|
|
// the user defined properties buffer to execute some function
|
|
// like: attaching a script, setting an attribute, setting a local parameter
|
|
BOOL Max2Nmo::evaluateNodeUserDefinedProperties( INode* node ){
|
|
|
|
// Only export if exporting everything or it's selected
|
|
if(!exportSelected || node->Selected()) {
|
|
|
|
// Stop recursing if the user pressed Cancel
|
|
if (ip->GetCancel())
|
|
return FALSE;
|
|
|
|
// The ObjectState is a 'thing' that flows down the pipeline containing
|
|
// all information about the object. By calling EvalWorldState() we tell
|
|
// max to eveluate the object at end of the pipeline.
|
|
ObjectState os = node->EvalWorldState(0);
|
|
|
|
// The obj member of ObjectState is the actual object we will export.
|
|
if (os.obj) {
|
|
|
|
// We look at the super class ID to determine the type of the object.
|
|
switch(os.obj->SuperClassID()) {
|
|
case GEOMOBJECT_CLASS_ID:
|
|
case CAMERA_CLASS_ID:
|
|
case LIGHT_CLASS_ID:
|
|
case SHAPE_CLASS_ID:
|
|
case HELPER_CLASS_ID:
|
|
{
|
|
PropertiesEvaluator pe( VirtoolsExporter, node, this, m_VirtoolsObjects );
|
|
} break;
|
|
}
|
|
}
|
|
|
|
// For each child of this node, we recurse into ourselves
|
|
// until no more children are found.
|
|
for (int c = 0; c < node->NumberOfChildren(); c++) {
|
|
if (!evaluateNodeUserDefinedProperties(node->GetChildNode(c)))
|
|
return FALSE;
|
|
}
|
|
|
|
} else {
|
|
// node is not selected but one of its child may
|
|
// For each child of this node, we recurse into ourselves
|
|
// until no more children are found.
|
|
for (int c = 0; c < node->NumberOfChildren(); c++) {
|
|
if (!evaluateNodeUserDefinedProperties(node->GetChildNode(c)))
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
|
|
// This method is the main object exporter.
|
|
// It is called once of every node in the scene. The objects are
|
|
// exported as they are encoutered.
|
|
|
|
// Before recursing into the children of a node, we will export it.
|
|
// The benefit of this is that a nodes parent is always before the
|
|
// children in the resulting file. This is desired since a child's
|
|
// transformation matrix is optionally relative to the parent.
|
|
|
|
BOOL Max2Nmo::nodeEnum(INode* node)
|
|
{
|
|
// Only export if exporting everything or it's selected
|
|
if(!exportSelected || node->Selected()) {
|
|
nCurNode++;
|
|
if( GetShowProgressionBar() ){
|
|
ip->ProgressUpdate((int)((float)nCurNode/nTotalNodeCount*100.0f));
|
|
}
|
|
|
|
// Stop recursing if the user pressed Cancel
|
|
if (ip->GetCancel())
|
|
return FALSE;
|
|
|
|
// If this node is a group head, all children are
|
|
// members of this group. The node will be a dummy node and the node name
|
|
// is the actualy group name.
|
|
if (node->IsGroupHead()) {
|
|
// TODO
|
|
if (!GetGroupAsPlace()) {
|
|
CKGroup* group = VirtoolsExporter->AddGroup(node->GetName(),node);
|
|
// If there was a group being parsed : Add the newly created group
|
|
CKGroup* PrevGroup = CKGroups.Size() ? CKGroups.Back() : NULL;
|
|
if (PrevGroup) {
|
|
PrevGroup->AddObject(group);
|
|
}
|
|
|
|
CKGroups.PushBack(group);
|
|
}
|
|
}
|
|
|
|
// The ObjectState is a 'thing' that flows down the pipeline containing
|
|
// all information about the object. By calling EvalWorldState() we tell
|
|
// max to eveluate the object at end of the pipeline.
|
|
ObjectState os = node->EvalWorldState(0);
|
|
|
|
// The obj member of ObjectState is the actual object we will export.
|
|
if (os.obj) {
|
|
|
|
// We look at the super class ID to determine the type of the object.
|
|
switch(os.obj->SuperClassID()) {
|
|
|
|
case GEOMOBJECT_CLASS_ID:
|
|
ExportGeomObject(node);
|
|
break;
|
|
|
|
case CAMERA_CLASS_ID:
|
|
ExportCameraObject(node);
|
|
break;
|
|
|
|
case LIGHT_CLASS_ID:
|
|
ExportLightObject(node);
|
|
break;
|
|
|
|
case SHAPE_CLASS_ID:
|
|
//Export the curve as a dummy if the checkbox is checked
|
|
//or if it is a character.
|
|
if(this->GetSplinesAsDummies())
|
|
ExportHelperObject(node);
|
|
else
|
|
ExportShapeObject(node);
|
|
break;
|
|
|
|
case HELPER_CLASS_ID:
|
|
ExportHelperObject(node);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// For each child of this node, we recurse into ourselves
|
|
// until no more children are found.
|
|
for (int c = 0; c < node->NumberOfChildren(); c++) {
|
|
if (!nodeEnum(node->GetChildNode(c)))
|
|
return FALSE;
|
|
}
|
|
|
|
// If this is true here, it is the end of the group we started above.
|
|
if (node->IsGroupHead()) {
|
|
if (!GetGroupAsPlace()) {
|
|
CKGroups.PopBack();
|
|
}
|
|
GroupIndent-=2;
|
|
}
|
|
} else {
|
|
// node is not selected but one of its child may
|
|
// For each child of this node, we recurse into ourselves
|
|
// until no more children are found.
|
|
for (int c = 0; c < node->NumberOfChildren(); c++) {
|
|
if (!nodeEnum(node->GetChildNode(c)))
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
XString Max2Nmo::StrGroupIndent()
|
|
{
|
|
XString str = "";
|
|
for (int i=0;i<GroupIndent;++i)
|
|
str << " ";
|
|
return str;
|
|
}
|
|
|
|
void Max2Nmo::PreProcess(INode* node, int& nodeCount)
|
|
{
|
|
nodeCount++;
|
|
|
|
|
|
// Add the nodes material to out material list
|
|
// Null entries are ignored when added...
|
|
if (!exportSelected || (node->Selected() == TRUE))
|
|
mtlList.AddMtl(node->GetMtl());
|
|
|
|
// For each child of this node, we recurse into ourselves
|
|
// and increment the counter until no more children are found.
|
|
for (int c = 0; c < node->NumberOfChildren(); c++) {
|
|
PreProcess(node->GetChildNode(c), nodeCount);
|
|
}
|
|
}
|
|
|
|
void Max2Nmo::PostProcess(INode* node)
|
|
{
|
|
|
|
if(!exportSelected || node->Selected()) {
|
|
ExportAnimMesh(node);
|
|
}
|
|
|
|
// For each child of this node, we recurse into ourselves
|
|
for (int c = 0; c < node->NumberOfChildren(); c++) {
|
|
PostProcess(node->GetChildNode(c));
|
|
}
|
|
}
|
|
/****************************************************************************
|
|
|
|
Configuration.
|
|
To make all options "sticky" across sessions, the options are read and
|
|
written to a configuration file every time the exporter is executed.
|
|
|
|
****************************************************************************/
|
|
|
|
TSTR Max2Nmo::GetCfgFilename()
|
|
{
|
|
TSTR filename;
|
|
|
|
filename += ip->GetDir(APP_PLUGCFG_DIR);
|
|
filename += "\\";
|
|
filename += CFGFILENAME;
|
|
|
|
return filename;
|
|
}
|
|
|
|
// NOTE: Update anytime the CFG file changes
|
|
#define CFG_BEFORECOMPRESSVERSION 0x02
|
|
#define CFG_BEFOREOPTIONREDOUNDANT 0x03
|
|
#define CFG_BEFOREOPTIONSHELLASSINGLE 0x04
|
|
#define CFG_BEFOREOPTIONIGNORE1KEYANIM 0x05
|
|
#define CFG_BEFOREOPTIONSELECTIONASGROUP 0x06 //Had to add Selection as group at the end it was not there
|
|
#define CFG_ALPHAREFADDED 0x07
|
|
#define CFG_OPTIONFORCESKINTOMORPHADDED 0x08
|
|
#define CFG_BLENDSHAPESEXPORT 0x09
|
|
#define CFG_VERSION 0x09
|
|
|
|
BOOL Max2Nmo::ReadConfig()
|
|
{
|
|
TSTR filename = GetCfgFilename();
|
|
FILE* cfgStream;
|
|
|
|
cfgStream = fopen(filename, "rt");
|
|
if (!cfgStream)
|
|
return FALSE;
|
|
int version;
|
|
char CharacterName[256];
|
|
char AnimationName[256];
|
|
char CameraName[256];
|
|
char ReadChannels[512];
|
|
|
|
CharacterName[0] = 0;
|
|
AnimationName[0] = 0;
|
|
CameraName[0] = 0;
|
|
ReadChannels[0] = 0;
|
|
|
|
|
|
|
|
//---- read Version
|
|
fscanf(cfgStream,"%d",&version);
|
|
|
|
//---- read settings
|
|
if (version < CFG_BEFORECOMPRESSVERSION) {
|
|
nCompressionLevel = 0;
|
|
fscanf(cfgStream,"%d %d %d %d %d %d %d %d %d %s %s %d %d\n",
|
|
&bExportAsObjects,
|
|
&bExportAsCharacter,
|
|
&bExportAsAnimationOnly,
|
|
&bConvertPhysiqueToSkin,
|
|
&bStoreOnlyTextureFilenames,
|
|
&bRescaleScene,
|
|
&nReportLevel,
|
|
&nMeshFrameStep,
|
|
&nKeyFrameStep,
|
|
CharacterName,
|
|
AnimationName,
|
|
&bGroupAsPlace,
|
|
&bSaveBipedGeom);
|
|
|
|
} else
|
|
//---- read settings
|
|
if (version < CFG_BEFOREOPTIONREDOUNDANT) {
|
|
fscanf(cfgStream,"%d %d %d %d %d %d %d %d %d %s %s %d %d %d %d\n",
|
|
&bExportAsObjects,
|
|
&bExportAsCharacter,
|
|
&bExportAsAnimationOnly,
|
|
&bConvertPhysiqueToSkin,
|
|
&bStoreOnlyTextureFilenames,
|
|
&bRescaleScene,
|
|
&nReportLevel,
|
|
&nMeshFrameStep,
|
|
&nKeyFrameStep,
|
|
CharacterName,
|
|
AnimationName,
|
|
&bGroupAsPlace,
|
|
&bSaveBipedGeom,
|
|
&nCompressionLevel,
|
|
&bAlignAnimOnZ);
|
|
|
|
} else {
|
|
if (version < CFG_BEFOREOPTIONSHELLASSINGLE)
|
|
fscanf(cfgStream,"%d %d %d %d %d %d %d %d %d %s %s %d %d %d %d %d\n",
|
|
&bExportAsObjects,
|
|
&bExportAsCharacter,
|
|
&bExportAsAnimationOnly,
|
|
&bConvertPhysiqueToSkin,
|
|
&bStoreOnlyTextureFilenames,
|
|
&bRescaleScene,
|
|
&nReportLevel,
|
|
&nMeshFrameStep,
|
|
&nKeyFrameStep,
|
|
CharacterName,
|
|
AnimationName,
|
|
&bGroupAsPlace,
|
|
&bSaveBipedGeom,
|
|
&nCompressionLevel,
|
|
&bAlignAnimOnZ,
|
|
&bReduceRedondantKeys);
|
|
else {
|
|
if (version < CFG_BEFOREOPTIONIGNORE1KEYANIM) {
|
|
fscanf(cfgStream,"%d %d %d %d %d %d %d %d %d %s %s %d %d %d %d %d %d\n",
|
|
&bExportAsObjects,
|
|
&bExportAsCharacter,
|
|
&bExportAsAnimationOnly,
|
|
&bConvertPhysiqueToSkin,
|
|
&bStoreOnlyTextureFilenames,
|
|
&bRescaleScene,
|
|
&nReportLevel,
|
|
&nMeshFrameStep,
|
|
&nKeyFrameStep,
|
|
CharacterName,
|
|
AnimationName,
|
|
&bGroupAsPlace,
|
|
&bSaveBipedGeom,
|
|
&nCompressionLevel,
|
|
&bAlignAnimOnZ,
|
|
&bReduceRedondantKeys,
|
|
&bShellMaterialExportBoth);
|
|
}
|
|
else {
|
|
if(version < CFG_BEFOREOPTIONSELECTIONASGROUP) {
|
|
fscanf(cfgStream,"%d %d %d %d %d %d %d %d %d %s %s %d %d %d %d %d %d %d\n",
|
|
&bExportAsObjects,
|
|
&bExportAsCharacter,
|
|
&bExportAsAnimationOnly,
|
|
&bConvertPhysiqueToSkin,
|
|
&bStoreOnlyTextureFilenames,
|
|
&bRescaleScene,
|
|
&nReportLevel,
|
|
&nMeshFrameStep,
|
|
&nKeyFrameStep,
|
|
CharacterName,
|
|
AnimationName,
|
|
&bGroupAsPlace,
|
|
&bSaveBipedGeom,
|
|
&nCompressionLevel,
|
|
&bAlignAnimOnZ,
|
|
&bReduceRedondantKeys,
|
|
&bShellMaterialExportBoth,
|
|
&bIgnore1KeyAnimation);
|
|
}
|
|
else { //Current Version
|
|
//fscanf(cfgStream,"%d %d %d %d %d %d %d %d %d %s %s %d %d %d %d %d %d %d %d %d %f %d %d %d %d %d %d %d %d %d %d %d %d %d %d %s %d %d\n",
|
|
fscanf(cfgStream,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %f %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
|
|
&bExportAsObjects,
|
|
&bExportAsCharacter,
|
|
&bExportAsAnimationOnly,
|
|
&bConvertPhysiqueToSkin,
|
|
&bStoreOnlyTextureFilenames,
|
|
&bRescaleScene,
|
|
&nReportLevel,
|
|
&nMeshFrameStep,
|
|
&nKeyFrameStep,
|
|
//CharacterName,
|
|
//AnimationName,
|
|
&bGroupAsPlace,
|
|
&bSaveBipedGeom,
|
|
&nCompressionLevel,
|
|
&bAlignAnimOnZ,
|
|
&bReduceRedondantKeys,
|
|
&bShellMaterialExportBoth,
|
|
&bIgnore1KeyAnimation,
|
|
|
|
&bExportAnimation,
|
|
&bExportAsLevel,
|
|
&fKeysThreshold,
|
|
&bForceAllUVs,
|
|
&bSplitMesh,
|
|
&bLOD,
|
|
&bSplinesAsDummies,
|
|
&bExportAlphaMap,
|
|
&bUsePower2,
|
|
&bForce1x1Ratio,
|
|
&nForce1x1RatioMethod,
|
|
&bDeactivateMeshChannels,
|
|
&bHideHelpers,
|
|
&bDASIAnimation,
|
|
&bDASIMesh,
|
|
&bDASIMaterial,
|
|
&bDASITexture,
|
|
//CameraName,
|
|
&bSelectionAsGroup,
|
|
&bReadChannels
|
|
);
|
|
|
|
fgets(CharacterName,256,cfgStream);
|
|
fgets(AnimationName,256,cfgStream);
|
|
fgets(CameraName,256,cfgStream);
|
|
fgets(ReadChannels,512,cfgStream);
|
|
|
|
if (version>=CFG_ALPHAREFADDED)
|
|
{
|
|
fscanf(cfgStream,"\n%d %d\n",
|
|
&bAlphaRef,
|
|
&iAlphaRefValue);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
if (version >= CFG_OPTIONFORCESKINTOMORPHADDED) {
|
|
fscanf(cfgStream,"%d \n", &bForceSkinToMorph);
|
|
}
|
|
|
|
if (version>=CFG_BLENDSHAPESEXPORT)
|
|
{
|
|
fscanf(cfgStream,"%d %d %d %d %f %d\n",
|
|
&bExportBlendShapes,
|
|
&bExportBlendShapeAnims,
|
|
&bIncludeBlendShapesInMorphController,
|
|
&bReduceRedondantBlendShapesKeys,
|
|
&fBlendShapesKeysThreshold,
|
|
&nBlendShapesStep
|
|
);
|
|
}
|
|
|
|
fclose(cfgStream);
|
|
|
|
if(version >= CFG_BEFOREOPTIONSELECTIONASGROUP) {
|
|
//Remove the \n character
|
|
CharacterName[strlen(CharacterName)-1]='\0';
|
|
AnimationName[strlen(AnimationName)-1]='\0';
|
|
CameraName[strlen(CameraName)-1]='\0';
|
|
ReadChannels[strlen(ReadChannels)-1]='\0';
|
|
}
|
|
|
|
|
|
SetCharacterName(CharacterName);
|
|
SetAnimationName(AnimationName);
|
|
SetStartingCamera(CameraName);
|
|
SetReadChannelsFilename(ReadChannels);
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void Max2Nmo::WriteConfig()
|
|
{
|
|
TSTR filename = GetCfgFilename();
|
|
FILE* cfgStream;
|
|
|
|
cfgStream = fopen(filename, "wt");
|
|
if (!cfgStream)
|
|
return;
|
|
|
|
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
|
fprintf(cfgStream,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %f %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n%s\n%s\n%s\n%s\n",
|
|
//01
|
|
CFG_VERSION,
|
|
GetExportAsObjects(),
|
|
GetExportAsCharacter(),
|
|
GetExportAsAnimationOnly(),
|
|
GetConvertPhysiqueToSkin(),
|
|
GetStoreOnlyFilenames(),
|
|
GetRescaleScene(),
|
|
GetReportLevel(),
|
|
GetMeshFrameStep(),
|
|
GetKeyFrameStep(),
|
|
|
|
//11
|
|
bGroupAsPlace,
|
|
bSaveBipedGeom,
|
|
GetCompressionLevel(),
|
|
bAlignAnimOnZ,
|
|
bReduceRedondantKeys,
|
|
bShellMaterialExportBoth,
|
|
bIgnore1KeyAnimation,
|
|
GetExportAnimation(),
|
|
GetExportAsLevel(),
|
|
GetKeysThreshold(),
|
|
|
|
//21
|
|
GetForceAllUVs(),
|
|
GetSplitMesh(),
|
|
GetLOD(),
|
|
GetSplinesAsDummies(),
|
|
GetExportAlphaMap(),
|
|
GetUsePower2(),
|
|
GetForce1x1Ratio(),
|
|
GetForce1x1RatioMethod(),
|
|
|
|
//31
|
|
GetDeactivateMeshChannels(),
|
|
GetHideHelpers(),
|
|
GetDASIAnimation(),
|
|
GetDASIMesh(),
|
|
GetDASIMaterial(),
|
|
GetDASITexture(),
|
|
GetSelectionAsGroup(),
|
|
GetReadChannels(),
|
|
(char *)GetCharacterName(),
|
|
(char *)GetAnimationName(),
|
|
(char *)GetStartingCamera(),
|
|
(char *)GetReadChannelsFilename()
|
|
);
|
|
|
|
//alphra ref
|
|
fprintf(cfgStream,"%d %d \n",GetAlphaRef(),GetAlphaRefValue());
|
|
fprintf(cfgStream,"%d \n", GetForceSkinToMorph());
|
|
// blend shapes
|
|
fprintf(cfgStream,"%d %d %d %d %f %d\n",
|
|
GetExportBlendShapes(),
|
|
GetExportBlendShapeAnims(),
|
|
GetIncludeBlendShapesInMorphController(),
|
|
GetReduceRedondantBlendShapesKeys(),
|
|
GetBlendShapesKeysThreshold(),
|
|
GetBlendShapesStep()
|
|
);
|
|
fclose(cfgStream);
|
|
}
|
|
|
|
|
|
|
|
|
|
void Max2Nmo::RescaleScene()
|
|
{
|
|
int type;
|
|
float scale;
|
|
float convertFactor=1.0f;
|
|
|
|
//--- Araya: If the Unit's type is Generic then we never rescale the scene... which is wrong no ?
|
|
///// well anyway I commented this line...
|
|
if (1){//UNITDISP_GENERIC != GetUnitDisplayType()) {
|
|
GetMasterUnitInfo(&type, &scale);
|
|
convertFactor=scale;
|
|
switch(type) {
|
|
case UNITS_INCHES: convertFactor*=0.0254f; break;
|
|
case UNITS_FEET: convertFactor*=0.3048f; break;
|
|
case UNITS_MILES: convertFactor*=1609.344f; break;
|
|
case UNITS_MILLIMETERS: convertFactor*=0.001f; break;
|
|
case UNITS_CENTIMETERS: convertFactor*=0.01f; break;
|
|
case UNITS_METERS: convertFactor*=1.0f; break;
|
|
case UNITS_KILOMETERS: convertFactor*=1000; break;
|
|
}
|
|
}
|
|
|
|
this->m_RescaleFactor=convertFactor;
|
|
|
|
/*Done in Post Process now
|
|
if(convertFactor!=1.0f)
|
|
{
|
|
ip->RescaleWorldUnits(convertFactor, FALSE);
|
|
SetMasterUnitInfo(UNITS_METERS,1.0f);
|
|
ip->ForceCompleteRedraw();
|
|
}*/
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
User Interface.
|
|
Functions for UI interactivity.
|
|
|
|
****************************************************************************/
|
|
void Max2Nmo::UIEnableAnimation(HWND hWnd, BOOL v)
|
|
{
|
|
EnableWindow( GetDlgItem(hWnd, IDC_CHECKALIGNANIMATIONS), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_CHECK_IGNORE1KEYANIMATION), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_CHECKREDUCEREDOUNDANTKEYS), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_KEYSTHRESHOLD), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_KEYSTHRESHOLDSPIN), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_MESH_STEP), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_MESH_STEP_SPIN), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_CONT_STEP), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_CONT_STEP_SPIN), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_EDITANIMATIONNAME), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_CHECK_FORCESKINTOMORPH), v);
|
|
|
|
EnableWindow( GetDlgItem(hWnd, IDC_RADIOSKIN), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_RADIOMORPH), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_STATIC_PHYSIQUECONVERSION), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_STATIC_CONTROLLERSOUTPUT), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_STATIC_THRESHOLD), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_STATIC_CONTROLLERS1), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_STATIC_CONTROLLERS2), v);
|
|
|
|
EnableWindow( GetDlgItem(hWnd, IDC_EXPORTBLENDSHAPEANIMS), v);
|
|
|
|
EnableWindow( GetDlgItem(hWnd, IDC_KEYSTHRESHOLD_BLENDSHAPES), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_KEYSTHRESHOLDSPIN_BLENDSHAPES), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_STATIC_THRESHOLD_BLENDSHAPES), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_STATIC_THRESHOLD_RANGE_BLENDSHAPES), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_STATIC_CONTROLLERS3), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_BLENDSHAPES_STEP), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_BLENDSHAPES_STEP_SPIN), v);
|
|
EnableWindow( GetDlgItem(hWnd, IDC_CHECKREDUCEREDOUNDANTKEYS_BLENDSHAPES), v);
|
|
|
|
|
|
BOOL blendShapesOn = IsDlgButtonChecked(hWnd, IDC_EXPORTBLENDSHAPES) || IsDlgButtonChecked(hWnd, IDC_EXPORTBLENDSHAPEANIMS);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_INCLUDEBLENDSHAPESINMORPHCONTROLLER), !blendShapesOn && v);
|
|
|
|
// converting physique or skin to morph is not compatible with separate blend shape export
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECK_FORCESKINTOMORPH), !blendShapesOn && v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_STATIC_PHYSIQUECONVERSION), !blendShapesOn && v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_RADIOSKIN), !blendShapesOn && v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_RADIOMORPH), !blendShapesOn && v);
|
|
}
|
|
|
|
void Max2Nmo::UIEnableCharacter(HWND hWnd, BOOL v)
|
|
{
|
|
EnableWindow(GetDlgItem(hWnd, IDC_EDITCHARACTERNAME), v);
|
|
}
|
|
|
|
void Max2Nmo::UIEnableLevel(HWND hWnd, BOOL v)
|
|
{
|
|
EnableWindow(GetDlgItem(hWnd, IDC_EDITSTARTINGCAMERA), v);
|
|
}
|
|
|
|
void Max2Nmo::UIEnableTextureOptions(HWND hWnd, BOOL v)
|
|
{
|
|
if(!IsDlgButtonChecked(hWnd, IDC_RADIOEXPORTASANIMATION )){
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKPOWER2), v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKFORCERATIO), v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_COMBOFORCERATIOMETHOD), v);
|
|
}
|
|
|
|
}
|
|
|
|
void Max2Nmo::UIAnimationOnly(HWND hWnd)
|
|
{
|
|
BOOL v= IsDlgButtonChecked(hWnd, IDC_RADIOEXPORTASANIMATION )==TRUE;
|
|
|
|
//Force Export Anim
|
|
if(v)
|
|
{
|
|
CheckDlgButton(hWnd, IDC_CHECKEXPORTANIMATION ,v );
|
|
}
|
|
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKEXPORTANIMATION), !v );
|
|
|
|
//Disable unwanted settings
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKGROUPASPLACE), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKFORCEUVS), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKSPLITMESH), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKSHELLMATERIALASSINGLE), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKALPHAMAP), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKSTOREFILENAMES), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKPOWER2), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKFORCERATIO), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_COMBOFORCERATIOMETHOD), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKDEACTIVATEMESHCHANNELS), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKCHANNELSETTINGS), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_EDITREADCHANNELSFILENAME), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_BUTTON_GETCHANNELFILE), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKHIDEHELPERS), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKDASIMESH), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKDASIMATERIAL), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKDASITEXTURE), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKDEACTIVATEMESHCHANNELS), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKBIPEDMESH), !v);
|
|
//EnableWindow(GetDlgItem(hWnd, IDC_ALPHAREF_CHECK), !v);
|
|
if (GetAlphaRef())
|
|
{
|
|
EnableWindow(GetDlgItem(hWnd, IDC_ALPHAREF_STEP), !v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_ALPHAREF_STEP_SPIN), !v);
|
|
}
|
|
}
|
|
|
|
void Max2Nmo::UIEnableGeometryOptions(HWND hWnd, BOOL v )
|
|
{
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKDEACTIVATEMESHCHANNELS), v);
|
|
}
|
|
|
|
void Max2Nmo::UIEnableResizeTexture(HWND hWnd, BOOL v )
|
|
{
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKFORCERATIO), v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_COMBOFORCERATIOMETHOD), v);
|
|
}
|
|
|
|
void Max2Nmo::UIEnableReadChannels(HWND hWnd, BOOL v )
|
|
{
|
|
EnableWindow(GetDlgItem(hWnd, IDC_EDITREADCHANNELSFILENAME), v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_BUTTON_GETCHANNELFILE), v);
|
|
}
|
|
|
|
void Max2Nmo::UIEnableReport(HWND hWnd, BOOL v )
|
|
{
|
|
EnableWindow(GetDlgItem(hWnd, IDC_EDITREPORTFILENAME), v);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_BUTTON_GETREPORTFILE), v);
|
|
}
|
|
|
|
void Max2Nmo::UIUpdate(HWND hWnd)
|
|
{
|
|
UIAnimationOnly(hWnd);
|
|
UIEnableAnimation(hWnd, IsDlgButtonChecked(hWnd, IDC_CHECKEXPORTANIMATION )==1 );
|
|
UIEnableCharacter(hWnd, IsDlgButtonChecked(hWnd, IDC_RADIOEXPORTASCHARACTER )==1);
|
|
UIEnableLevel(hWnd, IsDlgButtonChecked(hWnd, IDC_RADIOEXPORTASLEVEL )==1);
|
|
UIEnableTextureOptions(hWnd, IsDlgButtonChecked(hWnd, IDC_CHECKSTOREFILENAMES )==0);
|
|
|
|
if( IsWindowEnabled(GetDlgItem(hWnd, IDC_CHECKFORCEUVS)))
|
|
UIEnableGeometryOptions(hWnd, IsDlgButtonChecked(hWnd, IDC_CHECKFORCEUVS )==1 );
|
|
|
|
if( IsWindowEnabled(GetDlgItem(hWnd, IDC_CHECKPOWER2)))
|
|
UIEnableResizeTexture(hWnd, IsDlgButtonChecked(hWnd, IDC_CHECKPOWER2 )==1 );
|
|
|
|
if( IsWindowEnabled(GetDlgItem(hWnd, IDC_CHECKCHANNELSETTINGS)))
|
|
UIEnableReadChannels(hWnd, IsDlgButtonChecked(hWnd, IDC_CHECKCHANNELSETTINGS )==1 );
|
|
|
|
if( IsWindowEnabled(GetDlgItem(hWnd, IDC_CHECKREPORT)))
|
|
UIEnableReport(hWnd, IsDlgButtonChecked(hWnd, IDC_CHECKREPORT )==1 );
|
|
|
|
BOOL b = IsDlgButtonChecked(hWnd, IDC_CHECKSTOREFILENAMES);
|
|
EnableWindow(GetDlgItem(hWnd, IDC_CHECKALPHAMAP), !b);
|
|
|
|
if (b)
|
|
CheckDlgButton(hWnd, IDC_CHECKALPHAMAP,0);
|
|
|
|
|
|
}
|
|
|
|
void Max2Nmo::UIToolTips(HWND hWnd)
|
|
{
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_RADIO_USEKEYS), (LPTSTR)"ToolTip1" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_RADIO_SAMPLE), (LPTSTR)"ToolTip2" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_IKJOINTS), (LPTSTR)"ToolTip3" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_OBJ_LIGHT), (LPTSTR)"ToolTip4" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_VERTEXCOLORS), (LPTSTR)"ToolTip5" );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_RADIOEXPORTASOBJECTS), (LPTSTR)"Export scene to objects" );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_RADIOEXPORTASCHARACTER), (LPTSTR)"Export scene as a character. Be sure there is only one root in the scene." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_RADIOEXPORTASANIMATION), (LPTSTR)"Export scene as animation only." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_RADIOEXPORTASLEVEL), (LPTSTR)"Export scene as a level. It produce a CMO and save ambient lighting and fog settings." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_EDITANIMATIONNAME), (LPTSTR)"Enter the animation name." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_EDITSTARTINGCAMERA), (LPTSTR)"The level starting camera name. You need a valid camera to export fog settings correctly since the Effect near and far camera planes influence how the fog is calculated by the 3DSMax renderer." );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_STATIC_ANIMNAME), (LPTSTR)"ToolTip11" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_EDITCHARACTERNAME), (LPTSTR)"ToolTip12" );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_RADIOSKIN), (LPTSTR)"Physique Deformation will be converted to a Virtools Skin and the bones' animations will be exported." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_RADIOMORPH), (LPTSTR)"Physique Deformation will be converted to Morph Animation. The bones won't be link to the mesh." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKRESCALESCENE), (LPTSTR)"Enabling this will apply a scaling where 1 MAX unit = 1 Virtools (NOT SURE)" );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKSTOREFILENAMES), (LPTSTR)"Enabling this will save only the texture name. Otherwise textures are included in the file. If you see blank texture in Virtools check your ressources paths for a _marker or the Path Manager." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKGROUPASPLACE), (LPTSTR)"Groups will be converted to places." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKBIPEDMESH), (LPTSTR)"Checking this will export the Biped geometry" );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKALIGNANIMATIONS), (LPTSTR)"Align the character animation on the Z." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKREDUCEREDOUNDANTKEYS), (LPTSTR)"When successive animation keys are equal, keys will be deleted to optimize the size of the animation." );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_MATERIAL_OPTIONSGROUP), (LPTSTR)"ToolTip21" );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKSHELLMATERIALASSINGLE), (LPTSTR)"A shell material has 2 submaterials, a render one and a viewport one. By default only the viewport one is exported. Check this if you want both." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKFORCEUVS), (LPTSTR)"By default UVs are extracted every time a MAX material or a sub material (Std, MultiSubObject, Blend, Shell, Composite) has a bitmap map in its diffuse slot. Check this to force the export of all mapping channels even if there is no map applied." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECK_IGNORE1KEYANIMATION), (LPTSTR)"Check this to ignore animation on object with only one keyframe. It is usfull if you want to make secondary animations" );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_COMBOFORCERATIOMETHOD), (LPTSTR)"Select the method used when converting the size of textures." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKALPHAMAP), (LPTSTR)"Export opacity map. If the alpha map is not the same as the opacity map, a copy of the texture is created." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKPOWER2), (LPTSTR)"Force the texture size to a power of 2. (2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 or 2048)" );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKFORCERATIO), (LPTSTR)"Force textures to have the same weight and height." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKDEACTIVATEMESHCHANNELS), (LPTSTR)"Deactive all the mesh channels. Usefull when using shaders because you don't want to use the fixed multipass pipeline.");
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKHIDEHELPERS), (LPTSTR)"Only meshes will be visible. This is usefull for a character skin export when you don't want to see bones or curves.");
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKLOD), (LPTSTR)"Meshes having the LOD1,LOD2,...LOD9 suffixes will be considered Level of Detail Meshes. A LOD object attribute is added to LOD 3DEntities and unwanted 3DEntities are removed." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKSPLINESASDUMMIES), (LPTSTR)"Consider Spline as Dummies usefull when you have a character rig with spline controlling the bones. Only the transformation matrix of the spline is used and a 3DFrame is created." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKEXPORTANIMATION), (LPTSTR)"Enable or Disable the Animation Export." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECK_FORCESKINTOMORPH), (LPTSTR)"Force skin animations to be exported as mesh animations." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKDASIANIMATION), (LPTSTR)"PostProcess: Detect and Share Identical Animations." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKDASIMESH), (LPTSTR)"PostProcess: Detect and Share Identical Meshes." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKDASIMATERIAL), (LPTSTR)"PostProcess: Detect and Share Identical Materials." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKDASITEXTURE), (LPTSTR)"PostProcess: Detect and Share Identical Textures." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CHECKSPLITMESH), (LPTSTR)"This options will split a mesh if more than one multilayer material(shell, blend, composite) is used by a MultiSubObject Material." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CONT_STEP), (LPTSTR)"Change the sampling rate of unsupported controllers." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_CONT_STEP_SPIN), (LPTSTR)"Change the sampling rate of unsupported controllers." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_MESH_STEP), (LPTSTR)"Change the sampling rate use for morph animations." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_MESH_STEP_SPIN), (LPTSTR)"Change the sampling rate use for morph animations." );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_CONT_REPORT), (LPTSTR)"ToolTip48" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_CONT_REPORTSPIN), (LPTSTR)"ToolTip49" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_STATIC_FRAME), (LPTSTR)"ToolTip50" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_CONT_COMPRESSION), (LPTSTR)"ToolTip51" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_STATIC_FRAME_SPIN), (LPTSTR)"ToolTip52" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_CONT_COMPRESSIONSPIN), (LPTSTR)"ToolTip53" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_PREC), (LPTSTR)"ToolTip54" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_KEYSTHRESHOLD), (LPTSTR)"ToolTip55" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_PREC_SPIN), (LPTSTR)"ToolTip56" );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_KEYSTHRESHOLDSPIN), (LPTSTR)"ToolTip57" );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_COMBOFORCERATIOMETHOD), (LPTSTR)"Set the report level." );
|
|
//UICreateToolTip( GetDlgItem(hWnd, IDC_ALPHAREF_CHECK), (LPTSTR)"Alpha ref value for materials." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_ALPHAREF_STEP), (LPTSTR)"Alpha ref value for materials." );
|
|
UICreateToolTip( GetDlgItem(hWnd, IDC_ALPHAREF_STEP_SPIN), (LPTSTR)"Alpha ref value for materials." );
|
|
|
|
|
|
}
|
|
|
|
void Max2Nmo::UICreateToolTip(HWND hWnd, LPTSTR lptstr)
|
|
{
|
|
// struct specifying control classes to register
|
|
INITCOMMONCONTROLSEX iccex;
|
|
HWND hwndTT; // handle to the ToolTip control
|
|
// struct specifying info about tool in ToolTip control
|
|
TOOLINFO ti;
|
|
unsigned int uid = 0; // for ti initialization
|
|
|
|
RECT rect; // for client area coordinates
|
|
|
|
/* INITIALIZE COMMON CONTROLS */
|
|
iccex.dwICC = ICC_WIN95_CLASSES;
|
|
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
|
|
InitCommonControlsEx(&iccex);
|
|
|
|
/* CREATE A TOOLTIP WINDOW */
|
|
hwndTT = CreateWindowEx(WS_EX_TOPMOST,
|
|
TOOLTIPS_CLASS,
|
|
NULL,
|
|
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
hWnd,
|
|
NULL,
|
|
hInstance,
|
|
NULL
|
|
);
|
|
|
|
SetWindowPos(hwndTT,
|
|
HWND_TOPMOST,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
|
|
|
/* GET COORDINATES OF THE MAIN CLIENT AREA */
|
|
GetClientRect (hWnd, &rect);
|
|
|
|
/* INITIALIZE MEMBERS OF THE TOOLINFO STRUCTURE */
|
|
ti.cbSize = sizeof(TOOLINFO);
|
|
ti.uFlags = TTF_SUBCLASS;
|
|
ti.hwnd = hWnd;
|
|
ti.hinst = hInstance;
|
|
ti.uId = uid;
|
|
ti.lpszText = lptstr;
|
|
// ToolTip control will cover the whole window
|
|
ti.rect.left = rect.left;
|
|
ti.rect.top = rect.top;
|
|
ti.rect.right = rect.right;
|
|
ti.rect.bottom = rect.bottom;
|
|
|
|
/* SEND AN ADDTOOL MESSAGE TO THE TOOLTIP CONTROL WINDOW */
|
|
SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
|
|
|
|
//Set a Max Width for the tooltips
|
|
SendMessage( // returns LRESULT in lResult
|
|
(HWND) hwndTT, // handle to destination control
|
|
(UINT) TTM_SETMAXTIPWIDTH, // message ID
|
|
(WPARAM) 0, // = 0; not used, must be zero
|
|
(LPARAM) 350 // = (LPARAM) (INT) iWidth;
|
|
);
|
|
|
|
//Don't work...
|
|
//Set the popup visible time delay to really high
|
|
SendMessage( // returns LRESULT in lResult
|
|
(HWND) hwndTT, // handle to destination control
|
|
(UINT) TTM_SETDELAYTIME, // message ID
|
|
TTDT_AUTOPOP, // = (WPARAM) (DWORD) dwDuration
|
|
(LPARAM) MAKELONG(99999, 0) // = (LPARAM) MAKELONG(iTime, 0)
|
|
);
|
|
|
|
|
|
}
|
|
|
|
const char* Max2Nmo::UIGetFilename(HWND hWnd, TCHAR szFile[], DWORD iMaxLength, TCHAR* szFilter, BOOL iSave)
|
|
{
|
|
// Initialize the OPENFILENAME members.
|
|
OPENFILENAME Ofn;
|
|
|
|
if(!szFilter)
|
|
szFilter = "All\0*.*\0";
|
|
szFile[0]='\0';
|
|
|
|
Ofn.lStructSize=sizeof(OPENFILENAME);
|
|
Ofn.hwndOwner=hWnd;
|
|
Ofn.hInstance=NULL;
|
|
Ofn.lpstrFilter=NULL;
|
|
Ofn.lpstrCustomFilter=NULL;
|
|
Ofn.nMaxCustFilter;
|
|
Ofn.nFilterIndex=1;
|
|
Ofn.lpstrFile=szFile;
|
|
Ofn.nMaxFile=iMaxLength;
|
|
Ofn.lpstrFileTitle=NULL;
|
|
Ofn.nMaxFileTitle;
|
|
Ofn.lpstrInitialDir=NULL;
|
|
Ofn.lpstrTitle=NULL;
|
|
Ofn.Flags=0;
|
|
Ofn.nFileOffset;
|
|
Ofn.nFileExtension;
|
|
Ofn.lpstrDefExt=NULL;
|
|
Ofn.lCustData;
|
|
Ofn.lpfnHook=NULL;
|
|
Ofn.lpTemplateName=NULL;
|
|
|
|
// Display the Filename common dialog box.
|
|
if(iSave) {
|
|
if(GetSaveFileName(&Ofn))
|
|
return szFile;
|
|
}
|
|
else {
|
|
if(GetOpenFileName(&Ofn))
|
|
return szFile;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
BOOL MtlKeeper::AddMtl(Mtl* mtl)
|
|
{
|
|
if (!mtl) {
|
|
return FALSE;
|
|
}
|
|
|
|
int numMtls = mtlTab.Count();
|
|
for (int i=0; i<numMtls; i++) {
|
|
if (mtlTab[i] == mtl) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
mtlTab.Append(1, &mtl, 25);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int MtlKeeper::GetMtlID(Mtl* mtl)
|
|
{
|
|
int numMtls = mtlTab.Count();
|
|
for (int i=0; i<numMtls; i++) {
|
|
if (mtlTab[i] == mtl) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int MtlKeeper::Count()
|
|
{
|
|
return mtlTab.Count();
|
|
}
|
|
|
|
Mtl* MtlKeeper::GetMtl(int id)
|
|
{
|
|
return mtlTab[id];
|
|
}
|
|
|
|
|
|
|