# include <windows.h>
#endif
+#include <string.h> // for strcmp()
+
#include <simgear/compiler.h>
-#include <simgear/misc/fgpath.hxx>
+#include <simgear/structure/exception.hxx>
#include <simgear/debug/logstream.hxx>
-#include <simgear/misc/props.hxx>
-
-#include <iostream>
-#include <fstream>
-#include <string>
-
-#include <Main/options.hxx>
-
-#include "panel.hxx"
-#include "steam.hxx"
-#include "panel_io.hxx"
-
-FG_USING_STD(istream);
-FG_USING_STD(ifstream);
-FG_USING_STD(string);
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// 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());
- }
-};
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Built-in layer for the magnetic compass ribbon layer.
-//
-// TODO: move this out into a special directory for built-in
-// layers of various sorts.
-////////////////////////////////////////////////////////////////////////
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/props/props.hxx>
-class FGMagRibbon : public FGTexturedLayer
-{
-public:
- FGMagRibbon (int w, int h);
- virtual ~FGMagRibbon () {}
+#include STL_IOSTREAM
+#include STL_FSTREAM
+#include STL_STRING
- virtual void draw ();
-};
+#include <Main/globals.hxx>
+#include <Main/fg_props.hxx>
-FGMagRibbon::FGMagRibbon (int w, int h)
- : FGTexturedLayer(w, h)
-{
- FGCroppedTexture texture("Instruments/Default/Textures/compass-ribbon.rgb");
- setTexture(texture);
-}
+#include <GUI/gui.h>
-void
-FGMagRibbon::draw ()
-{
- double heading = FGSteam::get_MH_deg();
- double xoffset, yoffset;
-
- while (heading >= 360.0) {
- heading -= 360.0;
- }
- while (heading < 0.0) {
- heading += 360.0;
- }
-
- 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"
- 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();
-}
+SG_USING_STD(istream);
+SG_USING_STD(ifstream);
+SG_USING_STD(string);
\f
* 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.
+ */
+\f
+////////////////////////////////////////////////////////////////////////
+// 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) );
}
* 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:
*
* 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;
+ string name = node->getStringValue("name");
- string name = node.getStringValue("name");
- string type = node.getStringValue("type");
+ 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);
- 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);
+ FGPanelAction * action = new FGPanelAction(button, x, y, w, h, repeatable);
- if (type == "") {
- FG_LOG(FG_INPUT, FG_ALERT,
- "No type supplied for action " << name << " assuming \"adjust\"");
- type = "adjust";
- }
+ vector<SGPropertyNode_ptr>bindings = node->getChildren("binding");
- // 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);
- }
-
- // 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);
- }
-
- // 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);
- }
+ unsigned int i;
+ for (i = 0; i < bindings.size(); i++) {
+ SG_LOG(SG_INPUT, SG_INFO, "Reading binding "
+ << bindings[i]->getStringValue("command"));
+ action->addBinding(new FGBinding(bindings[i]), 0);
+ }
- // Unrecognized type
- else {
- FG_LOG(FG_INPUT, FG_ALERT, "Unrecognized action type " << type);
- return 0;
+ if (node->hasChild("mod-up")) {
+ bindings = node->getChild("mod-up")->getChildren("binding");
+ for (i = 0; i < bindings.size(); i++) {
+ action->addBinding(new FGBinding(bindings[i]), 1);
+ }
}
+ readConditions(action, node);
return action;
}
* 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();
+ for(int i = 0; i < trans_table->nChildren(); i++) {
+ const SGPropertyNode * node = trans_table->getChild(i);
+ if (!strcmp(node->getName(), "entry")) {
+ double ind = node->getDoubleValue("ind", 0.0);
+ double dep = node->getDoubleValue("dep", 0.0);
+ SG_LOG( SG_COCKPIT, SG_INFO, "Adding interpolation entry "
+ << ind << "==>" << dep );
+ t->table->addEntry(ind, dep);
+ } else {
+ SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
+ << " in interpolation" );
+ }
+ }
+ } 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
}
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;
}
* 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;
}
* 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);
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);
}
+ // 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));
+ }
+ }
+
// A textual instrument layer.
else if (type == "text") {
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", "default");
+ 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;
}
//
// 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;
}
* 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);
//
// Get the actions for the instrument.
//
- SGPropertyNode action_group = node.getSubNode("actions");
- int nActions = action_group.size();
- for (int 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 (int 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]") );
+ FGPanel * panel = new FGPanel();
+ panel->setWidth(root->getIntValue("w", 1024));
+ panel->setHeight(root->getIntValue("h", 443));
//
- // Read the property list from disk.
+ // Grab the visible external viewing area, default to
//
- 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"));
+ panel->setViewHeight(root->getIntValue("view-height",
+ 768 - panel->getHeight() + 2));
//
- // Construct a new, empty panel.
+ // Grab the panel's initial offsets, default to 0, 0.
//
- FGPanel * panel = new FGPanel(0, 0, 1024, 768);// FIXME: use variable size
+ 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));
//
// 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 {
+ 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" );
//
}
+/**
+ * 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.
*
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
+
+
+