Added simple proof-of-concept support for running PSL scripts from
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.
This commit is contained in:
parent
5424c65f00
commit
9bbe8a78b6
9 changed files with 301 additions and 5 deletions
37
configure.ac
37
configure.ac
|
@ -340,8 +340,29 @@ int main() {
|
||||||
dnl If we get here then plib is available, so force use of plib
|
dnl If we get here then plib is available, so force use of plib
|
||||||
dnl joystick lib
|
dnl joystick lib
|
||||||
AC_DEFINE([ENABLE_PLIB_JOYSTICK], 1, [Define to enable plib joystick support])
|
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
|
dnl Check for MetaKit
|
||||||
AC_CHECK_HEADER(mk4.h)
|
AC_CHECK_HEADER(mk4.h)
|
||||||
|
@ -546,6 +567,7 @@ AC_CONFIG_FILES([ \
|
||||||
src/NetworkOLK/Makefile \
|
src/NetworkOLK/Makefile \
|
||||||
src/Objects/Makefile \
|
src/Objects/Makefile \
|
||||||
src/Scenery/Makefile \
|
src/Scenery/Makefile \
|
||||||
|
src/Scripting/Makefile \
|
||||||
src/Sound/Makefile \
|
src/Sound/Makefile \
|
||||||
src/Systems/Makefile \
|
src/Systems/Makefile \
|
||||||
src/Time/Makefile \
|
src/Time/Makefile \
|
||||||
|
@ -564,6 +586,15 @@ echo "================="
|
||||||
|
|
||||||
echo "Prefix: $prefix"
|
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
|
if test "x$with_logging" != "x"; then
|
||||||
echo "Debug messages: $with_logging"
|
echo "Debug messages: $with_logging"
|
||||||
else
|
else
|
||||||
|
@ -573,8 +604,6 @@ fi
|
||||||
echo -n "Automake version: "
|
echo -n "Automake version: "
|
||||||
automake --version | head -1
|
automake --version | head -1
|
||||||
|
|
||||||
echo "New plib joystick name support: $plib_js_has_getname"
|
|
||||||
|
|
||||||
if test "x$with_weathercm" != "x"; then
|
if test "x$with_weathercm" != "x"; then
|
||||||
echo "WeatherCM instead of FGEnvironment: $with_weathercm"
|
echo "WeatherCM instead of FGEnvironment: $with_weathercm"
|
||||||
else
|
else
|
||||||
|
|
|
@ -66,6 +66,7 @@ fgfs_LDADD = \
|
||||||
$(top_builddir)/src/Model/libModel.a \
|
$(top_builddir)/src/Model/libModel.a \
|
||||||
$(top_builddir)/src/Navaids/libNavaids.a \
|
$(top_builddir)/src/Navaids/libNavaids.a \
|
||||||
$(top_builddir)/src/Scenery/libScenery.a \
|
$(top_builddir)/src/Scenery/libScenery.a \
|
||||||
|
$(top_builddir)/src/Scripting/libScripting.a \
|
||||||
$(top_builddir)/src/Sound/libSound.a \
|
$(top_builddir)/src/Sound/libSound.a \
|
||||||
$(top_builddir)/src/Airports/libAirports.a \
|
$(top_builddir)/src/Airports/libAirports.a \
|
||||||
$(NETWORK_LIBS) \
|
$(NETWORK_LIBS) \
|
||||||
|
@ -77,7 +78,7 @@ fgfs_LDADD = \
|
||||||
-lsgmath -lsgbucket -lsgdebug -lsgmagvar -lsgmisc -lsgxml \
|
-lsgmath -lsgbucket -lsgdebug -lsgmagvar -lsgmisc -lsgxml \
|
||||||
-lsgserial \
|
-lsgserial \
|
||||||
$(THREAD_LIBS) \
|
$(THREAD_LIBS) \
|
||||||
-lplibpu -lplibfnt -lplibjs -lplibnet -lplibssg -lplibsg -lplibul \
|
-lplibpu -lplibfnt -lplibjs -lplibnet -lplibssg -lplibsg -lplibul -lplibpsl \
|
||||||
-lmk4 -lz \
|
-lmk4 -lz \
|
||||||
$(opengl_LIBS) \
|
$(opengl_LIBS) \
|
||||||
$(audio_LIBS)
|
$(audio_LIBS)
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <GUI/gui.h>
|
#include <GUI/gui.h>
|
||||||
#include <GUI/new_gui.hxx>
|
#include <GUI/new_gui.hxx>
|
||||||
#include <Scenery/tilemgr.hxx>
|
#include <Scenery/tilemgr.hxx>
|
||||||
|
#include <Scripting/scriptmgr.hxx>
|
||||||
#include <Time/tmp.hxx>
|
#include <Time/tmp.hxx>
|
||||||
|
|
||||||
#include "fg_init.hxx"
|
#include "fg_init.hxx"
|
||||||
|
@ -128,6 +129,18 @@ do_null (const SGPropertyNode * arg)
|
||||||
return true;
|
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.
|
* Built-in command: exit FlightGear.
|
||||||
|
@ -641,6 +654,7 @@ static struct {
|
||||||
SGCommandMgr::command_t command;
|
SGCommandMgr::command_t command;
|
||||||
} built_ins [] = {
|
} built_ins [] = {
|
||||||
{ "null", do_null },
|
{ "null", do_null },
|
||||||
|
{ "script", do_script },
|
||||||
{ "exit", do_exit },
|
{ "exit", do_exit },
|
||||||
{ "load", do_load },
|
{ "load", do_load },
|
||||||
{ "save", do_save },
|
{ "save", do_save },
|
||||||
|
|
|
@ -109,6 +109,7 @@
|
||||||
#include <Navaids/navlist.hxx>
|
#include <Navaids/navlist.hxx>
|
||||||
#include <Scenery/scenery.hxx>
|
#include <Scenery/scenery.hxx>
|
||||||
#include <Scenery/tilemgr.hxx>
|
#include <Scenery/tilemgr.hxx>
|
||||||
|
#include <Scripting/scriptmgr.hxx>
|
||||||
#include <Sound/fg_fx.hxx>
|
#include <Sound/fg_fx.hxx>
|
||||||
#include <Sound/soundmgr.hxx>
|
#include <Sound/soundmgr.hxx>
|
||||||
#include <Systems/system_mgr.hxx>
|
#include <Systems/system_mgr.hxx>
|
||||||
|
@ -1479,6 +1480,15 @@ bool fgInitSubsystems() {
|
||||||
new FGLogger);
|
new FGLogger);
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Create and register the script manager.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
globals->get_subsystem_mgr()->add(FGSubsystemMgr::GENERAL,
|
||||||
|
"scripting",
|
||||||
|
new FGScriptMgr);
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Create and register the XML GUI.
|
// Create and register the XML GUI.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -27,6 +27,7 @@ SUBDIRS = \
|
||||||
$(NETWORK_DIRS) \
|
$(NETWORK_DIRS) \
|
||||||
Objects \
|
Objects \
|
||||||
Scenery \
|
Scenery \
|
||||||
|
Scripting \
|
||||||
Sound \
|
Sound \
|
||||||
Systems \
|
Systems \
|
||||||
Time \
|
Time \
|
||||||
|
|
3
src/Scripting/.cvsignore
Normal file
3
src/Scripting/.cvsignore
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.deps
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
5
src/Scripting/Makefile.am
Normal file
5
src/Scripting/Makefile.am
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
noinst_LIBRARIES = libScripting.a
|
||||||
|
|
||||||
|
libScripting_a_SOURCES = scriptmgr.cxx scriptmgr.hxx
|
||||||
|
|
||||||
|
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
|
155
src/Scripting/scriptmgr.cxx
Normal file
155
src/Scripting/scriptmgr.cxx
Normal file
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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} };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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
|
78
src/Scripting/scriptmgr.hxx
Normal file
78
src/Scripting/scriptmgr.hxx
Normal file
|
@ -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
|
Loading…
Add table
Reference in a new issue