Changed: #1092 Reliability improvements for batched anim export from max

This commit is contained in:
kaetemi 2010-09-26 17:00:01 +02:00
parent b13b869dd5
commit 7f0ad4a2d1
4 changed files with 136 additions and 57 deletions

View file

@ -766,7 +766,7 @@ static INT_PTR CALLBACK CNelExportDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LP
//--- CNelExport ------------------------------------------------------- //--- CNelExport -------------------------------------------------------
CNelExport::CNelExport() CNelExport::CNelExport() : _ErrorInDialog(true), _TerminateOnFileOpenIssues(false)
{ {
_Ip = NULL; _Ip = NULL;
theHPanel = NULL; theHPanel = NULL;
@ -869,3 +869,11 @@ void CNelExport::init (bool view, bool errorInDialog, Interface *ip, bool loadSt
// Create the CExportNel class // Create the CExportNel class
_ExportNel = new CExportNel (errorInDialog, view, view, ip, "NeL Export", &theExportSceneStruct); _ExportNel = new CExportNel (errorInDialog, view, view, ip, "NeL Export", &theExportSceneStruct);
} }
void nelExportTerminateProcess()
{
DWORD ec = 0;
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId());
GetExitCodeProcess(h, &ec);
TerminateProcess(h, ec);
}

View file

@ -99,10 +99,13 @@ public:
Interface *_Ip; Interface *_Ip;
// View // View
bool _View; // bool _View;
// View // View
bool _ErrorInDialog; bool _ErrorInDialog;
// Handle problematic file handles with max.
bool _TerminateOnFileOpenIssues;
}; };
class CNelExportClassDesc:public ClassDesc2 class CNelExportClassDesc:public ClassDesc2
@ -122,5 +125,7 @@ extern CNelExportClassDesc CNelExportDesc;
extern CNelExport theCNelExport; extern CNelExport theCNelExport;
void nelExportTerminateProcess();
#endif // __NEL_EXPORT__H #endif // __NEL_EXPORT__H

View file

