Skip to content

Commit c6fb147

Browse files
committed
Event serialization.
1 parent 925bb49 commit c6fb147

6 files changed

Lines changed: 165 additions & 32 deletions

File tree

3DRadSpace/3DRadSpace_Editor_WindowsDX11/Frontend/Windows/EditObjectDialog.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ void EditObjectDialog::createForms()
490490
}
491491
case FieldRepresentationType::Skybox:
492492
{
493-
auto value = *static_cast<const AssetID<SkyboxAsset>*>(valuePtr);
493+
auto value = *reinterpret_cast<const AssetID<SkyboxAsset>*>(reinterpret_cast<const char*>(valuePtr) + fOffset);
494494

495495
SkyboxControl *ctrl = new SkyboxControl(window, hInstance, _content, value, fieldName.data(), x, y);
496496
windows.push_back(ctrl);
@@ -501,7 +501,7 @@ void EditObjectDialog::createForms()
501501
}
502502
case FieldRepresentationType::Sound:
503503
{
504-
auto value = *static_cast<const AssetID<Sound>*>(valuePtr);
504+
auto value = *reinterpret_cast<const AssetID<Sound>*>(reinterpret_cast<const char*>(valuePtr) + fOffset);
505505

506506
SoundControl *ctrl = new SoundControl(window, hInstance, _content, value, fieldName.data(), x, y);
507507
windows.push_back(ctrl);

3DRadSpace/Engine3DRadSpace/Plugins/CustomObject.hpp

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,43 @@
22
#include "../Reflection/ReflectedObject.hpp"
33
#include "../FFI/Core/RawSpan.h"
44

5-
namespace Engine3DRadSpace::Plugins
5+
namespace Engine3DRadSpace
66
{
7-
/// <summary>
8-
/// Returns a span of ReflectedObject references that contain custom object reflection data.
9-
/// </summary>
10-
typedef E3DRSP_RawSpan (*LoadCustomObjects)(void);
11-
12-
/// <summary>
13-
/// Loads custom objects from a library handle for the editor.
14-
/// </summary>
15-
/// <returns>The number of custom objects loaded.</returns>
16-
/// <param name="libraryHandle">HMODULE in Windows, void* in Linux</param>
17-
size_t E3DRSP_PLUGINS_EXPORT LoadCustomObjectsFromLibHandle(void* libraryHandle);
7+
namespace Plugins
8+
{
9+
/// <summary>
10+
/// Returns a span of ReflectedObject references that contain custom object reflection data.
11+
/// </summary>
12+
typedef E3DRSP_RawSpan(*LoadCustomObjects)(void);
1813

14+
/// <summary>
15+
/// Loads custom objects from a library handle for the editor.
16+
/// </summary>
17+
/// <returns>The number of custom objects loaded.</returns>
18+
/// <param name="libraryHandle">HMODULE in Windows, void* in Linux</param>
19+
size_t E3DRSP_PLUGINS_EXPORT LoadCustomObjectsFromLibHandle(void* libraryHandle);
1920

21+
/// <summary>
22+
/// The function signature for the function that creates a custom window for editing a custom object in the editor.
23+
/// </summary>
24+
/// <remarks>
25+
/// Returns a pointer to the new or updated object.
26+
///
27+
/// The arguments are:
28+
/// - HWND : Window Handle
29+
/// - HINSTANCE : Instance Handle
30+
/// - Engine3DRadSpace::Reflection::ReflectedObject* : Reflection data for the object
31+
/// - Engine3DRadSpace::Content::ContentManager* : Content manager for the object
32+
/// - Engine3DRadSpace::Objects::IObject* : The object being edited, can be nullptr if the object is being created for the first time
33+
///
34+
/// An analogue for the default implementation would be EditObjectDialog(...).ShowDialog().
35+
/// </remarks>
36+
typedef void*(*ObjectCustomWindow)(
37+
void* hwnd,
38+
void* hInstance,
39+
void* reflectionData,
40+
void* contentManager,
41+
void* object
42+
);
43+
}
2044
}

3DRadSpace/Engine3DRadSpace/Projects/Serialization.cpp

Lines changed: 89 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#include "Serialization.hpp"
2-
#include "Serialization.hpp"
3-
#include "Serialization.hpp"
42
#include "../Content/AssetID.hpp"
53
#include "../Objects/Impl/Objects.hpp"
64
#include "../Objects/ObjectList.hpp"
5+
#include "../Reflection/Event.hpp"
76
#include <fstream>
7+
#include "EventInvocationRepresentation.hpp"
88

99
using namespace Engine3DRadSpace;
1010
using namespace Engine3DRadSpace::Content;
@@ -33,6 +33,48 @@ static void deserializeObjectHierarchy(ObjectList* lst, IObject* obj, const json
3333
}
3434
}
3535

