dnl If we get here then plib is available, so force use of plib
dnl joystick lib
AC_DEFINE([ENABLE_PLIB_JOYSTICK], 1, [Define to enable plib joystick support])
-AC_DEFINE([FG_PLIB_JOYSTICK_GETNAME], 1,
- [Define to enable plib joystick name support])
+
+
+dnl Compiling an in-memory PSL script is available only in the CVS
+dnl version of plib, so check for it.
+AC_MSG_CHECKING([for plib PSL in-memory script compilation support])
+AC_COMPILE_IFELSE([
+#include <plib/psl.h>
+
+int main() {
+ // not for running...
+ pslProgram program((pslExtension *)0);
+ program.compile("int main () {}", "");
+ return 0;
+}
+],
+ [AC_MSG_RESULT(yes);
+ fg_psl_string_compile=yes],
+ AC_MSG_RESULT(no)
+)
+if test "x$fg_psl_string_compile" = "xyes"; then
+ AC_DEFINE([FG_PSL_STRING_COMPILE], 1,
+ [Support for compiling PSL scripts from an in-memory string.])
+fi
dnl Check for MetaKit
AC_CHECK_HEADER(mk4.h)
src/NetworkOLK/Makefile \
src/Objects/Makefile \
src/Scenery/Makefile \
+ src/Scripting/Makefile \
src/Sound/Makefile \
src/Systems/Makefile \
src/Time/Makefile \
echo "Prefix: $prefix"
+if test "x$fg_psl_string_compile" = "xyes"; then
+ echo "Scripts for input bindings: yes"
+else
+ echo "Scripts for input bindings: $fg_psl_string_compile"
+ echo " PSL scripts attached to input bindings will not"
+ echo " work. Download the latest CVS version of plib"
+ echo " if you would like to enable them."
+fi
+
if test "x$with_logging" != "x"; then
echo "Debug messages: $with_logging"
else
echo -n "Automake version: "
automake --version | head -1
-echo "New plib joystick name support: $plib_js_has_getname"
-
if test "x$with_weathercm" != "x"; then
echo "WeatherCM instead of FGEnvironment: $with_weathercm"
else
$(top_builddir)/src/Model/libModel.a \
$(top_builddir)/src/Navaids/libNavaids.a \
$(top_builddir)/src/Scenery/libScenery.a \
+ $(top_builddir)/src/Scripting/libScripting.a \
$(top_builddir)/src/Sound/libSound.a \
$(top_builddir)/src/Airports/libAirports.a \
$(NETWORK_LIBS) \
-lsgmath -lsgbucket -lsgdebug -lsgmagvar -lsgmisc -lsgxml \
-lsgserial \
$(THREAD_LIBS) \
- -lplibpu -lplibfnt -lplibjs -lplibnet -lplibssg -lplibsg -lplibul \
+ -lplibpu -lplibfnt -lplibjs -lplibnet -lplibssg -lplibsg -lplibul -lplibpsl \
-lmk4 -lz \
$(opengl_LIBS) \
$(audio_LIBS)
#include <GUI/gui.h>
#include <GUI/new_gui.hxx>
#include <Scenery/tilemgr.hxx>
+#include <Scripting/scriptmgr.hxx>
#include <Time/tmp.hxx>
#include "fg_init.hxx"
return true;
}
+/**
+ * Built-in command: run a PSL script.
+ */
+static bool
+do_script (const SGPropertyNode * arg)
+{
+ FGScriptMgr * mgr = (FGScriptMgr *)globals->get_subsystem_mgr()
+ ->get_group(FGSubsystemMgr::GENERAL)->get_subsystem("scripting");
+
+ return mgr->run(arg->getStringValue("script"));
+}
+
/**
* Built-in command: exit FlightGear.
SGCommandMgr::command_t command;
} built_ins [] = {
{ "null", do_null },
+ { "script", do_script },
{ "exit", do_exit },
{ "load", do_load },
{ "save", do_save },
#include <Navaids/navlist.hxx>
#include <Scenery/scenery.hxx>
#include <Scenery/tilemgr.hxx>
+#include <Scripting/scriptmgr.hxx>
#include <Sound/fg_fx.hxx>
#include <Sound/soundmgr.hxx>
#include <Systems/system_mgr.hxx>
new FGLogger);
+ ////////////////////////////////////////////////////////////////////
+ // Create and register the script manager.
+ ////////////////////////////////////////////////////////////////////
+
+ globals->get_subsystem_mgr()->add(FGSubsystemMgr::GENERAL,
+ "scripting",
+ new FGScriptMgr);
+
+
////////////////////////////////////////////////////////////////////
// Create and register the XML GUI.
////////////////////////////////////////////////////////////////////
$(NETWORK_DIRS) \
Objects \
Scenery \
+ Scripting \
Sound \
Systems \
Time \
--- /dev/null
+.deps
+Makefile
+Makefile.in
--- /dev/null
+noinst_LIBRARIES = libScripting.a
+
+libScripting_a_SOURCES = scriptmgr.cxx scriptmgr.hxx
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
--- /dev/null
+// scriptmgr.cxx - run user scripts
+// Written by David Megginson, started 2002.
+//
+// This file is in the Public Domain, and comes with no warranty.
+
+
+#include "scriptmgr.hxx"
+
+#include <iostream>
+
+#include <plib/psl.h>
+
+#include <Main/globals.hxx>
+#include <Main/fg_props.hxx>
+
+SG_USING_STD(cout);
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Extensions.
+////////////////////////////////////////////////////////////////////////
+
+static pslValue
+do_print (int argc, pslValue * argv, pslProgram * p)
+{
+ for (int i = 0; i < argc; i++) {
+ switch(argv[i].getType()) {
+ case PSL_INT:
+ cout << argv[i].getInt();
+ break;
+ case PSL_FLOAT:
+ cout << argv[i].getFloat();
+ break;
+ case PSL_STRING:
+ cout << argv[i].getString();
+ break;
+ case PSL_VOID:
+ cout << "(void)";
+ break;
+ default:
+ cout << "(**bad value**)";
+ break;
+ }
+ }
+}
+
+static pslValue
+do_get_property (int argc, pslValue * argv, pslProgram * p)
+{
+ pslValue result;
+ SGPropertyNode * prop = fgGetNode(argv[0].getString());
+ if (prop != 0) {
+ switch (prop->getType()) {
+ case SGPropertyNode::BOOL:
+ case SGPropertyNode::INT:
+ case SGPropertyNode::LONG:
+ result.set(prop->getIntValue());
+ break;
+ case SGPropertyNode::FLOAT:
+ case SGPropertyNode::DOUBLE:
+ result.set(prop->getFloatValue());
+ break;
+ case SGPropertyNode::STRING:
+ case SGPropertyNode::UNSPECIFIED:
+ result.set(prop->getStringValue());
+ break;
+ default:
+ // DO SOMETHING
+ break;
+ }
+ } else {
+ result.set();
+ }
+
+ return result;
+}
+
+static pslValue
+do_set_property (int argc, pslValue * argv, pslProgram * p)
+{
+ pslValue result;
+ SGPropertyNode * prop = fgGetNode(argv[0].getString(), true);
+ switch (argv[1].getType()) {
+ case PSL_INT:
+ prop->setIntValue(argv[1].getInt());
+ break;
+ case PSL_FLOAT:
+ prop->setFloatValue(argv[1].getFloat());
+ break;
+ case PSL_STRING:
+ prop->setStringValue(argv[1].getString());
+ break;
+ case PSL_VOID:
+ prop->setUnspecifiedValue("");
+ break;
+ default:
+ // TODO: report an error.
+ break;
+ }
+
+ result.set();
+ return result;
+}
+
+static pslExtension
+extensions[] = { {"print", -1, do_print},
+ {"get_property", 1, do_get_property},
+ {"set_property", 2, do_set_property},
+ {0, 0, 0} };
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGScriptMgr.
+////////////////////////////////////////////////////////////////////////
+
+FGScriptMgr::FGScriptMgr ()
+{
+}
+
+FGScriptMgr::~FGScriptMgr ()
+{
+}
+
+void
+FGScriptMgr::init ()
+{
+ pslInit();
+}
+
+void
+FGScriptMgr::update (double delta_time_sec)
+{
+}
+
+bool
+FGScriptMgr::run (const char * script)
+{
+#if defined(FG_PSL_STRING_COMPILE)
+ // FIXME: detect and report errors
+ pslProgram program(extensions);
+ if (program.compile(script, globals->get_fg_root().c_str()) > 0)
+ return false;
+ while (program.step() != PSL_PROGRAM_END)
+ ;
+ return true;
+#else
+ SG_LOG(SG_INPUT, SG_ALERT, "Input-binding scripts not supported");
+ return false;
+#endif
+}
+
+
+// end of scriptmgr.cxx
--- /dev/null
+// scriptmgr.hxx - run user scripts
+// Written by David Megginson, started 2002.
+//
+// This file is in the Public Domain, and comes with no warranty.
+
+#ifndef __SCRIPTMGR_HXX
+#define __SCRIPTMGR_HXX
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+
+#include <simgear/compiler.h> // for SG_USING_STD
+
+#include <Main/fgfs.hxx>
+
+class pslExtension;
+
+
+/**
+ * Manager for user scripts in PSL (PLIB's scripting language).
+ *
+ * The initial draft of this subsystem does nothing on update, and
+ * simply executes scripts on demand from various input bindings, but
+ * I plan to merge in code from Erik Hofman for events and scheduled
+ * tasks.
+ *
+ * Right now, there are three extension commands for
+ * FlightGear:
+ *
+ * print(...) - prints all of its arguments to standard output.
+ * get_property(name) - get a property value
+ * set_property(name, value) - set a property value
+ */
+class FGScriptMgr : public FGSubsystem
+{
+public:
+
+ /**
+ * Constructor.
+ */
+ FGScriptMgr ();
+
+
+ /**
+ * Destructor.
+ */
+ virtual ~FGScriptMgr ();
+
+
+ /**
+ * Initialize PSL.
+ */
+ virtual void init ();
+
+
+ /**
+ * Update (no-op for now).
+ */
+ virtual void update (double delta_time_sec);
+
+
+ /**
+ * Run an in-memory user script.
+ *
+ * Any included files are referenced relative to $FG_ROOT. This
+ * is not very efficient right now, since it recompiles the script
+ * every time it runs.
+ *
+ * @param script A string containing the script.
+ * @return true if the script compiled properly, false otherwise.
+ */
+ virtual bool run (const char * script);
+
+};
+
+
+#endif // __SCRIPTMGR_HXX