2024-08-02 17:04:37 +08:00
|
|
|
#include "ExportCore.hpp"
|
2024-08-08 17:47:27 +08:00
|
|
|
#include "Database.hpp"
|
|
|
|
|
#include "DataTypes.hpp"
|
|
|
|
|
#include "Utilities.hpp"
|
|
|
|
|
#include <numeric>
|
|
|
|
|
#include <type_traits>
|
2024-08-01 22:38:55 +08:00
|
|
|
|
|
|
|
|
namespace VSW::Materializer::ExportScript {
|
|
|
|
|
|
2024-08-08 17:47:27 +08:00
|
|
|
struct ExportContext {
|
|
|
|
|
ExportContext(CKContext* ctx, const YYCC::yycc_u8string_view& db_path, UINT code_page) :
|
|
|
|
|
db(db_path), cache(), reporter(ctx), cp(code_page), attr_set(), param_mgr(ctx->GetParameterManager()) {}
|
|
|
|
|
Database::ScriptDatabase db;
|
|
|
|
|
DataTypes::Script::DataCache cache;
|
|
|
|
|
Utilities::EnhancedReporter reporter;
|
|
|
|
|
UINT cp;
|
|
|
|
|
/// @brief Variable for removing duplicated exported attributes.
|
|
|
|
|
std::set<CK_ID> attr_set;
|
|
|
|
|
CKParameterManager* param_mgr;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#pragma region Assist Functions
|
|
|
|
|
|
|
|
|
|
static void DataDictWriter(ExportContext& expctx, const YYCC::yycc_u8string_view& field, const void* data, size_t data_length, CK_ID parent) {
|
|
|
|
|
// check given data length
|
|
|
|
|
using db_size_t = decltype(expctx.cache.data.data.length);
|
|
|
|
|
if (data_length > static_cast<size_t>(std::numeric_limits<db_size_t>::max()))
|
|
|
|
|
throw std::runtime_error("Too long data length when exporting to data dictionary.");
|
|
|
|
|
// write data
|
|
|
|
|
expctx.cache.data.field = field;
|
|
|
|
|
expctx.cache.data.data.ptr = data;
|
|
|
|
|
expctx.cache.data.data.length = static_cast<db_size_t>(data_length);
|
|
|
|
|
expctx.cache.data.parent = parent;
|
|
|
|
|
expctx.db.Write(expctx.cache.data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void DataDictWriter(ExportContext& expctx, const YYCC::yycc_u8string_view& field, const YYCC::yycc_u8string& data, CK_ID parent) {
|
|
|
|
|
DataDictWriter(expctx, field, data.c_str(), data.length(), parent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class _Ty, std::enable_if_t<!std::is_same_v<_Ty, YYCC::yycc_u8string>, int> = 0>
|
|
|
|
|
static void DataDictWriter(ExportContext& expctx, const YYCC::yycc_u8string_view& field, const _Ty& data, CK_ID parent) {
|
|
|
|
|
DataDictWriter(expctx, field, &data, sizeof(_Ty), parent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define REC_RAW_DATA(field, data, len) DataDictWriter(expctx, YYCC_U8(field), data, len, parent)
|
|
|
|
|
#define REC_DATA(field, data) DataDictWriter(expctx, YYCC_U8(field), data, parent)
|
|
|
|
|
|
|
|
|
|
void DigParameterData(ExportContext& expctx, CKParameter* p, CK_ID parent) {
|
|
|
|
|
// According to our algorithm, CKParameter passed in this function can not be duplicated.
|
|
|
|
|
// So we don't need check it anymore.
|
|
|
|
|
// Get CKGUID and Parameter Type first
|
|
|
|
|
CKGUID t = p->GetGUID();
|
|
|
|
|
CKParameterType pt = p->GetType();
|
|
|
|
|
|
|
|
|
|
// Record GUID
|
|
|
|
|
int64_t exported_t;
|
|
|
|
|
CP_GUID(exported_t, t);
|
|
|
|
|
REC_DATA("dumper-guid", exported_t);
|
|
|
|
|
// Record Parameter Type name
|
|
|
|
|
YYCC::yycc_u8string exported_pt;
|
|
|
|
|
CP_CKSTR(exported_pt, expctx.param_mgr->ParameterTypeToName(pt));
|
|
|
|
|
REC_DATA("dumper-type-name", exported_pt);
|
|
|
|
|
|
|
|
|
|
// Detect value object scenario (associated with an existing CKObject)
|
|
|
|
|
if (p->GetParameterClassID() && p->GetValueObject(false)) {
|
|
|
|
|
// Record CK_ID of associated object
|
|
|
|
|
CKObject* assoc_obj = p->GetValueObject(false);
|
|
|
|
|
REC_DATA("dumper-assoc-ckobj", assoc_obj->GetID());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Nothing
|
|
|
|
|
if (t == CKPGUID_NONE) return;
|
|
|
|
|
|
|
|
|
|
// Float value
|
|
|
|
|
if (t == CKPGUID_FLOAT || t == CKPGUID_ANGLE || t == CKPGUID_PERCENTAGE || t == CKPGUID_TIME
|
|
|
|
|
#if defined(VIRTOOLS_50) || defined(VIRTOOLS_40) || defined(VIRTOOLS_35)
|
|
|
|
|
|| t == CKPGUID_FLOATSLIDER
|
|
|
|
|
#endif
|
|
|
|
|
) {
|
|
|
|
|
REC_DATA("dumper-float", *static_cast<float*>(p->GetReadDataPtr(false)));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// Integral value
|
|
|
|
|
if (t == CKPGUID_INT || t == CKPGUID_KEY || t == CKPGUID_BOOL || t == CKPGUID_ID || t == CKPGUID_POINTER
|
|
|
|
|
|| t == CKPGUID_MESSAGE || t == CKPGUID_ATTRIBUTE || t == CKPGUID_BLENDMODE || t == CKPGUID_FILTERMODE
|
|
|
|
|
|| t == CKPGUID_BLENDFACTOR || t == CKPGUID_FILLMODE || t == CKPGUID_LITMODE || t == CKPGUID_SHADEMODE
|
|
|
|
|
|| t == CKPGUID_ADDRESSMODE || t == CKPGUID_WRAPMODE || t == CKPGUID_3DSPRITEMODE || t == CKPGUID_FOGMODE
|
|
|
|
|
|| t == CKPGUID_LIGHTTYPE || t == CKPGUID_SPRITEALIGN || t == CKPGUID_DIRECTION || t == CKPGUID_LAYERTYPE
|
|
|
|
|
|| t == CKPGUID_COMPOPERATOR || t == CKPGUID_BINARYOPERATOR || t == CKPGUID_SETOPERATOR
|
|
|
|
|
|| t == CKPGUID_OBSTACLEPRECISION || t == CKPGUID_OBSTACLEPRECISIONBEH) {
|
|
|
|
|
REC_DATA("dumper-int", *static_cast<int*>(p->GetReadDataPtr(false)));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// Vector value
|
|
|
|
|
if (t == CKPGUID_VECTOR) {
|
|
|
|
|
REC_DATA("dumper-vector", *static_cast<VxVector*>(p->GetReadDataPtr(false)));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (t == CKPGUID_2DVECTOR) {
|
|
|
|
|
REC_DATA("dumper-2dvector", *static_cast<Vx2DVector*>(p->GetReadDataPtr(false)));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (t == CKPGUID_MATRIX) {
|
|
|
|
|
REC_DATA("dumper-matrix", *static_cast<VxMatrix*>(p->GetReadDataPtr(false)));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (t == CKPGUID_COLOR) {
|
|
|
|
|
REC_DATA("dumper-color", *static_cast<VxColor*>(p->GetReadDataPtr(false)));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 2D Curve value
|
|
|
|
|
if (t == CKPGUID_2DCURVE) {
|
|
|
|
|
// Get instance
|
|
|
|
|
CK2dCurve* c = static_cast<CK2dCurve*>(p->GetReadDataPtr(false));
|
|
|
|
|
// We build our unique binary 2d curve data.
|
|
|
|
|
Utilities::Curve2DBuilder builder(c);
|
|
|
|
|
REC_RAW_DATA("dumper-2d-curve", builder.GetDataPtr(), builder.GetDataLength());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// String value
|
|
|
|
|
if (t == CKPGUID_STRING) {
|
|
|
|
|
// Virtools internal data may not have null terminal,
|
|
|
|
|
// so we use need copy it into container first.
|
|
|
|
|
std::string native_string(
|
|
|
|
|
static_cast<char*>(p->GetReadDataPtr(false)),
|
|
|
|
|
static_cast<size_t>(p->GetDataSize())
|
|
|
|
|
);
|
|
|
|
|
// Then do encoding convertion
|
|
|
|
|
YYCC::yycc_u8string utf8_string;
|
|
|
|
|
if (!YYCC::EncodingHelper::CharToUTF8(native_string, utf8_string, expctx.cp)) {
|
|
|
|
|
// If failed, report error
|
|
|
|
|
expctx.reporter.Err(YYCC_U8("Fail to convert string encoding for data of CKParameter. Some value may be empty!"));
|
|
|
|
|
// reset to blank string
|
|
|
|
|
utf8_string.clear();
|
|
|
|
|
}
|
|
|
|
|
REC_DATA("dumper-string", utf8_string);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// If it gets here, we have no idea what it really is. so simply dump it.
|
|
|
|
|
// Buffer-like
|
|
|
|
|
if (t == CKPGUID_VOIDBUF
|
|
|
|
|
#if defined(VIRTOOLS_50) || defined(VIRTOOLS_40) || defined(VIRTOOLS_35)
|
|
|
|
|
|| t == CKPGUID_SHADER || t == CKPGUID_TECHNIQUE || t == CKPGUID_PASS
|
|
|
|
|
#endif
|
|
|
|
|
|| true // All unknown type goes there.
|
|
|
|
|
) {
|
|
|
|
|
// Raw data is similar with string,
|
|
|
|
|
// but we don't need do encoding convertion.
|
|
|
|
|
const void* data_ptr = p->GetReadDataPtr(false);
|
|
|
|
|
size_t data_len = static_cast<size_t>(p->GetDataSize());
|
|
|
|
|
REC_RAW_DATA("dumper-raw", data_ptr, data_len);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma endregion
|
2024-08-02 17:04:37 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-08-04 17:43:18 +08:00
|
|
|
void Export(CKContext* ctx, const YYCC::yycc_u8string_view& db_path, UINT code_page) {
|
2024-08-08 17:47:27 +08:00
|
|
|
// create export context
|
|
|
|
|
ExportContext expctx(ctx, db_path, code_page);
|
|
|
|
|
if (!expctx.db.IsValid()) {
|
|
|
|
|
expctx.reporter.Err(YYCC_U8("Fail to open database. Export process aborted."));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-08-02 17:04:37 +08:00
|
|
|
|
2024-08-08 17:47:27 +08:00
|
|
|
// export script
|
2024-08-02 17:04:37 +08:00
|
|
|
}
|
|
|
|
|
|
2024-08-01 22:38:55 +08:00
|
|
|
}
|