Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
field_set_op.ipp
Go to the documentation of this file.
1#pragma once
2
6#include "SDL/sdl_helpers.h"
7
8#include <Common/assertion.h>
9
10#include <array>
11#include <utility>
12
13namespace ph::field_set_op
14{
15
16template<
17 typename Owner,
18 typename FieldSet,
19 typename NoticeReceiver,
20 bool SHOULD_NOTIFY_REDUNDANT_CLAUSE>
22 Owner& owner,
23 FieldSet& fieldSet,
24 SdlInputClauses& clauses,
25 const SdlInputContext& ctx,
26 NoticeReceiver noticeReceiver)
27{
28 // Consider to increase the number if not enough
29 constexpr std::size_t MAX_FIELD_FLAGS = 64;
30 PH_ASSERT_GE(MAX_FIELD_FLAGS, fieldSet.numFields());
31
32 // Zero initialization performed on array elements (defaults to false)
33 std::array<bool, MAX_FIELD_FLAGS> isFieldTouched{};
34
35 // For each clause, load them into matching field
36 for(std::size_t clauseIdx = 0; clauseIdx < clauses.size();)
37 {
38 // TODO: check isFieldTouched and warn on duplicating clauses?
39
40 const auto& clause = clauses[clauseIdx];
41 const auto& fieldIdx = fieldSet.findFieldIndex(clause.type, clause.name);
42 if(fieldIdx)
43 {
44 const auto& field = fieldSet[fieldIdx.value()];
45 field.fromSdl(owner, clause, ctx);
46
47 isFieldTouched[fieldIdx.value()] = true;
48
49 // Consume the clause once a match is found; no need to increment
50 // <clauseIdx> since a new one will fill the empty slot
51 clauses.consumeBySwapPop(clauseIdx);
52 }
53 else
54 {
55 if constexpr(SHOULD_NOTIFY_REDUNDANT_CLAUSE)
56 {
57 // Treat a redundant clause input as an optional field
58 noticeReceiver(
59 "no matching field for input clause <" + clause.genPrettyName() + "> "
60 "(" + ctx.genPrettySrcInfo() + "), ignoring",
62 }
63
64 // No match is found, skip to next clause
65 ++clauseIdx;
66 }
67 }
68
69 // Check and process uninitialized fields
70 for(std::size_t fieldIdx = 0; fieldIdx < fieldSet.numFields(); ++fieldIdx)
71 {
72 if(!isFieldTouched[fieldIdx])
73 {
74 const auto& field = fieldSet[fieldIdx];
75 const auto importance = field.getImportance();
76 if(field.isFallbackEnabled())
77 {
78 field.ownedValueToDefault(owner);
79
80 // Only optional field will be silently set to default
81 // (emit notice for other importance levels)
82 if(importance != EFieldImportance::Optional)
83 {
84 noticeReceiver(
85 "no clause for field <" + sdl::gen_pretty_name(&field) + "> "
86 "(" + ctx.genPrettySrcInfo() + "), default to "
87 "<" + field.valueToString(owner) + ">",
88 importance);
89 }
90 }
91 else
92 {
93 // For importance levels other than optional, uninitialized field is an error
94 if(importance != EFieldImportance::Optional)
95 {
96 throw SdlLoadError(
97 "a clause for value <" + field.genPrettyName() + "> is required");
98 }
99 }
100
101 // TODO: util for generating class + field info string
102 }
103 }
104}
105
106template<
107 typename Owner,
108 typename FieldSet,
109 typename NoticeReceiver>
111 Owner& owner,
112 FieldSet& fieldSet,
113 SdlInputClauses& clauses,
114 const SdlInputContext& ctx,
115 NoticeReceiver noticeReceiver)
116{
118 owner,
119 fieldSet,
120 clauses,
121 ctx,
122 std::move(noticeReceiver));
123}
124
125}// end namespace ph::field_set_op
std::string genPrettySrcInfo() const
Definition SdlIOContext.cpp:8
Container for input clauses.
Definition SdlInputClauses.h:18
std::size_t size() const
Get number of clauses.
Definition SdlInputClauses.h:110
void consumeBySwapPop(std::size_t index)
Remove a clause by index. Does not preserve the order of remaining clauses.
Definition SdlInputClauses.h:94
Data that SDL input process can rely on.
Definition SdlInputContext.h:19
Error on the SDL input process.
Definition sdl_exceptions.h:22
Definition field_set_op.h:10
void load_fields_from_sdl(Owner &owner, FieldSet &fieldSet, SdlInputClauses &clauses, const SdlInputContext &ctx, NoticeReceiver noticeReceiver=NoOpNoticeReceiver())
Definition field_set_op.ipp:21
void load_fields_from_sdl_with_redundant_clauses(Owner &owner, FieldSet &fieldSet, SdlInputClauses &clauses, const SdlInputContext &ctx, NoticeReceiver noticeReceiver=NoOpNoticeReceiver())
Definition field_set_op.ipp:110
std::string gen_pretty_name(const SdlClass *const clazz)
Generate a human-readable name for the SDL types. These helpers allow input types to be null.
Definition sdl_helpers.cpp:24
Low-level helpers for SDL. Helpers are in an additional sdl namespace.