Plasma Engine  2.0
Loading...
Searching...
No Matches
SimpleAssetDocument.h
1#pragma once
2
3#include <EditorEngineProcessFramework/EngineProcess/ViewRenderSettings.h>
4#include <EditorFramework/Assets/AssetDocument.h>
5#include <EditorFramework/Preferences/EditorPreferences.h>
6#include <Foundation/Profiling/Profiling.h>
7#include <Foundation/Serialization/ApplyNativePropertyChangesContext.h>
8#include <ToolsFoundation/Object/DocumentObjectManager.h>
9#include <ToolsFoundation/Object/DocumentObjectMirror.h>
10#include <ToolsFoundation/Object/ObjectAccessorBase.h>
11#include <ToolsFoundation/Reflection/PhantomRttiManager.h>
12#include <ToolsFoundation/Serialization/DocumentObjectConverter.h>
13
14template <typename ObjectProperties>
16{
17public:
18 virtual void GetCreateableTypes(plHybridArray<const plRTTI*, 32>& ref_types) const override { ref_types.PushBack(plGetStaticRTTI<ObjectProperties>()); }
19};
20
21template <typename PropertyType, typename BaseClass = plAssetDocument>
22class plSimpleAssetDocument : public BaseClass
23{
24public:
25 plSimpleAssetDocument(plStringView sDocumentPath, plAssetDocEngineConnection engineConnectionType, bool bEnableDefaultLighting = false)
26 : BaseClass(sDocumentPath, PL_DEFAULT_NEW(plSimpleDocumentObjectManager<PropertyType>), engineConnectionType)
27 , m_LightSettings(bEnableDefaultLighting)
28 {
29 if (bEnableDefaultLighting)
30 {
32 pPreferences->ApplyDefaultValues(m_LightSettings);
33 }
34 }
35
36 plSimpleAssetDocument(plDocumentObjectManager* pObjectManager, plStringView sDocumentPath, plAssetDocEngineConnection engineConnectionType, bool bEnableDefaultLighting = false)
37 : BaseClass(sDocumentPath, pObjectManager, engineConnectionType)
38 , m_LightSettings(bEnableDefaultLighting)
39 {
40 if (bEnableDefaultLighting)
41 {
43 pPreferences->ApplyDefaultValues(m_LightSettings);
44 }
45 }
46
48 {
49 m_ObjectMirror.Clear();
50 m_ObjectMirror.DeInit();
51 }
52
53 const PropertyType* GetProperties() const
54 {
55 return static_cast<const PropertyType*>(m_ObjectMirror.GetNativeObjectPointer(this->GetObjectManager()->GetRootObject()->GetChildren()[0]));
56 }
57
58 PropertyType* GetProperties()
59 {
60 return static_cast<PropertyType*>(m_ObjectMirror.GetNativeObjectPointer(this->GetObjectManager()->GetRootObject()->GetChildren()[0]));
61 }
62
63 plDocumentObject* GetPropertyObject() { return this->GetObjectManager()->GetRootObject()->GetChildren()[0]; }
64
65protected:
66 virtual void InitializeAfterLoading(bool bFirstTimeCreation) override
67 {
68 EnsureSettingsObjectExist();
69
70 m_ObjectMirror.InitSender(this->GetObjectManager());
71 m_ObjectMirror.InitReceiver(&m_Context);
72 m_ObjectMirror.SendDocument();
73
74 BaseClass::InitializeAfterLoading(bFirstTimeCreation);
75
76 this->AddSyncObject(&m_LightSettings);
77 }
78
79 virtual plStatus InternalLoadDocument() override
80 {
81 this->GetObjectManager()->DestroyAllObjects();
82
83 plStatus ret = BaseClass::InternalLoadDocument();
84
85 return ret;
86 }
87
88 // Index based remapping ignores address identity and solely uses the object's parent index to define
89 // its guid. Set it to true if the native changes are complete clear and replace operations and
90 // not incremental changes to the existing data.
91 void ApplyNativePropertyChangesToObjectManager(bool bForceIndexBasedRemapping = false)
92 {
93 PL_PROFILE_SCOPE("ApplyNativePropertyChangesToObjectManager");
94 // Create object manager graph
95 plAbstractObjectGraph origGraph;
96 plAbstractObjectNode* pOrigRootNode = nullptr;
97 {
98 plDocumentObjectConverterWriter writer(&origGraph, this->GetObjectManager());
99 pOrigRootNode = writer.AddObjectToGraph(GetPropertyObject());
100 }
101
102 // Create native object graph
104 plAbstractObjectNode* pRootNode = nullptr;
105 {
106 // The plApplyNativePropertyChangesContext takes care of generating guids for native pointers that match those
107 // of the object manager.
108 plApplyNativePropertyChangesContext nativeChangesContext(m_Context, origGraph);
109 plRttiConverterWriter rttiConverter(&graph, &nativeChangesContext, true, true);
110 nativeChangesContext.RegisterObject(pOrigRootNode->GetGuid(), plGetStaticRTTI<PropertyType>(), GetProperties());
111 pRootNode = rttiConverter.AddObjectToGraph(GetProperties(), "Object");
112 }
113
114 // Remapping is no longer necessary as plApplyNativePropertyChangesContext takes care of mapping to the original nodes.
115 // However, if the native changes are done like clear+rebuild everything, then no original object will be found and
116 // every pointer will be deleted and re-created. Forcing the remapping (which works entirely via index and ignores
117 // pointer addresses) will yield better results (e.g. no changes on two back-to -back transform calls).
118 if (bForceIndexBasedRemapping)
119 {
120 // Remap native guids so they match the object manager (stuff like embedded classes will not have a guid on the native side).
121 graph.ReMapNodeGuidsToMatchGraph(pRootNode, origGraph, pOrigRootNode);
122 }
123
125 graph.CreateDiffWithBaseGraph(origGraph, diffResult);
126
127 // if index-based remapping is used, we MUST send a change event of some kind
128 // since the underlying data structures (memory locations) might have been changed,
129 // even if there is no actual change to the content
130 // the command history will detect that there was no change and actually send a "TransactionCanceled" event, but that is enough for other code to react to
131 if (!diffResult.IsEmpty() || bForceIndexBasedRemapping)
132 {
133 // As we messed up the native side the object mirror is no longer synced and needs to be destroyed.
134 m_ObjectMirror.Clear();
135
136 // Apply diff while object mirror is down.
137 this->GetObjectAccessor()->StartTransaction("Apply Native Property Changes to Object");
138
139 plDocumentObjectConverterReader::ApplyDiffToObject(this->GetObjectAccessor(), GetPropertyObject(), diffResult);
140
141 // Re-apply document
142 m_ObjectMirror.SendDocument();
143
144 this->GetObjectAccessor()->FinishTransaction();
145 }
146 }
147
148private:
149 void EnsureSettingsObjectExist()
150 {
151 auto pRoot = this->GetObjectManager()->GetRootObject();
152 if (pRoot->GetChildren().IsEmpty())
153 {
154 plDocumentObject* pObject = this->GetObjectManager()->CreateObject(plGetStaticRTTI<PropertyType>());
155 this->GetObjectManager()->AddObject(pObject, pRoot, "Children", 0);
156 }
157 }
158
159protected:
160 virtual plDocumentInfo* CreateDocumentInfo() override { return PL_DEFAULT_NEW(plAssetDocumentInfo); }
161
162 plDocumentObjectMirror m_ObjectMirror;
163 plRttiConverterContext m_Context;
164 plEngineViewLightSettings m_LightSettings;
165};
Definition AbstractObjectGraph.h:115
void ReMapNodeGuidsToMatchGraph(plAbstractObjectNode *pRoot, const plAbstractObjectGraph &rhsGraph, const plAbstractObjectNode *pRhsRoot)
Tries to remap the guids of this graph to those in rhsGraph by walking in both down the hierarchy,...
Definition AbstractObjectGraph.cpp:327
Definition AbstractObjectGraph.h:17
The plApplyNativePropertyChangesContext takes care of generating guids for native pointers that match...
Definition ApplyNativePropertyChangesContext.h:8
void PushBack(const T &value)
Pushes value at the end of the array.
Definition ArrayBase_inl.h:333
void AddSyncObject(plEditorEngineSyncObject *pSync) const
Registers a sync object for this document. It will be mirrored to the plEngineProcessDocumentContext ...
Definition AssetDocument.cpp:852
Definition AssetDocumentInfo.h:7
bool IsEmpty() const
Checks whether no elements are active in the deque.
Definition Deque_inl.h:601
Definition Deque.h:270
Definition Declarations.h:72
Writes the state of an plDocumentObject to an abstract graph.
Definition DocumentObjectConverter.h:13
Definition DocumentObjectBase.h:11
Represents to content of a document. Every document has exactly one root object under which all objec...
Definition DocumentObjectManager.h:116
Definition DocumentObjectMirror.h:34
Stores editor specific preferences for the current user.
Definition EditorPreferences.h:10
Definition ViewRenderSettings.h:65
A hybrid array uses in-place storage to handle the first few elements without any allocation....
Definition HybridArray.h:12
static TYPE * QueryPreferences(const plDocument *pDocument=nullptr)
Static function to query a preferences object of the given type. If the instance does not exist yet,...
Definition Preferences.h:31
Definition RttiConverter.h:33
Definition RttiConverter.h:81
Definition SimpleAssetDocument.h:23
Definition SimpleAssetDocument.h:16
plStringView represent a read-only sub-string of a larger string, as it can store a dedicated string ...
Definition StringView.h:34
An plResult with an additional message for the reason of failure.
Definition Status.h:12