I wrote: > 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).
That's one of those limitations that sounds kinda dumb when you see it in email. :) So here's an updated mouse.nas file that does (I think) literally everything that the existing mouse system does; and it fixes a few bugs with property names and directions, too. Again, the purpose here isn't to rewrite the mouse system, but to demonstrate how easy and clean it can be to write non-trivial functionality in Nasal. You'll need this hacked version of _update_mouse in your input.cxx to make things work: void FGInput::_update_mouse () { // // Hacked method to support Andy's mouse.nas script. Not to be // checked in. // 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); int oldCursor = m.modes[0].cursor; m.modes[0].cursor = m.mode_node->getIntValue("cursor", GLUT_CURSOR_INHERIT); if(oldCursor != m.modes[0].cursor) { glutSetCursor(m.modes[0].cursor); m.x = fgGetInt("/sim/startup/xsize", 800) / 2; m.y = fgGetInt("/sim/startup/ysize", 600) / 2; glutWarpPointer(m.x, m.y); } }
print("Loading mouse.nas"); # Cursor constants lifted from glut.h # Propertly, these should be synchronized with a FlightGear # definition, and not depend silently on a 3rd party include file. Cursors = { RIGHT_ARROW : 0, LEFT_ARROW : 1, INFO : 2, DESTROY : 3, HELP : 4, CYCLE : 5, SPRAY : 6, WAIT : 7, TEXT : 8, CROSSHAIR : 9, UP_DOWN : 10, LEFT_RIGHT : 11, TOP_SIDE : 12, BOTTOM_SIDE : 13, LEFT_SIDE : 14, RIGHT_SIDE : 15, TOP_LEFT_CORNER : 16, TOP_RIGHT_CORNER : 17, BOTTOM_RIGHT_CORNER : 18, BOTTOM_LEFT_CORNER : 19, INHERIT : 100, NONE : 101, FULL_CROSSHAIR : 102 }; # General utilities. This should probably live in a separate package, # or be implemented as extension functions. wrap = func { min = arg[0]; max = arg[1]; val = arg[2]; while(val < min) { val = val + (max-min); } while(val > max) { val = val - (max-min); } return val; } clamp = func { min = arg[0]; max = arg[1]; val = arg[2]; return if(val>max){max}elsif(val<min){min}else{val}; } adjprop = func { min = arg[0]; max = arg[1]; prop = arg[2]; val = arg[3]; v0 = getprop(prop); if(v0 == nil) { v0 = 0; } val = clamp(min, max, v0 + val); setprop(prop, val); } # Property tree root of the mouse properties. MouseRoot = "/devices/status/mice/mouse"; # Returns 0: no buttons pressed, 1: left, 2: middle, 3: both buttonState = func { result = 0; if(getprop(MouseRoot, "button[0]")) { result = result + 1; } if(getprop(MouseRoot, "button[1]")) { result = result + 2; } return result; } ######################################################################## # Mode object methods ######################################################################## Modes = []; # Forward reference. Will redefine later CurrMode = 0; # Cycle to the next mode. # Making the mode properties work requires changes to input.cxx nextMode = func { n = 1 + CurrMode; if(n >= size(Modes)) { n = 0; } CurrMode = n; print("nextMode: ", CurrMode); setprop(MouseRoot, "mode", "cursor", Modes[n].cursor); setprop(MouseRoot, "mode", "constrained", Modes[n].constrained); setprop(MouseRoot, "mode", "passThrough", Modes[n].passThrough); } # Center the view centerView = func { print("centerView()"); v = getprop("/sim/view/config/front-direction-deg"); setprop("/sim/current-view/heading-offset-deg", v); v = getprop("/sim/current-view/config/pitch-offset-deg"); setprop("/sim/current-view/goal-pitch-offset-deg", v); } # Pan the view horizontally lookX = func { if(buttonState() != 0) { return }; val = arg[0] * -360 + getprop("/sim/current-view/heading-offset-deg"); setprop("/sim/current-view/heading-offset-deg", wrap(0, 360, val)); } # Pan the view vertically lookY = func { if(buttonState() != 0) { return }; val = arg[0] * -180 + getprop("/sim/current-view/pitch-offset-deg"); setprop("/sim/current-view/pitch-offset-deg", clamp(-90, 90, val)); } # Handle horizontal mouse motion in control mode controlX = func { s = buttonState(); if (s == 0) { prop = "/controls/flight/aileron"; } elsif(s == 1) { prop = "/controls/flight/rudder"; } else { return; } adjprop(-1, 1, prop, 4 * arg[0]); } # Handle vertical mouse motion in control mode controlY = func { s = buttonState(); min = -1; if (s == 0) { prop = "/controls/flight/elevator"; } elsif(s == 2) { prop = "/controls/engines/engine[0]/throttle"; min = 0; } else { return; } adjprop(min, 1, prop, -4 * arg[0]); } ######################################################################## # Mode definitions. These define "objects" to implement each mode. # Note the use of Nasal inheritence via the parents array. ######################################################################## PointerMode = { cursor : Cursors.INHERIT, constrained : 0, passThrough : 1, button0 : func {}, button1 : func {}, button2 : nextMode, button3 : func { adjprop("/controls/flight/elevator-trim", 0.002) }, button4 : func { adjprop("/controls/flight/elevator-trim", -0.002) }, xAxis : func {}, yAxis : func {} }; ControlMode = { parents : [PointerMode], cursor : Cursors.CROSSHAIR, constrained : 1, passThrough : 0, xAxis : controlX, yAxis : controlY, }; LookMode = { parents : [PointerMode], cursor : Cursors.LEFT_RIGHT, constrained : 1, passThrough : 0, button0 : centerView, xAxis : lookX, yAxis : lookY, }; Modes = [PointerMode, ControlMode, LookMode]; ######################################################################## # Handlers for stuff in the XML file. Translate FG commands into # method calls on the current mode. ######################################################################## handleButton0 = func { Modes[CurrMode].button0() } handleButton1 = func { Modes[CurrMode].button1() } handleButton2 = func { Modes[CurrMode].button2() } handleButton3 = func { Modes[CurrMode].button3() } handleButton4 = func { Modes[CurrMode].button4() } handleXAxis = func { Modes[CurrMode].xAxis(arg[0]); } handleYAxis = func { Modes[CurrMode].yAxis(arg[0]); } print("mouse.nas initialization finished");
_______________________________________________ Flightgear-devel mailing list [EMAIL PROTECTED] http://mail.flightgear.org/mailman/listinfo/flightgear-devel