36+
static void validateEvents(IObject* obj, ObjectList* lst)
37+
{
38+
auto refl = GetReflDataFromUUID(obj->GetUUID());
39+
40+
std::vector<std::pair<EventInvocationRepresentation, IReflectedFunction*>> invocations;
41+
42+
for (auto& field : *refl)
43+
{
44+
auto repr = field->Representation();
45+
46+
for (auto& [reprType, sFieldName] : repr)
47+
{
48+
if (reprType == FieldRepresentationType::Event)
49+
{
50+
auto event = std::launder<Event>(reinterpret_cast<Event*>(reinterpret_cast<std::byte*>(obj) + field->FieldOffset()));
51+
52+
for (auto& binding : *event)
53+
{
54+
EventInvocationRepresentation invocRepr;
55+
invocRepr.FunctionID = binding.FunctionID;
56+
invocRepr.OwnerObject = binding.ObjectID;
57+
58+
auto reflObj = GetReflDataFromUUID(lst->operator[](binding.ObjectID)->GetUUID());
59+
invocations.emplace_back(invocRepr, invocRepr.FindFunction(reflObj, binding.FunctionID));
60+
}
61+
62+
event->Reset();
63+
64+
for (auto& [invocRepr, fn] : invocations)
65+
{
66+
if (fn == nullptr) continue;
67+
auto objPtr = lst->operator[](invocRepr.OwnerObject);
68+
69+
auto fn2 = dynamic_cast<IReflectedFunction*>(fn->Clone().release());
70+
event->Bind(std::move(std::unique_ptr<IReflectedFunction>(fn2)), invocRepr.OwnerObject, invocRepr.FunctionID);
71+
}
72+
}
73+
}
74+
75+
}
76+
}
77+
3678
static void serializeObjectHierarchy(std::unordered_map<IObject*, int> dictPtrID, ObjectList* lst, IObject* obj, json& j)
3779
{
3880
json children = json::array();
@@ -98,10 +140,18 @@ json Engine3DRadSpace::Projects::Serializer::SerializeObject(IObject* obj)
98140
intptr_t offset = 0;
99141
auto repr = field->Representation();
100142
bool useDirectGet = (field->FieldOffset() == 0 && repr.Size() == 1);
143+
144+
if (field->TypeSize() == 0 || repr.Size() == 0)
145+
continue;
146+
101147
for (int i = 0; auto &[reprType, sFieldName] : repr)
102148
{
103-
if(reprType == FieldRepresentationType::None) continue;
104-
if(reprType == FieldRepresentationType::Function) continue;
149+
if ((reprType == FieldRepresentationType::None) ||
150+
(reprType == FieldRepresentationType::Function))
151+
{
152+
++i;
153+
continue;
154+
}
105155

106156
auto subFieldName = !sFieldName.empty() ? sFieldName : "f";
107157

@@ -307,10 +357,17 @@ json Engine3DRadSpace::Projects::Serializer::SerializeObject(IObject* obj)
307357
}
308358
case FieldRepresentationType::Event:
309359
{
310-
//Projects::EventRepresentation e;
311-
//jsonField[subFieldName][str_i] = e;
360+
auto event = std::launder<Event>(reinterpret_cast<Event*>(static_cast<std::byte*>(objPtr) + field->FieldOffset() + offset));
312361

313-
//offset += sizeof(Event);
362+
jsonField[subFieldName][str_i]["NumInvocations"] = event->Count();
363+
364+
for (auto k = 0; k < event->Count(); k++)
365+
{
366+
jsonField[subFieldName][str_i]["Invocations"][std::to_string(k)]["OwnerObject"] = event->At(k).ObjectID;
367+
jsonField[subFieldName][str_i]["Invocations"][std::to_string(k)]["FunctionID"] = event->At(k).FunctionID;
368+
}
369+
370+
offset += sizeof(Event);
314371
break;
315372
}
316373
case FieldRepresentationType::ObjectID:
@@ -350,6 +407,9 @@ json Engine3DRadSpace::Projects::Serializer::SerializeObject(IObject* obj)
350407
auto newStruct = std::make_unique<uint8_t[]>(structSize);
351408
int offset = 0;
352409

410+
if (field->TypeSize() == 0 || repr.Size() == 0)
411+
continue;
412+
353413
bool useDirectSet = (field->FieldOffset() == 0 && repr.Size() == 1);
354414

355415
for (int i = 0; auto & [reprType, sFieldName] : repr)
@@ -632,13 +692,29 @@ json Engine3DRadSpace::Projects::Serializer::SerializeObject(IObject* obj)
632692
}
633693
case FieldRepresentationType::Event:
634694
{
635-
//EventRepresentation eventData = jsonField.get<EventRepresentation>();
636-
//Event event = eventData.Reconstruct(uuid).value();
695+
auto numInvocations = jsonField["NumInvocations"].get<size_t>();
696+
697+
Event event;
637698

638-
//void* dest = newStruct.get() + offset;
639-
//new (dest) Event();
640-
//offset += sizeof(Event);
699+
for (auto i = 0; i < numInvocations; i++)
700+
{
701+
auto invocation = jsonField["Invocations"][std::to_string(i)];
702+
703+
EventInvocationRepresentation repr;
704+
705+
repr.OwnerObject = invocation["OwnerObject"].get<size_t>();
706+
repr.FunctionID = invocation["FunctionID"].get<size_t>();
707+
708+
//TODO: Support arguments.
709+
710+
event.BindIncomplete(
711+
repr.OwnerObject,
712+
repr.FunctionID
713+
);
714+
}
641715

716+
new (newStruct.get() + offset) Event(std::move(event));
717+
offset += sizeof(Event);
642718
break;
643719
}
644720
case FieldRepresentationType::ObjectID:
@@ -696,6 +772,7 @@ bool Engine3DRadSpace::Projects::Serializer::LoadProject(ObjectList* lst, Conten
696772
{
697773
auto obj = lst->operator[](i);
698774
deserializeObjectHierarchy(lst, obj, j["objects"][std::to_string(i)]);
775+
validateEvents(obj, lst);
699776
}
700777

701778
return true;

3DRadSpace/Engine3DRadSpace/Reflection/Event.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ Event::MemberFunctionInvoker::MemberFunctionInvoker(
1818
{
1919
}
2020

21+
Event::MemberFunctionInvoker::MemberFunctionInvoker(size_t objID, size_t fnID) :
22+
Object(nullptr),
23+
Fn(nullptr),
24+
ReturnType(typeid(void)),
25+
ObjectID(objID),
26+
FunctionID(fnID)
27+
{
28+
}
29+
2130
Event::Event() :
2231
_empty(true)
2332
{
@@ -42,9 +51,16 @@ Event& Event::operator=(const Event& other)
4251
_fns.clear();
4352
for (const auto& fn : other._fns)
4453
{
45-
auto cloned = fn.Fn->Clone();
46-
std::unique_ptr<IReflectedFunction> clonedFn(static_cast<IReflectedFunction*>(cloned.release()));
47-
_fns.emplace_back(fn.Object, std::move(clonedFn), fn.ReturnType, fn.ObjectID, fn.FunctionID);
54+
if (fn.Fn)
55+
{
56+
auto cloned = fn.Fn->Clone();
57+
std::unique_ptr<IReflectedFunction> clonedFn(static_cast<IReflectedFunction*>(cloned.release()));
58+
_fns.emplace_back(fn.Object, std::move(clonedFn), fn.ReturnType, fn.ObjectID, fn.FunctionID);
59+
}
60+
else
61+
{
62+
_fns.emplace_back(fn.Object, nullptr, fn.ReturnType, fn.ObjectID, fn.FunctionID);
63+
}
4864
}
4965
return *this;
5066
}
@@ -183,4 +199,9 @@ Any Event::operator()(std::vector<Any> &args)
183199
void Event::Bind(std::function<Any(std::vector<Any>)> fnargs)
184200
{
185201

202+
}
203+
204+
void Event::BindIncomplete(size_t objID, size_t fnID)
205+
{
206+
_fns.emplace_back(objID, fnID);
186207
}

3DRadSpace/Engine3DRadSpace/Reflection/Event.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ namespace Engine3DRadSpace::Reflection
4343
/// </summary>
4444
MemberFunctionInvoker();
4545
MemberFunctionInvoker(void* object, std::unique_ptr<IReflectedFunction> &&fn, std::type_index returnType, size_t objID, size_t fnID);
46+
MemberFunctionInvoker(size_t objID, size_t fnID);
4647

4748
MemberFunctionInvoker(MemberFunctionInvoker&& other) noexcept = default;
4849
MemberFunctionInvoker& operator=(MemberFunctionInvoker&& other) noexcept = default;
@@ -89,6 +90,7 @@ namespace Engine3DRadSpace::Reflection
8990
}
9091

9192
void Bind(std::unique_ptr<IReflectedFunction> &&fn, size_t objID, size_t fnID);
93+
void BindIncomplete(size_t objID, size_t fnID);
9294

9395
template<typename R, typename ...Args>
9496
R operator()(int index, Args&& ...args)

3DRadSpace/Engine3DRadSpace/Reflection/Reflection.hpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
/// ---------------------------------------------------------------------------
44
/// Reflecting objects:
55
/// ---------------------------------------------------------------------------
6-
7-
///Reflecting IObject types:
86
#include "ReflectedObject.hpp"
97

108
///Reflects a class that inherits IObject.
@@ -59,4 +57,15 @@
5957
#define REFL_METHOD(ObjectType, ReturnType, Function, Name, ...) static_cast<::Engine3DRadSpace::Reflection::IReflectedField*>( new ::Engine3DRadSpace::Reflection::ReflectedMemberFunction<ReturnType, ObjectType, __VA_ARGS__>(Name, Function)),
6058

6159
#include "ReflectedFunction.hpp"
62-
#define REFL_FUNCTION(ReturnType, Function, Name, ...) static_cast<::Engine3DRadSpace::Reflection::IReflectedField*>( new ::Engine3DRadSpace::Reflection::ReflectedFunction<ReturnType, __VA_ARGS__>(Name, Function)),
60+
#define REFL_FUNCTION(ReturnType, Function, Name, ...) static_cast<::Engine3DRadSpace::Reflection::IReflectedField*>( new ::Engine3DRadSpace::Reflection::ReflectedFunction<ReturnType, __VA_ARGS__>(Name, Function)),
61+
62+
/// ---------------------------------------------------------------------------
63+
/// Metadata
64+
/// ---------------------------------------------------------------------------
65+
/// Supported attributes are:
66+
/// - "HelpURL": Provides a URL to the help documentation for the object being reflected.
67+
/// - "CustomWindow": Specifies that the given object doesn't use the default editor window, but an custom one instead. The value is the name of the function that creates the custom window.
68+
/// Refer to CustomEditObjectWindow inside the Plugin library for more details.
69+
//#include "Attribute.hpp"
70+
71+
#define REFL_ATTR(Name, Value) static_cast<::Engine3DRadSpace::Reflection::IReflectedField*>( new ::Engine3DRadSpace::Reflection::Attribute(Name, Value)),

0 commit comments

Comments
 (0)