diff --git a/code/nel/tools/3d/plugin_max/nel_export/nel_export_export.cpp b/code/nel/tools/3d/plugin_max/nel_export/nel_export_export.cpp index 9f582bd23..a9aa9e3d1 100644 --- a/code/nel/tools/3d/plugin_max/nel_export/nel_export_export.cpp +++ b/code/nel/tools/3d/plugin_max/nel_export/nel_export_export.cpp @@ -36,11 +36,18 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time) { // Result to return bool bRet = false; - char tempName[L_tmpnam]; - tmpnam(tempName); + char tempFileName[MAX_PATH] = { 0 }; + char tempPathBuffer[MAX_PATH] = { 0 }; try - { + { + DWORD dwRetVal = GetTempPathA(MAX_PATH, tempPathBuffer); + 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"); + // Eval the object a time ObjectState os = node.EvalWorldState(time); @@ -48,7 +55,7 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time) if (os.obj) { // Skeleton shape - CSmartPtr skeletonShape = NULL; + CSkeletonShape * skeletonShape = NULL; TInodePtrInt *mapIdPtr=NULL; TInodePtrInt mapId; @@ -69,7 +76,7 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time) CExportNel::addSkeletonBindPos (node, boneBindPos); // Build the skeleton based on the bind pos information - _ExportNel->buildSkeletonShape(*skeletonShape.getPtr(), *skeletonRoot, &boneBindPos, mapId, time); + _ExportNel->buildSkeletonShape(*skeletonShape, *skeletonRoot, &boneBindPos, mapId, time); // Set the pointer to not NULL mapIdPtr=&mapId; @@ -83,16 +90,16 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time) if (InfoLog) InfoLog->display("Beg buildShape %s \n", node.GetName()); // Export in mesh format - CSmartPtr pShape = _ExportNel->buildShape(node, time, mapIdPtr, true); + IShape *pShape = _ExportNel->buildShape(node, time, mapIdPtr, true); if (InfoLog) InfoLog->display("End buildShape in %d ms \n", timeGetTime()-t); // Conversion success ? - if (pShape.getPtr()) + if (pShape) { // Open a file COFile file; - if (file.open(tempName)) + if (file.open(tempFileName)) { try { @@ -102,6 +109,9 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time) // Serial the shape shapeStream.serial(file); + // Close the file + file.close(); + // All is good bRet = true; } @@ -116,29 +126,61 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time) { } - remove(tempName); + remove(tempFileName); } } else { - nlwarning("Failed to create file %s", tempName); + nlwarning("Failed to create file %s", tempFileName); } // Delete the pointer - nldebug ("Delete the pointer"); + nldebug("Delete the pointer"); try { bool tempBRet = bRet; bRet = false; - pShape = NULL; + // delete pShape; // FIXME: there is a delete bug with CMeshMultiLod exported from max!!! bRet = tempBRet; } catch (...) { nlwarning("Failed to delete pShape pointer! Something might be wrong."); - remove(tempName); + remove(tempFileName); bRet = false; } + + // Verify the file + nldebug("Verify exported shape file"); + try + { + bool tempBRet = bRet; + bRet = false; + CIFile vf; + if (vf.open(tempFileName)) + { + nldebug("File opened, size: %u", vf.getFileSize()); + CShapeStream s; + s.serial(vf); + nldebug("Shape serialized"); + vf.close(); + nldebug("File closed"); + delete s.getShapePointer(); + nldebug("Shape deleted"); + bRet = tempBRet; + } + else + { + nlwarning("Failed to open file: %s", tempFileName); + } + } + catch (...) + { + nlwarning("Failed to verify shape. Must crash now."); + remove(tempFileName); + bRet = false; + } + } } } @@ -158,8 +200,8 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time) { } - CFile::moveFile(sPath, tempName); - nlinfo("MOVE %s -> %s", tempName, sPath); + CFile::moveFile(sPath, tempFileName); + nlinfo("MOVE %s -> %s", tempFileName, sPath); } return bRet; diff --git a/code/nel/tools/3d/plugin_max/nel_export/nel_export_script.cpp b/code/nel/tools/3d/plugin_max/nel_export/nel_export_script.cpp index 6ad05dfcb..8767ff7a9 100644 --- a/code/nel/tools/3d/plugin_max/nel_export/nel_export_script.cpp +++ b/code/nel/tools/3d/plugin_max/nel_export/nel_export_script.cpp @@ -55,6 +55,9 @@ def_visible_primitive ( mirror_physique, "NelMirrorPhysique" ); def_visible_primitive ( get_file_modification_date, "NeLGetFileModificationDate" ); def_visible_primitive ( set_file_modification_date, "NeLSetFileModificationDate" ); +def_visible_primitive ( force_quit_on_msg_displayer, "NelForceQuitOnMsgDisplayer"); +def_visible_primitive ( force_quit_right_now, "NelForceQuitRightNow"); + char *sExportShapeErrorMsg = "NeLExportShape [Object] [Filename.shape]"; char *sExportShapeExErrorMsg = "NeLExportShapeEx [Object] [Filename.shape] [bShadow] [bExportLighting] [sLightmapPath] [nLightingLimit] [fLumelSize] [nOverSampling] [bExcludeNonSelected] [bShowLumel]"; char *sExportAnimationErrorMsg = "NelExportAnimation [node array] [Filename.anim] [bool_scene_animation]"; @@ -933,6 +936,55 @@ Value* set_file_modification_date_cf (Value** arg_list, int count) return &false_value; } +class CSuicideMsgBoxDisplayer : public CMsgBoxDisplayer +{ +public: + CSuicideMsgBoxDisplayer (const char *displayerName = "") : CMsgBoxDisplayer(displayerName) { } + +protected: + /// Put the string into the file. + virtual void doDisplay( const CLog::TDisplayInfo& args, const char *message ) + { + DWORD ec = 0; + HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId()); + GetExitCodeProcess(h, &ec); + TerminateProcess(h, ec); + } +}; + +Value* force_quit_on_msg_displayer_cf(Value** arg_list, int count) +{ + nlwarning("Enable force quit on NeL report msg displayer"); + // disable the Windows popup telling that the application aborted and disable the dr watson report. + _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + putenv("NEL_IGNORE_ASSERT=1"); + if (NLMISC::DefaultMsgBoxDisplayer || INelContext::getInstance().getDefaultMsgBoxDisplayer()) + { + if (!NLMISC::DefaultMsgBoxDisplayer) + NLMISC::DefaultMsgBoxDisplayer = INelContext::getInstance().getDefaultMsgBoxDisplayer(); + nldebug("Disable NeL report msg displayer"); + INelContext::getInstance().getAssertLog()->removeDisplayer(NLMISC::DefaultMsgBoxDisplayer); + INelContext::getInstance().getErrorLog()->removeDisplayer(NLMISC::DefaultMsgBoxDisplayer); + // TODO: Delete original NLMISC::DefaultMsgBoxDisplayer? + } + NLMISC::DefaultMsgBoxDisplayer = new CSuicideMsgBoxDisplayer("FORCEQUIT_MDB"); + INelContext::getInstance().setDefaultMsgBoxDisplayer(NLMISC::DefaultMsgBoxDisplayer); + INelContext::getInstance().getAssertLog()->addDisplayer(NLMISC::DefaultMsgBoxDisplayer); + INelContext::getInstance().getErrorLog()->addDisplayer(NLMISC::DefaultMsgBoxDisplayer); + return &true_value; +} + +Value* force_quit_right_now_cf(Value** arg_list, int count) +{ + // because quitMAX can fail + nlwarning("Force quit"); + DWORD ec = 0; + HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId()); + GetExitCodeProcess(h, &ec); + TerminateProcess(h, ec); + return &true_value; +} + /*===========================================================================*\ | MAXScript Plugin Initialization \*===========================================================================*/ diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_mesh.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_mesh.cpp index aad5ee1b9..48f24a61b 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_mesh.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_mesh.cpp @@ -131,7 +131,7 @@ static void copyMultiLodMeshBaseLod0Infos(CMeshBase::CMeshBaseBuild &dst, const // *************************************************************************** // Export a mesh -NLMISC::CSmartPtr CExportNel::buildShape (INode& node, TimeValue time, const TInodePtrInt *nodeMap, bool buildLods) +NL3D::IShape *CExportNel::buildShape (INode& node, TimeValue time, const TInodePtrInt *nodeMap, bool buildLods) { // Is this a multi lod object ? @@ -139,7 +139,7 @@ NLMISC::CSmartPtr CExportNel::buildShape (INode& node, TimeValue t // Here, we must check what kind of node we can build with this mesh. // For the time, just Triobj is supported. - CSmartPtr retShape = NULL; + NL3D::IShape *retShape = NULL; // If skinning, disable skin modifier if (nodeMap) @@ -206,7 +206,7 @@ NLMISC::CSmartPtr CExportNel::buildShape (INode& node, TimeValue t else { // Mesh base ? - CSmartPtr meshBase = NULL; + CMeshBase *meshBase = NULL; // Get the node matrix Matrix3 nodeMatrixMax; @@ -317,8 +317,7 @@ NLMISC::CSmartPtr CExportNel::buildShape (INode& node, TimeValue t // Make a CMeshMultiLod mesh object - CMeshMultiLod *multiMesh = new CMeshMultiLod; - ++multiMesh->crefs; // hack + CMeshMultiLod *multiMesh = new CMeshMultiLod; // FIXME: there is a delete bug with CMeshMultiLod exported from max!!! // Build it multiMesh->build(multiLodBuild); @@ -461,7 +460,7 @@ NLMISC::CSmartPtr CExportNel::buildShape (INode& node, TimeValue t enableSkinModifier (node, true); // Set the dist max for this shape - if (retShape.getPtr() && !multiLodObject && buildLods) + if (retShape && !multiLodObject && buildLods) { // Get the dist max for this node float distmax = getScriptAppData (&node, NEL3D_APPDATA_LOD_DIST_MAX, NEL3D_APPDATA_LOD_DIST_MAX_DEFAULT); diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_nel.h b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_nel.h index d413e1109..81fbac682 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_nel.h +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_nel.h @@ -292,7 +292,7 @@ public: * * skeletonShape must be NULL if no bones. */ - NLMISC::CSmartPtr buildShape (INode& node, TimeValue time, const TInodePtrInt *nodeMap, + NL3D::IShape* buildShape (INode& node, TimeValue time, const TInodePtrInt *nodeMap, bool buildLods); /**