1 #include "gui/Project.h"
2 #include "objects/utility/Streams.h"
3 #include "run/VirtualSettings.h"
4 
5 NAMESPACE_SPH_BEGIN
6 
Project()7 Project::Project() {
8     gui.set(GuiSettingsId::VIEW_WIDTH, 1024)
9         .set(GuiSettingsId::VIEW_HEIGHT, 768)
10         .set(GuiSettingsId::VIEW_MAX_FRAMERATE, 100)
11         .set(GuiSettingsId::WINDOW_WIDTH, 1600)
12         .set(GuiSettingsId::WINDOW_HEIGHT, 768)
13         .set(GuiSettingsId::PARTICLE_RADIUS, 1._f)
14         .set(GuiSettingsId::SURFACE_RESOLUTION, 1.e2_f)
15         .set(GuiSettingsId::SURFACE_LEVEL, 0.13_f)
16         .set(GuiSettingsId::SURFACE_AMBIENT, 0.1_f)
17         .set(GuiSettingsId::SURFACE_SUN_POSITION, getNormalized(Vector(-0.4f, -0.1f, 0.6f)))
18         .set(GuiSettingsId::RAYTRACE_ITERATION_LIMIT, 10)
19         .set(GuiSettingsId::RAYTRACE_SUBSAMPLING, 4)
20         .set(GuiSettingsId::CAMERA_TYPE, CameraEnum::ORTHO)
21         .set(GuiSettingsId::CAMERA_ORTHO_FOV, 1.e5_f)
22         .set(GuiSettingsId::CAMERA_ORTHO_CUTOFF, 0._f)
23         .set(GuiSettingsId::PLOT_INITIAL_PERIOD, 60._f)
24         .set(GuiSettingsId::PLOT_OVERPLOT_SFD, String("reference_sfd.txt"))
25         .set(GuiSettingsId::PLOT_INTEGRALS,
26             PlotEnum::KINETIC_ENERGY | PlotEnum::TOTAL_ENERGY | PlotEnum::INTERNAL_ENERGY |
27                 PlotEnum::TOTAL_ANGULAR_MOMENTUM | PlotEnum::TOTAL_MOMENTUM);
28 }
29 
save(Config & config)30 void Project::save(Config& config) {
31     this->savePalettes(config);
32     this->saveGui(config);
33 }
34 
load(Config & config)35 void Project::load(Config& config) {
36     this->loadPalettes(config);
37     this->loadGui(config);
38 }
39 
reset()40 void Project::reset(){
41     *this = Project();
42 }
43 
44 template <typename T>
settingsToConfigValue(const T & value)45 INLINE auto settingsToConfigValue(const T& value) {
46     return value;
47 }
48 
49 template <>
settingsToConfigValue(const EnumWrapper & value)50 INLINE auto settingsToConfigValue(const EnumWrapper& value) {
51     return int(value.value);
52 }
53 template <>
settingsToConfigValue(const TracelessTensor & UNUSED (value))54 INLINE auto settingsToConfigValue(const TracelessTensor& UNUSED(value)) {
55     NOT_IMPLEMENTED;
56     return 0;
57 }
58 template <>
settingsToConfigValue(const SymmetricTensor & UNUSED (value))59 INLINE auto settingsToConfigValue(const SymmetricTensor& UNUSED(value)) {
60     NOT_IMPLEMENTED;
61     return 0;
62 }
63 template <>
settingsToConfigValue(const Interval & UNUSED (value))64 INLINE auto settingsToConfigValue(const Interval& UNUSED(value)) {
65     NOT_IMPLEMENTED;
66     return 0;
67 }
68 
69 template <typename TOrig, typename TNew>
configToSettingsValue(const TOrig & UNUSED (original),const TNew & value)70 INLINE auto configToSettingsValue(const TOrig& UNUSED(original), const TNew& value) {
71     return value;
72 }
73 template <>
configToSettingsValue(const EnumWrapper & original,const int & value)74 INLINE auto configToSettingsValue(const EnumWrapper& original, const int& value) {
75     EnumWrapper ew;
76     ew.value = value;
77     ew.index = original.index;
78     return ew;
79 }
80 
81 
saveGui(Config & config)82 void Project::saveGui(Config& config) {
83     SharedPtr<ConfigNode> guiNode = config.addNode("gui");
84     for (const auto& entry : gui) {
85         const Optional<String> key = GuiSettings::getEntryName(entry.id);
86         if (!key) {
87             throw ConfigException("No settings entry with id {}", int(entry.id));
88         }
89         forValue(entry.value, [&guiNode, &key](const auto& value) { //
90             guiNode->set(key.value(), settingsToConfigValue(value));
91         });
92     }
93 }
94 
savePalettes(Config & config)95 void Project::savePalettes(Config& config) {
96     SharedPtr<ConfigNode> paletteParentNode = config.addNode("palettes");
97     for (auto& element : palettes) {
98         SharedPtr<ConfigNode> paletteNode = paletteParentNode->addChild(element.key());
99         const Palette& palette = element.value();
100         paletteNode->set("lower", palette.getInterval().lower());
101         paletteNode->set("upper", palette.getInterval().upper());
102         paletteNode->set("scale", int(palette.getScale()));
103 
104         StringTextOutputStream ss;
105         palette.saveToStream(ss);
106         String data = ss.toString();
107         data.replaceAll("\n", ";");
108         paletteNode->set("data", data);
109     }
110 }
111 
loadGui(Config & config)112 void Project::loadGui(Config& config) {
113     SharedPtr<ConfigNode> guiNode = config.getNode("gui");
114     for (const auto& entry : gui) {
115         const Optional<String> key = GuiSettings::getEntryName(entry.id);
116         if (!key) {
117             throw ConfigException("No settings entry with id {}", int(entry.id));
118         }
119 
120         forValue(entry.value, [this, &guiNode, &key, &entry](auto& value) {
121             using Type = decltype(settingsToConfigValue(value));
122 
123             try {
124                 const Type loadedValue = guiNode->get<Type>(key.value());
125                 gui.set(entry.id, configToSettingsValue(value, loadedValue));
126             } catch (ConfigException& UNUSED(e)) {
127                 /// \todo log the error somewhere - we don't want to bail out here to allow loading older
128                 /// sessions
129             }
130         });
131     }
132 
133     /// \todo more systematic solution
134     Rgba background = gui.get<Rgba>(GuiSettingsId::BACKGROUND_COLOR);
135     background.a() = 1.f;
136     gui.set<Rgba>(GuiSettingsId::BACKGROUND_COLOR, background);
137 
138     if (gui.get<Float>(GuiSettingsId::CAMERA_ORTHO_FOV) == 0._f) {
139         gui.set(GuiSettingsId::CAMERA_ORTHO_FOV, 1.e5_f);
140         gui.set(GuiSettingsId::CAMERA_AUTOSETUP, true);
141     }
142 }
143 
loadPalettes(Config & config)144 void Project::loadPalettes(Config& config) {
145     palettes.clear();
146     SharedPtr<ConfigNode> paletteParentNode = config.getNode("palettes");
147     paletteParentNode->enumerateChildren([this](const String& name, ConfigNode& paletteNode) {
148         const float lower = float(paletteNode.get<Float>("lower"));
149         const float upper = float(paletteNode.get<Float>("upper"));
150         const PaletteScale scale = PaletteScale(paletteNode.get<int>("scale"));
151         Palette palette({ { lower, Rgba::black() }, { upper, Rgba::white() } }, scale);
152 
153         if (paletteNode.contains("data")) {
154             String data = paletteNode.get<String>("data");
155             data.replaceAll(";", "\n");
156             StringTextInputStream ss(data);
157             if (palette.loadFromStream(ss)) {
158                 palettes.insert(name, palette);
159             }
160         } else { // older format, palettes in separate files
161             const String path = paletteNode.get<String>("file");
162             if (palette.loadFromFile(Path(path))) {
163                 palettes.insert(name, palette);
164             }
165         }
166     });
167 }
168 
169 NAMESPACE_SPH_END
170