diff --git a/materializer/DataTypes.hpp b/materializer/DataTypes.hpp index a9fd5f5..2a43207 100644 --- a/materializer/DataTypes.hpp +++ b/materializer/DataTypes.hpp @@ -12,9 +12,9 @@ namespace VSW::Materializer::DataTypes { namespace Script { struct Table_script { - CK_ID thisobj; - YYCC::yycc_u8string host_name; - int index; + CK_ID beobj; + YYCC::yycc_u8string beobj_name; + int behavior_index; CK_ID behavior; }; @@ -23,12 +23,15 @@ namespace VSW::Materializer::DataTypes { YYCC::yycc_u8string name; CK_BEHAVIOR_TYPE type; YYCC::yycc_u8string proto_name; - YYCC::yycc_u8string proto_guid; + int64_t proto_guid; CK_BEHAVIOR_FLAGS flags; int priority; CKDWORD version; - //pTarget, pIn, pOut, bIn, bOut - YYCC::yycc_u8string pin_count; + int pin_count_ptarget; + int pin_count_pin; + int pin_count_pout; + int pin_count_bin; + int pin_count_bout; CK_ID parent; }; @@ -44,8 +47,7 @@ namespace VSW::Materializer::DataTypes { struct Table_pTarget { CK_ID thisobj; YYCC::yycc_u8string name; - YYCC::yycc_u8string type; - YYCC::yycc_u8string type_guid; + int64_t type; CK_ID parent; CK_ID direct_source; CK_ID shared_source; @@ -55,8 +57,7 @@ namespace VSW::Materializer::DataTypes { CK_ID thisobj; int index; YYCC::yycc_u8string name; - YYCC::yycc_u8string type; - YYCC::yycc_u8string type_guid; + int64_t type; CK_ID parent; CK_ID direct_source; CK_ID shared_source; @@ -66,8 +67,7 @@ namespace VSW::Materializer::DataTypes { CK_ID thisobj; int index; YYCC::yycc_u8string name; - YYCC::yycc_u8string type; - YYCC::yycc_u8string type_guid; + int64_t type; CK_ID parent; }; @@ -89,17 +89,16 @@ namespace VSW::Materializer::DataTypes { struct Table_pLocal { CK_ID thisobj; YYCC::yycc_u8string name; - YYCC::yycc_u8string type; - YYCC::yycc_u8string type_guid; - BOOL is_setting; + int64_t type; + bool is_setting; CK_ID parent; }; struct Table_pAttr { CK_ID thisobj; YYCC::yycc_u8string name; - YYCC::yycc_u8string type; - YYCC::yycc_u8string type_guid; + int64_t type; + CK_ID owner; }; struct Table_pLink { @@ -110,25 +109,24 @@ namespace VSW::Materializer::DataTypes { //additional field CK_ID input_obj; VSW::DataTypes::ParameterLinkIOType input_type; - BOOL input_is_bb; + bool input_is_bb; int input_index; CK_ID output_obj; VSW::DataTypes::ParameterLinkIOType output_type; - BOOL output_is_bb; + bool output_is_bb; int output_index; }; struct Table_pOper { CK_ID thisobj; - YYCC::yycc_u8string op; - YYCC::yycc_u8string op_guid; + int64_t op; CK_ID parent; }; struct Table_eLink { CK_ID export_obj; CK_ID internal_obj; - BOOL is_in; + bool is_in; int index; CK_ID parent; }; diff --git a/materializer/ExportScript.cpp b/materializer/ExportScript.cpp index 135429c..11e4e7b 100644 --- a/materializer/ExportScript.cpp +++ b/materializer/ExportScript.cpp @@ -5,17 +5,25 @@ #include #include +/** + * @brief The namespace contain functions exporting scripts + * @details + * \c Generate mean that this function will analyse something to generate some objects which are not existed in original Virtools document. + * \c Proc meath that this function only just export something which is already existed in original Virtools document, or with slight modifications. +*/ namespace VSW::Materializer::ExportScript { 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()) {} + db(db_path), cache(), reporter(ctx), cp(code_page), attr_set(), ctx(ctx), 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 attr_set; + CKContext* ctx; CKParameterManager* param_mgr; }; @@ -56,17 +64,17 @@ namespace VSW::Materializer::ExportScript { // Record GUID int64_t exported_t; CP_GUID(exported_t, t); - REC_DATA("dumper-guid", exported_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); + 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()); + REC_DATA("dumper.assoc-ckobj", assoc_obj->GetID()); return; } @@ -79,7 +87,7 @@ namespace VSW::Materializer::ExportScript { || t == CKPGUID_FLOATSLIDER #endif ) { - REC_DATA("dumper-float", *static_cast(p->GetReadDataPtr(false))); + REC_DATA("dumper.float", *static_cast(p->GetReadDataPtr(false))); return; } // Integral value @@ -90,24 +98,24 @@ namespace VSW::Materializer::ExportScript { || 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(p->GetReadDataPtr(false))); + REC_DATA("dumper.int", *static_cast(p->GetReadDataPtr(false))); return; } // Vector value if (t == CKPGUID_VECTOR) { - REC_DATA("dumper-vector", *static_cast(p->GetReadDataPtr(false))); + REC_DATA("dumper.vector", *static_cast(p->GetReadDataPtr(false))); return; } if (t == CKPGUID_2DVECTOR) { - REC_DATA("dumper-2dvector", *static_cast(p->GetReadDataPtr(false))); + REC_DATA("dumper.2dvector", *static_cast(p->GetReadDataPtr(false))); return; } if (t == CKPGUID_MATRIX) { - REC_DATA("dumper-matrix", *static_cast(p->GetReadDataPtr(false))); + REC_DATA("dumper.matrix", *static_cast(p->GetReadDataPtr(false))); return; } if (t == CKPGUID_COLOR) { - REC_DATA("dumper-color", *static_cast(p->GetReadDataPtr(false))); + REC_DATA("dumper.color", *static_cast(p->GetReadDataPtr(false))); return; } // 2D Curve value @@ -116,7 +124,7 @@ namespace VSW::Materializer::ExportScript { CK2dCurve* c = static_cast(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()); + REC_RAW_DATA("dumper.2d-curve", builder.GetDataPtr(), builder.GetDataLength()); return; } // String value @@ -124,7 +132,7 @@ namespace VSW::Materializer::ExportScript { // Virtools internal data may not have null terminal, // so we use need copy it into container first. std::string native_string( - static_cast(p->GetReadDataPtr(false)), + static_cast(p->GetReadDataPtr(false)), static_cast(p->GetDataSize()) ); // Then do encoding convertion @@ -135,7 +143,7 @@ namespace VSW::Materializer::ExportScript { // reset to blank string utf8_string.clear(); } - REC_DATA("dumper-string", utf8_string); + REC_DATA("dumper.string", utf8_string); return; } // If it gets here, we have no idea what it really is. so simply dump it. @@ -150,16 +158,448 @@ namespace VSW::Materializer::ExportScript { // but we don't need do encoding convertion. const void* data_ptr = p->GetReadDataPtr(false); size_t data_len = static_cast(p->GetDataSize()); - REC_RAW_DATA("dumper-raw", data_ptr, data_len); + REC_RAW_DATA("dumper.raw", data_ptr, data_len); return; } } - #pragma endregion + + /** + * @brief Process Attribute Parameter + * @details + * pAttr do not have any explicit interface to get them, so they only can be find via pLink analyse. + * 2 pLink analyse funcstions will call this function to record each pAttr. + * Due to this mechanism, it might cause a duplication issues, + * so we need check possible duplication in there. + * @param[in] expctx Reference to export context. + * @param[in] ckobj Pointer to CKParameter (actually is attribute parameter) for processing. + */ + static void Proc_pAttr(ExportContext& expctx, CKParameter* ckobj) { + // Check duplication. + // We should not export duplicated pAttr + auto insert_result = expctx.attr_set.emplace(ckobj->GetID()); + if (!insert_result.second) return; + // Write self first + expctx.cache.pAttr.thisobj = ckobj->GetID(); + CP_CKSTR(expctx.cache.pAttr.name, ckobj->GetName()); + CP_GUID(expctx.cache.pAttr.type, ckobj->GetGUID()); + expctx.cache.pAttr.owner = ckobj->GetOwner()->GetID(); + expctx.db.Write(expctx.cache.pAttr); + } + /** + * @brief Generate pLink and eLink from pIn + * @param[in] expctx Reference to export context. + * @param[in] ckobj Pointer to CKParameterIn for analysing. + * @param[in] parent + * @param[in] grandparent + * @param[in] pin_index + * @param[in] executed_from_bb True if given CKParameterIn is belong to a CKBehavior, otherwise false (CKParamterOperation). + * @param[in] is_target True if this function is called from pTarget processor. + */ + static void Generate_pLink(ExportContext& expctx, CKParameterIn* analysed, CK_ID parent, CK_ID grandparent, int pin_index, bool executed_from_bb, bool is_target) { + CKParameter* direct_source = NULL; + CKObject* ds_Owner = NULL; + CKParameterIn* shared_source = NULL; + CKObject* ss_Owner = NULL; + + // first, we analyse eLink. + // check whether this is export parameter and write to database. + // if the behavior graph where this pIn's parent locate, also include this pIn, + // we can simply assume there is a eLink between them + if ((static_cast(expctx.ctx->GetObjectA(grandparent)))->GetInputParameterPosition(analysed) != -1) { + expctx.cache.eLink.export_obj = analysed->GetID(); + expctx.cache.eLink.internal_obj = parent; + expctx.cache.eLink.is_in = true; + expctx.cache.eLink.index = pin_index; + expctx.cache.eLink.parent = grandparent; + expctx.db.Write(expctx.cache.eLink); + + // if a eLink has been detected successfully, we returned immediately + // and do not analyse any pLink any more. + return; + } + + // start to analyse pLink + // first, analyse direct_src + if (direct_source = analysed->GetDirectSource()) { + expctx.cache.pLink.input = direct_source->GetID(); + // for almost pin, it is connected to a pLocal, so we use a if to test it first + if (direct_source->GetClassID() == CKCID_PARAMETERLOCAL || direct_source->GetClassID() == CKCID_PARAMETERVARIABLE) { + //pLocal + expctx.cache.pLink.input_obj = direct_source->GetID(); // the owner of pLocal is itself. + expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::PLOCAL; + expctx.cache.pLink.input_is_bb = false; + expctx.cache.pLink.input_index = Utilities::INVALID_INDEX; + } else { + // according to Virtools SDK document, there are 4 possible value gotten by us: + // bb pOut / pOper pOut / CKObject Attribute / CKDataArray + // however, the last 2 returned values have NOT been tested perfectly. + ds_Owner = direct_source->GetOwner(); + switch (ds_Owner->GetClassID()) { + case CKCID_BEHAVIOR: + expctx.cache.pLink.input_obj = ds_Owner->GetID(); + expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::POUT; + expctx.cache.pLink.input_is_bb = true; + expctx.cache.pLink.input_index = ((CKBehavior*)ds_Owner)->GetOutputParameterPosition((CKParameterOut*)direct_source); + break; + case CKCID_PARAMETEROPERATION: + expctx.cache.pLink.input_obj = ds_Owner->GetID(); + expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::POUT; + expctx.cache.pLink.input_is_bb = false; + expctx.cache.pLink.input_index = 0; // pOper only have 1 pOut + break; + case CKCID_DATAARRAY: + // CKDataArray, see as virtual bb pLocal shortcut + expctx.cache.pLink.input_obj = direct_source->GetID(); + expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::PATTR; + expctx.cache.pLink.input_is_bb = false; // omit + expctx.cache.pLink.input_index = Utilities::INVALID_INDEX; // omit + Proc_pAttr(expctx, direct_source); + break; + default: + // CKObject, because CKDataArray also a CKObject, so we test it first. + // see as virtual bb pLocal shortcut + expctx.cache.pLink.input_obj = direct_source->GetID(); + expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::PATTR; + expctx.cache.pLink.input_is_bb = false; // omit + expctx.cache.pLink.input_index = Utilities::INVALID_INDEX; // omit + Proc_pAttr(expctx, direct_source); + break; + } + } + } + // direct_src reflect the real source of current analysed pIn, + // however direct_src do not reflect export link + // so we need to analyse shared_src now. + // + // if this pIn has established some export relation, its shared_src must be filled. + // so we can detect it here. once its shared_src is not NULL + // we should consider export link here. + // + // we do not need to analyse any export link here, we just need to export some info + // to indicate this phenomeno. + if (shared_source = analysed->GetSharedSource()) { + //pIn from BB + expctx.cache.pLink.input = shared_source->GetID(); + ss_Owner = shared_source->GetOwner(); + expctx.cache.pLink.input_obj = ss_Owner->GetID(); + + switch (ss_Owner->GetClassID()) { + case CKCID_BEHAVIOR: // CKBehavior + { + if (((CKBehavior*)ss_Owner)->IsUsingTarget() && (((CKBehavior*)ss_Owner)->GetTargetParameter() == shared_source)) { + // pTarget + expctx.cache.pLink.input_type = DataStruct::pLinkInputOutputType_PTARGET; + expctx.cache.pLink.input_is_bb = true; + expctx.cache.pLink.input_index = Utilities::INVALID_INDEX; // omit + + } else { + // pIn + expctx.cache.pLink.input_type = DataStruct::pLinkInputOutputType_PIN; + expctx.cache.pLink.input_is_bb = true; + expctx.cache.pLink.input_index = ((CKBehavior*)ss_Owner)->GetInputParameterPosition(shared_source); + } + + break; + } + case CKCID_PARAMETEROPERATION: // CKParameterOperation + { + //pOper only have pIn. + expctx.cache.pLink.input_type = DataStruct::pLinkInputOutputType_PIN; + expctx.cache.pLink.input_is_bb = false; + expctx.cache.pLink.input_index = ((CKParameterOperation*)ss_Owner)->GetInParameter1() == shared_source ? 0 : 1; + break; + } + default: + // the unexpected value. according to SDK manual, + // there are only 2 possible types + return; + } + } + + // if the header of pLink has been analysed successfully, + // we can add tail info and push into database + if (shared_source != NULL || direct_source != NULL) { + expctx.cache.pLink.output = analysed->GetID(); + expctx.cache.pLink.output_obj = parent; + expctx.cache.pLink.output_type = is_target ? DataStruct::pLinkInputOutputType_PTARGET : DataStruct::pLinkInputOutputType_PIN; + expctx.cache.pLink.output_is_bb = executed_from_bb; + expctx.cache.pLink.output_index = pin_index; + expctx.cache.pLink.parent = grandparent; + + expctx.db.Write(expctx.cache.pLink); + } + } + + /** + * @brief Generate pLink and eLink from pOut + * @param expctx + * @param analysed + * @param parent + * @param grandparent + * @param pout_index + * @param executed_from_bb + */ + static void Generate_pLink(ExportContext& expctx, CKParameterOut* analysed, CK_ID parent, CK_ID grandparent, int pout_index, bool executed_from_bb) { + // check eLink first + // check whether expoer parameter and write to database + if (((CKBehavior*)ctx->GetObject(grandparent))->GetOutputParameterPosition(analysed) != -1) { + expctx.cache.eLink.export_obj = analysed->GetID(); + expctx.cache.eLink.internal_obj = parent; + expctx.cache.eLink.is_in = false; + expctx.cache.eLink.index = pout_index; + expctx.cache.eLink.parent = grandparent; + + expctx.db.Write(expctx.cache.eLink); + // if an eLink has been generated, skip following pLink generation + return; + } + + // try generate pLink + CKParameter* cache_Dest = NULL; + CKObject* cache_DestOwner = NULL; + for (int j = 0, jCount = analysed->GetDestinationCount(); j < jCount; j++) { + cache_Dest = analysed->GetDestination(j); + + expctx.cache.pLink.input = analysed->GetID(); + expctx.cache.pLink.input_obj = parent; + expctx.cache.pLink.input_type = DataStruct::pLinkInputOutputType_POUT; + expctx.cache.pLink.input_is_bb = executed_from_bb; + expctx.cache.pLink.input_index = pout_index; + + expctx.cache.pLink.output = cache_Dest->GetID(); + if (cache_Dest->GetClassID() == CKCID_PARAMETERLOCAL) { + //pLocal + expctx.cache.pLink.output_obj = cache_Dest->GetID(); + expctx.cache.pLink.output_type = DataStruct::pLinkInputOutputType_PLOCAL; + expctx.cache.pLink.output_is_bb = false; // omit + expctx.cache.pLink.output_index = -1; // omit + + } else { + //pOut, it must belong to a graph BB (pOut can not be shared, and prototype bb or pOper do not have link-able pOut). + cache_DestOwner = cache_Dest->GetOwner(); + switch (cache_DestOwner->GetClassID()) { + case CKCID_BEHAVIOR: + expctx.cache.pLink.output_obj = cache_DestOwner->GetID(); + expctx.cache.pLink.output_type = DataStruct::pLinkInputOutputType_POUT; + expctx.cache.pLink.output_is_bb = true; + expctx.cache.pLink.output_index = ((CKBehavior*)cache_DestOwner)->GetOutputParameterPosition((CKParameterOut*)cache_Dest); + break; + case CKCID_DATAARRAY: + // CKDataArray, see as virtual bb pLocal shortcut + expctx.cache.pLink.output_obj = cache_Dest->GetID(); + expctx.cache.pLink.output_type = DataStruct::pLinkInputOutputType_PATTR; + expctx.cache.pLink.input_is_bb = false; // omit + expctx.cache.pLink.input_index = -1; // omit + Proc_pAttr(ctx, mDb, cache_Dest); + break; + default: + // CKObject, because CKDataArray also a CKObject, so we test it first. + // see as virtual bb pLocal shortcut + expctx.cache.pLink.output_obj = cache_Dest->GetID(); + expctx.cache.pLink.output_type = DataStruct::pLinkInputOutputType_PATTR; + expctx.cache.pLink.input_is_bb = false; // omit + expctx.cache.pLink.input_index = -1; // omit + Proc_pAttr(ctx, mDb, cache_Dest); + break; + } + } + + expctx.cache.pLink.parent = grandparent; + + expctx.db.Write(expctx.cache.pLink); + } + } + + static void Proc_pTarget(ExportContext& expctx, CKParameterIn* ckobj, CK_ID parent, CK_ID grandparent) { + expctx.cache.pTarget.thisobj = ckobj->GetID(); + CP_CKSTR(expctx.cache.pTarget.name, ckobj->GetName()); + CP_GUID(expctx.cache.pTarget.type, ckobj->GetGUID()); + expctx.cache.pTarget.parent = parent; + expctx.cache.pTarget.direct_source = ckobj->GetDirectSource() ? ckobj->GetDirectSource()->GetID() : Utilities::INVALID_CK_ID; + expctx.cache.pTarget.shared_source = ckobj->GetSharedSource() ? ckobj->GetSharedSource()->GetID() : Utilities::INVALID_CK_ID; + expctx.db.Write(expctx.cache.pTarget); + + // try to generate pLink and eLink + Generate_pLink(expctx, ckobj, parent, grandparent, Utilities::INVALID_INDEX, true, true); + } + + static void Proc_pIn(ExportContext& expctx, CKParameterIn* ckobj, CK_ID parent, CK_ID grandparent, int index, bool executed_from_bb) { + expctx.cache.pIn.thisobj = ckobj->GetID(); + expctx.cache.pIn.index = index; + CP_CKSTR(expctx.cache.pIn.name, ckobj->GetName()); + CP_GUID(expctx.cache.pIn.type, ckobj->GetGUID()); + expctx.cache.pIn.parent = parent; + expctx.cache.pIn.direct_source = ckobj->GetDirectSource() ? ckobj->GetDirectSource()->GetID() : Utilities::INVALID_CK_ID; + expctx.cache.pIn.shared_source = ckobj->GetSharedSource() ? ckobj->GetSharedSource()->GetID() : Utilities::INVALID_CK_ID; + expctx.db.Write(expctx.cache.pIn); + + // try to generate pLink and eLink + Generate_pLink(expctx, ckobj, parent, grandparent, index, executed_from_bb, false); + } + + static void Proc_pOut(ExportContext& expctx, CKParameterOut* ckobj, CK_ID parent, CK_ID grandparent, int index, bool executed_from_bb) { + expctx.cache.pOut.thisobj = ckobj->GetID(); + expctx.cache.pOut.index = index; + CP_CKSTR(expctx.cache.pOut.name, ckobj->GetName()); + CP_GUID(expctx.cache.pOut.type, ckobj->GetGUID()); + expctx.cache.pOut.parent = parent; + expctx.db.Write(expctx.cache.pOut); + + // try generate pLink and eLink + Generate_pLink(expctx, ckobj, parent, grandparent, index, executed_from_bb); + } + + static void Proc_bIn(ExportContext& expctx, CKBehaviorIO* ckobj, CK_ID parent, int index) { + expctx.cache.bIn.thisobj = ckobj->GetID(); + expctx.cache.bIn.index = index; + CP_CKSTR(expctx.cache.bIn.name, ckobj->GetName()); + expctx.cache.bIn.parent = parent; + expctx.db.Write(expctx.cache.bIn); + } + + static void Proc_bOut(ExportContext& expctx, CKBehaviorIO* ckobj, CK_ID parent, int index) { + expctx.cache.bOut.thisobj = ckobj->GetID(); + expctx.cache.bOut.index = index; + CP_CKSTR(expctx.cache.bOut.name, ckobj->GetName()); + expctx.cache.bOut.parent = parent; + expctx.db.Write(expctx.cache.bOut); + } + + static void Proc_bLink(ExportContext& expctx, CKBehaviorLink* ckobj, CK_ID parent) { + // setup start terminal + CKBehaviorIO* io = ckobj->GetInBehaviorIO(); + CKBehavior* beh = io->GetOwner(); + expctx.cache.bLink.input = io->GetID(); + expctx.cache.bLink.input_obj = beh->GetID(); + expctx.cache.bLink.input_type = (io->GetType() == CK_BEHAVIORIO_IN ? VSW::DataTypes::BehaviorLinkIOType::INPUT : VSW::DataTypes::BehaviorLinkIOType::OUTPUT); + expctx.cache.bLink.input_index = (io->GetType() == CK_BEHAVIORIO_IN ? io->GetOwner()->GetInputPosition(io) : io->GetOwner()->GetOutputPosition(io)); + // setup end terminal + io = ckobj->GetOutBehaviorIO(); + beh = io->GetOwner(); + expctx.cache.bLink.output = io->GetID(); + expctx.cache.bLink.output_obj = beh->GetID(); + expctx.cache.bLink.output_type = (io->GetType() == CK_BEHAVIORIO_IN ? VSW::DataTypes::BehaviorLinkIOType::INPUT : VSW::DataTypes::BehaviorLinkIOType::OUTPUT); + expctx.cache.bLink.output_index = (io->GetType() == CK_BEHAVIORIO_IN ? io->GetOwner()->GetInputPosition(io) : io->GetOwner()->GetOutputPosition(io)); + // other properties + expctx.cache.bLink.delay = ckobj->GetActivationDelay(); + expctx.cache.bLink.parent = parent; + // write to database + expctx.db.Write(expctx.cache.bLink); + } + + static void Proc_pLocal(ExportContext& expctx, CKParameterLocal* ckobj, CK_ID parent, bool is_setting) { + expctx.cache.pLocal.thisobj = ckobj->GetID(); + CP_CKSTR(expctx.cache.pLocal.name, ckobj->GetName()); + CP_GUID(expctx.cache.pLocal.type, ckobj->GetGUID()); + expctx.cache.pLocal.is_setting = is_setting; + expctx.cache.pLocal.parent = parent; + expctx.db.Write(expctx.cache.pLocal); + + // Export pLocal internal data + DigParameterData(expctx, ckobj, ckobj->GetID()); + } + + static void Proc_pOper(ExportContext& expctx, CKParameterOperation* ckobj, CK_ID parent) { + expctx.cache.pOper.thisobj = ckobj->GetID(); + CP_GUID(expctx.cache.pOper.op, ckobj->GetOperationGuid()); + expctx.cache.pOper.parent = parent; + expctx.db.Write(expctx.cache.pOper); + + // Process associated 2 pIn and 1 pOut + Proc_pIn(expctx, ckobj->GetInParameter1(), ckobj->GetID(), parent, 0, false); + Proc_pIn(expctx, ckobj->GetInParameter2(), ckobj->GetID(), parent, 1, false); + Proc_pOut(expctx, ckobj->GetOutParameter(), ckobj->GetID(), parent, 0, false); + } + + /** + * @brief Process CKBehavior + * @param[in] expctx Reference to export context. + * @param[in] behavior Pointer to CKBehavior for processing. + * @param[in] parent The parent of this CKBehavior. Set to \c INVALID_CK_ID if it was called from script iterator. + */ + static void Proc_Behavior(ExportContext& expctx, CKBehavior* behavior, CK_ID parent) { + // Write basic behavior infomation + expctx.cache.behavior.thisobj = behavior->GetID(); + CP_CKSTR(expctx.cache.behavior.name, behavior->GetName()); + expctx.cache.behavior.type = behavior->GetType(); + CP_CKSTR(expctx.cache.behavior.proto_name, behavior->GetPrototypeName()); + CP_GUID(expctx.cache.behavior.proto_guid, behavior->GetPrototypeGuid()); + expctx.cache.behavior.flags = behavior->GetFlags(); + expctx.cache.behavior.priority = behavior->GetPriority(); + expctx.cache.behavior.version = behavior->GetVersion(); + expctx.cache.behavior.pin_count_ptarget = (behavior->IsUsingTarget() ? 1 : 0); + expctx.cache.behavior.pin_count_pin = behavior->GetInputParameterCount(); + expctx.cache.behavior.pin_count_pout = behavior->GetOutputParameterCount(); + expctx.cache.behavior.pin_count_bin = behavior->GetInputCount(); + expctx.cache.behavior.pin_count_bout = behavior->GetOutputCount(); + expctx.cache.behavior.parent = parent; + expctx.db.Write(expctx.cache.behavior); + + // pTarget + if (behavior->IsUsingTarget()) + Proc_pTarget(expctx, behavior->GetTargetParameter(), behavior->GetID(), parent); + + // pIn + for (int i = 0, count = behavior->GetInputParameterCount(); i < count; ++i) + Proc_pIn(expctx, behavior->GetInputParameter(i), behavior->GetID(), parent, i, true); + // pOut + for (int i = 0, count = behavior->GetOutputParameterCount(); i < count; ++i) + Proc_pOut(expctx, behavior->GetOutputParameter(i), behavior->GetID(), parent, i, true); + // bIn + for (int i = 0, count = behavior->GetInputCount(); i < count; ++i) + Proc_bIn(expctx, behavior->GetInput(i), behavior->GetID(), i); + // bOut + for (int i = 0, count = behavior->GetOutputCount(); i < count; ++i) + Proc_bOut(expctx, behavior->GetOutput(i), behavior->GetID(), i); + // bLink + for (int i = 0, count = behavior->GetSubBehaviorLinkCount(); i < count; ++i) + Proc_bLink(expctx, behavior->GetSubBehaviorLink(i), behavior->GetID()); + // pLocal + for (int i = 0, count = behavior->GetLocalParameterCount(); i < count; ++i) + Proc_pLocal(expctx, behavior->GetLocalParameter(i), behavior->GetID(), behavior->IsLocalParameterSetting(i)); + // pOper + for (int i = 0, count = behavior->GetParameterOperationCount(); i < count; ++i) + Proc_pOper(expctx, behavior->GetParameterOperation(i), behavior->GetID()); + + // Iterate sub behavior + for (int i = 0, count = behavior->GetSubBehaviorCount(); i < count; ++i) + Proc_Behavior(expctx, behavior->GetSubBehavior(i), behavior->GetID()); + } + + static void IterateScript(ExportContext& expctx) { + // Get all CKBeObjects to try to get all scripts, + // because only CKBeObject can own script. + XObjectPointerArray obj_array = expctx.ctx->GetObjectListByType(CKCID_BEOBJECT, TRUE); + int obj_count = obj_array.Size(); + for (int i = 0; i < obj_count; ++i) { + // Get CKBeObject + CKBeObject* beobj = static_cast(obj_array.GetObjectA(i)); + + // Get script count. If no script, skip this object. + int script_count = beobj->GetScriptCount(); + if (script_count == 0) continue; + + // Iterate binding scripts + for (int j = 0; j < script_count; ++j) { + // Get associated behavior + CKBehavior* behavior = beobj->GetScript(j); + // Write to database + expctx.cache.script.beobj = beobj->GetID(); + CP_CKSTR(expctx.cache.script.beobj_name, beobj->GetName()); + expctx.cache.script.behavior_index = j; + expctx.cache.script.behavior = behavior->GetID(); + expctx.db.Write(expctx.cache.script); + + // Process this script + Proc_Behavior(expctx, behavior, Utilities::INVALID_CK_ID); + } + } + } void Export(CKContext* ctx, const YYCC::yycc_u8string_view& db_path, UINT code_page) { // create export context @@ -170,6 +610,7 @@ namespace VSW::Materializer::ExportScript { } // export script + IterateScript(expctx); } } diff --git a/materializer/Utilities.hpp b/materializer/Utilities.hpp index 81c715b..0bc0906 100644 --- a/materializer/Utilities.hpp +++ b/materializer/Utilities.hpp @@ -6,6 +6,7 @@ namespace VSW::Materializer::Utilities { /// @brief The value representing a invalid CK_ID. constexpr CK_ID INVALID_CK_ID = static_cast(-1); + constexpr int INVALID_INDEX = static_cast(-1); constexpr char NULLPTR_CKSTRING[] = ""; class EnhancedReporter : public VSW::Reporter { diff --git a/shared/GenericHelper.hpp b/shared/GenericHelper.hpp index fd948a4..ede1846 100644 --- a/shared/GenericHelper.hpp +++ b/shared/GenericHelper.hpp @@ -24,19 +24,18 @@ namespace VSW { namespace DataTypes { enum class BehaviorLinkIOType : int { - Input, - Output + INPUT, OUTPUT }; enum class ParameterLinkIOType : int { - ParameterIn, - ParameterOut, + PIN, + POUT, /// @brief When using this, ignore [index] and [input_is_bb], set [input_index] to -1 - ParameterLocal, + PLOCAL, /// @brief When using this, ignore [index] and [input_is_bb], set [input_index] to -1 - ParameterTarget, + PTARGET, /// @brief When using this, ignore [index], and [input_is_bb] will become [input_is_dataarray] - pParameterAttribute + PATTR }; }