]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/panel_io.cxx
de3210a91705653f40945de8bad39ecfa8169476
[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 #include <map>
36
37 #include "panel.hxx"
38
39 using std::istream;
40 using std::hash_map;
41 using std::string;
42
43
44 \f
45 ////////////////////////////////////////////////////////////////////////
46 // Instruments.
47 ////////////////////////////////////////////////////////////////////////
48
49 struct ActionData
50 {
51   FGPanelAction * action;
52   int button, x, y, w, h;
53 };
54
55 struct TransData
56 {
57   enum Type {
58     End = 0,
59     Rotation,
60     XShift,
61     YShift
62   };
63   Type type;
64   const char * propName;
65   float min, max, factor, offset;
66 };
67
68 struct LayerData
69 {
70   FGInstrumentLayer * layer;
71   TransData transformations[16];
72 };
73
74 struct InstrumentData
75 {
76   const char * name;
77   int x, y, w, h;
78   ActionData actions[16];
79   LayerData layers[16];
80 };
81
82
83 \f
84 ////////////////////////////////////////////////////////////////////////
85 // Read and construct a panel.
86 ////////////////////////////////////////////////////////////////////////
87
88
89 /**
90  * Read a property list defining an instrument panel.
91  *
92  * Returns 0 if the read fails for any reason.
93  */
94 FGPanel *
95 fgReadPanel (istream &input)
96 {
97   SGPropertyList props;
98   map<string,CroppedTexture> textures;
99
100
101   //
102   // Read the property list from disk.
103   //
104   if (!readPropertyList(input, &props)) {
105     FG_LOG(FG_INPUT, FG_ALERT, "Malformed property list for panel.");
106     return 0;
107   }
108   FG_LOG(FG_INPUT, FG_INFO, "Read properties for panel " <<
109          props.getStringValue("/name"));
110
111   //
112   // Read the cropped textures from the property list.
113   //
114   SGPropertyNode texture_group("/textures", &props);
115   int nTextures = texture_group.size();
116   cout << "There are " << nTextures << " textures" << endl;
117   for (int i = 0; i < nTextures; i++) {
118     SGPropertyNode tex = texture_group.getChild(i);
119     const string &name = tex.getName();
120     textures[name] = CroppedTexture(tex.getStringValue("path"),
121                                     tex.getFloatValue("x1"),
122                                     tex.getFloatValue("y1"),
123                                     tex.getFloatValue("x2", 1.0),
124                                     tex.getFloatValue("y2", 1.0));
125     FG_LOG(FG_INPUT, FG_INFO, "Read texture " << name);
126   }
127
128
129   //
130   // Construct a new, empty panel.
131   //
132   FGPanel * panel = new FGPanel(0, 0, 1024, 768);// FIXME: use variable size
133
134
135   //
136   // Assign the background texture, if any, or a bogus chequerboard.
137   //
138   string bgTexture = props.getStringValue("/background");
139   if (bgTexture == "") {
140     panel->setBackground(FGTextureManager::createTexture("FOO"));
141   } else {
142     panel->setBackground(textures[bgTexture].texture);
143   }
144   FG_LOG(FG_INPUT, FG_INFO, "Set background texture to " << bgTexture);
145
146
147   //
148   // Create each instrument.
149   //
150   FG_LOG(FG_INPUT, FG_INFO, "Reading panel instruments");
151   SGPropertyNode instrument_group("/instruments", &props);
152   int nInstruments = instrument_group.size();
153   cout << "There are " << nInstruments << " instruments" << endl;
154   for (int i = 0; i < nInstruments; i++) {
155     SGPropertyNode inst = instrument_group.getChild(i);
156     const string &name = inst.getName();
157     FGLayeredInstrument * instrument =
158       new FGLayeredInstrument(inst.getIntValue("x"),
159                               inst.getIntValue("y"),
160                               inst.getIntValue("w"),
161                               inst.getIntValue("h"));
162
163
164     //
165     // Get the layers for each instrument.
166     //
167     SGPropertyNode layer_group = inst.getSubNode("layers");
168     SGPropertyNode layer;
169     int nLayers = layer_group.size();
170     cout << "There are " << nLayers << " layers" << endl;
171     for (int j = 0; j < nLayers; j++) {
172       layer = layer_group.getChild(j);
173       FGInstrumentLayer * l;
174       string name = layer.getName();
175
176       string tex = layer.getStringValue("texture");
177       if (tex != "") {
178         l = new FGTexturedLayer(textures[tex],
179                                 layer.getIntValue("w", -1),
180                                 layer.getIntValue("h", -1));
181       } else {
182         FG_LOG(FG_INPUT, FG_ALERT, "No texture for layer " << name);
183         return 0;
184       }
185
186       //
187       // Get the transformations for each layer.
188       //
189       SGPropertyNode trans_group = layer.getSubNode("transformations");
190       SGPropertyNode trans;
191       int nTransformations = trans_group.size();
192       cout << "There are " << nTransformations << " transformations" << endl;
193       for (int k = 0; k < nTransformations; k++) {
194         trans = trans_group.getChild(k);
195         string name = trans.getName();
196         string type = trans.getStringValue("type");
197         string propName = trans.getStringValue("property", "");
198         SGValue * value = 0;
199         cout << "Type is " << type << endl;
200         if (propName != "") {
201           value = current_properties.getValue(propName, true);
202         }
203         if (type == "x-shift") {
204           l->addTransformation(FGInstrumentLayer::XSHIFT,
205                                value,
206                                trans.getFloatValue("min", 0.0),
207                                trans.getFloatValue("max", 1.0),
208                                trans.getFloatValue("factor", 1.0),
209                                trans.getFloatValue("offset", 0.0));
210         } else if (type == "y-shift") {
211           l->addTransformation(FGInstrumentLayer::YSHIFT,
212                                value,
213                                trans.getFloatValue("min", 0.0),
214                                trans.getFloatValue("max", 1.0),
215                                trans.getFloatValue("factor", 1.0),
216                                trans.getFloatValue("offset", 0.0));
217         } else if (type == "rotation") {
218           l->addTransformation(FGInstrumentLayer::ROTATION,
219                                value,
220                                trans.getFloatValue("min", -360.0),
221                                trans.getFloatValue("max", 360.0),
222                                trans.getFloatValue("factor", 1.0),
223                                trans.getFloatValue("offset", 0.0));
224         } else if (type == "") {
225           FG_LOG(FG_INPUT, FG_ALERT,
226                  "'type' must be specified for transformation");
227           return 0;
228         } else {
229           FG_LOG(FG_INPUT, FG_ALERT, "Unrecognized transformation: " << type);
230           return 0;
231         }
232         FG_LOG(FG_INPUT, FG_INFO, "Read transformation " << name);
233       }
234
235       instrument->addLayer(l);
236       FG_LOG(FG_INPUT, FG_INFO, "Read layer " << name);
237     }
238
239     panel->addInstrument(instrument);
240     FG_LOG(FG_INPUT, FG_INFO, "Read instrument " << name);
241   }
242
243
244   //
245   // Return the new panel.
246   //
247   return panel;
248 }