@ -132,6 +132,8 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time)
else else
{ {
nlwarning("Failed to create file %s", tempFileName); nlwarning("Failed to create file %s", tempFileName);
if (_TerminateOnFileOpenIssues)
nelExportTerminateProcess();
} }
// Delete the pointer // Delete the pointer
@ -172,6 +174,8 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time)
else else
{ {
nlwarning("Failed to open file: %s", tempFileName); nlwarning("Failed to open file: %s", tempFileName);
if (_TerminateOnFileOpenIssues)
nelExportTerminateProcess();
} }
} }
catch (...) catch (...)
@ -246,67 +250,133 @@ bool CNelExport::exportAnim (const char *sPath, std::vector<INode*>& vectNode, T
{ {
// Result to return // Result to return
bool bRet=false; bool bRet=false;
char tempFileName[MAX_PATH] = { 0 };
char tempPathBuffer[MAX_PATH] = { 0 };
// Create an animation file try
CAnimation animFile;
// For each node to export
for (uint n=0; n<vectNode.size(); n++)
{ {
// Get name DWORD dwRetVal = GetTempPathA(MAX_PATH, tempPathBuffer);
std::string nodeName=""; if (dwRetVal > MAX_PATH || (dwRetVal == 0))
nlerror("GetTempPath failed");
UINT uRetVal = GetTempFileNameA(tempPathBuffer, TEXT("_nel_export_mesh_"), 0, tempFileName);
if (uRetVal == 0)
nlerror("GetTempFileName failed");
// Get NEL3D_APPDATA_EXPORT_ANIMATION_PREFIXE_NAME // Create an animation file
int prefixe = CExportNel::getScriptAppData (vectNode[n], NEL3D_APPDATA_EXPORT_ANIMATION_PREFIXE_NAME, 0); CAnimation animFile;
// Set the name only if it is a scene animation // For each node to export
if (scene || prefixe) for (uint n=0; n<vectNode.size(); n++)
{ {
// try to get the prefix from the appData if present. If not, takes it from the node name // Get name
nodeName = CExportNel::getScriptAppData (vectNode[n], NEL3D_APPDATA_INSTANCE_NAME, ""); std::string nodeName="";
if (nodeName == "") // not found ?
// Get NEL3D_APPDATA_EXPORT_ANIMATION_PREFIXE_NAME
int prefixe = CExportNel::getScriptAppData (vectNode[n], NEL3D_APPDATA_EXPORT_ANIMATION_PREFIXE_NAME, 0);
// Set the name only if it is a scene animation
if (scene || prefixe)
{ {
nodeName=CExportNel::getName (*vectNode[n]); // try to get the prefix from the appData if present. If not, takes it from the node name
nodeName = CExportNel::getScriptAppData (vectNode[n], NEL3D_APPDATA_INSTANCE_NAME, "");
if (nodeName == "") // not found ?
{
nodeName=CExportNel::getName (*vectNode[n]);
}
nodeName+=".";
} }
nodeName+=".";
// Is a root ?
bool root = vectNode[n]->GetParentNode () == _Ip->GetRootNode();
// Add animation
_ExportNel->addAnimation (animFile, *vectNode[n], nodeName.c_str(), root);
} }
// Is a root ? if (vectNode.size())
bool root = vectNode[n]->GetParentNode () == _Ip->GetRootNode();
// Add animation
_ExportNel->addAnimation (animFile, *vectNode[n], nodeName.c_str(), root);
}
if (vectNode.size())
{
// Open a file
COFile file;
if (file.open (sPath))
{ {
try // Open a file
COFile file;
if (file.open (tempFileName))
{ {
// Serial the animation try
animFile.serial (file); {
nldebug("Serialize the animation");
// All is good // Serial the animation
bRet=true; animFile.serial (file);
// Close the file
file.close();
// All is good
bRet=true;
// Verify the file
nldebug("Verify exported anim file");
try
{
bool tempBRet = bRet;
bRet = false;
CIFile vf;
if (vf.open(tempFileName))
{
nldebug("File opened, size: %u", vf.getFileSize());
CAnimation a;
a.serial(vf);
nldebug("Anim serialized");
vf.close();
nldebug("File closed");
bRet = tempBRet;
}
else
{
nlwarning("Failed to open file: %s", tempFileName);
bRet = false;
if (_TerminateOnFileOpenIssues)
nelExportTerminateProcess();
}
}
catch (...)
{
nlwarning("Failed to verify shape. Must crash now.");
remove(tempFileName);
bRet = false;
}
}
catch (Exception& e)
{
if (_ErrorInDialog)
MessageBox (NULL, e.what(), "NeL export", MB_OK|MB_ICONEXCLAMATION);
else
nlwarning ("ERROR : %s", e.what ());
}
} }
catch (Exception& e) else
{ {
if (_ErrorInDialog) if (_ErrorInDialog)
MessageBox (NULL, e.what(), "NeL export", MB_OK|MB_ICONEXCLAMATION); MessageBox (NULL, "Can't open the file for writing.", "NeL export", MB_OK|MB_ICONEXCLAMATION);
else else
nlwarning ("ERROR : %s", e.what ()); nlwarning ("ERROR : Can't open the file (%s) for writing", tempFileName);
if (_TerminateOnFileOpenIssues)
nelExportTerminateProcess();
} }
} }
else }
catch (...)
{
nlwarning("Fatal exception at CNelExport::exportAnim.");
bRet = false;
}
if (bRet)
{
try
{ {
if (_ErrorInDialog) remove(sPath);
MessageBox (NULL, "Can't open the file for writing.", "NeL export", MB_OK|MB_ICONEXCLAMATION);
else
nlwarning ("ERROR : Can't open the file (%s) for writing", sPath);
} }
catch (...)
{
}
CFile::moveFile(sPath, tempFileName);
nlinfo("MOVE %s -> %s", tempFileName, sPath);
} }
return bRet; return bRet;
} }

View file

@ -945,10 +945,7 @@ protected:
/// Put the string into the file. /// Put the string into the file.
virtual void doDisplay( const CLog::TDisplayInfo& args, const char *message ) virtual void doDisplay( const CLog::TDisplayInfo& args, const char *message )
{ {
DWORD ec = 0; nelExportTerminateProcess();
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId());
GetExitCodeProcess(h, &ec);
TerminateProcess(h, ec);
} }
}; };
@ -958,6 +955,8 @@ Value* force_quit_on_msg_displayer_cf(Value** arg_list, int count)
// disable the Windows popup telling that the application aborted and disable the dr watson report. // disable the Windows popup telling that the application aborted and disable the dr watson report.
_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
putenv("NEL_IGNORE_ASSERT=1"); putenv("NEL_IGNORE_ASSERT=1");
theCNelExport._ErrorInDialog = false;
theCNelExport._TerminateOnFileOpenIssues = true;
if (NLMISC::DefaultMsgBoxDisplayer || INelContext::getInstance().getDefaultMsgBoxDisplayer()) if (NLMISC::DefaultMsgBoxDisplayer || INelContext::getInstance().getDefaultMsgBoxDisplayer())
{ {
if (!NLMISC::DefaultMsgBoxDisplayer) if (!NLMISC::DefaultMsgBoxDisplayer)
@ -978,10 +977,7 @@ Value* force_quit_right_now_cf(Value** arg_list, int count)
{ {
// because quitMAX can fail // because quitMAX can fail
nlwarning("Force quit"); nlwarning("Force quit");
DWORD ec = 0; nelExportTerminateProcess();
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId());
GetExitCodeProcess(h, &ec);
TerminateProcess(h, ec);
return &true_value; return &true_value;
} }