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