1 /*
2  * CRRCsim - the Charles River Radio Control Club Flight Simulator Project
3  *
4  * Copyright (C) 2005, 2006, 2008 Jens Wilhelm Wulf (original author)
5  * Copyright (C) 2008 Jan Reucker
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2
9  * as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  */
22 
23 
24 // implementation of class CGUIWindThermalDialog
25 //
26 #include "../i18n.h"
27 #include "crrc_windthermal.h"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 
32 #include "util.h"
33 #include "../crrc_main.h"
34 #include "../global.h"
35 #include "../mod_misc/lib_conversions.h"
36 #include "../mod_misc/SimpleXMLTransfer.h"
37 #include "../mod_windfield/windfield.h"
38 #include "../mod_landscape/crrc_scenery.h"
39 
40 static void CGUIWindThermalCallback(puObject *obj);
41 static void CGUIWindPresetCallback(puObject *obj);
42 static void CGUIThermalPresetCallback(puObject *obj);
43 static void CGUIWindNewPresetCallback(puObject *obj);
44 static void CGUIThermalNewPresetCallback(puObject *obj);
45 
46 #define BUTTON_BOX_HEIGHT   (2*DLG_DEF_SPACE+DLG_DEF_BUTTON_HEIGHT)
47 #define SLIDER_W            330
48 #define SLIDER_H            DLG_DEF_BUTTON_HEIGHT
49 #define COMBO_W             330
50 #define COMBO_H             DLG_DEF_BUTTON_HEIGHT
51 #define LABEL_W             250
52 #define NUM_W               100
53 
CGUIWindThermalDialog()54 CGUIWindThermalDialog::CGUIWindThermalDialog()
55   : CRRCDialog()
56 {
57   SimpleXMLTransfer* thermaldata = cfg->getCurLocCfgPtr(cfgfile)->getChild("thermal");
58   if (thermaldata->indexOfChild("v3") < 0)
59   {
60     thermalv3data = 0;
61     std::cout << "Current thermal model is v1\n";
62   }
63   else
64   {
65     thermalv3data = thermaldata->getChild("v3");
66     std::cout << "Current thermal model is v3\n";
67   }
68 
69   // Load presets
70   presetGrpWind    = cfgfile->getChild("presets.wind", true);
71   presetsWind      = T_GUI_Util::loadnames(presetGrpWind, nPresetsWind);
72 
73   presetGrpThermal = cfgfile->getChild("presets.thermal", true);
74   presetsThermal   = T_GUI_Util::loadnames(presetGrpThermal, nPresetsThermal);
75 
76   // Create widgets
77   //
78   comboPresetsWind = new puaComboBox(LABEL_W + DLG_DEF_SPACE, BUTTON_BOX_HEIGHT + 13* DLG_DEF_SPACE + 12* SLIDER_H + 1*COMBO_H,
79                                      LABEL_W + COMBO_W,       BUTTON_BOX_HEIGHT + 13* DLG_DEF_SPACE + 12* SLIDER_H + 2*COMBO_H,
80                                      NULL, false);
81   comboPresetsWind->setChildColourScheme(PUCLASS_POPUPMENU, dlgCol1[0], dlgCol1[1], dlgCol1[2]);
82   comboPresetsWind->newList(presetsWind);
83   comboPresetsWind->setLabelPlace(PUPLACE_CENTERED_LEFT);
84   comboPresetsWind->setLabel(_("Load Preset"));
85   comboPresetsWind->setCurrentItem(0);
86   comboPresetsWind->setCallback(CGUIWindPresetCallback);
87   comboPresetsWind->reveal();
88   comboPresetsWind->activate();
89   comboPresetsWind->setUserData(this);
90 
91   slider_windVelocity = new crrcSlider(LABEL_W + DLG_DEF_SPACE,            BUTTON_BOX_HEIGHT + 12* DLG_DEF_SPACE + 11* SLIDER_H + 1*COMBO_H,
92                                        LABEL_W + DLG_DEF_SPACE + SLIDER_W, BUTTON_BOX_HEIGHT + 12* DLG_DEF_SPACE + 12* SLIDER_H + 1*COMBO_H,
93                                        NUM_W);
94   slider_windVelocity->setLabelPlace(PUPLACE_CENTERED_LEFT);
95   slider_windVelocity->setLabel(_("Velocity [ft/s]"));
96   slider_windVelocity->setSliderFraction(0.05);
97   slider_windVelocity->setMinValue(0);
98   slider_windVelocity->setMaxValue(80);
99   slider_windVelocity->setStepSize(1);
100   slider_windVelocity->setValue(cfg->wind->getVelocity());
101 
102   slider_windDir = new crrcSlider(LABEL_W + DLG_DEF_SPACE,            BUTTON_BOX_HEIGHT + 11* DLG_DEF_SPACE + 10* SLIDER_H + 1*COMBO_H,
103                                   LABEL_W + DLG_DEF_SPACE + SLIDER_W, BUTTON_BOX_HEIGHT + 11* DLG_DEF_SPACE + 11* SLIDER_H + 1*COMBO_H,
104                                   NUM_W);
105   slider_windDir->setLabelPlace(PUPLACE_CENTERED_LEFT);
106   slider_windDir->setLabel(_("Direction"));
107   slider_windDir->setSliderFraction(0.05);
108   slider_windDir->setMinValue(0);
109   slider_windDir->setMaxValue(359);
110   slider_windDir->setStepSize(1);
111   slider_windDir->setValue(cfg->wind->getDirection());
112   //if direction imposed on scenery file description invalidate wind slider :
113   if( Global::scenery->getImposeWindDirection() ) slider_windDir->greyOut();
114 
115   // Use turbulence model check box
116   slider_windTurbulence = new crrcSlider(LABEL_W + DLG_DEF_SPACE,            BUTTON_BOX_HEIGHT + 10* DLG_DEF_SPACE +  9* SLIDER_H + 1*COMBO_H,
117                                          LABEL_W + DLG_DEF_SPACE + SLIDER_W, BUTTON_BOX_HEIGHT + 10* DLG_DEF_SPACE + 10* SLIDER_H + 1*COMBO_H,
118                                          NUM_W);
119   slider_windTurbulence->setLabelPlace(PUPLACE_CENTERED_LEFT);
120   slider_windTurbulence->setLabel(_("Turbulence intensity [rel]"));
121   slider_windTurbulence->setSliderFraction(0.05);
122   slider_windTurbulence->setMinValue(0);
123   slider_windTurbulence->setMaxValue(2);
124   slider_windTurbulence->setStepSize(0.2);
125   slider_windTurbulence->setValue(cfg->wind->getTurbulence());
126 
127   inputNewWind = new puInput(DLG_DEF_SPACE,           BUTTON_BOX_HEIGHT + 9* DLG_DEF_SPACE + 8* SLIDER_H + 1*COMBO_H,
128                              LABEL_W + DLG_DEF_SPACE, BUTTON_BOX_HEIGHT + 9* DLG_DEF_SPACE + 9* SLIDER_H + 1*COMBO_H);
129   inputNewWind->setValue(_("Name of new preset"));
130 
131   puOneShot* buttonTmp = new puOneShot(LABEL_W + DLG_DEF_SPACE, BUTTON_BOX_HEIGHT + 9* DLG_DEF_SPACE + 8* SLIDER_H + 1*COMBO_H,
132                                        LABEL_W + COMBO_W,       BUTTON_BOX_HEIGHT + 9* DLG_DEF_SPACE + 9* SLIDER_H + 1*COMBO_H);
133   buttonTmp->setLegend(_("Save as new preset"));
134   buttonTmp->setCallback(CGUIWindNewPresetCallback);
135   buttonTmp->setUserData(this);
136 
137   comboPresetsThermal = new puaComboBox(LABEL_W + DLG_DEF_SPACE, BUTTON_BOX_HEIGHT + 8* DLG_DEF_SPACE + 8* SLIDER_H + 0*COMBO_H,
138                                        LABEL_W + COMBO_W,       BUTTON_BOX_HEIGHT + 8* DLG_DEF_SPACE + 8* SLIDER_H + 1*COMBO_H,
139                                        NULL, false);
140   comboPresetsThermal->setChildColourScheme(PUCLASS_POPUPMENU, dlgCol1[0], dlgCol1[1], dlgCol1[2]);
141   comboPresetsThermal->newList(presetsThermal);
142   comboPresetsThermal->setLabelPlace(PUPLACE_CENTERED_LEFT);
143   comboPresetsThermal->setLabel(_("Load Preset"));
144   comboPresetsThermal->setCurrentItem(0);
145   comboPresetsThermal->setCallback(CGUIThermalPresetCallback);
146   comboPresetsThermal->reveal();
147   comboPresetsThermal->activate();
148   comboPresetsThermal->setUserData(this);
149 
150   slider_thermalStrengthMean = new crrcSlider(LABEL_W + DLG_DEF_SPACE,            BUTTON_BOX_HEIGHT + 7* DLG_DEF_SPACE + 7* SLIDER_H,
151                                               LABEL_W + DLG_DEF_SPACE + SLIDER_W, BUTTON_BOX_HEIGHT + 7* DLG_DEF_SPACE + 8* SLIDER_H,
152                                               NUM_W);
153   slider_thermalStrengthMean->setLabelPlace(PUPLACE_CENTERED_LEFT);
154   slider_thermalStrengthMean->setLabel(_("Strength mean [ft/s]"));
155   slider_thermalStrengthMean->setSliderFraction(0.05);
156   slider_thermalStrengthMean->setMinValue(0);
157   slider_thermalStrengthMean->setMaxValue(30);
158   slider_thermalStrengthMean->setStepSize(0.5);
159   slider_thermalStrengthMean->setValue((float)(thermaldata->getDouble("strength_mean")));
160 
161   slider_thermalStrengthSigma = new crrcSlider(LABEL_W + DLG_DEF_SPACE,            BUTTON_BOX_HEIGHT + 6* DLG_DEF_SPACE + 6* SLIDER_H,
162                                                LABEL_W + DLG_DEF_SPACE + SLIDER_W, BUTTON_BOX_HEIGHT + 6* DLG_DEF_SPACE + 7* SLIDER_H,
163                                                NUM_W);
164   slider_thermalStrengthSigma->setLabelPlace(PUPLACE_CENTERED_LEFT);
165   slider_thermalStrengthSigma->setLabel(_("Strength sigma"));
166   slider_thermalStrengthSigma->setSliderFraction(0.05);
167   slider_thermalStrengthSigma->setMinValue(0);
168   slider_thermalStrengthSigma->setMaxValue(15);
169   slider_thermalStrengthSigma->setStepSize(0.2);
170   slider_thermalStrengthSigma->setValue((float)(thermaldata->getDouble("strength_sigma")));
171 
172   slider_thermalRadiusMean = new crrcSlider(LABEL_W + DLG_DEF_SPACE,            BUTTON_BOX_HEIGHT + 5* DLG_DEF_SPACE + 5* SLIDER_H,
173                                             LABEL_W + DLG_DEF_SPACE + SLIDER_W, BUTTON_BOX_HEIGHT + 5* DLG_DEF_SPACE + 6* SLIDER_H,
174                                             NUM_W);
175   slider_thermalRadiusMean->setLabelPlace(PUPLACE_CENTERED_LEFT);
176   slider_thermalRadiusMean->setLabel(_("Radius mean [ft]"));
177   slider_thermalRadiusMean->setSliderFraction(0.05);
178   slider_thermalRadiusMean->setMinValue(0);
179   slider_thermalRadiusMean->setMaxValue(200);
180   slider_thermalRadiusMean->setStepSize(1);
181   slider_thermalRadiusMean->setValue((float)(thermaldata->getDouble("radius_mean")));
182 
183   slider_thermalRadiusSigma = new crrcSlider(LABEL_W + DLG_DEF_SPACE,            BUTTON_BOX_HEIGHT + 4* DLG_DEF_SPACE + 4* SLIDER_H,
184                                              LABEL_W + DLG_DEF_SPACE + SLIDER_W, BUTTON_BOX_HEIGHT + 4* DLG_DEF_SPACE + 5* SLIDER_H,
185                                              NUM_W);
186   slider_thermalRadiusSigma->setLabelPlace(PUPLACE_CENTERED_LEFT);
187   slider_thermalRadiusSigma->setLabel(_("Radius sigma"));
188   slider_thermalRadiusSigma->setSliderFraction(0.05);
189   slider_thermalRadiusSigma->setMinValue(0);
190   slider_thermalRadiusSigma->setMaxValue(150);
191   slider_thermalRadiusSigma->setStepSize(0.5);
192   slider_thermalRadiusSigma->setValue((float)(thermaldata->getDouble("radius_sigma")));
193 
194   slider_thermalLifetimeMean = new crrcSlider(LABEL_W + DLG_DEF_SPACE,            BUTTON_BOX_HEIGHT + 3* DLG_DEF_SPACE + 3* SLIDER_H,
195                                               LABEL_W + DLG_DEF_SPACE + SLIDER_W, BUTTON_BOX_HEIGHT + 3* DLG_DEF_SPACE + 4* SLIDER_H,
196                                               NUM_W);
197   slider_thermalLifetimeMean->setLabelPlace(PUPLACE_CENTERED_LEFT);
198   slider_thermalLifetimeMean->setLabel(_("Lifetime mean [seconds]"));
199   slider_thermalLifetimeMean->setSliderFraction(0.05);
200   slider_thermalLifetimeMean->setMinValue(0);
201   slider_thermalLifetimeMean->setMaxValue(300);
202   slider_thermalLifetimeMean->setStepSize(1);
203   slider_thermalLifetimeMean->setValue((float)(thermaldata->getDouble("lifetime_mean")));
204 
205   slider_thermalLifetimeSigma = new crrcSlider(LABEL_W + DLG_DEF_SPACE,            BUTTON_BOX_HEIGHT + 2* DLG_DEF_SPACE + 2* SLIDER_H,
206                                                LABEL_W + DLG_DEF_SPACE + SLIDER_W, BUTTON_BOX_HEIGHT + 2* DLG_DEF_SPACE + 3* SLIDER_H,
207                                                NUM_W);
208   slider_thermalLifetimeSigma->setLabelPlace(PUPLACE_CENTERED_LEFT);
209   slider_thermalLifetimeSigma->setLabel(_("Lifetime sigma"));
210   slider_thermalLifetimeSigma->setSliderFraction(0.05);
211   slider_thermalLifetimeSigma->setMinValue(0);
212   slider_thermalLifetimeSigma->setMaxValue(300);
213   slider_thermalLifetimeSigma->setStepSize(1);
214   slider_thermalLifetimeSigma->setValue((float)(thermaldata->getDouble("lifetime_sigma")));
215 
216   slider_thermalDensity = new crrcSlider(LABEL_W + DLG_DEF_SPACE,            BUTTON_BOX_HEIGHT + 1* DLG_DEF_SPACE + 1* SLIDER_H,
217                                          LABEL_W + DLG_DEF_SPACE + SLIDER_W, BUTTON_BOX_HEIGHT + 1* DLG_DEF_SPACE + 2* SLIDER_H,
218                                          NUM_W);
219   slider_thermalDensity->setLabelPlace(PUPLACE_CENTERED_LEFT);
220   slider_thermalDensity->setLabel(_("Density [1/sq foot]"));
221   slider_thermalDensity->setSliderFraction(0.05);
222   slider_thermalDensity->setMinValue(0);
223   slider_thermalDensity->setMaxValue(getMaxThermalDensity());
224   slider_thermalDensity->setStepSize(2.0E-7);
225   slider_thermalDensity->setValue((float)(thermaldata->getDouble("density")));
226 
227   inputNewThermal = new puInput(DLG_DEF_SPACE,           BUTTON_BOX_HEIGHT + 0* DLG_DEF_SPACE + 0* SLIDER_H + 0*COMBO_H,
228                                 LABEL_W + DLG_DEF_SPACE, BUTTON_BOX_HEIGHT + 0* DLG_DEF_SPACE + 1* SLIDER_H + 0*COMBO_H);
229   inputNewThermal->setValue(_("Name of new preset"));
230 
231   buttonTmp = new puOneShot(LABEL_W + DLG_DEF_SPACE, BUTTON_BOX_HEIGHT + 0* DLG_DEF_SPACE + 0* SLIDER_H + 0*COMBO_H,
232                             LABEL_W + COMBO_W,       BUTTON_BOX_HEIGHT + 0* DLG_DEF_SPACE + 1* SLIDER_H + 0*COMBO_H);
233   buttonTmp->setLegend(_("Save as new preset"));
234   buttonTmp->setCallback(CGUIThermalNewPresetCallback);
235   buttonTmp->setUserData(this);
236 
237   // finalize the dialog
238   close();
239   setSize(SLIDER_W + LABEL_W + 2*DLG_DEF_SPACE,
240           12*SLIDER_H + 14*DLG_DEF_SPACE + 2*COMBO_H + BUTTON_BOX_HEIGHT);
241   setCallback(CGUIWindThermalCallback);
242   centerOnScreen();
243   reveal();
244 }
245 
246 /**
247  * Destroy the dialog.
248  */
249 
~CGUIWindThermalDialog()250 CGUIWindThermalDialog::~CGUIWindThermalDialog()
251 {
252   T_GUI_Util::freenames(presetsWind,    nPresetsWind);
253   T_GUI_Util::freenames(presetsThermal, nPresetsThermal);
254 }
255 
256 /** \brief callback to load a preset.
257  *
258  */
CGUIWindPresetCallback(puObject * obj)259 void CGUIWindPresetCallback(puObject *obj)
260 {
261   CGUIWindThermalDialog* dlg   = (CGUIWindThermalDialog*)obj->getUserData();
262   int                    nItem = dlg->comboPresetsWind->getCurrentItem();
263 
264   if (nItem == 0)
265   {
266     dlg->slider_windDir->setValue(270);
267     dlg->slider_windVelocity->setValue(5);
268     dlg->slider_windTurbulence->setValue(1);
269   }
270   else
271   {
272     SimpleXMLTransfer* preset = dlg->presetGrpWind->getChildAt(nItem-1);
273     dlg->slider_windDir->setValue((float)preset->getDouble("direction",270.));
274     dlg->slider_windVelocity->setValue((float)preset->getDouble("velocity",5.));
275     dlg->slider_windTurbulence->setValue((float)preset->getDouble("turbulence",1.));
276   }
277 }
278 
279 /** \brief callback to save a preset.
280  *
281  */
CGUIWindNewPresetCallback(puObject * obj)282 void CGUIWindNewPresetCallback(puObject *obj)
283 {
284   CGUIWindThermalDialog* dlg   = (CGUIWindThermalDialog*)obj->getUserData();
285 
286   SimpleXMLTransfer* wind      = new SimpleXMLTransfer();
287 
288   wind->setName("wind");
289   wind->setAttribute("name_en",    dlg->inputNewWind->getStringValue());
290   wind->setAttribute("velocity",   dlg->slider_windVelocity->getStringValue());
291   wind->setAttribute("direction",  dlg->slider_windDir->getStringValue());
292   wind->setAttribute("turbulence", dlg->slider_windTurbulence->getStringValue());
293 
294   cfgfile->getChild("presets.wind", true)->addChild(wind);
295 
296   // save file
297   options_saveToFile();
298 
299   // exit dialog (otherwise we would have to regenerate presetsWind)
300   dlg->setValue(CRRC_DIALOG_OK);
301   CGUIWindThermalCallback(dlg);
302 }
303 
304 /** \brief callback to save a preset.
305  *
306  */
CGUIThermalNewPresetCallback(puObject * obj)307 void CGUIThermalNewPresetCallback(puObject *obj)
308 {
309   CGUIWindThermalDialog* dlg   = (CGUIWindThermalDialog*)obj->getUserData();
310 
311   SimpleXMLTransfer* thermal   = new SimpleXMLTransfer();
312 
313   thermal->setName("thermal");
314   thermal->setAttribute("name_en",         dlg->inputNewThermal->getStringValue());
315   thermal->setAttribute("strength_mean",   dlg->slider_thermalStrengthMean->getStringValue());
316   thermal->setAttribute("strength_sigma",  dlg->slider_thermalStrengthSigma->getStringValue());
317   thermal->setAttribute("radius_mean",     dlg->slider_thermalRadiusMean->getStringValue());
318   thermal->setAttribute("radius_sigma",    dlg->slider_thermalRadiusSigma->getStringValue());
319   thermal->setAttribute("lifetime_mean",   dlg->slider_thermalLifetimeMean->getStringValue());
320   thermal->setAttribute("lifetime_sigma",  dlg->slider_thermalLifetimeSigma->getStringValue());
321   thermal->setAttribute("density",         dlg->slider_thermalDensity->getStringValue());
322   if (dlg->thermalv3data != 0)
323   {
324     std::cout << "New preset is thermal model v3\n";
325     thermal->addChild(new SimpleXMLTransfer(dlg->thermalv3data));
326   }
327   else
328     std::cout << "New preset is thermal model v1\n";
329 
330   cfgfile->getChild("presets.thermal", true)->addChild(thermal);
331 
332   // show new preset (debug only)
333   cfgfile->getChild("presets.thermal")->print(std::cout, 2);
334 
335   // save file
336   options_saveToFile();
337 
338   // exit dialog (otherwise we would have to regenerate presetsThermal)
339   dlg->setValue(CRRC_DIALOG_OK);
340   CGUIWindThermalCallback(dlg);
341 }
342 
343 /** \brief callback to load a preset.
344  *
345  */
CGUIThermalPresetCallback(puObject * obj)346 void CGUIThermalPresetCallback(puObject *obj)
347 {
348   CGUIWindThermalDialog* dlg   = (CGUIWindThermalDialog*)obj->getUserData();
349   int                    nItem = dlg->comboPresetsThermal->getCurrentItem();
350 
351   if (nItem == 0)
352   {
353     dlg->slider_thermalStrengthMean->setValue(5);
354     dlg->slider_thermalStrengthSigma->setValue(1);
355     dlg->slider_thermalRadiusMean->setValue(50);
356     dlg->slider_thermalRadiusSigma->setValue(10);
357     dlg->slider_thermalLifetimeMean->setValue(240);
358     dlg->slider_thermalLifetimeSigma->setValue(60);
359     dlg->slider_thermalDensity->setValue((float)0.5E-5);
360 
361     // v3-Data is removed, this preset is v1:
362     dlg->thermalv3data = 0;
363   }
364   else
365   {
366     SimpleXMLTransfer* preset = dlg->presetGrpThermal->getChildAt(nItem-1);
367     dlg->slider_thermalStrengthMean->setValue((float)preset->getDouble("strength_mean"));
368     dlg->slider_thermalStrengthSigma->setValue((float)preset->getDouble("strength_sigma"));
369     dlg->slider_thermalRadiusMean->setValue((float)preset->getDouble("radius_mean"));
370     dlg->slider_thermalRadiusSigma->setValue((float)preset->getDouble("radius_sigma"));
371     dlg->slider_thermalLifetimeMean->setValue((float)preset->getDouble("lifetime_mean"));
372     dlg->slider_thermalLifetimeSigma->setValue((float)preset->getDouble("lifetime_sigma"));
373     dlg->slider_thermalDensity->setValue((float)preset->getDouble("density"));
374 
375     if (preset->indexOfChild("v3") < 0)
376     {
377       std::cout << "Chosen preset is thermal model v1\n";
378       dlg->thermalv3data = 0;
379     }
380     else
381     {
382       std::cout << "Chosen preset is thermal model v3\n";
383       dlg->thermalv3data = preset->getChild("v3");
384     }
385   }
386 }
387 
388 /** \brief The dialog's callback.
389  *
390  */
CGUIWindThermalCallback(puObject * obj)391 void CGUIWindThermalCallback(puObject *obj)
392 {
393   if (obj->getIntegerValue() == CRRC_DIALOG_OK)
394   {
395     // Dialog left by clicking OK
396     CGUIWindThermalDialog* dlg   = (CGUIWindThermalDialog*)obj;
397 
398     cfg->wind->setDirection(dlg->slider_windDir->getFloatValue(), cfg);
399     cfg->wind->setVelocity(dlg->slider_windVelocity->getFloatValue());
400     cfg->wind->setTurbulence(dlg->slider_windTurbulence->getFloatValue());
401 
402     SimpleXMLTransfer* thermaldata = cfg->getCurLocCfgPtr(cfgfile)->getChild("thermal");
403     thermaldata->setAttributeOverwrite("strength_mean",  dlg->slider_thermalStrengthMean->getStringValue());
404     thermaldata->setAttributeOverwrite("strength_sigma", dlg->slider_thermalStrengthSigma->getStringValue());
405     thermaldata->setAttributeOverwrite("radius_mean",    dlg->slider_thermalRadiusMean->getStringValue());
406     thermaldata->setAttributeOverwrite("radius_sigma",   dlg->slider_thermalRadiusSigma->getStringValue());
407     thermaldata->setAttributeOverwrite("lifetime_mean",  dlg->slider_thermalLifetimeMean->getStringValue());
408     thermaldata->setAttributeOverwrite("lifetime_sigma", dlg->slider_thermalLifetimeSigma->getStringValue());
409     thermaldata->setAttributeOverwrite("density",        dlg->slider_thermalDensity->getStringValue());
410 
411     // handle v3 data
412     {
413       int n_v3idx = thermaldata->indexOfChild("v3");
414 
415       if (dlg->thermalv3data == 0)
416       {
417         if (n_v3idx >= 0)  // v3 has to be deleted after loading a preset without v3:
418         {
419           std::cout << "Chosen preset is thermal model v1, so v3 data is removed.\n";
420           SimpleXMLTransfer* tmp = thermaldata->getChildAt(n_v3idx);
421           thermaldata->removeChildAt(n_v3idx);
422           delete tmp;
423         }
424       }
425       else
426       {
427         // there is no v3 data yet?
428         if (n_v3idx < 0)
429         {
430           std::cout << "Load data for thermal model v3.\n";
431           thermaldata->addChild(new SimpleXMLTransfer(dlg->thermalv3data));
432         }
433         else
434         {
435           if (dlg->thermalv3data != thermaldata->getChildAt(n_v3idx))
436           {
437             std::cout << "Chosen preset is thermal model v3 and we currently have v3 which differs from chosen preset. Remove current data.\n";
438             SimpleXMLTransfer* tmp = thermaldata->getChildAt(n_v3idx);
439             thermaldata->removeChildAt(n_v3idx);
440             delete tmp;
441 
442             std::cout << "Load data for thermal model v3.\n";
443             thermaldata->addChild(new SimpleXMLTransfer(dlg->thermalv3data));
444           }
445         }
446       }
447     }
448 
449     // Thermals have to be recreated:
450     clear_wind_field();
451     cfg->thermal->read(cfgfile, cfg);
452     Init_mod_windfield();
453   }
454 
455   std::cout.flush();
456 
457   puDeleteObject(obj);
458 }
459