diff --git a/ExamplePlugin/include/YYToolkit/Shared.cpp b/ExamplePlugin/include/YYToolkit/Shared.cpp index 0439925..af7844f 100644 --- a/ExamplePlugin/include/YYToolkit/Shared.cpp +++ b/ExamplePlugin/include/YYToolkit/Shared.cpp @@ -3,11 +3,69 @@ using namespace Aurie; using namespace YYTK; +static YYTKInterface* GetYYTKInterface() +{ + static YYTKInterface* module_interface = nullptr; + + // Try getting the interface + // If we error, we return nullptr. + if (!module_interface) + { + ObGetInterface( + "YYTK_Main", + reinterpret_cast(module_interface) + ); + } + + return module_interface; +} + RValue::RValue() { this->m_Real = 0; this->m_Flags = 0; - this->m_Kind = VALUE_UNSET; + this->m_Kind = VALUE_UNDEFINED; +} + +YYTK::RValue::RValue( + IN std::initializer_list Values +) +{ + // Initialize to undefined + *this = RValue(); + + if (!GetYYTKInterface()) + return; + + if (!GetYYTKInterface()->GetRunnerInterface().YYCreateArray) + return; + + // Create a dummy array with the size of Values.size(), and initialize all members to 0 + std::vector dummy_array(Values.size(), 0.0); + + // Initialize this RValue as an array + GetYYTKInterface()->GetRunnerInterface().YYCreateArray( + this, + static_cast(dummy_array.size()), + dummy_array.data() + ); + + // Use direct object manipulation to set the actual values + for (size_t index = 0; index < Values.size(); index++) + { + RValue* member_value = nullptr; + AurieStatus last_status = GetYYTKInterface()->GetArrayEntry( + *this, + index, + member_value + ); + + // Make sure we got a valid pointer + if (!AurieSuccess(last_status)) + continue; + + *member_value = std::data(Values)[index]; + } } RValue::RValue( @@ -55,9 +113,35 @@ RValue::RValue( this->m_Kind = VALUE_OBJECT; } +YYTK::RValue::RValue( + IN const char* Value +) +{ + // Init to empty + *this = std::string_view(Value); +} + +RValue::RValue( + IN std::string_view Value +) +{ + // Initialize it to just empty stuff + *this = RValue(); + + // Let's not crash on invalid interfaces provided + if (!GetYYTKInterface()) + return; + + // We can ignore this, because if it fails, we're just initialized to UNSET + GetYYTKInterface()->StringToRValue( + Value, + *this + ); +} + RValue::RValue( IN std::string_view Value, - IN YYTKInterface* Interface + IN class YYTKInterface* Interface ) { // Initialize it to just empty stuff @@ -119,6 +203,19 @@ double RValue::AsReal() const return 0.0; } +std::string_view RValue::AsString() +{ + // Let's not crash on invalid interfaces provided + if (!GetYYTKInterface()) + return ""; + + if (!GetYYTKInterface()->GetRunnerInterface().YYGetString) + return ""; + + // Reason I don't use RValueToString is because that duplicates the string + return GetYYTKInterface()->GetRunnerInterface().YYGetString(this, 0); +} + std::string_view RValue::AsString( IN YYTKInterface* Interface ) @@ -132,3 +229,74 @@ std::string_view RValue::AsString( return Interface->GetRunnerInterface().YYGetString(this, 0); } + +RValue& RValue::operator[]( + IN size_t Index + ) +{ + if (!GetYYTKInterface()) + return *this; + + RValue* result = nullptr; + if (!AurieSuccess(GetYYTKInterface()->GetArrayEntry( + *this, + Index, + result + ))) + { + return *this; + } + + return *result; +} + +RValue& RValue::operator[]( + IN std::string_view Element + ) +{ + if (!GetYYTKInterface()) + return *this; + + RValue* instance_member = nullptr; + AurieStatus last_status = GetYYTKInterface()->GetInstanceMember( + *this, + Element.data(), + instance_member + ); + + // Prevents access violations, null references are undefined behavior in the C++ standard + if (!AurieSuccess(last_status) || !instance_member) + { + return *this; + } + + return *instance_member; +} + +RValue& RValue::at( + IN size_t Index +) +{ + return this->operator[](Index); +} + +RValue& RValue::at( + IN std::string_view Element +) +{ + return this->operator[](Element); +} + +RValue& CInstance::operator[]( + IN std::string_view Element + ) +{ + return RValue(this).at(Element); +} + +RValue& YYTK::CInstance::at( + IN std::string_view Element +) +{ + return RValue(this).at(Element); +} \ No newline at end of file diff --git a/ExamplePlugin/include/YYToolkit/Shared.hpp b/ExamplePlugin/include/YYToolkit/Shared.hpp index 4eb3ed8..68b350a 100644 --- a/ExamplePlugin/include/YYToolkit/Shared.hpp +++ b/ExamplePlugin/include/YYToolkit/Shared.hpp @@ -7,6 +7,10 @@ #ifndef YYTK_SHARED_H_ #define YYTK_SHARED_H_ +#define YYTK_MAJOR 3 +#define YYTK_MINOR 1 +#define YYTK_PATCH 0 + #include #include #include @@ -19,6 +23,10 @@ #define UTEXT(x) ((const unsigned char*)(x)) #endif // UTEXT +#ifndef NULL_INDEX +#define NULL_INDEX INT_MIN +#endif + namespace YYTK { enum CmColor : uint8_t @@ -91,6 +99,7 @@ namespace YYTK struct YYRunnerInterface; class YYTKInterface; struct RValue; + struct RVariableRoutine; struct YYGMLException { @@ -112,12 +121,12 @@ namespace YYTK using PFUNC_RAW = void(*)(); - using PFUNC_YYGMLScript = RValue * (*)( + using PFUNC_YYGMLScript = RValue & (*)( IN CInstance* Self, IN CInstance* Other, - OUT RValue* ReturnValue, + OUT RValue& Result, IN int ArgumentCount, - IN RValue** Arguments + IN RValue** Arguments // Array of RValue pointers ); #pragma pack(push, 4) @@ -139,6 +148,10 @@ namespace YYTK // Constructors RValue(); + RValue( + IN std::initializer_list Values + ); + RValue( IN bool Value ); @@ -159,18 +172,47 @@ namespace YYTK IN CInstance* Object ); + RValue( + IN const char* Value + ); + + RValue( + IN std::string_view Value + ); + RValue( IN std::string_view Value, IN YYTKInterface* Interface ); + // Custom getters bool AsBool() const; double AsReal() const; + std::string_view AsString(); + std::string_view AsString( IN YYTKInterface* Interface ); + + // Overloaded operators + RValue& operator[]( + IN size_t Index + ); + + RValue& operator[]( + IN std::string_view Element + ); + + // STL-like access + RValue& at( + IN size_t Index + ); + + RValue& at( + IN std::string_view Element + ); }; #pragma pack(pop) @@ -409,6 +451,19 @@ namespace YYTK bool (*isRunningFromIDE)(); }; + struct CInstance + { + // Overloaded operators + RValue& operator[]( + IN std::string_view Element + ); + + // STL-like access + RValue& at( + IN std::string_view Element + ); + }; + // ExecuteIt using FWCodeEvent = FunctionWrapper; // IDXGISwapChain::Present @@ -525,6 +580,36 @@ namespace YYTK IN int Index, OUT CScript*& Script ) = 0; + + virtual Aurie::AurieStatus GetBuiltinVariableIndex( + IN std::string_view Name, + OUT size_t& Index + ) = 0; + + virtual Aurie::AurieStatus GetBuiltinVariableInformation( + IN size_t Index, + OUT RVariableRoutine*& VariableInformation + ) = 0; + + virtual Aurie::AurieStatus GetBuiltin( + IN std::string_view Name, + IN CInstance* TargetInstance, + OPTIONAL IN int ArrayIndex, + OUT RValue& Value + ) = 0; + + virtual Aurie::AurieStatus SetBuiltin( + IN std::string_view Name, + IN CInstance* TargetInstance, + OPTIONAL IN int ArrayIndex, + IN RValue& Value + ) = 0; + + virtual Aurie::AurieStatus GetArrayEntry( + IN RValue& Value, + IN size_t ArrayIndex, + OUT RValue*& ArrayElement + ) = 0; }; }