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