From ea96a3af08df6ec31465bf8095438045d95bcc46 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 20 Sep 2015 14:08:38 +0200 Subject: [PATCH] Add pipeline v3 tool logger --- code/nel/include/nel/misc/tool_logger.h | 210 ++++++++++++++++++++ code/nel/src/misc/tool_logger.cpp | 45 +++++ code/nel/tools/3d/mesh_export/main.cpp | 7 + code/nel/tools/3d/mesh_utils/mesh_utils.cpp | 39 +++- code/nel/tools/3d/mesh_utils/mesh_utils.h | 2 + 5 files changed, 296 insertions(+), 7 deletions(-) create mode 100644 code/nel/include/nel/misc/tool_logger.h create mode 100644 code/nel/src/misc/tool_logger.cpp diff --git a/code/nel/include/nel/misc/tool_logger.h b/code/nel/include/nel/misc/tool_logger.h new file mode 100644 index 000000000..85171095c --- /dev/null +++ b/code/nel/include/nel/misc/tool_logger.h @@ -0,0 +1,210 @@ +/** + * \file tool_logger.h + * \brief CToolLogger + * \date 2012-02-19 10:33GMT + * \author Jan Boon (Kaetemi) + * Tool logger is fully implemented in header so small tools do not + * need to link to this library unnecessarily. + * NOTE: Needs to be changed not to use time_nl and string_common. + */ + +/* + * Copyright (C) 2012 by authors + * + * This file is part of RYZOM CORE PIPELINE. + * RYZOM CORE PIPELINE is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 2 of + * the License, or (at your option) any later version. + * + * RYZOM CORE PIPELINE is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RYZOM CORE PIPELINE; see the file COPYING. If not, see + * . + */ + +#ifndef NLMISC_TOOL_LOGGER_H +#define NLMISC_TOOL_LOGGER_H +#include + +// STL includes +#include +#include +#include + +// NeL includes +#include +#include + +// Project includes + +#ifdef ERROR +#undef ERROR +#endif + +#ifdef NL_DEBUG_H +#define tlerror(toolLogger, path, error, ...) nlwarning(error, __VA_ARGS__), toolLogger.writeError(NLMISC::ERROR, path, error, __VA_ARGS__) +#define tlwarning(toolLogger, path, error, ...) nlwarning(error, __VA_ARGS__), toolLogger.writeError(NLMISC::WARNING, path, error, __VA_ARGS__) +#define tlmessage(toolLogger, path, error, ...) nlinfo(error, __VA_ARGS__), toolLogger.writeError(NLMISC::MESSAGE, path, error, __VA_ARGS__) +#else +#define tlerror(toolLogger, path, error, ...) toolLogger.writeError(NLMISC::ERROR, path, error, __VA_ARGS__) +#define tlwarning(toolLogger, path, error, ...) toolLogger.writeError(NLMISC::WARNING, path, error, __VA_ARGS__) +#define tlmessage(toolLogger, path, error, ...) toolLogger.writeError(NLMISC::MESSAGE, path, error, __VA_ARGS__) +#endif + +namespace NLMISC { + +enum TError +{ + ERROR, + WARNING, + MESSAGE, +}; + +enum TDepend +{ + BUILD, + DIRECTORY, + RUNTIME, +}; + +const std::string s_ErrorHeader = "type\tpath\ttime\terror"; +const std::string s_DependHeader = "type\toutput_file\tinput_file"; + +/** + * \brief CToolLogger + * \date 2012-02-19 10:33GMT + * \author Jan Boon (Kaetemi) + * CToolLogger + */ +class CToolLogger +{ +private: + FILE *m_ErrorLog; + FILE *m_DependLog; + +public: + inline CToolLogger() + { + + } + + inline ~CToolLogger() + { + release(); + } + + inline void initError(const std::string &errorLog) + { + releaseError(); + + m_ErrorLog = fopen(errorLog.c_str(), "wt"); + fwrite(s_ErrorHeader.c_str(), 1, s_ErrorHeader.length(), m_ErrorLog); + fwrite("\n", 1, 1, m_ErrorLog); + fflush(m_ErrorLog); + + } + + inline void initDepend(const std::string &dependLog) + { + releaseDepend(); + + m_DependLog = fopen(dependLog.c_str(), "wt"); + fwrite(s_DependHeader.c_str(), 1, s_DependHeader.length(), m_DependLog); + fwrite("\n", 1, 1, m_DependLog); + // fflush(m_DependLog); + } + + inline void writeError(TError type, const char *path, const char *error, ...) + { + if (m_ErrorLog) + { + switch (type) + { + case ERROR: + fwrite("ERROR", 1, 5, m_ErrorLog); + break; + case WARNING: + fwrite("WARNING", 1, 7, m_ErrorLog); + break; + case MESSAGE: + fwrite("MESSAGE", 1, 7, m_ErrorLog); + break; + } + fwrite("\t", 1, 1, m_ErrorLog); + fprintf(m_ErrorLog, "%s", path); + fwrite("\t", 1, 1, m_ErrorLog); + std::string time = NLMISC::toString(NLMISC::CTime::getSecondsSince1970()); + fwrite(time.c_str(), 1, time.length(), m_ErrorLog); + fwrite("\t", 1, 1, m_ErrorLog); + va_list args; + va_start(args, error); + vfprintf(m_ErrorLog, error, args); + va_end(args); + fwrite("\n", 1, 1, m_ErrorLog); + fflush(m_ErrorLog); + } + } + + /// inputFile can only be file. [? May be not-yet-existing file for expected input for future build runs. ?] Directories are handled on process level. [? You should call this before calling writeError on inputFile, so the error is also linked from the outputFile. ?] + inline void writeDepend(TDepend type, const char *outputFile, const char *inputFile) + { + if (m_DependLog) + { + switch (type) + { + case BUILD: + fwrite("BUILD", 1, 5, m_DependLog); + break; + case DIRECTORY: + fwrite("DIRECTORY", 1, 9, m_DependLog); + break; + case RUNTIME: + fwrite("RUNTIME", 1, 7, m_DependLog); + break; + } + fwrite("\t", 1, 1, m_DependLog); + fprintf(m_DependLog, "%s", outputFile); + fwrite("\t", 1, 1, m_DependLog); + fprintf(m_DependLog, "%s", inputFile); + fwrite("\n", 1, 1, m_DependLog); + // fflush(m_DependLog); + } + } + + inline void releaseError() + { + if (m_ErrorLog) + { + fflush(m_ErrorLog); + fclose(m_ErrorLog); + m_ErrorLog = NULL; + } + } + + inline void releaseDepend() + { + if (m_DependLog) + { + fflush(m_DependLog); + fclose(m_DependLog); + m_DependLog = NULL; + } + } + + inline void release() + { + releaseError(); + releaseDepend(); + } +}; /* class CToolLogger */ + +} /* namespace NLMISC */ + +#endif /* #ifndef NLMISC_TOOL_LOGGER_H */ + +/* end of file */ diff --git a/code/nel/src/misc/tool_logger.cpp b/code/nel/src/misc/tool_logger.cpp new file mode 100644 index 000000000..e6a9fbf36 --- /dev/null +++ b/code/nel/src/misc/tool_logger.cpp @@ -0,0 +1,45 @@ +/** + * \file tool_logger.cpp + * \brief CToolLogger + * \date 2012-02-19 10:33GMT + * \author Jan Boon (Kaetemi) + * CToolLogger + */ + +/* + * Copyright (C) 2012 by authors + * + * This file is part of RYZOM CORE PIPELINE. + * RYZOM CORE PIPELINE is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 2 of + * the License, or (at your option) any later version. + * + * RYZOM CORE PIPELINE is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RYZOM CORE PIPELINE; see the file COPYING. If not, see + * . + */ + +#include "stdmisc.h" +#include "nel/misc/tool_logger.h" + +// STL includes + +// NeL includes +// #include + +// Project includes + +namespace NLMISC { + +// Tool logger is fully implemented in header so small tools do not need to link to this library unnecessarily. +void dummy_tool_logger_cpp() { } + +} /* namespace NLMISC */ + +/* end of file */ diff --git a/code/nel/tools/3d/mesh_export/main.cpp b/code/nel/tools/3d/mesh_export/main.cpp index 2e97be830..1503a4b16 100644 --- a/code/nel/tools/3d/mesh_export/main.cpp +++ b/code/nel/tools/3d/mesh_export/main.cpp @@ -61,6 +61,13 @@ int main(int argc, char *argv[]) settings.DestinationDirectoryPath = filePath + "_export"; settings.DestinationDirectoryPath += "/"; + settings.ToolDependLog = args.getLongArg("dependlog"); + if (settings.ToolDependLog.empty()) + settings.ToolDependLog = settings.DestinationDirectoryPath + "depend.log"; + settings.ToolErrorLog = args.getLongArg("errorlog"); + if (settings.ToolErrorLog.empty()) + settings.ToolErrorLog = settings.DestinationDirectoryPath + "error.log"; + NL3D::CScene::registerBasics(); NL3D::registerSerial3d(); diff --git a/code/nel/tools/3d/mesh_utils/mesh_utils.cpp b/code/nel/tools/3d/mesh_utils/mesh_utils.cpp index 60e5c7201..c8a0eb12d 100644 --- a/code/nel/tools/3d/mesh_utils/mesh_utils.cpp +++ b/code/nel/tools/3d/mesh_utils/mesh_utils.cpp @@ -19,6 +19,8 @@ #include "mesh_utils.h" #include +#include +#include #include #include @@ -52,9 +54,12 @@ struct CMeshUtilsContext } const CMeshUtilsSettings &Settings; + + NLMISC::CToolLogger ToolLogger; const aiScene *AssimpScene; - std::map Nodes; + std::map Nodes; + std::map MeshNames; // Maps meshes to a node name ********************* todo *************** }; struct CNodeMeta @@ -82,7 +87,8 @@ void validateAssimpNodeNames(CMeshUtilsContext &context, const aiNode *node) } else if (node->mName.length == 0) { - nlwarning("CRITICAL: Node has no name"); + tlwarning(context.ToolLogger, context.Settings.SourceFilePath.c_str(), + "Node has no name"); } else { @@ -90,7 +96,8 @@ void validateAssimpNodeNames(CMeshUtilsContext &context, const aiNode *node) if (nodeContext.AssimpNode && nodeContext.AssimpNode != node) { - nlwarning("CRITICAL: Node name '%s' appears multiple times", node->mName.C_Str()); + tlerror(context.ToolLogger, context.Settings.SourceFilePath.c_str(), + "Node name '%s' appears multiple times", node->mName.C_Str()); } else { @@ -115,7 +122,8 @@ void flagAssimpBones(CMeshUtilsContext &context) CNodeContext &nodeContext = context.Nodes[mesh->mBones[i]->mName.C_Str()]; if (!nodeContext.AssimpNode) { - nlwarning("CRITICAL: Bone '%s' has no associated node", mesh->mBones[i]->mName.C_Str()); + tlerror(context.ToolLogger, context.Settings.SourceFilePath.c_str(), + "Bone '%s' has no associated node", mesh->mBones[i]->mName.C_Str()); } else { @@ -123,11 +131,11 @@ void flagAssimpBones(CMeshUtilsContext &context) nodeContext.IsBone = true; // Flag all parents as bones - const aiNode *parent = nodeContext.AssimpNode; + /*const aiNode *parent = nodeContext.AssimpNode; while (parent = parent->mParent) if (parent->mName.length) { context.Nodes[parent->mName.C_Str()].IsBone = true; - } + }*/ } } } @@ -136,14 +144,31 @@ void flagAssimpBones(CMeshUtilsContext &context) // TODO: Separate load scene and save scene functions int exportScene(const CMeshUtilsSettings &settings) { + CMeshUtilsContext context(settings); + + if (!settings.ToolDependLog.empty()) + context.ToolLogger.initDepend(settings.ToolDependLog); + if (!settings.ToolErrorLog.empty()) + context.ToolLogger.initDepend(settings.ToolErrorLog); + context.ToolLogger.writeDepend(NLMISC::BUILD, "*", context.Settings.SourceFilePath.c_str()); // Base input file + + // Find database configuration + + Assimp::Importer importer; const aiScene *scene = importer.ReadFile(settings.SourceFilePath, aiProcess_Triangulate | aiProcess_ValidateDataStructure); // aiProcess_SplitLargeMeshes | aiProcess_LimitBoneWeights + if (!scene) + { + const char *errs = importer.GetErrorString(); + if (errs) tlerror(context.ToolLogger, context.Settings.SourceFilePath.c_str(), errs); + else tlerror(context.ToolLogger, context.Settings.SourceFilePath.c_str(), "Unable to load scene"); + return EXIT_FAILURE; + } // aiProcess_ValidateDataStructure: TODO: Catch Assimp error output stream // aiProcess_RemoveRedundantMaterials: Not used because we may override materials with NeL Material from meta // aiProcess_ImproveCacheLocality: TODO: Verify this does not modify vertex indices //scene->mRootNode->mMetaData - CMeshUtilsContext context(settings); context.AssimpScene = scene; flagAssimpBones(context); diff --git a/code/nel/tools/3d/mesh_utils/mesh_utils.h b/code/nel/tools/3d/mesh_utils/mesh_utils.h index b7c549689..1af319dec 100644 --- a/code/nel/tools/3d/mesh_utils/mesh_utils.h +++ b/code/nel/tools/3d/mesh_utils/mesh_utils.h @@ -26,6 +26,8 @@ struct CMeshUtilsSettings // Absolute Paths std::string SourceFilePath; std::string DestinationDirectoryPath; + std::string ToolDependLog; + std::string ToolErrorLog; // Relative Directories std::string ShapeDirectory;