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