warthog: support multiple overlay files; stick rotate; read hw state
This commit is contained in:
parent
0e321472d0
commit
a957cf9797
5 changed files with 109 additions and 21 deletions
|
@ -16,9 +16,11 @@ by the contents of property "x":
|
||||||
- generic.xml
|
- generic.xml
|
||||||
- helicopter.xml (only helicopters)
|
- helicopter.xml (only helicopters)
|
||||||
- </sim/type>.xml (some aircraft set this property to "seaplane")
|
- </sim/type>.xml (some aircraft set this property to "seaplane")
|
||||||
- </input/joysticks/overlay>.xml (not used by the system; meant to
|
- </input/joysticks/overlays>.xml (not used by the system; meant to
|
||||||
be set on the command line or in wrapper scripts,
|
be set on the command line or in wrapper scripts,
|
||||||
for example: --prop:input/joysticks/overlay=modern_jet)
|
for example: --prop:input/joysticks/overlays=modern_jet;
|
||||||
|
accepts a single overlay file name -- withtout extension --
|
||||||
|
or a list of names separated by colon ":")
|
||||||
- </sim/aircraft>.xml (aircraft name, for example "harrier.xml")
|
- </sim/aircraft>.xml (aircraft name, for example "harrier.xml")
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,6 +39,15 @@ and variables.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Standard overlay files:
|
||||||
|
- stick_rotate: rotates stick X/Y axis by given angle. Apparently desired
|
||||||
|
by some users who have the stick between their knees and want to move it
|
||||||
|
in a more natural fashion. Usage:
|
||||||
|
|
||||||
|
fgfs --prop:input/joysticks/overlays=stick_rotate --prop:d:input/joysticks/stick-angle=15
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Joystick configuration from within FlightGear under Linux:
|
Joystick configuration from within FlightGear under Linux:
|
||||||
|
|
54
Input/Joysticks/ThrustMaster/Warthog/Stick/stick_rotate.xml
Normal file
54
Input/Joysticks/ThrustMaster/Warthog/Stick/stick_rotate.xml
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
Overlay that rotates the stick angle.
|
||||||
|
Copyright (c) 2011 Melchior FRANZ mfranz # aon : at
|
||||||
|
|
||||||
|
Usage: fgfs ~~prop:input/joysticks/overlays=stick_rotate ~~prop:d:input/joysticks/stick-angle=15
|
||||||
|
-->
|
||||||
|
|
||||||
|
<PropertyList>
|
||||||
|
<nasal>
|
||||||
|
<script>
|
||||||
|
var stick = {
|
||||||
|
init: func {
|
||||||
|
me.x = me.y = 0;
|
||||||
|
jslistener("/input/joysticks/stick-angle", func(n) {
|
||||||
|
me.angle = n.getValue() * D2R;
|
||||||
|
me.sin = math.sin(me.angle);
|
||||||
|
me.cos = math.cos(me.angle);
|
||||||
|
}, 1);
|
||||||
|
},
|
||||||
|
value: func cmdarg().getNode("setting").getValue(),
|
||||||
|
setx: func {
|
||||||
|
me.x = me.value();
|
||||||
|
me.update();
|
||||||
|
},
|
||||||
|
sety: func {
|
||||||
|
me.y = -me.value();
|
||||||
|
me.update();
|
||||||
|
},
|
||||||
|
update: func {
|
||||||
|
setprop("/controls/flight/aileron", me.x * me.cos + me.y * me.sin);
|
||||||
|
setprop("/controls/flight/elevator", me.y * me.cos - me.x * me.sin);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
stick.init();
|
||||||
|
</script>
|
||||||
|
</nasal>
|
||||||
|
|
||||||
|
<axis n="0">
|
||||||
|
<tolerance>0.00001</tolerance>
|
||||||
|
<binding>
|
||||||
|
<command>nasal</command>
|
||||||
|
<script>stick.setx()</script>
|
||||||
|
</binding>
|
||||||
|
</axis>
|
||||||
|
|
||||||
|
<axis n="1">
|
||||||
|
<tolerance>0.00001</tolerance>
|
||||||
|
<binding>
|
||||||
|
<command>nasal</command>
|
||||||
|
<script>stick.sety()</script>
|
||||||
|
</binding>
|
||||||
|
</axis>
|
||||||
|
</PropertyList>
|
|
@ -24,7 +24,6 @@
|
||||||
var popup = func gui.popupTip(call(sprintf, arg));
|
var popup = func gui.popupTip(call(sprintf, arg));
|
||||||
var is_helicopter = (func {(var n = props.globals.getNode("rotors", 0)) != nil and n.getAttribute("children")})();
|
var is_helicopter = (func {(var n = props.globals.getNode("rotors", 0)) != nil and n.getAttribute("children")})();
|
||||||
var aircraft_type = getprop("/sim/type");
|
var aircraft_type = getprop("/sim/type");
|
||||||
var overlay = getprop("/input/joysticks/overlay");
|
|
||||||
|
|
||||||
var load_overlay = func(name) {
|
var load_overlay = func(name) {
|
||||||
foreach (var dir; [getprop("/sim/fg-home"), getprop("/sim/fg-root")]) {
|
foreach (var dir; [getprop("/sim/fg-home"), getprop("/sim/fg-root")]) {
|
||||||
|
@ -66,8 +65,8 @@
|
||||||
load_overlay("helicopter");
|
load_overlay("helicopter");
|
||||||
if (aircraft_type)
|
if (aircraft_type)
|
||||||
load_overlay(aircraft_type);
|
load_overlay(aircraft_type);
|
||||||
if (overlay)
|
foreach (var o; split(":", getprop("/input/joysticks/overlays") or ""))
|
||||||
load_overlay(overlay);
|
load_overlay(o);
|
||||||
load_overlay(getprop("/sim/aircraft"));
|
load_overlay(getprop("/sim/aircraft"));
|
||||||
</script>
|
</script>
|
||||||
</nasal>
|
</nasal>
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
var popup = func gui.popupTip(call(sprintf, arg));
|
var popup = func gui.popupTip(call(sprintf, arg));
|
||||||
var is_helicopter = (func {(var n = props.globals.getNode("rotors", 0)) != nil and n.getAttribute("children")})();
|
var is_helicopter = (func {(var n = props.globals.getNode("rotors", 0)) != nil and n.getAttribute("children")})();
|
||||||
var aircraft_type = getprop("/sim/type");
|
var aircraft_type = getprop("/sim/type");
|
||||||
var overlay = getprop("/input/joysticks/overlay");
|
|
||||||
|
|
||||||
var load_overlay = func(name) {
|
var load_overlay = func(name) {
|
||||||
foreach (var dir; [getprop("/sim/fg-home"), getprop("/sim/fg-root")]) {
|
foreach (var dir; [getprop("/sim/fg-home"), getprop("/sim/fg-root")]) {
|
||||||
|
@ -65,8 +64,8 @@
|
||||||
load_overlay("helicopter");
|
load_overlay("helicopter");
|
||||||
if (aircraft_type)
|
if (aircraft_type)
|
||||||
load_overlay(aircraft_type);
|
load_overlay(aircraft_type);
|
||||||
if (overlay)
|
foreach (var o; split(":", getprop("/input/joysticks/overlays") or ""))
|
||||||
load_overlay(overlay);
|
load_overlay(o);
|
||||||
load_overlay(getprop("/sim/aircraft"));
|
load_overlay(getprop("/sim/aircraft"));
|
||||||
</script>
|
</script>
|
||||||
</nasal>
|
</nasal>
|
||||||
|
|
|
@ -1,61 +1,86 @@
|
||||||
# Hardware Interface (currently Linux/HIDRAW-only; see README)
|
# Hardware Interface (currently Linux/HIDRAW-only)
|
||||||
|
# see README and http://members.aon.at/mfranz/warthog.html
|
||||||
|
|
||||||
|
|
||||||
|
if (io.stat("/dev/input") != nil and io.stat("/dev/input/hidraw") == nil) {
|
||||||
|
print("warthog: read file $FG_ROOT/Input/Joysticks/ThrustMaster/Warthog/README");
|
||||||
|
print(" for how to enable FlightGear to set backlight and LEDs etc.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var device = {
|
var device = {
|
||||||
new: func(path, bufsize) {
|
new: func(path, bufsize) {
|
||||||
var m = { parents: [device] };
|
var m = { parents: [device] };
|
||||||
m.path = path;
|
m.path = path;
|
||||||
m.bufsize = bufsize;
|
m.bufsize = bufsize;
|
||||||
m.leds = 0;
|
m.data = bits.buf(m.bufsize);
|
||||||
m.bright = 0;
|
|
||||||
var stat = io.stat(m.path);
|
var stat = io.stat(m.path);
|
||||||
if (stat == nil or stat[11] != "chr")
|
if (stat == nil or stat[11] != "chr")
|
||||||
m.send = func { nil };
|
m.send = m.receive = func {};
|
||||||
return m;
|
return m;
|
||||||
},
|
},
|
||||||
send: func {
|
send: func {
|
||||||
var buf = bits.buf(me.bufsize);
|
var buf = bits.buf(me.bufsize);
|
||||||
buf[0] = 1;
|
|
||||||
forindex (var i; arg)
|
forindex (var i; arg)
|
||||||
buf[i + 1] = arg[i];
|
buf[i] = arg[i];
|
||||||
var file = io.open(me.path, "wb");
|
var file = io.open(me.path, "wb");
|
||||||
io.write(file, buf);
|
io.write(file, buf);
|
||||||
io.close(file);
|
io.close(file);
|
||||||
},
|
},
|
||||||
|
receive: func {
|
||||||
|
var file = io.open(me.path, "rb");
|
||||||
|
io.read(file, me.data, me.bufsize);
|
||||||
|
io.close(file);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var joystick = {
|
var joystick = {
|
||||||
parents: [device.new("/dev/input/hidraw/Thustmaster_Joystick_-_HOTAS_Warthog", 12)],
|
parents: [device.new("/dev/input/hidraw/Thustmaster_Joystick_-_HOTAS_Warthog", 12)],
|
||||||
|
init: func {
|
||||||
|
me.receive();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var throttle = {
|
var throttle = {
|
||||||
parents: [device.new("/dev/input/hidraw/Thrustmaster_Throttle_-_HOTAS_Warthog", 36)],
|
parents: [device.new("/dev/input/hidraw/Thrustmaster_Throttle_-_HOTAS_Warthog", 36)],
|
||||||
|
init: func {
|
||||||
|
me.receive();
|
||||||
|
me.leds = me.data[26];
|
||||||
|
me.brightness = me.data[27];
|
||||||
|
},
|
||||||
set_leds: func(state, which...) { # on/off, list of leds (0: background, 1-5)
|
set_leds: func(state, which...) { # on/off, list of leds (0: background, 1-5)
|
||||||
|
var leds = me.leds;
|
||||||
foreach (var w; which)
|
foreach (var w; which)
|
||||||
me.leds = bits.switch(me.leds, me._ledmap[w], state);
|
me.leds = bits.switch(me.leds, me._ledmap[w], state);
|
||||||
me.send(6, me.leds, me.bright);
|
if (me.leds != leds)
|
||||||
|
me.send(1, 6, me.leds, me.brightness);
|
||||||
},
|
},
|
||||||
toggle_leds: func(which...) {
|
toggle_leds: func(which...) {
|
||||||
foreach (var w; which)
|
foreach (var w; which)
|
||||||
me.leds = bits.toggle(me.leds, me._ledmap[w]);
|
me.leds = bits.toggle(me.leds, me._ledmap[w]);
|
||||||
me.send(6, me.leds, me.bright);
|
me.send(1, 6, me.leds, me.brightness);
|
||||||
},
|
},
|
||||||
set_brightness: func(v) { # clamped to [0,5], where 0 is off and 5 is bright
|
set_brightness: func(v) { # clamped to [0,5], where 0 is off and 5 is bright
|
||||||
me.send(6, me.leds, me.bright = v < 0 ? 0 : v > 5 ? 5 : v);
|
if (v != me.brightness)
|
||||||
|
me.send(1, 6, me.leds, me.brightness = v < 0 ? 0 : v > 5 ? 5 : v);
|
||||||
},
|
},
|
||||||
brighter: func {
|
brighter: func {
|
||||||
me.leds = bits.set(me.leds, me._ledmap[0]);
|
me.leds = bits.set(me.leds, me._ledmap[0]);
|
||||||
me.set_brightness(me.bright + 1);
|
me.set_brightness(me.brightness + 1);
|
||||||
},
|
},
|
||||||
darker: func {
|
darker: func {
|
||||||
me.leds = bits.set(me.leds, me._ledmap[0]);
|
me.leds = bits.set(me.leds, me._ledmap[0]);
|
||||||
me.set_brightness(me.bright - 1);
|
me.set_brightness(me.brightness - 1);
|
||||||
},
|
},
|
||||||
_ledmap: {0: 3, 1: 2, 2: 1, 3: 4, 4: 0, 5: 6},
|
_ledmap: {0: 3, 1: 2, 2: 1, 3: 4, 4: 0, 5: 6},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
throttle.set_brightness(1); # LEDs dark (but on)
|
joystick.init();
|
||||||
throttle.set_leds(1, 0); # backlight on
|
throttle.init(); # read configuration
|
||||||
|
|
||||||
|
throttle.set_brightness(1); # LEDs dark (but on)
|
||||||
|
throttle.set_leds(1, 0); # backlight on
|
||||||
setlistener("/sim/signals/exit", func throttle.set_leds(0, 1, 2, 3, 4, 5), 1); # other LEDs off (now and at exit)
|
setlistener("/sim/signals/exit", func throttle.set_leds(0, 1, 2, 3, 4, 5), 1); # other LEDs off (now and at exit)
|
||||||
|
|
Loading…
Reference in a new issue