From 0e08e518c4f013b8e4b40d85f2246b9e1c919531 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Sun, 11 Aug 2024 00:25:08 +0800 Subject: [PATCH] fix: fix standalone code but not finished --- materializer/ExportDialog.cpp | 41 +----- materializer/PluginMain.cpp | 35 ++++- materializer/PluginMain.hpp | 16 +++ materializer/StandaloneMain.cpp | 232 +++++++++++++++++++++++--------- materializer/Utilities.cpp | 3 +- materializer/main.cpp | 19 +++ 6 files changed, 240 insertions(+), 106 deletions(-) diff --git a/materializer/ExportDialog.cpp b/materializer/ExportDialog.cpp index fc887b2..8199abc 100644 --- a/materializer/ExportDialog.cpp +++ b/materializer/ExportDialog.cpp @@ -1,46 +1,11 @@ #if defined(MATERIALIZER_PLUGIN) #include "ExportDialog.hpp" +#include "PluginMain.hpp" #include namespace VSW::Materializer { - class ExportDialogSetting { - public: - static ExportDialogSetting& GetSingleton(); - private: - static YYCC::yycc_u8string GetConfigFilePath(); - ExportDialogSetting() : - m_LastFilePath(YYCC_U8("last-file-path"), YYCC_U8("")), - m_Encoding(YYCC_U8("encoding"), CP_ACP), - m_Mgr(ExportDialogSetting::GetConfigFilePath(), UINT64_C(0), { - &m_LastFilePath, &m_Encoding - }) { - m_Mgr.Load(); - } - ~ExportDialogSetting() { - m_Mgr.Save(); - } - - public: - YYCC::ConfigManager::StringSetting m_LastFilePath; - YYCC::ConfigManager::NumberSetting m_Encoding; - YYCC::ConfigManager::CoreManager m_Mgr; - }; - ExportDialogSetting& ExportDialogSetting::GetSingleton() { - static ExportDialogSetting g_Singleton; - return g_Singleton; - } - YYCC::yycc_u8string ExportDialogSetting::GetConfigFilePath() { - // get path to executable virtools - YYCC::yycc_u8string u8_virtools_path; - if (!YYCC::WinFctHelper::GetModuleFileName(NULL, u8_virtools_path)) - u8_virtools_path.clear(); - // get its parent folder and append with cfg file name - std::filesystem::path virtools_path(YYCC::FsPathPatch::FromUTF8Path(u8_virtools_path.c_str())); - return YYCC::FsPathPatch::ToUTF8Path(virtools_path.parent_path() / YYCC::FsPathPatch::FromUTF8Path(YYCC_U8("vsw_materializer.cfg"))); - } - namespace ExportDialogHelper { #define RADIOBTN_GETCHECK(instance) (instance.GetCheck() == BST_CHECKED) @@ -118,7 +83,7 @@ namespace VSW::Materializer { CDialogEx::OnInitDialog(); // Read settings from config manager - auto& config_manager = ExportDialogSetting::GetSingleton(); + auto& config_manager = PluginMain::ConfigManager::GetSingleton(); auto u8_last_path = config_manager.m_LastFilePath.Get(); if (!u8_last_path.empty()) { auto last_path = YYCC::FsPathPatch::FromUTF8Path(u8_last_path.c_str()); @@ -158,7 +123,7 @@ namespace VSW::Materializer { } // check done. sync settings to config manager - auto& config_manager = ExportDialogSetting::GetSingleton(); + auto& config_manager = PluginMain::ConfigManager::GetSingleton(); config_manager.m_LastFilePath.Set(m_DatabaseFileResult); config_manager.m_Encoding.Set(m_EncodingResult); diff --git a/materializer/PluginMain.cpp b/materializer/PluginMain.cpp index d05c5c8..7472c27 100644 --- a/materializer/PluginMain.cpp +++ b/materializer/PluginMain.cpp @@ -3,9 +3,38 @@ #include "ExportDialog.hpp" namespace VSW::Materializer::PluginMain { - + #ifdef MATERIALIZER_PLUGIN - + +#pragma region Export Dialog Setting + + ConfigManager::ConfigManager() : + m_LastFilePath(YYCC_U8("last-file-path"), YYCC_U8("")), + m_Encoding(YYCC_U8("encoding"), CP_ACP), + m_Mgr(ConfigManager::GetConfigFilePath(), UINT64_C(0), { + &m_LastFilePath, &m_Encoding + }) {} + + ConfigManager::~ConfigManager() {} + + ConfigManager& ConfigManager::GetSingleton() { + static ConfigManager g_Singleton; + return g_Singleton; + } + + YYCC::yycc_u8string ConfigManager::GetConfigFilePath() { + // get path to executable virtools + YYCC::yycc_u8string u8_virtools_path; + if (!YYCC::WinFctHelper::GetModuleFileName(NULL, u8_virtools_path)) + u8_virtools_path.clear(); + // get its parent folder and append with cfg file name + std::filesystem::path virtools_path(YYCC::FsPathPatch::FromUTF8Path(u8_virtools_path.c_str())); + return YYCC::FsPathPatch::ToUTF8Path(virtools_path.parent_path() / YYCC::FsPathPatch::FromUTF8Path(YYCC_U8("vsw_materializer.cfg"))); + } + +#pragma endregion + + PluginInterface* g_Plugininterface = nullptr; PluginInfo g_PluginInfo; CMenu* g_MainMenu = nullptr; @@ -49,7 +78,7 @@ namespace VSW::Materializer::PluginMain { } case 4: { - const wchar_t* body = + const wchar_t* body = L"VSW Materializer v2.0.0 - Virtools Schematic Weaver Materializer.\n" L"The exporter of universal Virtools scripts analyser.\n" L"Under GPL v3 License.\n" diff --git a/materializer/PluginMain.hpp b/materializer/PluginMain.hpp index cf5b7fa..dbea422 100644 --- a/materializer/PluginMain.hpp +++ b/materializer/PluginMain.hpp @@ -4,9 +4,25 @@ namespace VSW::Materializer::PluginMain { #ifdef MATERIALIZER_PLUGIN + + class ConfigManager { + public: + static ConfigManager& GetSingleton(); + private: + static YYCC::yycc_u8string GetConfigFilePath(); + ConfigManager(); + ~ConfigManager(); + + public: + YYCC::ConfigManager::StringSetting m_LastFilePath; + YYCC::ConfigManager::NumberSetting m_Encoding; + YYCC::ConfigManager::CoreManager m_Mgr; + }; + void InitializePluginInfo(); PluginInfo* GetPluginInfo(); PluginInterface* GetPluginInterface(); + #endif } diff --git a/materializer/StandaloneMain.cpp b/materializer/StandaloneMain.cpp index ab60f57..a6dc185 100644 --- a/materializer/StandaloneMain.cpp +++ b/materializer/StandaloneMain.cpp @@ -1,86 +1,190 @@ #include "StandaloneMain.hpp" +#include "ExportCore.hpp" +#include "GenericHelper.hpp" namespace VSW::Materializer::StandaloneMain { #ifdef MATERIALIZER_STANDALONE - - void PlayerMain(int argc, char* argv[]) { - printf("Super Script Materializer\n"); - printf("Homepage: https://github.com/yyc12345/SuperScriptMaterializer\n"); - printf("Report bug: https://github.com/yyc12345/SuperScriptMaterializer/issues\n"); - // ====================== Init ck2 engine -#if defined(VIRTOOLS_21) - CommonAssert(LoadLibrary("CK2.dll") != NULL, "Error loading CK2.dll"); +#pragma region Program Command Line Parser + + struct CmdArguments { + CmdArguments() : + m_InputFilePath(), + m_ScriptDbPath(), m_DocumentDbPath(), m_EnvironmentDbPath(), + m_CodePage(CP_ACP) {} + YYCC::yycc_u8string m_InputFilePath; + YYCC::yycc_u8string m_ScriptDbPath, m_DocumentDbPath, m_EnvironmentDbPath; + UINT m_CodePage; + }; + static YYCC::Constraints::Constraint GetCodePageConstraint() { + return YYCC::Constraints::Constraint { + [](const UINT& val) -> bool { + return YYCC::WinFctHelper::IsValidCodePage(val); + } + }; + } + class CmdParser { + public: + CmdParser() : + m_InputFilePath(YYCC_U8("input"), YYCC_U8_CHAR('i'), YYCC_U8("The path to Virtools file for exporting."), YYCC_U8("example.cmo"), true), + m_ScriptDbPath(YYCC_U8("script"), YYCC_U8_CHAR('s'), YYCC_U8("The path to exported script database. Input file is required."), YYCC_U8("script.db"), true), + m_DocumentDbPath(YYCC_U8("document"), YYCC_U8_CHAR('d'), YYCC_U8("The path to exported document database. Input file is required."), YYCC_U8("doc.db"), true), + m_EnvironmentDbPath(YYCC_U8("environment"), YYCC_U8_CHAR('e'), YYCC_U8("The path to exported environment database. Input file is not required."), YYCC_U8("env.db"), true), + m_CodePage(YYCC_U8("code-page"), YYCC_U8_CHAR('c'), YYCC_U8("The code page used when reading Virtools document."), YYCC_U8("1252"), true, GetCodePageConstraint()), + m_Version(YYCC_U8("version"), YYCC_U8_CHAR('v'), YYCC_U8("Print version infomation about this program and exit.")), + m_Help(YYCC_U8("help"), YYCC_U8_CHAR('h'), YYCC_U8("Print this help page and exit.")), + m_OptionContext(YYCC_U8("Virtools Schematic Weaver - Materializer"), YYCC_U8("The exporter of Virtools Schematic Weaver"), { + &m_ScriptDbPath, &m_DocumentDbPath, &m_EnvironmentDbPath, &m_CodePage, + &m_Version, &m_Help + }) {} + ~CmdParser() {} + YYCC_DEL_CLS_COPY_MOVE(CmdParser); + + public: + YYCC::ArgParser::StringArgument m_InputFilePath; + YYCC::ArgParser::StringArgument m_ScriptDbPath; + YYCC::ArgParser::StringArgument m_DocumentDbPath; + YYCC::ArgParser::StringArgument m_EnvironmentDbPath; + YYCC::ArgParser::NumberArgument m_CodePage; + + YYCC::ArgParser::SwitchArgument m_Version; + YYCC::ArgParser::SwitchArgument m_Help; + + YYCC::ArgParser::OptionContext m_OptionContext; + }; + static bool ParseCmd(int argc, char* argv[], CmdArguments& captured) { + // fetch argument list +#if YYCC_OS == YYCC_OS_WINDOWS + auto al = YYCC::ArgParser::ArgumentList::CreateFromWin32(); +#else + auto al = YYCC::ArgParser::ArgumentList::CreateFromStd(argc, argv); #endif - CommonAssert(!CKStartUp(), "CKStartUp Error"); - CKPluginManager* pluginManager = CKGetPluginManager(); - CommonAssert(pluginManager != NULL, "PluginManager = null"); - CommonAssert(pluginManager->ParsePlugins("RenderEngines") > 0, "Error loading RenderEngines"); - CommonAssert(pluginManager->ParsePlugins("Managers") > 0, "Error loading Managers"); - CommonAssert(pluginManager->ParsePlugins("BuildingBlocks") > 0, "Error loading BuildingBlocks"); - CommonAssert(pluginManager->ParsePlugins("Plugins") > 0, "Error loading Plugins"); + // do parse + CmdParser parser; + if (!parser.m_OptionContext.Parse(al)) { + YYCC::ConsoleHelper::WriteLine(YYCC_U8(YYCC_COLOR_LIGHT_RED("Invalid command line."))); + parser.m_OptionContext.Help(); + return false; + } - // ====================== create context and load file - CKContext* context = NULL; - CommonAssert(!CKCreateContext(&context, NULL), "CKCreateContext Error"); + // check help command + if (parser.m_Help.IsCaptured()) { + parser.m_OptionContext.Help(); + return false; + } + // check version command + if (parser.m_Version.IsCaptured()) { + YYCC::ConsoleHelper::WriteLine(YYCC_U8("Virtools Schematic Weaver - Materializer v2.0.0")); + return false; + } + + // check command relation + // if specify script or document export, user must provide input file + if (parser.m_ScriptDbPath.IsCaptured() || parser.m_DocumentDbPath.IsCaptured()) { + if (!parser.m_InputFilePath.IsCaptured()) { + YYCC::ConsoleHelper::WriteLine(YYCC_U8(YYCC_COLOR_LIGHT_RED("You must specify one input file if you want to export script or document."))); + parser.m_OptionContext.Help(); + return false; + } + } + + // setup argument + if (parser.m_InputFilePath.IsCaptured()) captured.m_InputFilePath = parser.m_InputFilePath.Get(); + else captured.m_InputFilePath.clear(); + if (parser.m_ScriptDbPath.IsCaptured()) captured.m_ScriptDbPath = parser.m_ScriptDbPath.Get(); + else captured.m_ScriptDbPath.clear(); + if (parser.m_DocumentDbPath.IsCaptured()) captured.m_DocumentDbPath = parser.m_DocumentDbPath.Get(); + else captured.m_DocumentDbPath.clear(); + if (parser.m_EnvironmentDbPath.IsCaptured()) captured.m_EnvironmentDbPath = parser.m_EnvironmentDbPath.Get(); + else captured.m_EnvironmentDbPath.clear(); + if (parser.m_CodePage.IsCaptured()) captured.m_CodePage = parser.m_CodePage.Get(); + else captured.m_CodePage = CP_ACP; + // okey, return + return true; + } + +#pragma endregion + +#pragma region Assistant Functions + + static void CustomAssert(VSW::Reporter& reporter, bool condition, const YYCC::yycc_char8_t* msg) { + if (!condition) { + if (msg != nullptr) + reporter.Err(msg); + std::abort(); + } + } +#define CUSTOM_ASSERT(condition, msg) CustomAssert(reporter, (condition), YYCC_U8(msg)) + +#pragma endregion + + void PlayerMain(int argc, char* argv[]) { + // ========== Check Passed Arguments ========== + CmdArguments captured; + if (!ParseCmd(argc, argv, captured)) { + return; + } + + // ========== Print Header ========== + YYCC::ConsoleHelper::WriteLine(YYCC_U8("Virtools Schematic Weaver - Materializer")); + YYCC::ConsoleHelper::WriteLine(YYCC_U8("Homepage: https://github.com/yyc12345/SuperScriptMaterializer")); + YYCC::ConsoleHelper::WriteLine(YYCC_U8("Report bug: https://github.com/yyc12345/SuperScriptMaterializer/issues")); + + // ========== Init CK2 Engine ========== + // Prepare reporter + VSW::Reporter reporter; + + CUSTOM_ASSERT(CKStartUp() == CK_OK, "CKStartUp() Error"); + CKPluginManager* plugin_mgr = CKGetPluginManager(); + CUSTOM_ASSERT(plugin_mgr != nullptr, "CKPluginManager is nullptr"); + CUSTOM_ASSERT(plugin_mgr->ParsePlugins("RenderEngines") > 0, "Error loading RenderEngines"); + CUSTOM_ASSERT(plugin_mgr->ParsePlugins("Managers") > 0, "Error loading Managers"); + CUSTOM_ASSERT(plugin_mgr->ParsePlugins("BuildingBlocks") > 0, "Error loading BuildingBlocks"); + CUSTOM_ASSERT(plugin_mgr->ParsePlugins("Plugins") > 0, "Error loading Plugins"); + + // ========== Create CKContext and Load File ========== + CKContext* ctx = nullptr; +#if defined(VIRTOOLS_21) + CUSTOM_ASSERT(CKCreateContext(&ctx, NULL, 0, 0) == CK_OK, "CKCreateContext Error"); +#else + CUSTOM_ASSERT(CKCreateContext(&ctx, NULL) == CK_OK, "CKCreateContext Error"); +#endif CKObjectArray* array = CreateCKObjectArray(); - CommonAssert(!context->Load((char*)virtools_composition, array), "CKContext->Load() Error"); + CUSTOM_ASSERT(!ctx->Load((char*)virtools_composition, array), "CKContext::Load() Error"); printf("Parsing %s...\n", virtools_composition); - - // ====================== do SSMaterializerDatabase export - // define and Init - scriptDatabase* _script_db = new scriptDatabase(); - dbScriptDataStructHelper* _script_helper = new dbScriptDataStructHelper(); - envDatabase* _env_db = new envDatabase(); - dbEnvDataStructHelper* _env_helper = new dbEnvDataStructHelper(); - - DeleteFile(script_db_path); - DeleteFile(env_db_path); - _script_db->open(script_db_path); - _script_helper->init(context->GetParameterManager()); - _env_db->open(env_db_path); - _env_helper->init(); - - // export - IterateScript(context, _script_db, _script_helper); - - IterateParameterOperation(context->GetParameterManager(), _env_db, _env_helper); - IterateParameter(context->GetParameterManager(), _env_db, _env_helper); - IterateMessage(context->GetMessageManager(), _env_db, _env_helper); - IterateAttribute(context->GetAttributeManager(), _env_db, _env_helper); - IteratePlugin(CKGetPluginManager(), _env_db, _env_helper); -#if !defined(VIRTOOLS_21) - IterateVariable(context->GetVariableManager(), _env_db, _env_helper); -#endif - - // free - _script_helper->dispose(); - _script_db->close(); - _env_helper->dispose(); - _env_db->close(); - delete _script_helper; - delete _script_db; - delete _env_helper; - delete _env_db; - - printf("Done!"); + + // ========== Export Data ========== + if (!captured.m_ScriptDbPath.empty()) { + reporter.Info(YYCC_U8("Exporting script database...")); + ExportScript::Export(ctx, captured.m_ScriptDbPath, captured.m_CodePage); + } + if (!captured.m_DocumentDbPath.empty()) { + reporter.Info(YYCC_U8("Exporting document database...")); + ExportDocument::Export(ctx, captured.m_DocumentDbPath, captured.m_CodePage); + } + if (!captured.m_EnvironmentDbPath.empty()) { + reporter.Info(YYCC_U8("Exporting environment database...")); + ExportEnvironment::Export(ctx, captured.m_EnvironmentDbPath, captured.m_CodePage); + } // ====================== free resources and shutdown engine DeleteCKObjectArray(array); - context->Reset(); - context->ClearAll(); - - // todo: Virtools 4.0 standalone version throw exception in there, but i don't knwo why + ctx->Reset(); + ctx->ClearAll(); + + // ========== Destroy CKContext ========== + // todo: Virtools 4.0 standalone version throw exception in there, but i don't know why // but it doesn't affect SSMaterializerDatabase export, perhaps - CKCloseContext(context); + CUSTOM_ASSERT(CKCloseContext(ctx) == CK_OK, "CKCloseContext Error."); - CKShutdown(); + // ========== Shutdown CK2 Engine ========== + CUSTOM_ASSERT(CKShutdown() == CK_OK, "CKShutdown() Error."); - // todo: Virtools 2.5 standalone version throw exception in there, but i don't knwo why + // todo: Virtools 2.5 standalone version throw exception in there, but i don't know why // but it doesn't affect SSMaterializerDatabase export, perhaps } diff --git a/materializer/Utilities.cpp b/materializer/Utilities.cpp index 222391a..eb79759 100644 --- a/materializer/Utilities.cpp +++ b/materializer/Utilities.cpp @@ -14,7 +14,8 @@ namespace VSW::Materializer::Utilities { void EnhancedReporter::DisableBeep() { m_OrderBeep = false; } void EnhancedReporter::PrePrint(const YYCC::yycc_char8_t* strl) const { - if (m_Ctx != nullptr) + // only write when CKContext is not nullptr and we are in Interface Mode (Dev mode). + if (m_Ctx != nullptr && m_Ctx->IsInInterfaceMode()) m_Ctx->OutputToConsole(const_cast(YYCC::EncodingHelper::UTF8ToChar(strl, CP_ACP).c_str()), m_OrderBeep); } diff --git a/materializer/main.cpp b/materializer/main.cpp index 433b0c3..79cff4d 100644 --- a/materializer/main.cpp +++ b/materializer/main.cpp @@ -25,12 +25,19 @@ public: YYCC::ExceptionHelper::Register(vtobjplugin::VirtoolsMenu::UnhandledExceptionCallback); #endif + // load config from file + auto& config_manager = VSW::Materializer::PluginMain::ConfigManager::GetSingleton(); + config_manager.m_Mgr.Load(); + // init plugin info VSW::Materializer::PluginMain::InitializePluginInfo(); return CWinApp::InitInstance(); } virtual int ExitInstance() override { + // save config to file + auto& config_manager = VSW::Materializer::PluginMain::ConfigManager::GetSingleton(); + config_manager.m_Mgr.Save(); // unregister unhandler exception handler #ifdef MATERIALIZER_RELEASE @@ -45,7 +52,19 @@ CMaterializer theApp; #else int main(int argc, char* argv[]) { + // register unhandler exception handler +#ifdef MATERIALIZER_RELEASE + YYCC::ExceptionHelper::Register(vtobjplugin::VirtoolsMenu::UnhandledExceptionCallback); +#endif + + // Run core code. VSW::Materializer::StandaloneMain::PlayerMain(argc, argv); + + // unregister unhandler exception handler +#ifdef MATERIALIZER_RELEASE + YYCC::ExceptionHelper::Unregister(); +#endif + return 0; }