908 lines
20 KiB
C++
908 lines
20 KiB
C++
#pragma once
|
|
|
|
#include "Scaleform/F/Flags.h"
|
|
#include "Scaleform/N/NewOverrideBase.h"
|
|
#include "Scaleform/R/Render_EdgeAAMode.h"
|
|
#include "Scaleform/R/Render_Matrix.h"
|
|
|
|
namespace Scaleform::GFx
|
|
{
|
|
class Movie;
|
|
class MovieImpl;
|
|
|
|
class Value
|
|
{
|
|
public:
|
|
enum class ValueType : std::int32_t
|
|
{
|
|
kUndefined,
|
|
kNull,
|
|
kBoolean,
|
|
kInt,
|
|
kUInt,
|
|
kNumber,
|
|
kString,
|
|
|
|
kStringW,
|
|
|
|
kObject,
|
|
kArray,
|
|
kDisplayObject,
|
|
kClosure,
|
|
|
|
kOrphanedBit = 1 << 5,
|
|
kManagedBit = 1 << 6,
|
|
kConvertBit = 1 << 7,
|
|
|
|
kTypeMask = kConvertBit | 0x0F,
|
|
|
|
kConvertBoolean = kConvertBit | kBoolean,
|
|
kConvertInt = kConvertBit | kInt,
|
|
kConvertUInt = kConvertBit | kUInt,
|
|
kConvertNumber = kConvertBit | kNumber,
|
|
kConvertString = kConvertBit | kString,
|
|
kConvertStringW = kConvertBit | kStringW
|
|
};
|
|
|
|
union ValueUnion
|
|
{
|
|
ValueUnion() noexcept :
|
|
data(nullptr)
|
|
{}
|
|
|
|
ValueUnion(const ValueUnion& a_rhs) noexcept :
|
|
data(a_rhs.data)
|
|
{}
|
|
|
|
ValueUnion(ValueUnion&& a_rhs) noexcept :
|
|
data(a_rhs.data)
|
|
{
|
|
a_rhs.data = nullptr;
|
|
}
|
|
|
|
explicit ValueUnion(std::int32_t a_rhs) noexcept :
|
|
int32(a_rhs)
|
|
{}
|
|
|
|
explicit ValueUnion(std::uint32_t a_rhs) noexcept :
|
|
uint32(a_rhs)
|
|
{}
|
|
|
|
explicit ValueUnion(double a_rhs) noexcept :
|
|
number(a_rhs)
|
|
{}
|
|
|
|
explicit ValueUnion(bool a_rhs) noexcept :
|
|
boolean(a_rhs)
|
|
{}
|
|
|
|
explicit ValueUnion(const char* a_rhs) noexcept :
|
|
string(a_rhs)
|
|
{}
|
|
|
|
explicit ValueUnion(const wchar_t* a_rhs) noexcept :
|
|
wstring(a_rhs)
|
|
{}
|
|
|
|
ValueUnion& operator=(const ValueUnion& a_rhs) noexcept
|
|
{
|
|
if (this != std::addressof(a_rhs)) {
|
|
data = a_rhs.data;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
ValueUnion& operator=(ValueUnion&& a_rhs) noexcept
|
|
{
|
|
if (this != std::addressof(a_rhs)) {
|
|
data = a_rhs.data;
|
|
a_rhs.data = nullptr;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
ValueUnion& operator=(std::int32_t a_rhs) noexcept
|
|
{
|
|
int32 = a_rhs;
|
|
return *this;
|
|
}
|
|
|
|
ValueUnion& operator=(std::uint32_t a_rhs) noexcept
|
|
{
|
|
uint32 = a_rhs;
|
|
return *this;
|
|
}
|
|
|
|
ValueUnion& operator=(double a_rhs) noexcept
|
|
{
|
|
number = a_rhs;
|
|
return *this;
|
|
}
|
|
|
|
ValueUnion& operator=(bool a_rhs) noexcept
|
|
{
|
|
boolean = a_rhs;
|
|
return *this;
|
|
}
|
|
|
|
ValueUnion& operator=(const char* a_rhs) noexcept
|
|
{
|
|
string = a_rhs;
|
|
return *this;
|
|
}
|
|
|
|
ValueUnion& operator=(const wchar_t* a_rhs) noexcept
|
|
{
|
|
wstring = a_rhs;
|
|
return *this;
|
|
}
|
|
|
|
std::int32_t int32;
|
|
std::uint32_t uint32;
|
|
double number;
|
|
bool boolean;
|
|
const char* string;
|
|
const char** mstring;
|
|
const wchar_t* wstring;
|
|
void* data;
|
|
};
|
|
static_assert(sizeof(ValueUnion) == 0x8);
|
|
|
|
class DisplayInfo
|
|
{
|
|
public:
|
|
enum class SetFlags : std::uint16_t
|
|
{
|
|
kX = 0x01,
|
|
kY = 0x02,
|
|
kRotation = 0x04,
|
|
kXScale = 0x08,
|
|
kYScale = 0x10,
|
|
kAlpha = 0x20,
|
|
kVisible = 0x40,
|
|
kZ = 0x80,
|
|
kXRotation = 0x100,
|
|
kYRotation = 0x200,
|
|
kZScale = 0x400,
|
|
kFOV = 0x800,
|
|
kProjMatrix3D = 0x1000,
|
|
kViewMatrix3D = 0x2000,
|
|
kEdgeAAMode = 0x4000,
|
|
};
|
|
|
|
DisplayInfo() = default;
|
|
|
|
double GetX() const
|
|
{
|
|
assert(varsSet.any(SetFlags::kX));
|
|
return x;
|
|
}
|
|
|
|
double GetY() const
|
|
{
|
|
assert(varsSet.any(SetFlags::kY));
|
|
return y;
|
|
}
|
|
|
|
double GetZ() const
|
|
{
|
|
assert(varsSet.any(SetFlags::kZ));
|
|
return z;
|
|
}
|
|
|
|
double GetXScale() const
|
|
{
|
|
assert(varsSet.any(SetFlags::kXScale));
|
|
return xScale;
|
|
}
|
|
|
|
double GetYScale() const
|
|
{
|
|
assert(varsSet.any(SetFlags::kYScale));
|
|
return yScale;
|
|
}
|
|
|
|
double GetZScale() const
|
|
{
|
|
assert(varsSet.any(SetFlags::kZScale));
|
|
return zScale;
|
|
}
|
|
|
|
double GetRotation() const
|
|
{
|
|
assert(varsSet.any(SetFlags::kRotation));
|
|
return rotation;
|
|
}
|
|
|
|
double GetXRotation() const
|
|
{
|
|
assert(varsSet.any(SetFlags::kXRotation));
|
|
return xRotation;
|
|
}
|
|
|
|
double GetYRotation() const
|
|
{
|
|
assert(varsSet.any(SetFlags::kYRotation));
|
|
return yRotation;
|
|
}
|
|
|
|
double GetAlpha() const
|
|
{
|
|
assert(varsSet.any(SetFlags::kAlpha));
|
|
return alpha;
|
|
}
|
|
|
|
bool GetVisible() const
|
|
{
|
|
assert(varsSet.any(SetFlags::kVisible));
|
|
return visible;
|
|
}
|
|
|
|
double GetFOV() const
|
|
{
|
|
assert(varsSet.any(SetFlags::kFOV));
|
|
return fov;
|
|
}
|
|
|
|
const Render::Matrix3x4<float>* GetViewMatrix3D() const
|
|
{
|
|
return varsSet.any(SetFlags::kViewMatrix3D) ? &viewMatrix3D : nullptr;
|
|
}
|
|
|
|
const Render::Matrix4x4<float>* GetProjectionMatrix3D() const
|
|
{
|
|
return varsSet.any(SetFlags::kProjMatrix3D) ? &projectionMatrix3D : nullptr;
|
|
}
|
|
|
|
Render::EdgeAAMode GetEdgeAAMode() const
|
|
{
|
|
assert(varsSet.any(SetFlags::kEdgeAAMode));
|
|
return edgeAAMode;
|
|
}
|
|
|
|
void SetX(double a_x)
|
|
{
|
|
varsSet.set(SetFlags::kX);
|
|
x = a_x;
|
|
}
|
|
|
|
void SetY(double a_y)
|
|
{
|
|
varsSet.set(SetFlags::kY);
|
|
y = a_y;
|
|
}
|
|
|
|
void SetZ(double a_z)
|
|
{
|
|
varsSet.set(SetFlags::kZ);
|
|
z = a_z;
|
|
}
|
|
|
|
void SetXScale(double a_xScale)
|
|
{
|
|
varsSet.set(SetFlags::kXScale);
|
|
xScale = a_xScale;
|
|
}
|
|
|
|
void SetYScale(double a_yScale)
|
|
{
|
|
varsSet.set(SetFlags::kYScale);
|
|
yScale = a_yScale;
|
|
}
|
|
|
|
void SetZScale(double a_zScale)
|
|
{
|
|
varsSet.set(SetFlags::kZScale);
|
|
zScale = a_zScale;
|
|
}
|
|
|
|
void SetRotation(double a_rotation)
|
|
{
|
|
varsSet.set(SetFlags::kRotation);
|
|
rotation = a_rotation;
|
|
}
|
|
|
|
void SetXRotation(double a_xRotation)
|
|
{
|
|
varsSet.set(SetFlags::kXRotation);
|
|
xRotation = a_xRotation;
|
|
}
|
|
|
|
void SetYRotation(double a_yRotation)
|
|
{
|
|
varsSet.set(SetFlags::kYRotation);
|
|
yRotation = a_yRotation;
|
|
}
|
|
|
|
void SetAlpha(double a_alpha)
|
|
{
|
|
varsSet.set(SetFlags::kAlpha);
|
|
alpha = a_alpha;
|
|
}
|
|
|
|
void SetVisible(bool a_visible)
|
|
{
|
|
varsSet.set(SetFlags::kVisible);
|
|
visible = a_visible;
|
|
}
|
|
|
|
void SetFOV(double a_fov)
|
|
{
|
|
varsSet.set(SetFlags::kFOV);
|
|
fov = a_fov;
|
|
}
|
|
|
|
void SetViewMatrix3D(const Render::Matrix3x4<float>* a_matrix)
|
|
{
|
|
if (a_matrix) {
|
|
varsSet.set(SetFlags::kViewMatrix3D);
|
|
viewMatrix3D = *a_matrix;
|
|
} else {
|
|
varsSet.reset(SetFlags::kViewMatrix3D);
|
|
}
|
|
}
|
|
|
|
void SetProjectionMatrix3D(const Render::Matrix4x4<float>* a_matrix)
|
|
{
|
|
if (a_matrix) {
|
|
varsSet.set(SetFlags::kProjMatrix3D);
|
|
projectionMatrix3D = *a_matrix;
|
|
} else {
|
|
varsSet.reset(SetFlags::kProjMatrix3D);
|
|
}
|
|
}
|
|
|
|
void SetEdgeAAMode(Render::EdgeAAMode a_mode)
|
|
{
|
|
varsSet.set(SetFlags::kEdgeAAMode);
|
|
edgeAAMode = a_mode;
|
|
}
|
|
|
|
private:
|
|
// members
|
|
double x;
|
|
double y;
|
|
double rotation;
|
|
double xScale;
|
|
double yScale;
|
|
double alpha;
|
|
double z;
|
|
double xRotation;
|
|
double yRotation;
|
|
double zScale;
|
|
double fov;
|
|
alignas(16) Render::Matrix3x4<float> viewMatrix3D;
|
|
Render::Matrix4x4<float> projectionMatrix3D;
|
|
Render::EdgeAAMode edgeAAMode;
|
|
Flags<SetFlags> varsSet{};
|
|
bool visible;
|
|
};
|
|
static_assert(sizeof(DisplayInfo) == 0xE0);
|
|
|
|
class __declspec(novtable) ObjectInterface :
|
|
public NewOverrideBase<327>
|
|
{
|
|
public:
|
|
class __declspec(novtable) ObjVisitor
|
|
{
|
|
public:
|
|
virtual ~ObjVisitor() = default; // 00
|
|
|
|
// add
|
|
virtual bool IncludeAS3PublicMembers() const { return false; } // 01
|
|
virtual void Visit(const char* a_name, const Value& a_val) = 0; // 02
|
|
};
|
|
static_assert(sizeof(ObjVisitor) == 0x8);
|
|
|
|
class __declspec(novtable) ArrVisitor
|
|
{
|
|
public:
|
|
virtual ~ArrVisitor() = default;
|
|
|
|
// add
|
|
virtual void Visit(std::uint32_t a_idx, const Value& a_val) = 0; // 00
|
|
};
|
|
static_assert(sizeof(ArrVisitor) == 0x8);
|
|
|
|
virtual ~ObjectInterface() = default; // 00
|
|
|
|
void ObjectAddRef(Value* a_val, void* a_obj)
|
|
{
|
|
using func_t = decltype(&ObjectInterface::ObjectAddRef);
|
|
static REL::Relocation<func_t> func{ ID::GFx::Value::ObjectAddRef };
|
|
return func(this, a_val, a_obj);
|
|
}
|
|
|
|
void ObjectRelease(Value* a_val, void* a_obj)
|
|
{
|
|
using func_t = decltype(&ObjectInterface::ObjectRelease);
|
|
static REL::Relocation<func_t> func{ ID::GFx::Value::ObjectRelease };
|
|
return func(this, a_val, a_obj);
|
|
}
|
|
|
|
bool HasMember(void* a_data, const char* a_name, bool a_isdobj) const
|
|
{
|
|
using func_t = decltype(&ObjectInterface::HasMember);
|
|
static REL::Relocation<func_t> func{ ID::GFx::Value::HasMember };
|
|
return func(this, a_data, a_name, a_isdobj);
|
|
}
|
|
|
|
std::uint32_t GetArraySize(void* a_data) const
|
|
{
|
|
using func_t = decltype(&ObjectInterface::GetArraySize);
|
|
static REL::Relocation<func_t> func{ ID::GFx::Value::GetArraySize };
|
|
return func(this, a_data);
|
|
}
|
|
|
|
bool GetMember(void* a_data, const char* a_name, Value* a_val, bool a_isdobj) const
|
|
{
|
|
using func_t = decltype(&ObjectInterface::GetMember);
|
|
static REL::Relocation<func_t> func{ ID::GFx::Value::GetMember };
|
|
return func(this, a_data, a_name, a_val, a_isdobj);
|
|
}
|
|
|
|
bool GetElement(void* a_data, std::uint32_t a_idx, Value* a_val) const
|
|
{
|
|
using func_t = decltype(&ObjectInterface::GetElement);
|
|
static REL::Relocation<func_t> func{ ID::GFx::Value::GetElement };
|
|
return func(this, a_data, a_idx, a_val);
|
|
}
|
|
|
|
bool SetElement(void* a_data, std::uint32_t a_idx, const Value& a_val)
|
|
{
|
|
using func_t = decltype(&ObjectInterface::SetElement);
|
|
static REL::Relocation<func_t> func{ ID::GFx::Value::SetElement };
|
|
return func(this, a_data, a_idx, a_val);
|
|
}
|
|
|
|
bool SetMember(void* a_data, const char* a_name, const Value& a_value, bool a_isdobj)
|
|
{
|
|
using func_t = decltype(&ObjectInterface::SetMember);
|
|
static REL::Relocation<func_t> func{ ID::GFx::Value::SetMember };
|
|
return func(this, a_data, a_name, a_value, a_isdobj);
|
|
}
|
|
|
|
bool Invoke(void* a_data, Value* a_result, const char* a_name, const Value* a_args, std::size_t a_numArgs, bool a_isdobj)
|
|
{
|
|
using func_t = decltype(&ObjectInterface::Invoke);
|
|
static REL::Relocation<func_t> func{ ID::GFx::Value::Invoke };
|
|
return func(this, a_data, a_result, a_name, a_args, a_numArgs, a_isdobj);
|
|
}
|
|
|
|
bool PushBack(void* a_data, const Value& a_value)
|
|
{
|
|
using func_t = decltype(&ObjectInterface::PushBack);
|
|
static REL::Relocation<func_t> func{ ID::GFx::Value::PushBack };
|
|
return func(this, a_data, a_value);
|
|
}
|
|
|
|
bool RemoveElements(void* a_data, std::uint32_t a_idx, std::int32_t a_count)
|
|
{
|
|
using func_t = decltype(&ObjectInterface::RemoveElements);
|
|
static REL::Relocation<func_t> func{ ID::GFx::Value::RemoveElements };
|
|
return func(this, a_data, a_idx, a_count);
|
|
}
|
|
|
|
void VisitMembers(void* a_data, ObjVisitor* a_visitor, bool a_isDObj) const
|
|
{
|
|
using func_t = decltype(&ObjectInterface::VisitMembers);
|
|
static REL::Relocation<func_t> func{ ID::GFx::Value::VisitMembers };
|
|
return func(this, a_data, a_visitor, a_isDObj);
|
|
}
|
|
|
|
bool GetDisplayInfo(void* a_data, DisplayInfo* a_info) const
|
|
{
|
|
using func_t = decltype(&ObjectInterface::GetDisplayInfo);
|
|
static REL::Relocation<func_t> func{ ID::GFx::Value::GetDisplayInfo };
|
|
return func(this, a_data, a_info);
|
|
}
|
|
|
|
// members
|
|
MovieImpl* movieRoot; // 08
|
|
};
|
|
static_assert(sizeof(ObjectInterface) == 0x10);
|
|
|
|
using ObjectVisitor = ObjectInterface::ObjVisitor;
|
|
using ArrayVisitor = ObjectInterface::ArrVisitor;
|
|
using ObjectVisitFn = std::function<void(const char*, const Value&)>;
|
|
|
|
Value() noexcept = default;
|
|
|
|
Value(const Value& a_rhs) :
|
|
_type(a_rhs._type),
|
|
_value(a_rhs._value),
|
|
_dataAux(a_rhs._dataAux)
|
|
{
|
|
if (a_rhs.IsManagedValue()) {
|
|
AcquireManagedValue(a_rhs);
|
|
}
|
|
}
|
|
|
|
Value(Value&& a_rhs) noexcept :
|
|
_objectInterface(a_rhs._objectInterface),
|
|
_type(a_rhs._type),
|
|
_value(std::move(a_rhs._value)),
|
|
_dataAux(a_rhs._dataAux)
|
|
{
|
|
a_rhs._objectInterface = nullptr;
|
|
a_rhs._type = ValueType::kUndefined;
|
|
a_rhs._dataAux = 0;
|
|
}
|
|
|
|
Value(std::nullptr_t) noexcept :
|
|
_type(ValueType::kNull)
|
|
{}
|
|
|
|
Value(std::int32_t a_rhs) noexcept :
|
|
_type(ValueType::kInt),
|
|
_value(a_rhs)
|
|
{}
|
|
|
|
Value(std::uint32_t a_rhs) noexcept :
|
|
_type(ValueType::kUInt),
|
|
_value(a_rhs)
|
|
{}
|
|
|
|
Value(double a_rhs) noexcept :
|
|
_type(ValueType::kNumber),
|
|
_value(a_rhs)
|
|
{}
|
|
|
|
Value(bool a_rhs) noexcept :
|
|
_type(ValueType::kBoolean),
|
|
_value(a_rhs)
|
|
{}
|
|
|
|
Value(const char* a_rhs) noexcept :
|
|
_type(ValueType::kString),
|
|
_value(a_rhs)
|
|
{}
|
|
|
|
Value(std::string_view a_rhs) noexcept :
|
|
_type(ValueType::kString),
|
|
_value(a_rhs.data())
|
|
{}
|
|
|
|
Value(const wchar_t* a_rhs) noexcept :
|
|
_type(ValueType::kStringW),
|
|
_value(a_rhs)
|
|
{}
|
|
|
|
Value(std::wstring_view a_rhs) noexcept :
|
|
_type(ValueType::kStringW),
|
|
_value(a_rhs.data())
|
|
{}
|
|
|
|
~Value()
|
|
{
|
|
if (IsManagedValue()) {
|
|
ReleaseManagedValue();
|
|
}
|
|
|
|
_type = ValueType::kUndefined;
|
|
}
|
|
|
|
Value& operator=(const Value& a_rhs)
|
|
{
|
|
if (this != std::addressof(a_rhs)) {
|
|
if (IsManagedValue()) {
|
|
ReleaseManagedValue();
|
|
}
|
|
|
|
_type = a_rhs._type;
|
|
_value = a_rhs._value;
|
|
_dataAux = a_rhs._dataAux;
|
|
|
|
if (a_rhs.IsManagedValue()) {
|
|
AcquireManagedValue(a_rhs);
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
Value& operator=(Value&& a_rhs)
|
|
{
|
|
if (this != std::addressof(a_rhs)) {
|
|
if (IsManagedValue()) {
|
|
ReleaseManagedValue();
|
|
}
|
|
|
|
_objectInterface = a_rhs._objectInterface;
|
|
a_rhs._objectInterface = nullptr;
|
|
|
|
_type = a_rhs._type;
|
|
a_rhs._type = ValueType::kUndefined;
|
|
|
|
_value = std::move(a_rhs._value);
|
|
|
|
_dataAux = a_rhs._dataAux;
|
|
a_rhs._dataAux = 0;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
Value& operator=(std::nullptr_t) noexcept
|
|
{
|
|
if (IsManagedValue()) {
|
|
ReleaseManagedValue();
|
|
}
|
|
|
|
_type = ValueType::kNull;
|
|
return *this;
|
|
}
|
|
|
|
Value& operator=(std::int32_t a_rhs) noexcept
|
|
{
|
|
if (IsManagedValue()) {
|
|
ReleaseManagedValue();
|
|
}
|
|
|
|
_type = ValueType::kInt;
|
|
_value = a_rhs;
|
|
return *this;
|
|
}
|
|
|
|
Value& operator=(std::uint32_t a_rhs) noexcept
|
|
{
|
|
if (IsManagedValue()) {
|
|
ReleaseManagedValue();
|
|
}
|
|
|
|
_type = ValueType::kUInt;
|
|
_value = a_rhs;
|
|
return *this;
|
|
}
|
|
|
|
Value& operator=(double a_rhs) noexcept
|
|
{
|
|
if (IsManagedValue()) {
|
|
ReleaseManagedValue();
|
|
}
|
|
|
|
_type = ValueType::kNumber;
|
|
_value = a_rhs;
|
|
return *this;
|
|
}
|
|
|
|
Value& operator=(bool a_rhs) noexcept
|
|
{
|
|
if (IsManagedValue()) {
|
|
ReleaseManagedValue();
|
|
}
|
|
|
|
_type = ValueType::kBoolean;
|
|
_value = a_rhs;
|
|
return *this;
|
|
}
|
|
|
|
Value& operator=(const char* a_rhs) noexcept
|
|
{
|
|
if (IsManagedValue()) {
|
|
ReleaseManagedValue();
|
|
}
|
|
|
|
_type = ValueType::kString;
|
|
_value = a_rhs;
|
|
return *this;
|
|
}
|
|
|
|
Value& operator=(const wchar_t* a_rhs) noexcept
|
|
{
|
|
if (IsManagedValue()) {
|
|
ReleaseManagedValue();
|
|
}
|
|
|
|
_type = ValueType::kStringW;
|
|
_value = a_rhs;
|
|
return *this;
|
|
}
|
|
|
|
[[nodiscard]] ValueType GetType() const noexcept { return *(_type & ValueType::kTypeMask); }
|
|
|
|
[[nodiscard]] bool IsArray() const noexcept { return GetType() == ValueType::kArray; }
|
|
[[nodiscard]] bool IsBoolean() const noexcept { return GetType() == ValueType::kBoolean; }
|
|
[[nodiscard]] bool IsDisplayObject() const noexcept { return GetType() == ValueType::kDisplayObject; }
|
|
[[nodiscard]] bool IsInt() const noexcept { return GetType() == ValueType::kInt; }
|
|
[[nodiscard]] bool IsNumber() const noexcept { return GetType() == ValueType::kNumber; }
|
|
[[nodiscard]] bool IsString() const noexcept { return GetType() == ValueType::kString; }
|
|
[[nodiscard]] bool IsUndefined() const noexcept { return GetType() == ValueType::kUndefined; }
|
|
[[nodiscard]] bool IsUInt() const noexcept { return GetType() == ValueType::kUInt; }
|
|
|
|
[[nodiscard]] bool IsObject() const noexcept
|
|
{
|
|
switch (GetType()) {
|
|
case ValueType::kObject:
|
|
case ValueType::kArray:
|
|
case ValueType::kDisplayObject:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
[[nodiscard]] bool GetBoolean() const
|
|
{
|
|
assert(IsBoolean());
|
|
return _value.boolean;
|
|
}
|
|
|
|
[[nodiscard]] std::int32_t GetInt() const
|
|
{
|
|
assert(IsInt());
|
|
return _value.int32;
|
|
}
|
|
|
|
[[nodiscard]] double GetNumber() const
|
|
{
|
|
assert(IsNumber());
|
|
return _value.number;
|
|
}
|
|
|
|
[[nodiscard]] const char* GetString() const
|
|
{
|
|
assert(IsString());
|
|
return IsManagedValue() ? *_value.mstring : _value.string;
|
|
}
|
|
|
|
[[nodiscard]] std::uint32_t GetUInt() const
|
|
{
|
|
assert(IsUInt());
|
|
return _value.uint32;
|
|
}
|
|
|
|
bool HasMember(std::string_view a_name) const
|
|
{
|
|
assert(IsObject());
|
|
return _objectInterface->HasMember(_value.data, a_name.data(), IsDisplayObject());
|
|
}
|
|
|
|
void VisitMembers(ObjectVisitor* a_visitor) const
|
|
{
|
|
assert(IsObject());
|
|
return _objectInterface->VisitMembers(_value.data, a_visitor, IsDisplayObject());
|
|
}
|
|
|
|
void VisitMembers(ObjectVisitFn&& a_visitor) const
|
|
{
|
|
assert(IsObject());
|
|
|
|
class MemberVisitor :
|
|
public ObjectInterface::ObjVisitor
|
|
{
|
|
public:
|
|
MemberVisitor(ObjectVisitFn&& a_fn) :
|
|
_fn(a_fn) {}
|
|
|
|
void Visit(const char* a_name, const Value& a_val) override
|
|
{
|
|
if (_fn) {
|
|
_fn(a_name, a_val);
|
|
}
|
|
}
|
|
|
|
private:
|
|
ObjectVisitFn _fn;
|
|
};
|
|
|
|
MemberVisitor visitor{ std::forward<ObjectVisitFn>(a_visitor) };
|
|
return _objectInterface->VisitMembers(_value.data, std::addressof(visitor), IsDisplayObject());
|
|
}
|
|
|
|
std::uint32_t GetArraySize() const
|
|
{
|
|
assert(IsArray());
|
|
return _objectInterface->GetArraySize(_value.data);
|
|
}
|
|
|
|
bool GetElement(std::uint32_t a_idx, Value* a_val) const
|
|
{
|
|
assert(IsArray());
|
|
return _objectInterface->GetElement(_value.data, a_idx, a_val);
|
|
}
|
|
|
|
bool SetElement(std::uint32_t a_idx, const Value& a_val)
|
|
{
|
|
assert(IsArray());
|
|
return _objectInterface->SetElement(_value.data, a_idx, a_val);
|
|
}
|
|
|
|
bool GetMember(std::string_view a_name, Value* a_val) const
|
|
{
|
|
assert(IsObject());
|
|
return _objectInterface->GetMember(_value.data, a_name.data(), a_val, IsDisplayObject());
|
|
}
|
|
|
|
bool SetMember(std::string_view a_name, const Value& a_val)
|
|
{
|
|
assert(IsObject());
|
|
return _objectInterface->SetMember(_value.data, a_name.data(), a_val, IsDisplayObject());
|
|
}
|
|
|
|
bool Invoke(const char* a_name, Value* a_result, const Value* a_args, std::size_t a_numArgs)
|
|
{
|
|
assert(IsObject());
|
|
return _objectInterface->Invoke(_value.data, a_result, a_name, a_args, a_numArgs, IsDisplayObject());
|
|
}
|
|
|
|
bool Invoke(const char* a_name, Value* a_result = nullptr)
|
|
{
|
|
return Invoke(a_name, a_result, nullptr, 0);
|
|
}
|
|
|
|
template <std::size_t N>
|
|
inline bool Invoke(const char* a_name, const std::array<Value, N>& a_args)
|
|
{
|
|
return Invoke(a_name, nullptr, a_args);
|
|
}
|
|
|
|
template <std::size_t N>
|
|
inline bool Invoke(const char* a_name, Value* a_result, const std::array<Value, N>& a_args)
|
|
{
|
|
return Invoke(a_name, a_result, a_args.data(), a_args.size());
|
|
}
|
|
|
|
bool PushBack(const Value& a_val)
|
|
{
|
|
assert(IsArray());
|
|
return _objectInterface->PushBack(_value.data, a_val);
|
|
}
|
|
|
|
bool RemoveElements(std::uint32_t a_idx, std::int32_t a_count = -1)
|
|
{
|
|
assert(IsArray());
|
|
return _objectInterface->RemoveElements(_value.data, a_idx, a_count);
|
|
}
|
|
|
|
bool RemoveElement(std::uint32_t a_idx)
|
|
{
|
|
return RemoveElements(a_idx, 1);
|
|
}
|
|
|
|
bool ClearElements()
|
|
{
|
|
return RemoveElements(0);
|
|
}
|
|
|
|
bool GetDisplayInfo(DisplayInfo* a_info) const
|
|
{
|
|
assert(IsDisplayObject());
|
|
return _objectInterface->GetDisplayInfo(_value.data, a_info);
|
|
}
|
|
|
|
[[nodiscard]] Movie* GetMovie() const
|
|
{
|
|
assert(_objectInterface && _objectInterface->movieRoot);
|
|
return reinterpret_cast<Movie*>(_objectInterface->movieRoot);
|
|
}
|
|
|
|
private:
|
|
void AcquireManagedValue(const Value& a_rhs)
|
|
{
|
|
assert(a_rhs._value.data && a_rhs._objectInterface);
|
|
_objectInterface = a_rhs._objectInterface;
|
|
_objectInterface->ObjectAddRef(this, _value.data);
|
|
}
|
|
|
|
[[nodiscard]] bool IsManagedValue() const noexcept
|
|
{
|
|
const auto managed = _type.all(ValueType::kManagedBit);
|
|
assert(managed ? _objectInterface != nullptr : true);
|
|
return managed;
|
|
}
|
|
|
|
void ReleaseManagedValue()
|
|
{
|
|
assert(_value.data && _objectInterface);
|
|
_objectInterface->ObjectRelease(this, _value.data);
|
|
_objectInterface = nullptr;
|
|
}
|
|
|
|
// members
|
|
ObjectInterface* _objectInterface{ nullptr }; // 00
|
|
REX::TEnumSet<ValueType, std::int32_t> _type{ ValueType::kUndefined }; // 08
|
|
ValueUnion _value{}; // 10
|
|
std::size_t _dataAux{ 0 }; // 18
|
|
};
|
|
static_assert(sizeof(Value) == 0x20);
|
|
}
|