OK, more code at:

   http://www.plausible.org/andy/fg-nasal-1.3.tar.gz

This one is essentially bug fixes to the engine, mostly with garbage
collection issues: making sure that everything is findable when the
collector runs and that important stuff (like, heh, the global
namespace) doesn't get collected accidentally.

One new feature is that command bindings pick up the "value" and/or
"offset" arguments from the SGPropertyNode argument.  This was needed
for the mouse axis handlers below.  A better interface would wrap the
SGPropertyNode object more elaborately -- not everything lives in the
global tree.

The first new script file is fuel.nas, the fuel selector handler that
I posted yesterday.  It works to the extent that it runs silently and
doesn't interfere with existing FDMs.  Doing useful things requires a
few lines of YASim modifications that I'm not done with yet.  But it's
still a good example of what can be done with Nasal.  Consider writing
specialized handlers for weird aircraft.  Don't like what the default
fuel system does?  Just hook it (i.e. "fuel.update = myNewFunction")
and rewrite it.

The second is more of a fun proof of concept.  I went looking for an
example of a situation where the "property tree as programming
language" idiom got pushed a little far, and found the mouse handler
system.  It works great, obviously, but it's big.  The existing
mice.xml is a very large file, and because of the lack of a "real"
programming language has to resort to some clumsy constructions in
places -- every mode defines duplicate handlers for the right, up, and
down mouse buttons, for example.  And for efficiency, it has to be
backed up by a non-trivial amount of C++ code in input.cxx that
pre-computes caches the values that it finds in the property tree.

Instead, take a look at mouse.nas -- it's (almost) a complete
reimplementation of the mouse system.  It uses a tiny bootstrap
mice.xml file to hooks all input for a single mode to Nasal handlers.
Written in Nasal, where you can combine the data (mode definitions)
and code (utility functions), this kind of thing is trivial.  And it's
really very clean; a mode is just an object with methods, there's a
list of modes that a nextMode() method iterates through.  It even uses
object inheritence to allow the nextMode() and elevator trim handlers
to be inherited from a default mode.

If you want to try this (it's not really production code, but it's fun
to play with), you'll need to replace your mice.xml file with the one
that is attached to this message.  You will also need to modify your
input.cxx file a little; the caching of data gets in the way of a
system that is trying to set it via the property tree at runtime.
Just replace the FGInput::_update_mouse() method with the following
two-liner which re-reads the appropriate properties every frame
instead of using the cached values:

void FGInput::_update_mouse()
{
  mouse &m = _mouse_bindings[0];
  m.modes[0].constrained = m.mode_node->getBoolValue("constrained", false);
  m.modes[0].pass_through = m.mode_node->getBoolValue("pass-through",
false);
}

The new code does everything the old does except for the warping of
the mouse cursor at mode change (no API for that from either Nasal or
the property tree) and mouse cursor changing (I was too lazy to put
the list of Glut cursor names into the Nasal script).

The point here isn't to replace the existing mouse code -- it's
stable, solid, has been debugged for a long time and doesn't do
anything wrong.  But it's also worth pointing out that the mouse.nas
script is significantly smaller than the existing C++ code, does
almost all the work itself, is (IMHO) easier to read and modify.  It's
even smaller than the mice.xml configuration file was by itself A
complete reimplementation that eliminated the mode-handling C++ code
entirely would be much smaller still (basically, it would just forward
the Glut callbacks to Nasal bindings and watch the constrained,
pass-through, and cursor properties for changes).

Anyway, have fun, try it, and report bugs.  I'm not bored yet, so this
isn't going away. :)

Andy

<?xml version="1.0"?>

<!--
 This is a trivial "bootstrap" configuration that does nothing but
 forward all mouse events to handler functions in the mouse.nas
 Nasal script.  The "constrained", and "pass-through" features
 require some C++-level support.  See attached email...
-->

<PropertyList>
 <mouse>
  <mode-count>1</mode-count>
  <mode>0</mode>
  <mode n="0">
   <cursor>inherit</cursor>
   <constrained type="bool">false</constrained>
   <pass-through type="bool">true</pass-through>

   <button n="0">
    <binding>
     <command>nasal</command><script> mouse.handleButton0() </script>
    </binding>
   </button>
   <button n="1">
    <binding>
     <command>nasal</command><script> mouse.handleButton1() </script>
    </binding>
   </button>
   <button n="2">
    <binding>
     <command>nasal</command><script> mouse.handleButton2() </script>
    </binding>
   </button>
   <button n="3">
    <binding>
     <command>nasal</command><script> mouse.handleButton3() </script>
    </binding>
   </button>
   <button n="4">
    <binding>
     <command>nasal</command><script> mouse.handleButton4() </script>
    </binding>
   </button>

   <x-axis>
    <binding>
     <command>nasal</command><script> mouse.handleXAxis(offset) </script>
    </binding>
   </x-axis>
   <y-axis>
    <binding>
     <command>nasal</command><script> mouse.handleYAxis(offset) </script>
    </binding>
   </y-axis>

  </mode>
 </mouse>
</PropertyList>

_______________________________________________
Flightgear-devel mailing list
[EMAIL PROTECTED]
http://mail.flightgear.org/mailman/listinfo/flightgear-devel

Reply via email to