Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
TSdlReferenceArray.ipp
Go to the documentation of this file.
1#pragma once
2
8#include "SDL/ISdlResource.h"
10#include "SDL/sdl_exceptions.h"
11#include "SDL/sdl_helpers.h"
12#include "SDL/sdl_parser.h"
13#include "SDL/Tokenizer.h"
14
15#include <Common/assertion.h>
16#include <Common/Utility/string_utils.h>
17
18#include <utility>
19
20namespace ph
21{
22
23template<typename T, typename Owner>
25 std::string valueName,
26 std::vector<std::shared_ptr<T>> Owner::* const valuePtr)
27
28 : TSdlOwnedField<Owner>(
29 std::string(sdl::category_to_string(sdl::category_of<T>())) + "-array",
30 std::move(valueName))
31
32 , m_valuePtr(valuePtr)
33{
34 static_assert(std::is_base_of_v<ISdlResource, T>,
35 "T must be a SDL resource (derive from ISdlResource).");
36
37 PH_ASSERT(m_valuePtr);
38}
39
40template<typename T, typename Owner>
42{
43 // Default value for an array is empty
44 owner.*m_valuePtr = std::vector<std::shared_ptr<T>>{};
45}
46
47template<typename T, typename Owner>
48inline std::string TSdlReferenceArray<T, Owner>::valueToString(const Owner& owner) const
49{
50 const std::vector<std::shared_ptr<T>>& referenceVector = owner.*m_valuePtr;
51
52 return
53 "[" + std::to_string(referenceVector.size()) + " " +
54 std::string(sdl::category_to_string(sdl::category_of<T>())) + " references...]";
55}
56
57template<typename T, typename Owner>
59 const Owner& owner,
60 std::vector<const ISdlResource*>& out_resources) const
61{
62 const std::vector<std::shared_ptr<T>>& storedVector = getValueVec(owner);
63 for(const std::shared_ptr<T>& storedResource : storedVector)
64 {
65 out_resources.push_back(storedResource.get());
66 }
67}
68
69template<typename T, typename Owner>
71{
72 std::vector<std::shared_ptr<T>>* const refVec = &(owner.*m_valuePtr);
73
74 SdlNativeData data;
75 if(refVec)
76 {
77 std::shared_ptr<T>* const refVecData = refVec->data();
78
79 // Read-only for ordinary access to avoid accidental object slicing and other polymorphic
80 // assignment issues. User should use direct accessor for assignment.
81 data = SdlNativeData(
82 [refVecData](std::size_t elementIdx) -> SdlGetterVariant
83 {
84 T* const originalDataPtr = refVecData[elementIdx].get();
85 return originalDataPtr
88 });
89
90 data.numElements = refVec->size();
92 }
95 return data;
96}
97
98template<typename T, typename Owner>
100 Owner& owner,
101 std::vector<std::shared_ptr<T>> value) const
102{
103 owner.*m_valuePtr = std::move(value);
104}
105
106template<typename T, typename Owner>
107inline auto TSdlReferenceArray<T, Owner>::getValueVec(const Owner& owner) const
108-> const std::vector<std::shared_ptr<T>>&
109{
110 return owner.*m_valuePtr;
111}
112
113template<typename T, typename Owner>
115 Owner& owner,
116 const SdlInputClause& clause,
117 const SdlInputContext& ctx) const
118{
119 try
120 {
121 setValueVec(owner, loadReferenceArray(clause, ctx));
122 }
123 catch(const SdlException& e)
124 {
125 throw_formatted<SdlLoadError>(
126 "on parsing reference array {} -> {}",
127 valueToString(owner), e.whatStr());
128 }
129}
130
131template<typename T, typename Owner>
133 const Owner& owner,
134 SdlOutputClause& out_clause,
135 const SdlOutputContext& ctx) const
136{
137 const std::vector<std::shared_ptr<T>>& referenceVector = getValueVec(owner);
138 if(referenceVector.empty())
139 {
140 out_clause.isEmpty = true;
141 return;
142 }
143
144 // Basically generates a list of reference names (with proper specifier)
145 try
146 {
147 out_clause.value = '{';
148 for(const std::shared_ptr<T>& resource : referenceVector)
149 {
150 const auto resourceName = ctx.getResourceName(resource.get());
151 if(resourceName.empty())
152 {
153 throw SdlSaveError(
154 "resource name unavailable");
155 }
156
157 const bool hasWhitespaces = string_utils::has_any_of(resourceName, string_utils::get_whitespaces());
159 out_clause.value += hasWhitespaces ? "\"" : "";
160 out_clause.value += resourceName;
161 out_clause.value += hasWhitespaces ? "\"" : "";
162 out_clause.value += ' ';
163 }
164 out_clause.value += '}';
165 }
166 catch(const SdlException& e)
167 {
168 throw_formatted<SdlSaveError>(
169 "on saving reference array {} -> {}", valueToString(owner), e.whatStr());
170 }
171}
172
173template<typename T, typename Owner>
174template<typename ResourceType>
175inline std::vector<std::shared_ptr<T>> TSdlReferenceArray<T, Owner>::loadReferenceArray(
176 const SdlInputClause& clause,
177 const SdlInputContext& ctx)
178{
179 static const Tokenizer tokenizer({' ', '\t', '\n', '\r'}, {{'"', '"'}});
180
181 if(!ctx.getSrcResources())
182 {
183 throw SdlLoadError(
184 "no target reference group specified");
185 }
186
188 {
189 auto resource = TSdlReference<T, Owner>::loadReference(clause, ctx);
190 return {resource};
191 }
192 else if(clause.valueType == ESdlClauseValue::General)
193 {
194 std::vector<std::string> tokens;
195 tokenizer.tokenize(clause.value, tokens);
196 if(tokens.size() % 2 != 0)
197 {
198 throw SdlLoadError(
199 "syntax error: unexpected input format");
200 }
201
202 const auto numReferenceTokens = tokens.size() / 2;
203 std::vector<std::shared_ptr<T>> referenceVector(numReferenceTokens);
204 for(std::size_t i = 0; i < numReferenceTokens; ++i)
205 {
206 const std::string referenceToken = tokens[i * 2] + tokens[i * 2 + 1];
207 const auto reference = sdl_parser::get_reference(referenceToken);
208 referenceVector[i] = TSdlReference<T, Owner>::loadReference(reference, ctx);
209 }
210
211 return referenceVector;
212 }
213 else
214 {
215 throw SdlLoadError(
216 "bad reference type (only persistent target is supported)");
217 }
218}
219
220template<typename T, typename Owner>
223{
224 this->setImportance(importance);
225 return *this;
226}
227
228template<typename T, typename Owner>
229inline auto TSdlReferenceArray<T, Owner>::description(std::string descriptionStr)
231{
232 this->setDescription(std::move(descriptionStr));
233 return *this;
234}
235
236template<typename T, typename Owner>
239{
240 return withImportance(EFieldImportance::Optional);
241}
242
243template<typename T, typename Owner>
246{
247 return withImportance(EFieldImportance::NiceToHave);
248}
249
250template<typename T, typename Owner>
253{
254 return withImportance(EFieldImportance::Required);
255}
256
257}// end namespace ph
General exception thrown on error related to SDL.
Definition sdl_exceptions.h:13
Carries SDL representation of various data during the input process. Helps to read input data such as...
Definition SdlInputClause.h:15
std::string value
Loaded stringified data of a clause. All potential SDL value prefixes or suffixes (e....
Definition SdlInputClause.h:25
ESdlClauseValue valueType
Type of the carried value. For identifying the type of the value string only. Does not check whether ...
Definition SdlInputClause.h:33
Data that SDL input process can rely on.
Definition SdlInputContext.h:19
const ISdlReferenceGroup * getSrcResources() const
Definition SdlInputContext.h:93
Error on the SDL input process.
Definition sdl_exceptions.h:22
Definition SdlNativeData.h:88
std::size_t numElements
Hint for number of elements in this block of native data. For example, numElements would be 12 for an...
Definition SdlNativeData.h:99
void setDirectAccessor(AnyNonConstPtr accessor)
Definition SdlNativeData.ipp:267
static auto permissiveElementGetter(ElementType *elementPtr) -> SdlGetterVariant
Given a valid target element, get its value in a permissive way (with auto conversions).
Definition SdlNativeData.ipp:312
ESdlDataType elementType
Hint for the type of elements.
Definition SdlNativeData.h:113
ESdlDataFormat elementContainer
Hint for the type that encapsulates elements.
Definition SdlNativeData.h:109
Carries SDL representation of various data during the output process. Helps to write output data such...
Definition SdlOutputClause.h:14
std::string value
Stores stringified data of a clause. As the output clause generator knows best how its data look like...
Definition SdlOutputClause.h:29
bool isEmpty
If the clause carries no data and does not need to be written.
Definition SdlOutputClause.h:41
Data that SDL output process can rely on.
Definition SdlOutputContext.h:19
std::string_view getResourceName(const ISdlResource *resource) const
Definition SdlOutputContext.cpp:9
Error on the SDL output process.
Definition sdl_exceptions.h:30
Definition SdlNativeData.h:24
T & get()
Definition SdlNativeData.ipp:38
References a SDL object. This is a lightweight utility for referencing SDL objects....
Definition TSdlAnyInstance.h:20
Abstraction for a value that is owned by some owner type. Governs how a field should be initialized o...
Definition TSdlOwnedField.h:15
A value that points to an array of SDL resources.
Definition TSdlReferenceArray.h:23
static std::vector< std::shared_ptr< T > > loadReferenceArray(const SdlInputClause &clause, const SdlInputContext &ctx)
Definition TSdlReferenceArray.ipp:175
TSdlReferenceArray & description(std::string descriptionStr)
Definition TSdlReferenceArray.ipp:229
SdlNativeData ownedNativeData(Owner &owner) const override
Direct access to the field memory of an owner. Short-lived owner objects such as function parameter s...
Definition TSdlReferenceArray.ipp:70
void ownedValueToDefault(Owner &owner) const override
By default, default value of the array is empty.
Definition TSdlReferenceArray.ipp:41
TSdlReferenceArray & optional()
Definition TSdlReferenceArray.ipp:237
const std::vector< std::shared_ptr< T > > & getValueVec(const Owner &owner) const
Definition TSdlReferenceArray.ipp:107
TSdlReferenceArray(std::string valueName, std::vector< std::shared_ptr< T > > Owner::*valuePtr)
Definition TSdlReferenceArray.ipp:24
void ownedResources(const Owner &owner, std::vector< const ISdlResource * > &out_resources) const override
Get all SDL resources associated by owner.
Definition TSdlReferenceArray.ipp:58
TSdlReferenceArray & niceToHave()
Definition TSdlReferenceArray.ipp:244
std::string valueToString(const Owner &owner) const override
Convert the value of the field to human-readable string.
Definition TSdlReferenceArray.ipp:48
void saveToSdl(const Owner &owner, SdlOutputClause &out_clause, const SdlOutputContext &ctx) const override
Convert actual value back to SDL value. Saving a loaded value as SDL value should rarely fail–as load...
Definition TSdlReferenceArray.ipp:132
void setValueVec(Owner &owner, std::vector< std::shared_ptr< T > > value) const
Definition TSdlReferenceArray.ipp:99
TSdlReferenceArray & withImportance(EFieldImportance importance)
Definition TSdlReferenceArray.ipp:221
TSdlReferenceArray & required()
Definition TSdlReferenceArray.ipp:251
void loadFromSdl(Owner &owner, const SdlInputClause &clause, const SdlInputContext &ctx) const override
Load SDL value to actual value and store it in the owner's field. Implementations are highly encourag...
Definition TSdlReferenceArray.ipp:114
static std::shared_ptr< ResourceType > loadReference(const SdlInputClause &clause, const SdlInputContext &ctx)
Definition TSdlReference.ipp:155
Definition Tokenizer.h:13
std::string_view get_reference(std::string_view referenceToken)
Retrieve reference from a single reference token. A reference token is not the same as a reference....
Definition sdl_parser.cpp:124
constexpr char persistent_specifier
Definition sdl_parser.h:9
std::string_view category_to_string(const ESdlTypeCategory category)
Definition ESdlTypeCategory.h:59
constexpr ESdlTypeCategory category_of()
Statically gets the SDL category of T.
Definition sdl_helpers.ipp:409
constexpr ESdlDataType resource_type_of()
Definition sdl_helpers.ipp:492
The root for all renderer implementations.
Definition EEngineProject.h:6
TAnyPtr< false > AnyNonConstPtr
A type-safe, lightweight wrapper for any non-const raw pointer type.
Definition TAnyPtr.h:47
EFieldImportance
Definition EFieldImportance.h:7
@ PersistentTargetName
Definition sdl_fwd.h:48
@ General
Definition sdl_fwd.h:45
Definition TAABB2D.h:96
Low-level helpers for SDL. Helpers are in an additional sdl namespace.