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

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

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

View file

@ -109,6 +109,7 @@
#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.
////////////////////////////////////////////////////////////////////

View file

@ -27,6 +27,7 @@ SUBDIRS = \
$(NETWORK_DIRS) \
Objects \
Scenery \
Scripting \
Sound \
Systems \
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