Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
SdlNativeData.ipp
Go to the documentation of this file.
1#pragma once
2
4#include "SDL/sdl_traits.h"
5
6#include <Common/assertion.h>
7
8#include <utility>
9
10namespace ph
11{
12
13template<typename Variant>
15 : m_variant(std::monostate{})
16{}
17
18template<typename Variant>
19template<typename T>
21 : m_variant(std::move(value))
22{}
23
24template<typename Variant>
26 : m_variant(std::move(variant))
27{}
28
29template<typename Variant>
30template<typename T>
32{
33 return std::holds_alternative<T>(m_variant);
34}
35
36template<typename Variant>
37template<typename T>
39{
40 PH_ASSERT(has<T>());
41 return std::get<T>(m_variant);
42}
43
44template<typename Variant>
45template<typename T>
46inline const T& TSdlAccessorVariant<Variant>::get() const
47{
48 PH_ASSERT(has<T>());
49 return std::get<T>(m_variant);
50}
51
52template<typename Variant>
53template<typename T>
55{
56 std::get<T>(m_variant) = std::move(value);
57}
58
59template<typename Variant>
60inline std::size_t TSdlAccessorVariant<Variant>::index() const
61{
62 return m_variant.index();
63}
64
65template<typename Variant>
67{
68 return has<std::monostate>();
69}
70
71template<typename Variant>
74{
75 return m_variant;
76}
77
78template<typename Variant>
80-> const VariantType&
81{
82 return m_variant;
83}
84
85template<typename ElementType>
87 ElementType* const elementPtr,
88 ESdlDataFormat elementContainer,
89 ESdlDataType elementType,
90 const bool canSet,
91 const bool canDirectAccess)
92{
93 SdlNativeData nativeData;
94
95 // We do not capture element value directly to save memory--value needs to be obtained from
96 // pointer, so any data modifications can be observed.
97
98 if(elementPtr)
99 {
100 nativeData.m_elementGetter =
101 [elementPtr](std::size_t /* elementIdx */) -> SdlGetterVariant
102 {
103 return permissiveElementGetter(elementPtr);
104 };
105 }
106 else
107 {
108 nativeData.m_elementGetter =
109 [elementPtr](std::size_t /* elementIdx */) -> SdlGetterVariant
110 {
111 return std::monostate{};
112 };
113 }
114
115 if(canSet)
116 {
117 if(elementPtr)
118 {
119 nativeData.m_elementSetter =
120 [elementPtr](std::size_t /* elementIdx */, SdlSetterVariant input) -> bool
121 {
122 return permissiveElementSetter(input, elementPtr);
123 };
124 }
125 else
126 {
127 nativeData.m_elementSetter =
128 [elementPtr](std::size_t /* elementIdx */, SdlSetterVariant input) -> bool
129 {
130 return false;
131 };
132 }
133 }
134
135 if(canDirectAccess)
136 {
137 nativeData.m_directPtr = elementPtr;
138 }
139
140 nativeData.numElements = elementPtr ? 1 : 0;
142 nativeData.elementType = elementType;
143 return nativeData;
144}
145
148 [](std::size_t /* elementIdx */) -> SdlGetterVariant
149 {
150 return std::monostate{};
151 })
152{}
153
156 std::move(getter),
157 [](std::size_t /* elementIdx */, SdlSetterVariant /* input */) -> bool
158 {
159 return false;
160 })
161{}
162
165 std::move(getter),
166 std::move(setter),
167 nullptr)
168{}
169
171 ElementGetter getter,
172 ElementSetter setter,
173 AnyNonConstPtr directPtr)
174
175 : m_elementGetter(std::move(getter))
176 , m_elementSetter(std::move(setter))
177 , m_directPtr(directPtr)
178{}
179
180template<typename T>
181 requires std::is_arithmetic_v<T> || std::is_enum_v<T>
182inline std::optional<T> SdlNativeData::get(const std::size_t elementIdx) const
183{
184 PH_ASSERT(m_elementGetter);
185
186 SdlGetterVariant output = m_elementGetter(elementIdx);
187 switch(output.index())
188 {
189 case 1: return static_cast<T>(output.get<int64>());
190 case 2: return static_cast<T>(output.get<float64>());
191 default: return std::nullopt;
192 }
193}
194
195template<typename T>
196 requires std::is_pointer_v<T>
197inline T SdlNativeData::get(const std::size_t elementIdx) const
198{
199 PH_ASSERT(m_elementGetter);
200
201 using PtrRemovedT = std::remove_pointer_t<T>;
202
203 SdlGetterVariant output = m_elementGetter(elementIdx);
204 if constexpr(CSdlInstance<PtrRemovedT>)
205 {
206 return output.has<SdlConstInstance>()
207 ? output.get<SdlConstInstance>().get<PtrRemovedT>() : nullptr;
208 }
209 else
210 {
211 return output.has<AnyConstPtr>()
212 ? output.get<AnyConstPtr>().get<PtrRemovedT>() : nullptr;
213 }
214}
215
216template<typename T>
217 requires std::is_arithmetic_v<T> || std::is_enum_v<T>
218inline bool SdlNativeData::set(const std::size_t elementIdx, const T value) const
219{
220 PH_ASSERT(m_elementSetter);
221
222 if constexpr(std::is_integral_v<T> || std::is_enum_v<T>)
223 {
224 return m_elementSetter(elementIdx, static_cast<int64>(value));
225 }
226 else if constexpr(std::is_floating_point_v<T>)
227 {
228 return m_elementSetter(elementIdx, static_cast<float64>(value));
229 }
230 else
231 {
232 return false;
233 }
234}
235
236template<typename T>
237 requires std::is_pointer_v<T>
238inline bool SdlNativeData::set(const std::size_t elementIdx, T const ptr) const
239{
240 PH_ASSERT(m_elementSetter);
241
242 using PtrRemovedT = std::remove_pointer_t<T>;
243
244 if constexpr(CSdlInstance<PtrRemovedT>)
245 {
246 return m_elementSetter(elementIdx, SdlNonConstInstance(ptr));
247 }
248 else
249 {
250 return m_elementSetter(elementIdx, AnyNonConstPtr(ptr));
251 }
252}
253
254template<typename T>
255 requires std::is_null_pointer_v<T>
256inline bool SdlNativeData::set(std::size_t elementIdx, T /* nullPtr */) const
257{
258 return m_elementSetter(elementIdx, std::monostate{});
259}
260
261template<typename T>
263{
264 return m_directPtr.get<T>();
265}
266
268{
269 m_directPtr = accessor;
270}
271
273{
274 switch(elementType)
275 {
286 return true;
287
288 default:
289 return false;
290 }
291}
292
294{
295 switch(elementType)
296 {
299 return true;
300
301 default:
302 return false;
303 }
304}
305
306inline SdlNativeData::operator bool () const
307{
308 return numElements > 0;
309}
310
311template<typename ElementType>
312inline auto SdlNativeData::permissiveElementGetter(ElementType* const elementPtr)
314{
315 PH_ASSERT(elementPtr);
316
317 if constexpr(std::is_arithmetic_v<ElementType> || std::is_enum_v<ElementType>)
318 {
319 const auto elementValue = *elementPtr;
320 if constexpr(std::is_integral_v<ElementType> || std::is_enum_v<ElementType>)
321 {
322 // `int64` may not be able to hold all values (e.g., `uint64` or large enum types),
323 // we `static_cast` anyway since user should instead use direct access if this from of
324 // data exchange is unsatisfactory
325 return static_cast<int64>(elementValue);
326 }
327 else if constexpr(std::is_floating_point_v<ElementType>)
328 {
329 // `float64` should be able to hold any floating point value
330 return static_cast<float64>(elementValue);
331 }
332 else
333 {
334 PH_STATIC_ASSERT_DEPENDENT_FALSE(ElementType,
335 "Unsupported element value type.");
336 }
337 }
338 else if constexpr(CSdlInstance<ElementType>)
339 {
340 return SdlConstInstance(elementPtr);
341 }
342 else
343 {
344 return AnyConstPtr(elementPtr);
345 }
346}
347
348template<typename ElementType>
349inline auto SdlNativeData::permissiveElementSetter(SdlSetterVariant input, ElementType* const out_elementPtr)
350-> bool
351{
352 PH_ASSERT(out_elementPtr);
353
354 if constexpr(std::is_arithmetic_v<ElementType> || std::is_enum_v<ElementType>)
355 {
356 // `ElementType` may not be able to hold all values passed in via `input` (e.g., `ElementType`
357 // being `char`), we `static_cast` anyway since user should instead use direct access if this
358 // from of data exchange is unsatisfactory
359 switch(input.index())
360 {
361 case 1:
362 *out_elementPtr = static_cast<ElementType>(input.get<int64>());
363 return true;
364
365 case 2:
366 *out_elementPtr = static_cast<ElementType>(input.get<float64>());
367 return true;
368
369 default:
370 return false;
371 }
372 }
373 else if constexpr(CSdlInstance<ElementType>)
374 {
375 ElementType* const inputPtr = input.has<SdlNonConstInstance>()
376 ? input.get<SdlNonConstInstance>().get<ElementType>() : nullptr;
377 if(inputPtr)
378 {
379 *out_elementPtr = *inputPtr;
380 return true;
381 }
382 else
383 {
384 return false;
385 }
386 }
387 else
388 {
389 ElementType* const inputPtr = input.has<AnyNonConstPtr>()
390 ? input.get<AnyNonConstPtr>().get<ElementType>() : nullptr;
391 if(inputPtr)
392 {
393 *out_elementPtr = *inputPtr;
394 return true;
395 }
396 else
397 {
398 return false;
399 }
400 }
401}
402
403}// end namespace ph
Definition SdlNativeData.h:88
static auto permissiveElementSetter(SdlSetterVariant input, ElementType *out_elementPtr) -> bool
Given a valid target element, set its value in a permissive way (with auto conversions).
Definition SdlNativeData.ipp:349
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
T * directAccess() const
Directly access the underlying data. Use of direct accessor may invalidate getter and setter accessor...
Definition SdlNativeData.ipp:262
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
bool set(std::size_t elementIdx, T value) const
Definition SdlNativeData.ipp:218
std::optional< T > get(std::size_t elementIdx) const
Definition SdlNativeData.ipp:182
ESdlDataFormat elementContainer
Hint for the type that encapsulates elements.
Definition SdlNativeData.h:109
bool isFloatingPointElement() const
Definition SdlNativeData.ipp:293
SdlNativeData()
Creates empty native data.
Definition SdlNativeData.ipp:146
static SdlNativeData fromSingleElement(ElementType *elementPtr, ESdlDataFormat elementContainer, ESdlDataType elementType, bool canSet=false, bool canDirectAccess=false)
Creates native data for a single element pointer.
Definition SdlNativeData.ipp:86
bool isIntegerElement() const
Definition SdlNativeData.ipp:272
auto * get() const
Definition TAnyPtr.h:72
Definition SdlNativeData.h:24
Variant VariantType
Definition SdlNativeData.h:26
T & get()
Definition SdlNativeData.ipp:38
auto getVariant() -> VariantType &
Definition SdlNativeData.ipp:72
bool has() const
Definition SdlNativeData.ipp:31
TSdlAccessorVariant()
Definition SdlNativeData.ipp:14
bool isEmpty() const
Definition SdlNativeData.ipp:66
void set(T value)
Definition SdlNativeData.ipp:54
std::size_t index() const
Definition SdlNativeData.ipp:60
References a SDL object. This is a lightweight utility for referencing SDL objects....
Definition TSdlAnyInstance.h:20
auto * get() const
Definition TSdlAnyInstance.ipp:82
Definition TFunction.h:23
Definition sdl_traits.h:55
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
TAnyPtr< true > AnyConstPtr
A type-safe, lightweight wrapper for any const raw pointer type.
Definition TAnyPtr.h:43
TSdlAnyInstance< true > SdlConstInstance
Definition sdl_fwd.h:33
ESdlDataFormat
Format of the data used by SDL. Each listed data format tells how a group of data is arranged interna...
Definition ESdlDataFormat.h:13
ESdlDataType
Common data types used by SDL. Each listed data type has some form of one to one mapping to a specifi...
Definition ESdlDataType.h:13
TSdlAnyInstance< false > SdlNonConstInstance
Definition sdl_fwd.h:34
Definition TAABB2D.h:96