1
0
Fork 0

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:
david 2003-01-11 16:30:32 +00:00
parent 5424c65f00
commit 9bbe8a78b6
9 changed files with 301 additions and 5 deletions

View file

@ -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

View file

@ -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)

View file

@ -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 },

View file

@ -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.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View file

@ -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
View file

@ -0,0 +1,3 @@
.deps
Makefile
Makefile.in

View 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
View 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

View 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