deargui-vpl/ref/virtools/Samples/ExportPlugins/3dsMax Export/Max2Nmo.cpp

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 &empty;
}
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 &empty;
}
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];
}