X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FCockpit%2Fpanel_io.cxx;h=dd1f1036155c0df275f02c9f1e1ed391a0ebe5e4;hb=b07ad149aebeb1d060bc9a0d505fdc1ca1081654;hp=da80239e9cb997696cedb374de61513806fa1828;hpb=f6fac40a11bf6c9de69ec51a9cf9229ec25ae20d;p=flightgear.git diff --git a/src/Cockpit/panel_io.cxx b/src/Cockpit/panel_io.cxx index da80239e9..dd1f10361 100644 --- a/src/Cockpit/panel_io.cxx +++ b/src/Cockpit/panel_io.cxx @@ -11,10 +11,10 @@ // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ @@ -22,138 +22,33 @@ # include #endif -#ifdef HAVE_WINDOWS_H -# include -#endif +#include // for strcmp() #include -#include +#include #include -#include +#include +#include -#include +#include #include #include -#include
- -#include "panel.hxx" -#include "steam.hxx" -#include "panel_io.hxx" - -FG_USING_STD(istream); -FG_USING_STD(ifstream); -FG_USING_STD(string); - - - -//////////////////////////////////////////////////////////////////////// -// Default panel, instrument, and layer for when things go wrong... -//////////////////////////////////////////////////////////////////////// - -static FGCroppedTexture defaultTexture("Textures/default.rgb"); - - -/** - * Default layer: the default texture. - */ -class DefaultLayer : public FGTexturedLayer -{ -public: - DefaultLayer () : FGTexturedLayer(defaultTexture) - { - } - -}; - -/** - * Default instrument: a single default layer. - */ -class DefaultInstrument : public FGLayeredInstrument -{ -public: - DefaultInstrument (int x, int y, int w, int h) - : FGLayeredInstrument(x, y, w, h) - { - addLayer(new DefaultLayer()); - } -}; - - -/** - * Default panel: the default texture. - */ -class DefaultPanel : public FGPanel -{ -public: - DefaultPanel (int x, int y, int w, int h) : FGPanel(x, y, w, h) - { - setBackground(defaultTexture.getTexture()); - } -}; - - - -//////////////////////////////////////////////////////////////////////// -// Built-in layer for the magnetic compass ribbon layer. -// -// TODO: move this out into a special directory for built-in -// layers of various sorts. -//////////////////////////////////////////////////////////////////////// - -class FGMagRibbon : public FGTexturedLayer -{ -public: - FGMagRibbon (int w, int h); - virtual ~FGMagRibbon () {} - - virtual void draw (); -}; - -FGMagRibbon::FGMagRibbon (int w, int h) - : FGTexturedLayer(w, h) -{ - FGCroppedTexture texture("Instruments/Default/Textures/compass-ribbon.rgb"); - setTexture(texture); -} - -void -FGMagRibbon::draw () -{ - double heading = FGSteam::get_MH_deg(); - double xoffset, yoffset; +#include
+#include
- while (heading >= 360.0) { - heading -= 360.0; - } - while (heading < 0.0) { - heading += 360.0; - } +#include - if (heading >= 60.0 && heading <= 180.0) { - xoffset = heading / 240.0; - yoffset = 0.75; - } else if (heading >= 150.0 && heading <= 270.0) { - xoffset = (heading - 90.0) / 240.0; - yoffset = 0.50; - } else if (heading >= 240.0 && heading <= 360.0) { - xoffset = (heading - 180.0) / 240.0; - yoffset = 0.25; - } else { - if (heading < 270.0) - heading += 360.0; - xoffset = (heading - 270.0) / 240.0; - yoffset = 0.0; - } +// #include "panel.hxx" +#include "panel_io.hxx" +#include - xoffset = 1.0 - xoffset; - // Adjust to put the number in the centre - xoffset -= 0.25; +//built-in layers +#include "built_in/FGMagRibbon.hxx" - FGCroppedTexture &t = getTexture(); - t.setCrop(xoffset, yoffset, xoffset + 0.5, yoffset + 0.25); - FGTexturedLayer::draw(); -} +using std::istream; +using std::ifstream; +using std::string; @@ -212,15 +107,34 @@ FGMagRibbon::draw () * texture, x1=0.0, y1=0.0, x2=0.5, y2=0.5. */ static FGCroppedTexture -readTexture (SGPropertyNode node) +readTexture (const SGPropertyNode * node) +{ + FGCroppedTexture texture(node->getStringValue("path"), + node->getFloatValue("x1"), + node->getFloatValue("y1"), + node->getFloatValue("x2", 1.0), + node->getFloatValue("y2", 1.0)); + SG_LOG(SG_COCKPIT, SG_DEBUG, "Read texture " << node->getName()); + return texture; +} + + +/** + * Test for a condition in the current node. + */ + +//////////////////////////////////////////////////////////////////////// +// Read a condition and use it if necessary. +//////////////////////////////////////////////////////////////////////// + +static void +readConditions (SGConditional *component, const SGPropertyNode *node) { - FGCroppedTexture texture(node.getStringValue("path"), - node.getFloatValue("x1"), - node.getFloatValue("y1"), - node.getFloatValue("x2", 1.0), - node.getFloatValue("y2", 1.0)); - FG_LOG(FG_INPUT, FG_INFO, "Read texture " << node.getName()); - return texture; + const SGPropertyNode * conditionNode = node->getChild("condition"); + if (conditionNode != 0) + // The top level is implicitly AND + component->setCondition(sgReadCondition(globals->get_props(), + conditionNode) ); } @@ -228,8 +142,9 @@ readTexture (SGPropertyNode node) * Read an action from the instrument's property list. * * The action will be performed when the user clicks a mouse button - * within the specified region of the instrument. Actions always - * work by modifying the value of a property (see the SGValue class). + * within the specified region of the instrument. Actions always work + * by modifying the value of a property (see the SGPropertyNode + * class). * * The following action types are defined: * @@ -250,62 +165,61 @@ readTexture (SGPropertyNode node) * being drawn at its regular size. */ static FGPanelAction * -readAction (SGPropertyNode node, float hscale, float vscale) +readAction (const SGPropertyNode * node, float w_scale, float h_scale) { - FGPanelAction * action = 0; + unsigned int i, j; + SGPropertyNode *binding; + vectorbindings = node->getChildren("binding"); + + // button-less actions are fired initially + if (!node->hasValue("w") || !node->hasValue("h")) { + for (i = 0; i < bindings.size(); i++) { + SGBinding b(bindings[i], globals->get_props()); + b.fire(); + } + return 0; + } - string name = node.getStringValue("name"); - string type = node.getStringValue("type"); + string name = node->getStringValue("name"); - int button = node.getIntValue("button"); - int x = int(node.getIntValue("x") * hscale); - int y = int(node.getIntValue("y") * vscale); - int w = int(node.getIntValue("w") * hscale); - int h = int(node.getIntValue("h") * vscale); + int button = node->getIntValue("button"); + int x = int(node->getIntValue("x") * w_scale); + int y = int(node->getIntValue("y") * h_scale); + int w = int(node->getIntValue("w") * w_scale); + int h = int(node->getIntValue("h") * h_scale); + bool repeatable = node->getBoolValue("repeatable", true); - if (type == "") { - FG_LOG(FG_INPUT, FG_ALERT, - "No type supplied for action " << name << " assuming \"adjust\""); - type = "adjust"; - } + FGPanelAction * action = new FGPanelAction(button, x, y, w, h, repeatable); - // Adjust a property value - if (type == "adjust") { - string propName = node.getStringValue("property"); - SGValue * value = current_properties.getValue(propName, true); - float increment = node.getFloatValue("increment", 1.0); - float min = node.getFloatValue("min", 0.0); - float max = node.getFloatValue("max", 0.0); - bool wrap = node.getBoolValue("wrap", false); - if (min == max) - FG_LOG(FG_INPUT, FG_ALERT, "Action " << node.getName() - << " has same min and max value"); - action = new FGAdjustAction(button, x, y, w, h, value, - increment, min, max, wrap); - } + SGPropertyNode * dest = fgGetNode("/sim/bindings/panel", true); - // Swap two property values - else if (type == "swap") { - string propName1 = node.getStringValue("property1"); - string propName2 = node.getStringValue("property2"); - SGValue * value1 = current_properties.getValue(propName1, true); - SGValue * value2 = current_properties.getValue(propName2, true); - action = new FGSwapAction(button, x, y, w, h, value1, value2); - } + for (i = 0; i < bindings.size(); i++) { + SG_LOG(SG_INPUT, SG_INFO, "Reading binding " + << bindings[i]->getStringValue("command")); - // Toggle a boolean value - else if (type == "toggle") { - string propName = node.getStringValue("property"); - SGValue * value = current_properties.getValue(propName, true); - action = new FGToggleAction(button, x, y, w, h, value); - } + j = 0; + while (dest->getChild("binding", j)) + j++; - // Unrecognized type - else { - FG_LOG(FG_INPUT, FG_ALERT, "Unrecognized action type " << type); - return 0; + binding = dest->getChild("binding", j, true); + copyProperties(bindings[i], binding); + action->addBinding(new SGBinding(binding, globals->get_props()), 0); } + if (node->hasChild("mod-up")) { + bindings = node->getChild("mod-up")->getChildren("binding"); + for (i = 0; i < bindings.size(); i++) { + j = 0; + while (dest->getChild("binding", j)) + j++; + + binding = dest->getChild("binding", j, true); + copyProperties(bindings[i], binding); + action->addBinding(new SGBinding(binding, globals->get_props()), 1); + } + } + + readConditions(action, node); return action; } @@ -336,46 +250,61 @@ readAction (SGPropertyNode node, float hscale, float vscale) * appear to be applied backwards. */ static FGPanelTransformation * -readTransformation (SGPropertyNode node, float hscale, float vscale) +readTransformation (const SGPropertyNode * node, float w_scale, float h_scale) { FGPanelTransformation * t = new FGPanelTransformation; - string name = node.getName(); - string type = node.getStringValue("type"); - string propName = node.getStringValue("property", ""); - SGValue * value = 0; + string name = node->getName(); + string type = node->getStringValue("type"); + string propName = node->getStringValue("property", ""); + SGPropertyNode * target = 0; - if (type == "") { - FG_LOG(FG_INPUT, FG_ALERT, - "No type supplied for transformation " << name - << " assuming \"rotation\""); + if (type.empty()) { + SG_LOG( SG_COCKPIT, SG_INFO, + "No type supplied for transformation " << name + << " assuming \"rotation\"" ); type = "rotation"; } - if (propName != "") { - value = current_properties.getValue(propName, true); + if (!propName.empty()) { + target = fgGetNode(propName.c_str(), true); } - t->value = value; - t->min = node.getFloatValue("min", -9999999); - t->max = node.getFloatValue("max", 99999999); - t->factor = node.getFloatValue("scale", 1.0); - t->offset = node.getFloatValue("offset", 0.0); - + t->node = target; + t->min = node->getFloatValue("min", -9999999); + t->max = node->getFloatValue("max", 99999999); + t->has_mod = node->hasChild("modulator"); + if (t->has_mod) + t->mod = node->getFloatValue("modulator"); + t->factor = node->getFloatValue("scale", 1.0); + t->offset = node->getFloatValue("offset", 0.0); + + // Check for an interpolation table + const SGPropertyNode * trans_table = node->getNode("interpolation"); + if (trans_table != 0) { + SG_LOG( SG_COCKPIT, SG_INFO, "Found interpolation table with " + << trans_table->nChildren() << " children" ); + t->table = new SGInterpTable(trans_table); + } else { + t->table = 0; + } + // Move the layer horizontally. if (type == "x-shift") { t->type = FGPanelTransformation::XSHIFT; - t->min *= hscale; - t->max *= hscale; - t->offset *= hscale; +// t->min *= w_scale; //removed by Martin Dressler +// t->max *= w_scale; //removed by Martin Dressler + t->offset *= w_scale; + t->factor *= w_scale; //Added by Martin Dressler } // Move the layer vertically. else if (type == "y-shift") { t->type = FGPanelTransformation::YSHIFT; - t->min *= vscale; - t->max *= vscale; - t->offset *= vscale; + //t->min *= h_scale; //removed + //t->max *= h_scale; //removed + t->offset *= h_scale; + t->factor *= h_scale; //Added } // Rotate the layer. The rotation @@ -386,12 +315,13 @@ readTransformation (SGPropertyNode node, float hscale, float vscale) } else { - FG_LOG(FG_INPUT, FG_ALERT, "Unrecognized transformation type " << type); + SG_LOG( SG_COCKPIT, SG_ALERT, "Unrecognized transformation type " << type ); delete t; return 0; } - FG_LOG(FG_INPUT, FG_INFO, "Read transformation " << name); + readConditions(t, node); + SG_LOG( SG_COCKPIT, SG_DEBUG, "Read transformation " << name ); return t; } @@ -413,49 +343,52 @@ readTransformation (SGPropertyNode node, float hscale, float vscale) * All three may also include a printf-style format string. */ FGTextLayer::Chunk * -readTextChunk (SGPropertyNode node) +readTextChunk (const SGPropertyNode * node) { FGTextLayer::Chunk * chunk; - string name = node.getStringValue("name"); - string type = node.getStringValue("type"); - string format = node.getStringValue("format"); + string name = node->getStringValue("name"); + string type = node->getStringValue("type"); + string format = node->getStringValue("format"); // Default to literal text. - if (type == "") { - FG_LOG(FG_INPUT, FG_INFO, "No type provided for text chunk " << name - << " assuming \"literal\""); + if (type.empty()) { + SG_LOG( SG_COCKPIT, SG_INFO, "No type provided for text chunk " << name + << " assuming \"literal\""); type = "literal"; } // A literal text string. if (type == "literal") { - string text = node.getStringValue("text"); + string text = node->getStringValue("text"); chunk = new FGTextLayer::Chunk(text, format); } // The value of a string property. else if (type == "text-value") { - SGValue * value = - current_properties.getValue(node.getStringValue("property"), true); - chunk = new FGTextLayer::Chunk(FGTextLayer::TEXT_VALUE, value, format); + SGPropertyNode * target = + fgGetNode(node->getStringValue("property"), true); + chunk = new FGTextLayer::Chunk(FGTextLayer::TEXT_VALUE, target, format); } // The value of a float property. else if (type == "number-value") { - string propName = node.getStringValue("property"); - float scale = node.getFloatValue("scale", 1.0); - SGValue * value = current_properties.getValue(propName, true); - chunk = new FGTextLayer::Chunk(FGTextLayer::DOUBLE_VALUE, value, - format, scale); + string propName = node->getStringValue("property"); + float scale = node->getFloatValue("scale", 1.0); + float offset = node->getFloatValue("offset", 0.0); + bool truncation = node->getBoolValue("truncate", false); + SGPropertyNode * target = fgGetNode(propName.c_str(), true); + chunk = new FGTextLayer::Chunk(FGTextLayer::DOUBLE_VALUE, target, + format, scale, offset, truncation); } // Unknown type. else { - FG_LOG(FG_INPUT, FG_ALERT, "Unrecognized type " << type - << " for text chunk " << name); + SG_LOG( SG_COCKPIT, SG_ALERT, "Unrecognized type " << type + << " for text chunk " << name ); return 0; } + readConditions(chunk, node); return chunk; } @@ -482,31 +415,47 @@ readTextChunk (SGPropertyNode node) * Currently, the only built-in layer class is "compass-ribbon". */ static FGInstrumentLayer * -readLayer (SGPropertyNode node, float hscale, float vscale) +readLayer (const SGPropertyNode * node, float w_scale, float h_scale) { FGInstrumentLayer * layer = NULL; - string name = node.getStringValue("name"); - string type = node.getStringValue("type"); - int w = node.getIntValue("w", -1); - int h = node.getIntValue("h", -1); + string name = node->getStringValue("name"); + string type = node->getStringValue("type"); + int w = node->getIntValue("w", -1); + int h = node->getIntValue("h", -1); + bool emissive = node->getBoolValue("emissive", false); if (w != -1) - w = int(w * hscale); + w = int(w * w_scale); if (h != -1) - h = int(h * vscale); + h = int(h * h_scale); - if (type == "") { - FG_LOG(FG_INPUT, FG_ALERT, - "No type supplied for layer " << name - << " assuming \"texture\""); + if (type.empty()) { + SG_LOG( SG_COCKPIT, SG_INFO, + "No type supplied for layer " << name + << " assuming \"texture\"" ); type = "texture"; } // A textured instrument layer. if (type == "texture") { - FGCroppedTexture texture = readTexture(node.getSubNode("texture")); + FGCroppedTexture texture = readTexture(node->getNode("texture")); layer = new FGTexturedLayer(texture, w, h); + if (emissive) { + FGTexturedLayer *tl=(FGTexturedLayer*)layer; + tl->setEmissive(true); + } + + } + + // A group of sublayers. + else if (type == "group") { + layer = new FGGroupLayer(); + for (int i = 0; i < node->nChildren(); i++) { + const SGPropertyNode * child = node->getChild(i); + if (!strcmp(child->getName(), "layer")) + ((FGGroupLayer *)layer)->addLayer(readLayer(child, w_scale, h_scale)); + } } @@ -515,66 +464,71 @@ readLayer (SGPropertyNode node, float hscale, float vscale) FGTextLayer * tlayer = new FGTextLayer(w, h); // FIXME // Set the text color. - float red = node.getFloatValue("color/red", 0.0); - float green = node.getFloatValue("color/green", 0.0); - float blue = node.getFloatValue("color/blue", 0.0); + float red = node->getFloatValue("color/red", 0.0); + float green = node->getFloatValue("color/green", 0.0); + float blue = node->getFloatValue("color/blue", 0.0); tlayer->setColor(red, green, blue); // Set the point size. - float pointSize = node.getFloatValue("point-size", 10.0) * hscale; + float pointSize = node->getFloatValue("point-size", 10.0) * w_scale; tlayer->setPointSize(pointSize); // Set the font. - // TODO - - SGPropertyNode chunk_group = node.getSubNode("chunks"); - int nChunks = chunk_group.size(); - for (int i = 0; i < nChunks; i++) { - FGTextLayer::Chunk * chunk = readTextChunk(chunk_group.getChild(i)); - if (chunk == 0) { - delete layer; - return 0; + string fontName = node->getStringValue("font", "Helvetica"); + tlayer->setFontName(fontName); + + const SGPropertyNode * chunk_group = node->getNode("chunks"); + if (chunk_group != 0) { + int nChunks = chunk_group->nChildren(); + for (int i = 0; i < nChunks; i++) { + const SGPropertyNode * node = chunk_group->getChild(i); + if (!strcmp(node->getName(), "chunk")) { + FGTextLayer::Chunk * chunk = readTextChunk(node); + if (chunk != 0) + tlayer->addChunk(chunk); + } else { + SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName() + << " in chunks" ); + } } - tlayer->addChunk(chunk); + layer = tlayer; } - layer = tlayer; } // A switch instrument layer. else if (type == "switch") { - SGValue * value = - current_properties.getValue(node.getStringValue("property"), true); - FGInstrumentLayer * layer1 = - readLayer(node.getSubNode("layer1"), hscale, vscale); - FGInstrumentLayer * layer2 = - readLayer(node.getSubNode("layer2"), hscale, vscale); - layer = new FGSwitchLayer(w, h, value, layer1, layer2); + layer = new FGSwitchLayer(); + for (int i = 0; i < node->nChildren(); i++) { + const SGPropertyNode * child = node->getChild(i); + if (!strcmp(child->getName(), "layer")) + ((FGGroupLayer *)layer)->addLayer(readLayer(child, w_scale, h_scale)); + } } // A built-in instrument layer. else if (type == "built-in") { - string layerclass = node.getStringValue("class"); + string layerclass = node->getStringValue("class"); if (layerclass == "mag-ribbon") { layer = new FGMagRibbon(w, h); } - else if (layerclass == "") { - FG_LOG(FG_INPUT, FG_ALERT, "No class provided for built-in layer " - << name); + else if (layerclass.empty()) { + SG_LOG( SG_COCKPIT, SG_ALERT, "No class provided for built-in layer " + << name ); return 0; } else { - FG_LOG(FG_INPUT, FG_ALERT, "Unknown built-in layer class " - << layerclass); + SG_LOG( SG_COCKPIT, SG_ALERT, "Unknown built-in layer class " + << layerclass); return 0; } } // An unknown type. else { - FG_LOG(FG_INPUT, FG_ALERT, "Unrecognized layer type " << type); + SG_LOG( SG_COCKPIT, SG_ALERT, "Unrecognized layer type " << type ); delete layer; return 0; } @@ -582,19 +536,24 @@ readLayer (SGPropertyNode node, float hscale, float vscale) // // Get the transformations for each layer. // - SGPropertyNode trans_group = node.getSubNode("transformations"); - int nTransformations = trans_group.size(); - for (int k = 0; k < nTransformations; k++) { - FGPanelTransformation * t = readTransformation(trans_group.getChild(k), - hscale, vscale); - if (t == 0) { - delete layer; - return 0; + const SGPropertyNode * trans_group = node->getNode("transformations"); + if (trans_group != 0) { + int nTransformations = trans_group->nChildren(); + for (int i = 0; i < nTransformations; i++) { + const SGPropertyNode * node = trans_group->getChild(i); + if (!strcmp(node->getName(), "transformation")) { + FGPanelTransformation * t = readTransformation(node, w_scale, h_scale); + if (t != 0) + layer->addTransformation(t); + } else { + SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName() + << " in transformations" ); + } } - layer->addTransformation(t); } - - FG_LOG(FG_INPUT, FG_INFO, "Read layer " << name); + + readConditions(layer, node); + SG_LOG( SG_COCKPIT, SG_DEBUG, "Read layer " << name ); return layer; } @@ -611,24 +570,34 @@ readLayer (SGPropertyNode node, float hscale, float vscale) * scaled automatically if the instrument is not at its preferred size. */ static FGPanelInstrument * -readInstrument (SGPropertyNode node, int x, int y, int real_w, int real_h) +readInstrument (const SGPropertyNode * node) { - int w = node.getIntValue("w"); - int h = node.getIntValue("h"); - const string &name = node.getStringValue("name"); + const string name = node->getStringValue("name"); + int x = node->getIntValue("x", -1); + int y = node->getIntValue("y", -1); + int real_w = node->getIntValue("w", -1); + int real_h = node->getIntValue("h", -1); + int w = node->getIntValue("w-base", -1); + int h = node->getIntValue("h-base", -1); + + if (x == -1 || y == -1) { + SG_LOG( SG_COCKPIT, SG_ALERT, + "x and y positions must be specified and > 0" ); + return 0; + } - float hscale = 1.0; - float vscale = 1.0; + float w_scale = 1.0; + float h_scale = 1.0; if (real_w != -1) { - hscale = float(real_w) / float(w); + w_scale = float(real_w) / float(w); w = real_w; } if (real_h != -1) { - vscale = float(real_h) / float(h); + h_scale = float(real_h) / float(h); h = real_h; } - FG_LOG(FG_INPUT, FG_INFO, "Reading instrument " << name); + SG_LOG( SG_COCKPIT, SG_DEBUG, "Reading instrument " << name ); FGLayeredInstrument * instrument = new FGLayeredInstrument(x, y, w, h); @@ -636,149 +605,207 @@ readInstrument (SGPropertyNode node, int x, int y, int real_w, int real_h) // // Get the actions for the instrument. // - SGPropertyNode action_group = node.getSubNode("actions"); - int nActions = action_group.size(); - int j; - for (j = 0; j < nActions; j++) { - FGPanelAction * action = readAction(action_group.getChild(j), - hscale, vscale); - if (action == 0) { - delete instrument; - return new DefaultInstrument(x, y, w, h); + const SGPropertyNode * action_group = node->getNode("actions"); + if (action_group != 0) { + int nActions = action_group->nChildren(); + for (int i = 0; i < nActions; i++) { + const SGPropertyNode * node = action_group->getChild(i); + if (!strcmp(node->getName(), "action")) { + FGPanelAction * action = readAction(node, w_scale, h_scale); + if (action != 0) + instrument->addAction(action); + } else { + SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName() + << " in actions" ); + } } - instrument->addAction(action); } // // Get the layers for the instrument. // - SGPropertyNode layer_group = node.getSubNode("layers"); - int nLayers = layer_group.size(); - for (j = 0; j < nLayers; j++) { - FGInstrumentLayer * layer = readLayer(layer_group.getChild(j), - hscale, vscale); - if (layer == 0) { - delete instrument; - return new DefaultInstrument(x, y, w, h); + const SGPropertyNode * layer_group = node->getNode("layers"); + if (layer_group != 0) { + int nLayers = layer_group->nChildren(); + for (int i = 0; i < nLayers; i++) { + const SGPropertyNode * node = layer_group->getChild(i); + if (!strcmp(node->getName(), "layer")) { + FGInstrumentLayer * layer = readLayer(node, w_scale, h_scale); + if (layer != 0) + instrument->addLayer(layer); + } else { + SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName() + << " in layers" ); + } } - instrument->addLayer(layer); } - FG_LOG(FG_INPUT, FG_INFO, "Done reading instrument " << name); + readConditions(instrument, node); + SG_LOG( SG_COCKPIT, SG_DEBUG, "Done reading instrument " << name ); return instrument; } /** - * Read a panel from a property list. - * - * Each panel instrument will appear in its own, separate - * property list. The top level simply names the panel and - * places the instruments in their appropriate locations (and - * optionally resizes them if necessary). - * - * Returns 0 if the read fails for any reason. + * Construct the panel from a property tree. */ FGPanel * -fgReadPanel (istream &input) +readPanel (const SGPropertyNode * root) { - SGPropertyList props; + SG_LOG( SG_COCKPIT, SG_INFO, "Reading properties for panel " << + root->getStringValue("name", "[Unnamed Panel]") ); - - // - // Read the property list from disk. - // - if (!readPropertyList(input, &props)) { - FG_LOG(FG_INPUT, FG_ALERT, "Malformed property list for panel."); - return 0; - } - FG_LOG(FG_INPUT, FG_INFO, "Read properties for panel " << - props.getStringValue("/name")); - - // - // Construct a new, empty panel. - // - FGPanel * panel = new FGPanel(0, 0, 1024, 768);// FIXME: use variable size - - - // - // Grab the panel's dimensions, default to 1024x443. - // - int panel_w = (props.hasValue("/w") ? props.getIntValue("/w") : 1024); - int panel_h = (props.hasValue("/h") ? props.getIntValue("/h") : 443); - panel->setWidth(panel_w); - panel->setHeight(panel_h); + FGPanel * panel = new FGPanel(); + panel->setWidth(root->getIntValue("w", 1024)); + panel->setHeight(root->getIntValue("h", 443)); // // Grab the visible external viewing area, default to // - panel->setViewHeight(props.hasValue("/view-height") ? - props.getIntValue("/view-height") : - 768 - panel_h + 2); + panel->setViewHeight(root->getIntValue("view-height", + 768 - panel->getHeight() + 2)); // // Grab the panel's initial offsets, default to 0, 0. // - int xoffset = (props.hasValue("/x-offset") ? - props.getIntValue("x-offset") : - 0); - int yoffset = (props.hasValue("/y-offset") ? - props.getIntValue("y-offset") : - 0); - panel->setXOffset(xoffset); - panel->setYOffset(yoffset); + if (!fgHasNode("/sim/panel/x-offset")) + fgSetInt("/sim/panel/x-offset", root->getIntValue("x-offset", 0)); + + // conditional removed by jim wilson to allow panel xml code + // with y-offset defined to work... + if (!fgHasNode("/sim/panel/y-offset")) + fgSetInt("/sim/panel/y-offset", root->getIntValue("y-offset", 0)); + + panel->setAutohide(root->getBoolValue("autohide", true)); // // Assign the background texture, if any, or a bogus chequerboard. // - string bgTexture = props.getStringValue("/background"); - if (bgTexture == "") + string bgTexture = root->getStringValue("background"); + if (bgTexture.empty()) bgTexture = "FOO"; panel->setBackground(FGTextureManager::createTexture(bgTexture.c_str())); - FG_LOG(FG_INPUT, FG_INFO, "Set background texture to " << bgTexture); - + SG_LOG( SG_COCKPIT, SG_INFO, "Set background texture to " << bgTexture ); // - // Create each instrument. + // Get multibackground if any... // - FG_LOG(FG_INPUT, FG_INFO, "Reading panel instruments"); - SGPropertyNode instrument_group("/instruments", &props); - int nInstruments = instrument_group.size(); - for (int i = 0; i < nInstruments; i++) { - SGPropertyList props2; - SGPropertyNode node = instrument_group.getChild(i); - - FGPath path(current_options.get_fg_root()); - path.append(node.getStringValue("path")); - - FG_LOG(FG_INPUT, FG_INFO, "Reading instrument " - << node.getName() - << " from " - << path.str()); - - int x = node.getIntValue("x", -1); - int y = node.getIntValue("y", -1); - int w = node.getIntValue("w", -1); - int h = node.getIntValue("h", -1); - - if (x == -1 || y == -1) { - FG_LOG(FG_INPUT, FG_ALERT, "x and y positions must be specified and >0"); - delete panel; - return 0; - } + string mbgTexture = root->getStringValue("multibackground[0]"); + if (!mbgTexture.empty()) { + panel->setMultiBackground(FGTextureManager::createTexture(mbgTexture.c_str()), 0); + SG_LOG( SG_COCKPIT, SG_INFO, "Set background texture to " << mbgTexture ); + + mbgTexture = root->getStringValue("multibackground[1]"); + if (mbgTexture.empty()) + mbgTexture = "FOO"; + panel->setMultiBackground(FGTextureManager::createTexture(mbgTexture.c_str()), 1); + SG_LOG( SG_COCKPIT, SG_INFO, "Set background texture to " << mbgTexture ); + + mbgTexture = root->getStringValue("multibackground[2]"); + if (mbgTexture.empty()) + mbgTexture = "FOO"; + panel->setMultiBackground(FGTextureManager::createTexture(mbgTexture.c_str()), 2); + SG_LOG( SG_COCKPIT, SG_INFO, "Set background texture to " << mbgTexture ); + + mbgTexture = root->getStringValue("multibackground[3]"); + if (mbgTexture.empty()) + mbgTexture = "FOO"; + panel->setMultiBackground(FGTextureManager::createTexture(mbgTexture.c_str()), 3); + SG_LOG( SG_COCKPIT, SG_INFO, "Set background texture to " << mbgTexture ); + + mbgTexture = root->getStringValue("multibackground[4]"); + if (mbgTexture.empty()) + mbgTexture = "FOO"; + panel->setMultiBackground(FGTextureManager::createTexture(mbgTexture.c_str()), 4); + SG_LOG( SG_COCKPIT, SG_INFO, "Set background texture to " << mbgTexture ); + + mbgTexture = root->getStringValue("multibackground[5]"); + if (mbgTexture.empty()) + mbgTexture = "FOO"; + panel->setMultiBackground(FGTextureManager::createTexture(mbgTexture.c_str()), 5); + SG_LOG( SG_COCKPIT, SG_INFO, "Set background texture to " << mbgTexture ); + + mbgTexture = root->getStringValue("multibackground[6]"); + if (mbgTexture.empty()) + mbgTexture = "FOO"; + panel->setMultiBackground(FGTextureManager::createTexture(mbgTexture.c_str()), 6); + SG_LOG( SG_COCKPIT, SG_INFO, "Set background texture to " << mbgTexture ); + + mbgTexture = root->getStringValue("multibackground[7]"); + if (mbgTexture.empty()) + mbgTexture = "FOO"; + panel->setMultiBackground(FGTextureManager::createTexture(mbgTexture.c_str()), 7); + SG_LOG( SG_COCKPIT, SG_INFO, "Set background texture to " << mbgTexture ); + } + - FGPanelInstrument * instrument = 0; - if (readPropertyList(path.str(), &props2)) { - instrument = readInstrument(SGPropertyNode("/", &props2), x, y, w, h); - } - if (instrument == 0) { - instrument = new DefaultInstrument(x, y, w, h); + // + // Create each instrument. + // + SG_LOG( SG_COCKPIT, SG_INFO, "Reading panel instruments" ); + const SGPropertyNode * instrument_group = root->getChild("instruments"); + if (instrument_group != 0) { + int nInstruments = instrument_group->nChildren(); + for (int i = 0; i < nInstruments; i++) { + const SGPropertyNode * node = instrument_group->getChild(i); + if (!strcmp(node->getName(), "instrument")) { + FGPanelInstrument * instrument = readInstrument(node); + if (instrument != 0) + panel->addInstrument(instrument); + } else if (!strcmp(node->getName(), "special-instrument")) { + //cout << "Special instrument found in instruments section!\n"; + const string name = node->getStringValue("name"); + if (name == "KLN89 GPS") { + //cout << "Special instrument is KLN89\n"; + + int x = node->getIntValue("x", -1); + int y = node->getIntValue("y", -1); + int real_w = node->getIntValue("w", -1); + int real_h = node->getIntValue("h", -1); + int w = node->getIntValue("w-base", -1); + int h = node->getIntValue("h-base", -1); + + if (x == -1 || y == -1) { + SG_LOG( SG_COCKPIT, SG_ALERT, + "x and y positions must be specified and > 0" ); + return 0; + } + + float w_scale = 1.0; + float h_scale = 1.0; + if (real_w != -1) { + w_scale = float(real_w) / float(w); + w = real_w; + } + if (real_h != -1) { + h_scale = float(real_h) / float(h); + h = real_h; + } + + SG_LOG( SG_COCKPIT, SG_DEBUG, "Reading instrument " << name ); + + // Warning - hardwired size!!! + RenderArea2D* instrument = new RenderArea2D(158, 40, 158, 40, x, y); + KLN89* gps = (KLN89*)globals->get_subsystem("kln89"); + if (gps == NULL) { + gps = new KLN89(instrument); + globals->add_subsystem("kln89", gps); + } + //gps->init(); // init seems to get called automagically. + FGSpecialInstrument* gpsinst = new FGSpecialInstrument(gps); + panel->addInstrument(gpsinst); + } else { + SG_LOG( SG_COCKPIT, SG_WARN, "Unknown special instrument found" ); + } + } else { + SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName() + << " in instruments section" ); + } } - panel->addInstrument(instrument); } - FG_LOG(FG_INPUT, FG_INFO, "Done reading panel instruments"); + SG_LOG( SG_COCKPIT, SG_INFO, "Done reading panel instruments" ); // @@ -788,6 +815,31 @@ fgReadPanel (istream &input) } +/** + * Read a panel from a property list. + * + * Each panel instrument will appear in its own, separate + * property list. The top level simply names the panel and + * places the instruments in their appropriate locations (and + * optionally resizes them if necessary). + * + * Returns 0 if the read fails for any reason. + */ +FGPanel * +fgReadPanel (istream &input) +{ + SGPropertyNode root; + + try { + readProperties(input, &root); + } catch (const sg_exception &e) { + guiErrorMessage("Error reading panel: ", e); + return 0; + } + return readPanel(&root); +} + + /** * Read a panel from a property list. * @@ -797,22 +849,22 @@ fgReadPanel (istream &input) FGPanel * fgReadPanel (const string &relative_path) { - FGPanel * panel = 0; - FGPath path(current_options.get_fg_root()); + SGPath path(globals->get_fg_root()); path.append(relative_path); - ifstream input(path.c_str()); - if (!input.good()) { - FG_LOG(FG_INPUT, FG_ALERT, - "Cannot read panel configuration from " << path.str()); - } else { - panel = fgReadPanel(input); - input.close(); + SGPropertyNode root; + + try { + readProperties(path.str(), &root); + } catch (const sg_exception &e) { + guiErrorMessage("Error reading panel: ", e); + return 0; } - if (panel == 0) - panel = new DefaultPanel(0, 0, 1024, 768); - return panel; + return readPanel(&root); } // end of panel_io.cxx + + +