feat: basically finish standalone mode.
- finish standalone mode but only tested on Virtools 2.1 environment. - add DROP TABLE statement before CREATE TABLE to resolve fail to create table issue when opening an existing database file.
This commit is contained in:
@@ -124,6 +124,20 @@ failed: throw std::runtime_error("fail to bind value for prepared statement.");
|
||||
AbstractDatabase(file) {
|
||||
// initialize table
|
||||
BEGIN_CTOR;
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [script];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [behavior];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [bIO];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pTarget];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pIn];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pOut];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [bLink];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pLocal];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pAttr];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pLink];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pOper];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [eLink];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [data];");
|
||||
|
||||
CTOR_SQL_EXEC("CREATE TABLE [script] ([beobj] INTEGER, [beobj_name] TEXT, [behavior_index] INTEGER, [behavior] INTEGER);");
|
||||
CTOR_SQL_EXEC("CREATE TABLE [behavior] ([thisobj] INTEGER, [name] TEXT, [type] INTEGER, [proto_name] TEXT, [proto_guid] INTEGER, [flags] INTEGER, [priority] INTEGER, [version] INTEGER, [pin_count_ptarget] INTEGER, [pin_count_pin] INTEGER, [pin_count_pout] INTEGER, [pin_count_bin] INTEGER, [pin_count_bout] INTEGER, [parent] INTEGER);");
|
||||
CTOR_SQL_EXEC("CREATE TABLE [pTarget] ([thisobj] INTEGER, [name] TEXT, [type] INTEGER, [parent] INTEGER, [direct_source] INTEGER, [shared_source] INTEGER);");
|
||||
@@ -144,7 +158,6 @@ failed: throw std::runtime_error("fail to bind value for prepared statement.");
|
||||
ScriptDatabase::~ScriptDatabase() {
|
||||
// create index for quick select in following process
|
||||
BEGIN_DTOR;
|
||||
DTOR_SQL_EXEC("begin;");
|
||||
DTOR_SQL_EXEC("CREATE INDEX [quick_where1] ON [behavior] ([parent])");
|
||||
DTOR_SQL_EXEC("CREATE INDEX [quick_where2] ON [pOper] ([parent], [thisobj])");
|
||||
DTOR_SQL_EXEC("CREATE INDEX [quick_where3] ON [pTarget] ([parent])");
|
||||
@@ -158,7 +171,6 @@ failed: throw std::runtime_error("fail to bind value for prepared statement.");
|
||||
DTOR_SQL_EXEC("CREATE INDEX [quick_where11] ON [elink] ([parent])");
|
||||
DTOR_SQL_EXEC("CREATE INDEX [quick_where12] ON [pAttr] ([thisobj])");
|
||||
DTOR_SQL_EXEC("CREATE INDEX [quick_where13] ON [data] ([parent])");
|
||||
DTOR_SQL_EXEC("commit;");
|
||||
END_DTOR;
|
||||
}
|
||||
|
||||
@@ -312,6 +324,9 @@ failed: throw std::runtime_error("fail to bind value for prepared statement.");
|
||||
AbstractDatabase(file) {
|
||||
// initialize table
|
||||
BEGIN_CTOR;
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [msg];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [obj];");
|
||||
|
||||
CTOR_SQL_EXEC("CREATE TABLE [msg] ([index] INTEGER, [name] TEXT);");
|
||||
CTOR_SQL_EXEC("CREATE TABLE [obj] ([id] INTEGER, [name] TEXT, [classid] INTEGER, [classid_name] TEXT);");
|
||||
END_CTOR;
|
||||
@@ -320,10 +335,8 @@ failed: throw std::runtime_error("fail to bind value for prepared statement.");
|
||||
DocumentDatabase::~DocumentDatabase() {
|
||||
// create index for quick select in following process
|
||||
BEGIN_DTOR;
|
||||
DTOR_SQL_EXEC("begin;");
|
||||
DTOR_SQL_EXEC("CREATE INDEX [quick_where1] ON [msg] ([index])");
|
||||
DTOR_SQL_EXEC("CREATE INDEX [quick_where2] ON [obj] ([id])");
|
||||
DTOR_SQL_EXEC("commit;");
|
||||
END_DTOR;
|
||||
}
|
||||
|
||||
@@ -350,6 +363,12 @@ failed: throw std::runtime_error("fail to bind value for prepared statement.");
|
||||
AbstractDatabase(file) {
|
||||
// initialize table
|
||||
BEGIN_CTOR;
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [op];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [param];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [attr];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [plugin];");
|
||||
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [variable];");
|
||||
|
||||
CTOR_SQL_EXEC("CREATE TABLE [op] ([func_ptr] TEXT, [in1_guid] INTEGER, [in2_guid] INTEGER, [out_guid] INTEGER, [op_guid] INTEGER, [op_name] TEXT, [op_code] INTEGER);");
|
||||
CTOR_SQL_EXEC("CREATE TABLE [param] ([index] INTEGER, [guid] INTEGER, [derived_from] INTEGER, [name] TEXT, [default_size] INTEGER, [func_CreateDefault] TEXT, [func_Delete] TEXT, [func_SaveLoad] TEXT, [func_Check] TEXT, [func_Copy] TEXT, [func_String] TEXT, [func_UICreator] TEXT, [dll_name] TEXT, [dll_index] INTEGER, [position_in_dll] INTEGER, [flags] INTEGER, [dw_param] INTEGER, [cid] INTEGER, [saver_manager] INTEGER);");
|
||||
CTOR_SQL_EXEC("CREATE TABLE [attr] ([index] INTEGER, [name] TEXT, [category_index] INTEGER, [category_name] TEXT, [flags] INTEGER, [param_index] INTEGER, [param_guid] INTEGER, [compatible_classid] INTEGER, [default_value] TEXT);");
|
||||
@@ -359,7 +378,9 @@ failed: throw std::runtime_error("fail to bind value for prepared statement.");
|
||||
}
|
||||
|
||||
EnvironmentDatabase::~EnvironmentDatabase() {
|
||||
// do nothing
|
||||
// create index for quick select in following process
|
||||
BEGIN_DTOR;
|
||||
END_DTOR;
|
||||
}
|
||||
|
||||
void EnvironmentDatabase::Write(const DataTypes::Environment::Table_op& data) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "StandaloneMain.hpp"
|
||||
#include "ExportCore.hpp"
|
||||
#include "GenericHelper.hpp"
|
||||
#include <optional>
|
||||
|
||||
namespace VSW::Materializer::StandaloneMain {
|
||||
|
||||
@@ -35,6 +36,7 @@ namespace VSW::Materializer::StandaloneMain {
|
||||
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_InputFilePath,
|
||||
&m_ScriptDbPath, &m_DocumentDbPath, &m_EnvironmentDbPath, &m_CodePage,
|
||||
&m_Version, &m_Help
|
||||
}) {}
|
||||
@@ -109,6 +111,67 @@ namespace VSW::Materializer::StandaloneMain {
|
||||
|
||||
#pragma region Assistant Functions
|
||||
|
||||
class TemporaryFile {
|
||||
public:
|
||||
TemporaryFile(CKContext* ctx, const YYCC::yycc_u8string_view& u8_vt_file) :
|
||||
m_IsSuccess(false), m_TempFile() {
|
||||
if (ctx == nullptr) throw std::invalid_argument("Invalid CKContext");
|
||||
if (u8_vt_file.empty()) throw std::invalid_argument("Invalid Virtools file path");
|
||||
|
||||
// build source virtools file
|
||||
auto vt_file = YYCC::FsPathPatch::FromUTF8Path(u8_vt_file.data());
|
||||
|
||||
// build cache path located in Windows temp path and keep its extension
|
||||
YYCC::yycc_u8string u8_temp_dir;
|
||||
if (!YYCC::WinFctHelper::GetTempDirectory(u8_temp_dir))
|
||||
throw std::runtime_error("Fail to fetch Windows Temp directory");
|
||||
auto temp_dir = YYCC::FsPathPatch::FromUTF8Path(u8_temp_dir.c_str());
|
||||
temp_dir /= YYCC::FsPathPatch::FromUTF8Path(YYCC_U8("07159749-81e5-4ec2-b649-87b8eb9c1f5a"));
|
||||
temp_dir.replace_extension(vt_file.extension());
|
||||
m_TempFile = YYCC::FsPathPatch::ToUTF8Path(temp_dir);
|
||||
|
||||
// copy it to temp directory
|
||||
std::wstring w_temp_file, w_vt_file;
|
||||
if (!YYCC::EncodingHelper::UTF8ToWchar(u8_vt_file, w_vt_file))
|
||||
throw std::runtime_error("Fail to fetch source file.");
|
||||
if (!YYCC::EncodingHelper::UTF8ToWchar(m_TempFile, w_temp_file))
|
||||
throw std::runtime_error("Fail to fetch temporary file.");
|
||||
if (!::CopyFileW(w_vt_file.c_str(), w_temp_file.c_str(), FALSE))
|
||||
throw std::runtime_error("Fail to copy file.");
|
||||
|
||||
// okey
|
||||
m_IsSuccess = true;
|
||||
}
|
||||
~TemporaryFile() {
|
||||
if (m_IsSuccess) {
|
||||
std::wstring w_temp_file;
|
||||
if (!YYCC::EncodingHelper::UTF8ToWchar(m_TempFile, w_temp_file)) return;
|
||||
::DeleteFileW(w_temp_file.c_str());
|
||||
}
|
||||
}
|
||||
TemporaryFile(TemporaryFile&& rhs) :
|
||||
m_IsSuccess(rhs.m_IsSuccess), m_TempFile(rhs.m_TempFile) {
|
||||
rhs.m_IsSuccess = false;
|
||||
rhs.m_TempFile.clear();
|
||||
}
|
||||
TemporaryFile& operator=(TemporaryFile&& rhs) {
|
||||
this->m_IsSuccess = rhs.m_IsSuccess;
|
||||
this->m_TempFile = rhs.m_TempFile;
|
||||
rhs.m_IsSuccess = false;
|
||||
rhs.m_TempFile.clear();
|
||||
return *this;
|
||||
}
|
||||
YYCC_DEL_CLS_COPY(TemporaryFile);
|
||||
|
||||
public:
|
||||
bool IsSuccess() const { return m_IsSuccess; }
|
||||
const YYCC::yycc_u8string& GetPath() const { return m_TempFile; }
|
||||
|
||||
private:
|
||||
bool m_IsSuccess;
|
||||
YYCC::yycc_u8string m_TempFile;
|
||||
};
|
||||
|
||||
static void CustomAssert(VSW::Reporter& reporter, bool condition, const YYCC::yycc_char8_t* msg) {
|
||||
if (!condition) {
|
||||
if (msg != nullptr)
|
||||
@@ -143,8 +206,8 @@ namespace VSW::Materializer::StandaloneMain {
|
||||
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 ==========
|
||||
|
||||
// ========== Create CKContext ==========
|
||||
CKContext* ctx = nullptr;
|
||||
#if defined(VIRTOOLS_21)
|
||||
CUSTOM_ASSERT(CKCreateContext(&ctx, NULL, 0, 0) == CK_OK, "CKCreateContext Error");
|
||||
@@ -152,11 +215,22 @@ namespace VSW::Materializer::StandaloneMain {
|
||||
CUSTOM_ASSERT(CKCreateContext(&ctx, NULL) == CK_OK, "CKCreateContext Error");
|
||||
#endif
|
||||
|
||||
CKObjectArray* array = CreateCKObjectArray();
|
||||
CUSTOM_ASSERT(!ctx->Load((char*)virtools_composition, array), "CKContext::Load() Error");
|
||||
// ========== Load File ==========
|
||||
std::optional<TemporaryFile> loaded_file;
|
||||
CKObjectArray* loaded_file_objs = CreateCKObjectArray();
|
||||
if (!captured.m_InputFilePath.empty()) {
|
||||
TemporaryFile cache(ctx, captured.m_InputFilePath);
|
||||
if (cache.IsSuccess()) {
|
||||
std::string temp_file;
|
||||
if (YYCC::EncodingHelper::UTF8ToChar(cache.GetPath(), temp_file, CP_ACP)) {
|
||||
if (ctx->Load(const_cast<CKSTRING>(temp_file.c_str()), loaded_file_objs) == CK_OK) {
|
||||
loaded_file = std::move(cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
CUSTOM_ASSERT(loaded_file.has_value(), "Fail to open specified file.");
|
||||
}
|
||||
|
||||
printf("Parsing %s...\n", virtools_composition);
|
||||
|
||||
// ========== Export Data ==========
|
||||
if (!captured.m_ScriptDbPath.empty()) {
|
||||
reporter.Info(YYCC_U8("Exporting script database..."));
|
||||
@@ -171,18 +245,19 @@ namespace VSW::Materializer::StandaloneMain {
|
||||
ExportEnvironment::Export(ctx, captured.m_EnvironmentDbPath, captured.m_CodePage);
|
||||
}
|
||||
|
||||
// ====================== free resources and shutdown engine
|
||||
DeleteCKObjectArray(array);
|
||||
// ========== Unload File and Clear CKContext ==========
|
||||
DeleteCKObjectArray(loaded_file_objs);
|
||||
loaded_file.reset();
|
||||
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
|
||||
CUSTOM_ASSERT(CKCloseContext(ctx) == CK_OK, "CKCloseContext Error.");
|
||||
CKCloseContext(ctx);
|
||||
|
||||
// ========== Shutdown CK2 Engine ==========
|
||||
CUSTOM_ASSERT(CKShutdown() == CK_OK, "CKShutdown() Error.");
|
||||
CKShutdown();
|
||||
|
||||
// todo: Virtools 2.5 standalone version throw exception in there, but i don't know why
|
||||
// but it doesn't affect SSMaterializerDatabase export, perhaps
|
||||
|
||||
Reference in New Issue
Block a user