+/**
+ * Redraw GUI (applying new widget colors). Doesn't reload the dialogs,
+ * unlike reinit().
+ */
+static bool
+do_gui_redraw (const SGPropertyNode * arg)
+{
+ NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
+ gui->redraw();
+ return true;
+}
+
+
+/**
+ * Adds model to the scenery. The path to the added branch (/models/model[*])
+ * is returned in property "property".
+ */
+static bool
+do_add_model (const SGPropertyNode * arg)
+{
+ SGPropertyNode * model = fgGetNode("models", true);
+ for (int i = 0;; i++) {
+ if (i < 0)
+ return false;
+ if (!model->getChild("model", i, false)) {
+ model = model->getChild("model", i, true);
+ break;
+ }
+ }
+ copyProperties(arg, model);
+ if (model->hasValue("elevation-m"))
+ model->setDoubleValue("elevation-ft", model->getDoubleValue("elevation-m")
+ * SG_METER_TO_FEET);
+ model->getNode("load", true);
+ model->removeChildren("load");
+ const_cast<SGPropertyNode *>(arg)->setStringValue("property", model->getPath());
+ return true;
+}
+
+
+/**
+ * Set mouse cursor coordinates and cursor shape.
+ */
+static bool
+do_set_cursor (const SGPropertyNode * arg)
+{
+ if (arg->hasValue("x") || arg->hasValue("y")) {
+ SGPropertyNode *mx = fgGetNode("/devices/status/mice/mouse/x", true);
+ SGPropertyNode *my = fgGetNode("/devices/status/mice/mouse/y", true);
+ int x = arg->getIntValue("x", mx->getIntValue());
+ int y = arg->getIntValue("y", my->getIntValue());
+ fgWarpMouse(x, y);
+ mx->setIntValue(x);
+ my->setIntValue(y);
+ }
+
+ SGPropertyNode *cursor = const_cast<SGPropertyNode *>(arg)->getNode("cursor", true);
+ if (cursor->getType() != SGPropertyNode::NONE)
+ fgSetMouseCursor(cursor->getIntValue());
+
+ cursor->setIntValue(fgGetMouseCursor());
+ return true;
+}
+
+
+/**
+ * Built-in command: play an audio message (i.e. a wav file) This is
+ * fire and forget. Call this once per message and it will get dumped
+ * into a queue. Messages are played sequentially so they do not
+ * overlap.
+ */
+static bool
+do_play_audio_sample (const SGPropertyNode * arg)
+{
+ FGFX *fx = (FGFX *)globals->get_subsystem("fx");
+ string path = arg->getStringValue("path");
+ string file = arg->getStringValue("file");
+ double volume = arg->getDoubleValue("volume");
+ // cout << "playing " << path << " / " << file << endl;
+ try {
+ fx->play_message( path, file, volume );
+ return true;
+
+ } catch (const sg_io_exception& e) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "play-audio-sample: "
+ "failed to load" << path << '/' << file);
+ return false;
+ }
+}
+