]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/panel_io.cxx
1175b0d7129f10937656babc6cba2408de4a1c21
[flightgear.git] / src / Cockpit / panel_io.cxx
1 //  panel_io.cxx - I/O for 2D panel.
2 //
3 //  Written by David Megginson, started January 2000.
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License as
7 //  published by the Free Software Foundation; either version 2 of the
8 //  License, or (at your option) any later version.
9 // 
10 //  This program is distributed in the hope that it will be useful, but
11 //  WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 //  General Public License for more details.
14 // 
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //
19 //  $Id$
20
21 #ifdef HAVE_CONFIG_H
22 #  include <config.h>
23 #endif
24
25 #ifdef HAVE_WINDOWS_H          
26 #  include <windows.h>
27 #endif
28
29 #include <simgear/compiler.h>
30 #include <simgear/debug/logstream.hxx>
31 #include <simgear/misc/props.hxx>
32
33 #include <iostream>
34 #include <string>
35
36 #include "panel.hxx"
37
38 using std::istream;
39 using std::string;
40
41
42 \f
43 ////////////////////////////////////////////////////////////////////////
44 // Read and construct a panel.
45 ////////////////////////////////////////////////////////////////////////
46
47
48 /**
49  * Read a cropped texture.
50  */
51 static CroppedTexture
52 readTexture (SGPropertyNode node)
53 {
54   CroppedTexture texture(node.getStringValue("path"),
55                          node.getFloatValue("x1"),
56                          node.getFloatValue("y1"),
57                          node.getFloatValue("x2", 1.0),
58                          node.getFloatValue("y2", 1.0));
59   FG_LOG(FG_INPUT, FG_INFO, "Read texture " << node.getName());
60   return texture;
61 }
62
63
64 /**
65  * Read an action.
66  */
67 static FGPanelAction *
68 readAction (SGPropertyNode node)
69 {
70   FGPanelAction * action = 0;
71
72   cerr << "Reading action\n";
73
74   string type = node.getStringValue("type");
75
76   int button = node.getIntValue("button");
77   int x = node.getIntValue("x");
78   int y = node.getIntValue("y");
79   int w = node.getIntValue("w");
80   int h = node.getIntValue("h");
81
82                                 // Adjust a property value
83   if (type == "adjust") {
84     string propName = node.getStringValue("property");
85     SGValue * value = current_properties.getValue(propName, true);
86     float increment = node.getFloatValue("increment", 1.0);
87     float min = node.getFloatValue("min", 0.0);
88     float max = node.getFloatValue("max", 0.0);
89     bool wrap = node.getBoolValue("wrap", false);
90     if (min == max)
91       FG_LOG(FG_INPUT, FG_ALERT, "Action " << node.getName()
92              << " has same min and max value");
93     action = new FGAdjustAction(button, x, y, w, h, value,
94                                 increment, min, max, wrap);
95   } 
96
97                                 // Swap two property values
98   else if (type == "swap") {
99     string propName1 = node.getStringValue("property1");
100     string propName2 = node.getStringValue("property2");
101     SGValue * value1 = current_properties.getValue(propName1, true);
102     SGValue * value2 = current_properties.getValue(propName2, true);
103     action = new FGSwapAction(button, x, y, w, h, value1, value2);
104   } 
105
106                                 // Toggle a boolean value
107   else if (type == "toggle") {
108     string propName = node.getStringValue("property");
109     SGValue * value = current_properties.getValue(propName, true);
110     action = new FGToggleAction(button, x, y, w, h, value);
111   } 
112
113                                 // No type supplied
114   else if (type == "") {
115     FG_LOG(FG_INPUT, FG_ALERT, "No type specified for action "
116            << node.getName());
117     return 0;
118   } 
119
120                                 // Unrecognized type
121   else {
122     FG_LOG(FG_INPUT, FG_ALERT, "Unrecognized action type " << node.getName());
123     return 0;
124   }
125
126   return action;
127 }
128
129
130 /**
131  * Read a single transformation.
132  */
133 static FGPanelTransformation *
134 readTransformation (SGPropertyNode node)
135 {
136   FGPanelTransformation * t = new FGPanelTransformation;
137
138   string name = node.getName();
139   string type = node.getStringValue("type");
140   string propName = node.getStringValue("property", "");
141   SGValue * value = 0;
142
143   if (propName != "") {
144     value = current_properties.getValue(propName, true);
145   }
146
147   t->value = value;
148   t->min = node.getFloatValue("min", 0.0);
149   t->max = node.getFloatValue("max", 1.0);
150   t->factor = node.getFloatValue("factor", 1.0);
151   t->offset = node.getFloatValue("offset", 0.0);
152   if (type == "x-shift") {
153     t->type = FGPanelTransformation::XSHIFT;
154   } else if (type == "y-shift") {
155     t->type = FGPanelTransformation::YSHIFT;
156   } else if (type == "rotation") {
157     t->type = FGPanelTransformation::ROTATION;
158   } else if (type == "") {
159     FG_LOG(FG_INPUT, FG_ALERT,
160            "'type' must be specified for transformation");
161     delete t;
162     return 0;
163   } else {
164     FG_LOG(FG_INPUT, FG_ALERT, "Unrecognized transformation: " << type);
165     delete t;
166     return 0;
167   }
168
169   FG_LOG(FG_INPUT, FG_INFO, "Read transformation " << name);
170   return t;
171 }
172
173
174 /**
175  * Read a single layer of an instrument.
176  */
177 static FGInstrumentLayer *
178 readLayer (SGPropertyNode node)
179 {
180   FGInstrumentLayer * l;
181   string name = node.getName();
182
183   CroppedTexture texture = readTexture(node.getSubNode("texture"));
184   l = new FGTexturedLayer(texture,
185                           node.getIntValue("w", -1),
186                           node.getIntValue("h", -1));
187   
188   //
189   // Get the transformations for each layer.
190   //
191   SGPropertyNode trans_group = node.getSubNode("transformations");
192   int nTransformations = trans_group.size();
193   for (int k = 0; k < nTransformations; k++) {
194     FGPanelTransformation * t = readTransformation(trans_group.getChild(k));
195     if (t == 0) {
196       delete l;
197       return 0;
198     }
199     l->addTransformation(t);
200   }
201   
202   FG_LOG(FG_INPUT, FG_INFO, "Read layer " << name);
203   return l;
204 }
205
206
207 /**
208  * Read an instrument.
209  */
210 static FGPanelInstrument *
211 readInstrument (SGPropertyNode node)
212 {
213   const string &name = node.getStringValue("name");
214
215   FG_LOG(FG_INPUT, FG_INFO, "Reading instrument " << name);
216
217   FGLayeredInstrument * instrument =
218     new FGLayeredInstrument(0, 0,
219                             node.getIntValue("w"),
220                             node.getIntValue("h"));
221
222   //
223   // Get the actions for the instrument.
224   //
225   SGPropertyNode action_group = node.getSubNode("actions");
226   int nActions = action_group.size();
227   cerr << "There are " << nActions << " actions\n";
228   for (int j = 0; j < nActions; j++) {
229     FGPanelAction * action = readAction(action_group.getChild(j));
230     if (action == 0) {
231       delete instrument;
232       return 0;
233     }
234     instrument->addAction(action);
235   }
236
237   //
238   // Get the layers for the instrument.
239   //
240   SGPropertyNode layer_group = node.getSubNode("layers");
241   int nLayers = layer_group.size();
242   for (int j = 0; j < nLayers; j++) {
243     FGInstrumentLayer * layer = readLayer(layer_group.getChild(j));
244     if (layer == 0) {
245       delete instrument;
246       return 0;
247     }
248     instrument->addLayer(layer);
249   }
250
251   FG_LOG(FG_INPUT, FG_INFO, "Done reading instrument " << name);
252   return instrument;
253 }
254
255
256 /**
257  * Read a property list defining an instrument panel.
258  *
259  * Returns 0 if the read fails for any reason.
260  */
261 FGPanel *
262 fgReadPanel (istream &input)
263 {
264   SGPropertyList props;
265
266
267   //
268   // Read the property list from disk.
269   //
270   if (!readPropertyList(input, &props)) {
271     FG_LOG(FG_INPUT, FG_ALERT, "Malformed property list for panel.");
272     return 0;
273   }
274   FG_LOG(FG_INPUT, FG_INFO, "Read properties for panel " <<
275          props.getStringValue("/name"));
276
277   //
278   // Construct a new, empty panel.
279   //
280   FGPanel * panel = new FGPanel(0, 0, 1024, 768);// FIXME: use variable size
281
282   //
283   // Assign the background texture, if any, or a bogus chequerboard.
284   //
285   string bgTexture = props.getStringValue("/background");
286   if (bgTexture == "")
287     bgTexture = "FOO";
288   panel->setBackground(FGTextureManager::createTexture(bgTexture.c_str()));
289   FG_LOG(FG_INPUT, FG_INFO, "Set background texture to " << bgTexture);
290
291
292   //
293   // Create each instrument.
294   //
295   FG_LOG(FG_INPUT, FG_INFO, "Reading panel instruments");
296   SGPropertyNode instrument_group("/instruments", &props);
297   int nInstruments = instrument_group.size();
298   for (int i = 0; i < nInstruments; i++) {
299     SGPropertyList props2;
300     SGPropertyNode node = instrument_group.getChild(i);
301
302     string path = node.getStringValue("path");
303     int x = node.getIntValue("x");
304     int y = node.getIntValue("y");
305     int w = node.getIntValue("w");
306     int h = node.getIntValue("h");
307
308     FG_LOG(FG_INPUT, FG_INFO, "Reading instrument "
309            << node.getName()
310            << " from "
311            << path);
312
313     if (!readPropertyList(path, &props2)) {
314       delete panel;
315       return 0;
316     }
317
318     FGPanelInstrument * instrument =
319       readInstrument(SGPropertyNode("/", &props2));
320     if (instrument == 0) {
321       delete instrument;
322       delete panel;
323       return 0;
324     }
325     instrument->setPosition(x, y);
326     panel->addInstrument(instrument);
327   }
328   FG_LOG(FG_INPUT, FG_INFO, "Done reading panel instruments");
329
330
331   //
332   // Return the new panel.
333   //
334   return panel;
335 }
336
337
338 // end of panel_io.cxx