1 #include "run/VirtualSettings.h"
2
3 NAMESPACE_SPH_BEGIN
4
5 namespace Detail {
6
7 template <typename T, typename = void>
8 class UnitAdapter {
9 public:
get(const T & input,const Float mult)10 INLINE const T& get(const T& input, const Float mult) const {
11 SPH_ASSERT(mult == 1._f, "Units not implemented for entries other than float or vector");
12 return input;
13 }
14
set(const T & input,const Float mult)15 INLINE const T& set(const T& input, const Float mult) const {
16 SPH_ASSERT(mult == 1._f, "Units not implemented for entries other than float or vector");
17 return input;
18 }
19 };
20
21 template <typename T>
22 class UnitAdapter<T, std::enable_if_t<std::is_same<T, Float>::value || std::is_same<T, Vector>::value>> {
23 public:
get(const T & input,const Float mult)24 INLINE T get(const T& input, const Float mult) const {
25 return input / mult;
26 }
27
set(const T & input,const Float mult)28 INLINE T set(const T& input, const Float mult) const {
29 return input * mult;
30 }
31 };
32
33 } // namespace Detail
34
addEntry(const String & key,AutoPtr<IVirtualEntry> && entry)35 inline void VirtualSettings::Category::addEntry(const String& key, AutoPtr<IVirtualEntry>&& entry) {
36 entries.insert(key, std::move(entry));
37 }
38
39 namespace Detail {
40
41 template <typename TValue, typename = void>
42 class ValueEntry : public EntryControl {
43 private:
44 TValue& ref;
45 String name;
46
47 public:
ValueEntry(TValue & ref,const String & name)48 ValueEntry(TValue& ref, const String& name)
49 : ref(ref)
50 , name(name) {}
51
setImpl(const Value & value)52 virtual void setImpl(const Value& value) override {
53 UnitAdapter<TValue> adapter;
54 ref = adapter.set(value.get<TValue>(), mult);
55 }
56
get()57 virtual Value get() const override {
58 UnitAdapter<TValue> adapter;
59 return adapter.get(ref, mult);
60 }
61
getType()62 virtual Type getType() const override {
63 // path has to be included to get correct index of EnumWrapper
64 return Type(
65 getTypeIndex<TValue, bool, int, Float, Vector, Interval, String, Path, EnumWrapper, ExtraEntry>);
66 }
67
getName()68 virtual String getName() const override {
69 return name;
70 }
71 };
72
73 template <typename TValue>
74 class ValueEntry<TValue, std::enable_if_t<FlagsTraits<TValue>::isFlags>> : public EntryControl {
75 private:
76 TValue& ref;
77 String name;
78
79 using TEnum = typename FlagsTraits<TValue>::Type;
80
81 public:
ValueEntry(TValue & ref,const String & name)82 ValueEntry(TValue& ref, const String& name)
83 : ref(ref)
84 , name(name) {}
85
setImpl(const Value & value)86 virtual void setImpl(const Value& value) override {
87 ref = TValue::fromValue(value.get<EnumWrapper>().value);
88 }
89
get()90 virtual Value get() const override {
91 return EnumWrapper(TEnum(ref.value()));
92 }
93
getType()94 virtual Type getType() const override {
95 return Type::FLAGS;
96 }
97
getName()98 virtual String getName() const override {
99 return name;
100 }
101 };
102
103 } // namespace Detail
104
105 template <typename TValue>
connect(const String & name,const String & key,TValue & value)106 inline EntryControl& VirtualSettings::Category::connect(const String& name,
107 const String& key,
108 TValue& value) {
109 auto entry = makeAuto<Detail::ValueEntry<TValue>>(value, name);
110 EntryControl& control = *entry;
111 entries.insert(key, std::move(entry));
112 return control;
113 }
114
115
116 namespace Detail {
117
118 template <typename TEnum>
makeTooltip(const TEnum id)119 inline String makeTooltip(const TEnum id) {
120 Optional<String> key = Settings<TEnum>::getEntryName(id);
121 Optional<int> type = Settings<TEnum>::getEntryType(id);
122 String scriptTooltip;
123 if (key) {
124 String typeName = Settings<TEnum>::typeToString(type.value());
125 scriptTooltip = "Script name: " + key.value() + " (" + typeName + ")";
126 }
127
128 Optional<String> desc = Settings<TEnum>::getEntryDesc(id);
129 if (desc) {
130 String tooltip = desc.value();
131 if (key) {
132 tooltip += "\n\n" + scriptTooltip;
133 }
134 return tooltip;
135 } else {
136 return scriptTooltip;
137 }
138 }
139
140 template <typename TValue, typename TEnum, typename TEnabler = void>
141 class SettingsEntry : public EntryControl {
142 private:
143 Settings<TEnum>& settings;
144 String name;
145 TEnum id;
146
147 public:
SettingsEntry(Settings<TEnum> & settings,const TEnum id,const String & name)148 SettingsEntry(Settings<TEnum>& settings, const TEnum id, const String& name)
149 : settings(settings)
150 , name(name)
151 , id(id) {
152 tooltip = makeTooltip(id);
153 }
154
setImpl(const Value & value)155 virtual void setImpl(const Value& value) override {
156 UnitAdapter<TValue> adapter;
157 settings.set(id, adapter.set(value.get<TValue>(), mult));
158 }
159
get()160 virtual Value get() const override {
161 UnitAdapter<TValue> adapter;
162 return adapter.get(settings.template get<TValue>(id), mult);
163 }
164
getType()165 virtual Type getType() const override {
166 return Type(getTypeIndex<TValue, bool, int, Float, Vector, Interval, String, Path, EnumWrapper>);
167 }
168
getName()169 virtual String getName() const override {
170 return name;
171 }
172 };
173
174 /// Partial specialization for Flags
175 template <typename TValue, typename TEnum>
176 class SettingsEntry<TValue, TEnum, std::enable_if_t<FlagsTraits<TValue>::isFlags>> : public EntryControl {
177 private:
178 Settings<TEnum>& settings;
179 String name;
180 TEnum id;
181
182 public:
SettingsEntry(Settings<TEnum> & settings,const TEnum id,const String & name)183 SettingsEntry(Settings<TEnum>& settings, const TEnum id, const String& name)
184 : settings(settings)
185 , name(name)
186 , id(id) {
187 tooltip = makeTooltip(id);
188 }
189
setImpl(const Value & value)190 virtual void setImpl(const Value& value) override {
191 settings.set(id, value.get<EnumWrapper>());
192 }
193
get()194 virtual Value get() const override {
195 return settings.template get<EnumWrapper>(id);
196 }
197
getType()198 virtual Type getType() const override {
199 return Type::FLAGS;
200 }
201
getName()202 virtual String getName() const override {
203 return name;
204 }
205 };
206
207 /// Partial specialization for Path
208 template <typename TEnum>
209 class SettingsEntry<Path, TEnum> : public EntryControl {
210 private:
211 Settings<TEnum>& settings;
212 String name;
213 TEnum id;
214
215 public:
SettingsEntry(Settings<TEnum> & settings,const TEnum id,const String & name)216 SettingsEntry(Settings<TEnum>& settings, const TEnum id, const String& name)
217 : settings(settings)
218 , name(name)
219 , id(id) {
220 tooltip = makeTooltip(id);
221 }
222
setImpl(const Value & value)223 virtual void setImpl(const Value& value) override {
224 settings.set(id, value.get<Path>().string());
225 }
226
get()227 virtual Value get() const override {
228 return Path(settings.template get<String>(id));
229 }
230
getType()231 virtual Type getType() const override {
232 return Type::PATH;
233 }
234
getName()235 virtual String getName() const override {
236 return name;
237 }
238 };
239
240
241 } // namespace Detail
242
243 template <typename TValue, typename TEnum>
connect(const String & name,Settings<TEnum> & settings,const TEnum id)244 EntryControl& VirtualSettings::Category::connect(const String& name,
245 Settings<TEnum>& settings,
246 const TEnum id) {
247 const Optional<String> key = Settings<TEnum>::getEntryName(id);
248 if (!key) {
249 throw InvalidSetup("No settings entry with id {}", int(id));
250 }
251 auto entry = makeAuto<Detail::SettingsEntry<TValue, TEnum>>(settings, id, name);
252 EntryControl& control = *entry;
253 entries.insert(key.value(), std::move(entry));
254 return control;
255 }
256
257
258 template <typename TEnum, typename>
set(const TEnum id,const IVirtualEntry::Value & value)259 void VirtualSettings::set(const TEnum id, const IVirtualEntry::Value& value) {
260 const Optional<String> key = Settings<TEnum>::getEntryName(id);
261 if (!key) {
262 throw InvalidSetup("No entry with ID {}", int(id));
263 }
264
265 this->set(key.value(), value);
266 }
267
268 NAMESPACE_SPH_END
269