]> git.mxchange.org Git - flightgear.git/commitdiff
Added simple proof-of-concept support for running PSL scripts from
authordavid <david>
Sat, 11 Jan 2003 16:30:32 +0000 (16:30 +0000)
committerdavid <david>
Sat, 11 Jan 2003 16:30:32 +0000 (16:30 +0000)
input bindings.  They will work only with the latest CVS; otherwise,
./configure will disable them.  There is a new command, 'script',
which takes a single argument, also called 'script', containing PSL
code (currently PSL requires a main() function).

Erik Hofman has written some more elaborate code for triggering PSL
code from drop-down menus and scheduling events; I will look at
integrating that next.

configure.ac
src/Main/Makefile.am
src/Main/fg_commands.cxx
src/Main/fg_init.cxx
src/Makefile.am
src/Scripting/.cvsignore [new file with mode: 0644]
src/Scripting/Makefile.am [new file with mode: 0644]
src/Scripting/scriptmgr.cxx [new file with mode: 0644]
src/Scripting/scriptmgr.hxx [new file with mode: 0644]

index 083aab14420048caa4532bd271d8903d21d84332..56c7987bec01feb190a9c7cab7b4f7e9dc6a0189 100644 (file)
@@ -340,8 +340,29 @@ int main() {
 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)
@@ -546,6 +567,7 @@ AC_CONFIG_FILES([ \
        src/NetworkOLK/Makefile \
        src/Objects/Makefile \
        src/Scenery/Makefile \
+       src/Scripting/Makefile \
        src/Sound/Makefile \
        src/Systems/Makefile \
        src/Time/Makefile \
@@ -564,6 +586,15 @@ echo "================="
 
 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
@@ -573,8 +604,6 @@ fi
 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
index fb8060b0063727e68f44854c58376ab5d46f996a..184fff0df2f45eb00d918d567823fc01bc8b004b 100644 (file)
@@ -66,6 +66,7 @@ fgfs_LDADD = \
        $(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) \
@@ -77,7 +78,7 @@ fgfs_LDADD = \
        -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)
index 82e7f47c9db4a18738e473f0b7a9bb241129cbe2..d12fc57f58da67a45628c375179b9bb2d1825564 100644 (file)
@@ -19,6 +19,7 @@
 #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"
@@ -128,6 +129,18 @@ do_null (const SGPropertyNode * arg)
   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.
@@ -641,6 +654,7 @@ static struct {
   SGCommandMgr::command_t command;
 } built_ins [] = {
     { "null", do_null },
+    { "script", do_script },
     { "exit", do_exit },
     { "load", do_load },
     { "save", do_save },
index 223ad80f2c25057e66284e7fa37dd4a94f431da5..6728b5e363a2f5c628e84c39f5c2cbaf63760aae 100644 (file)
 #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>
@@ -1479,6 +1480,15 @@ bool fgInitSubsystems() {
                                       new FGLogger);
 
 
+    ////////////////////////////////////////////////////////////////////
+    // Create and register the script manager.
+    ////////////////////////////////////////////////////////////////////
+
+    globals->get_subsystem_mgr()->add(FGSubsystemMgr::GENERAL,
+                                      "scripting",
+                                      new FGScriptMgr);
+
+
     ////////////////////////////////////////////////////////////////////
     // Create and register the XML GUI.
     ////////////////////////////////////////////////////////////////////
index e2eceacfc8527f0f3f253ab1054a43a3cccc9bb8..0aa54451b9166ede1f34b3c0cf105dc7b89d710e 100644 (file)
@@ -27,6 +27,7 @@ SUBDIRS = \
         $(NETWORK_DIRS) \
         Objects \
         Scenery \
+        Scripting \
         Sound \
         Systems \
         Time \
diff --git a/src/Scripting/.cvsignore b/src/Scripting/.cvsignore
new file mode 100644 (file)
index 0000000..e995588
--- /dev/null
@@ -0,0 +1,3 @@
+.deps
+Makefile
+Makefile.in
diff --git a/src/Scripting/Makefile.am b/src/Scripting/Makefile.am
new file mode 100644 (file)
index 0000000..1d568bb
--- /dev/null
@@ -0,0 +1,5 @@
+noinst_LIBRARIES = libScripting.a
+
+libScripting_a_SOURCES = scriptmgr.cxx scriptmgr.hxx
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
diff --git a/src/Scripting/scriptmgr.cxx b/src/Scripting/scriptmgr.cxx
new file mode 100644 (file)
index 0000000..106cd03
--- /dev/null
@@ -0,0 +1,155 @@
+// 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
diff --git a/src/Scripting/scriptmgr.hxx b/src/Scripting/scriptmgr.hxx
new file mode 100644 (file)
index 0000000..849449e
--- /dev/null
@@ -0,0 +1,78 @@
+// 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