610 lines
15 KiB
XML
610 lines
15 KiB
XML
<?xml version="1.0"?>
|
|
<!--
|
|
$Id$
|
|
|
|
|
|
_______________________________________ Layout _______________________________________
|
|
|
|
|
|
axis 0: aileron
|
|
axis 1: elevator
|
|
axis 2: rudder
|
|
axis 3: throttle
|
|
|
|
|
|
no modifier F3 F4 F3+F4
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
button 0 (trigger): brakes parking brake speed brake thrust revers.
|
|
button 1 (left): flaps up gear up previous view *
|
|
button 2 (middle): reset view dir tail wheel lock cockpit view reset all trim
|
|
button 3 (right): flaps down gear down next view *
|
|
button 4 (F1): brakes left * zoom out *
|
|
button 5 (F2): brakes right * zoom in *
|
|
button 6 (F3): //////////////////////// modifier 0 /////////////////////////
|
|
button 7 (F4): //////////////////////// modifier 1 /////////////////////////
|
|
button 8 (>>): * * * *
|
|
button 9 (<<): * * * *
|
|
hat left: look left leaner mixture aileron trim rudder trim
|
|
hat right: look right richer mixture aileron trim rudder trim
|
|
hat back: look down dec prop pitch elevator trim *
|
|
hat forward: look up inc prop pitch elevator trim *
|
|
|
|
|
|
F3 and F4 are used like "Shift", "Control", or "Alternate" on computer keyboards.
|
|
For example: press F3 and keep holding it down while pressing the fire
|
|
button/trigger -> toggle parking brake
|
|
|
|
When flying the Harrier, "F3/hat left" and "right" control the thrust vector.
|
|
|
|
|
|
|
|
With the keyboard's Control key pressed, the following keys have a different meaning:
|
|
|
|
Control + no modifier
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
button 0 (trigger): trigger selected weapon
|
|
button 1 (left): switch to previous weapon system
|
|
button 3 (right): switch to next weapobn system
|
|
|
|
|
|
|
|
___________________________________ Customization ____________________________________
|
|
|
|
|
|
|
|
If you want to change some (or all) of the bindings, the recommended way is
|
|
to copy this file to your home directory, make your changes there, and include
|
|
it from your personal preferences.xml file. You can use any number lower than
|
|
1000 for n in <js-named n="0">. The lowest takes precedence in case of identical
|
|
names. You can include such a preferences.xml file with the ~~config option,
|
|
e.g. ~~config=$HOME/.fgfs/preferences.xml, and you can put that ~~config line
|
|
into your personal $HOME/.fgfsrc file.
|
|
|
|
<?xml version="1.0"?>
|
|
<PropertyList>
|
|
<input>
|
|
<js-named n="100">
|
|
<joysticks include="your-modified-copy.xml"/>
|
|
</js-named>
|
|
</input>
|
|
</PropertyList>
|
|
|
|
|
|
The property "/input/joysticks/js[0]/data/modifier" indicates the "shift" level.
|
|
F3 sets bit 0, F4 sets bit 1. The property is zero if none of the shift buttons
|
|
is pressed, 1 if F3 is pressed, 2 if F4 is pressed, and 3 if both F3 and F4 are
|
|
pressed.
|
|
|
|
Note that you have to enclose nasal scripts in <script><![CDATA[...]]></script>
|
|
if they contain characters that interfere with the xml markup. This is the case
|
|
if you are, for example, using < (lower than). Alternatively, you can 'escape'
|
|
the character with "<".
|
|
|
|
Also note that all nasal code shares a common namespace, so it's possible to set
|
|
a variable in one nasal binding, and to read it in another.
|
|
|
|
|
|
|
|
____________________________________ References ______________________________________
|
|
|
|
|
|
|
|
Joysticks: $FG_ROOT/Docs/README.Joystick.html
|
|
Properties: see property browser (fgfs menu: "File"->"Browse internal properties")
|
|
|
|
Nasal: http://www.plausible.org/nasal/
|
|
Nasal examples: $FG_ROOT/Nasal/
|
|
|
|
|
|
______________________________________________________________________________________
|
|
|
|
~~ Melchior FRANZ <mfranz # aon : at>
|
|
-->
|
|
|
|
<PropertyList>
|
|
<name>SAITEK CYBORG 3D USB</name>
|
|
<name>CYBORG 3D USB</name>
|
|
|
|
<data>
|
|
<mode type="int">0</mode>
|
|
<modifier type="int">0</modifier>
|
|
</data>
|
|
|
|
<nasal>
|
|
<script><![CDATA[
|
|
self = cmdarg().getParent();
|
|
data = self.getNode("data");
|
|
mode = data.getNode("mode");
|
|
modifier = data.getNode("modifier");
|
|
f1 = f2 = 0;
|
|
left_brake = right_brake = 0;
|
|
trigger = 0;
|
|
|
|
if (props.globals.getNode("/rotors", 0) != nil) {
|
|
self.getNode("axis[0]/binding/power").setIntValue(1);
|
|
self.getNode("axis[1]/binding/power").setIntValue(1);
|
|
}
|
|
|
|
kbdshift = props.globals.getNode("/devices/status/keyboard/shift", 1);
|
|
kbdctrl = props.globals.getNode("/devices/status/keyboard/ctrl", 1);
|
|
kbdalt = props.globals.getNode("/devices/status/keyboard/alt", 1);
|
|
|
|
get_mode = func { modifier.getValue() + mode.getValue() * 4 }
|
|
|
|
harrier = func {
|
|
if (getprop("/sim/aero") == "harrier") {
|
|
thv = getprop("/controls/engines/engine[0]/mixture");
|
|
gui.popupTip("Thrust vector " ~ int(thv * 120 - 20));
|
|
}
|
|
}
|
|
]]></script>
|
|
</nasal>
|
|
|
|
<axis n="0">
|
|
<desc>aileron</desc>
|
|
<binding>
|
|
<command>property-scale</command>
|
|
<property>/controls/flight/aileron</property>
|
|
<power type="int">2</power>
|
|
</binding>
|
|
</axis>
|
|
|
|
<axis n="1">
|
|
<desc>elevator</desc>
|
|
<binding>
|
|
<command>property-scale</command>
|
|
<property>/controls/flight/elevator</property>
|
|
<factor type="double">-1.0</factor>
|
|
<power type="int">2</power>
|
|
</binding>
|
|
</axis>
|
|
|
|
<axis>
|
|
<desc>rudder</desc>
|
|
<number>
|
|
<unix>2</unix>
|
|
<mac>2</mac>
|
|
<windows>3</windows>
|
|
</number>
|
|
<binding>
|
|
<command>property-scale</command>
|
|
<property>/controls/flight/rudder</property>
|
|
<offset type="double">0.0</offset>
|
|
<factor type="double">1.0</factor>
|
|
<power type="int">2</power>
|
|
</binding>
|
|
</axis>
|
|
|
|
<axis>
|
|
<desc>throttle</desc>
|
|
<number>
|
|
<unix>3</unix>
|
|
<mac>2</mac>
|
|
<windows>2</windows>
|
|
</number>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>controls.throttleAxis()</script>
|
|
</binding>
|
|
</axis>
|
|
|
|
<button n="0">
|
|
<name>Trigger</name>
|
|
<desc>brakes, +Ctrl: fire, +F3: parking brake, +F4: speedbrake, +F3+F4: thrust reverser</desc>
|
|
<repeatable type="bool">false</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
if (kbdctrl.getBoolValue()) {
|
|
controls.trigger(trigger = 1);
|
|
} else {
|
|
controls.applyBrakes(1);
|
|
}
|
|
} elsif (m == 1) {
|
|
controls.applyBrakes(1);
|
|
} elsif (m == 2) {
|
|
#
|
|
} elsif (m == 3) {
|
|
#
|
|
}
|
|
</script>
|
|
</binding>
|
|
<mod-up>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
if (trigger) {
|
|
controls.trigger(trigger = 0);
|
|
} else {
|
|
controls.applyBrakes(0);
|
|
}
|
|
controls.applyBrakes(0);
|
|
} elsif (m == 1) {
|
|
i = controls.applyParkingBrake(1);
|
|
gui.popupTip("Parking Brake " ~ ["OFF", "ON"][i]);
|
|
controls.applyBrakes(0);
|
|
} elsif (m == 2) {
|
|
i = !getprop("/controls/flight/speedbrake");
|
|
setprop("/controls/flight/speedbrake", i);
|
|
gui.popupTip("Speed Brake " ~ ["OFF", "ON"][i]);
|
|
} elsif (m == 3) {
|
|
i = !getprop("/controls/engines/engine[0]/reverser");
|
|
props.setAll("/controls/engines/engine", "reverser", i);
|
|
gui.popupTip("Thrust Reverser " ~ ["OFF", "ON"][i]);
|
|
}
|
|
</script>
|
|
</binding>
|
|
</mod-up>
|
|
</button>
|
|
|
|
<button n="1">
|
|
<name>Left Button</name>
|
|
<desc>flaps up, +F3: gear up, +F4: previous view</desc>
|
|
<repeatable type="bool">false</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
if (kbdctrl.getBoolValue()) {
|
|
controls.weaponSelect(-1);
|
|
} else {
|
|
controls.flapsDown(-1);
|
|
}
|
|
} elsif (m == 1) {
|
|
controls.gearDown(-1);
|
|
} elsif (m == 2) {
|
|
view.stepView(-1);
|
|
} elsif (m == 3) {
|
|
#
|
|
}
|
|
</script>
|
|
</binding>
|
|
<mod-up>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
controls.flapsDown(0);
|
|
} elsif (m == 1) {
|
|
controls.gearDown(0);
|
|
} elsif (m == 2) {
|
|
#
|
|
} elsif (m == 3) {
|
|
#
|
|
}
|
|
</script>
|
|
</binding>
|
|
</mod-up>
|
|
</button>
|
|
|
|
<button n="2">
|
|
<name>Middle Button</name>
|
|
<desc>center view, +F3: toggle tail-wheel lock, +F4: reset view, +F3+F4: reset trim</desc>
|
|
<repeatable type="bool">false</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
view.resetView();
|
|
} elsif (m == 1) {
|
|
i = !getprop("/controls/gear/tailwheel-lock");
|
|
setprop("/controls/gear/tailwheel-lock", i);
|
|
gui.popupTip("Tail Wheel " ~ ["UNLOCKED", "LOCKED"][i]);
|
|
} elsif (m == 2) {
|
|
setprop("/sim/current-view/view-number", 0);
|
|
view.resetView();
|
|
} elsif (m == 3) {
|
|
setprop("/controls/flight/elevator-trim", 0);
|
|
setprop("/controls/flight/aileron-trim", 0);
|
|
setprop("/controls/flight/rudder-trim", 0);
|
|
}
|
|
</script>
|
|
</binding>
|
|
</button>
|
|
|
|
<button n="3">
|
|
<name>Right Button</name>
|
|
<desc>flaps down, +Ctrl: weapon select, +F3: gear down, +F4: next view</desc>
|
|
<repeatable type="bool">false</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
if (kbdctrl.getBoolValue()) {
|
|
controls.weaponSelect(1);
|
|
} else {
|
|
controls.flapsDown(1);
|
|
}
|
|
} elsif (m == 1) {
|
|
controls.gearDown(1);
|
|
} elsif (m == 2) {
|
|
view.stepView(1);
|
|
} elsif (m == 3) {
|
|
#
|
|
}
|
|
</script>
|
|
</binding>
|
|
<mod-up>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
controls.flapsDown(0);
|
|
} elsif (m == 1) {
|
|
controls.gearDown(0);
|
|
} elsif (m == 2) {
|
|
#
|
|
} elsif (m == 3) {
|
|
#
|
|
}
|
|
</script>
|
|
</binding>
|
|
</mod-up>
|
|
</button>
|
|
|
|
<button n="4">
|
|
<name>F1</name>
|
|
<desc>brakes left, +F4: zoom out</desc>
|
|
<repeatable type="bool">true</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
f1 = 1;
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
if (!left_brake) {
|
|
controls.applyBrakes(left_brake = 1, -1);
|
|
}
|
|
} elsif (m == 1) {
|
|
#
|
|
} elsif (m == 2) {
|
|
f2 ? view.resetFOV() : view.increase();
|
|
} elsif (m == 3) {
|
|
#
|
|
}
|
|
</script>
|
|
</binding>
|
|
<mod-up>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
f1 = 0;
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
controls.applyBrakes(left_brake = 0, -1);
|
|
} elsif (m == 1) {
|
|
#
|
|
} elsif (m == 2) {
|
|
#
|
|
} elsif (m == 3) {
|
|
#
|
|
}
|
|
</script>
|
|
</binding>
|
|
</mod-up>
|
|
</button>
|
|
|
|
<button n="5">
|
|
<name>F2</name>
|
|
<desc>brakes right, +F4: zoom in</desc>
|
|
<repeatable type="bool">true</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
f2 = 1;
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
if (!right_brake) {
|
|
controls.applyBrakes(right_brake = 1, 1);
|
|
}
|
|
} elsif (m == 1) {
|
|
#
|
|
} elsif (m == 2) {
|
|
f1 ? view.resetFOV() : view.decrease();
|
|
} elsif (m == 3) {
|
|
#
|
|
}
|
|
</script>
|
|
</binding>
|
|
<mod-up>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
f2 = 0;
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
controls.applyBrakes(right_brake = 0, 1);
|
|
} elsif (m == 1) {
|
|
#
|
|
} elsif (m == 2) {
|
|
#
|
|
} elsif (m == 3) {
|
|
#
|
|
}
|
|
</script>
|
|
</binding>
|
|
</mod-up>
|
|
</button>
|
|
|
|
<button n="6"><!-- bit 0 -->
|
|
<name>F3</name>
|
|
<desc>modifier for other buttons</desc>
|
|
<repeatable type="bool">false</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = modifier.getValue();
|
|
if (m == 0 or m == 2) {
|
|
modifier.setIntValue(m + 1);
|
|
}
|
|
</script>
|
|
</binding>
|
|
<mod-up>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = modifier.getValue();
|
|
if (m == 1 or m == 3) {
|
|
modifier.setIntValue(m - 1);
|
|
}
|
|
</script>
|
|
</binding>
|
|
</mod-up>
|
|
</button>
|
|
|
|
<button n="7"><!-- bit 1 -->
|
|
<name>F4</name>
|
|
<desc>modifier for other buttons</desc>
|
|
<repeatable type="bool">false</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = modifier.getValue();
|
|
if (m == 0 or m == 1) {
|
|
modifier.setIntValue(m + 2);
|
|
}
|
|
</script>
|
|
</binding>
|
|
<mod-up>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = modifier.getValue();
|
|
if (m == 2 or m == 3) {
|
|
modifier.setIntValue(m - 2);
|
|
}
|
|
</script>
|
|
</binding>
|
|
</mod-up>
|
|
</button>
|
|
|
|
<button n="8">
|
|
<name>>></name>
|
|
<desc>unused</desc>
|
|
<repeatable type="bool">false</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
<![CDATA[
|
|
text = "read $FG_ROOT/Input/Joysticks/Saitek/Cyborg-Gold-3d-USB.xml";
|
|
print("Please " ~ text ~ " for the full joystick layout.");
|
|
gui.popupTip(text);
|
|
]]>
|
|
</script>
|
|
</binding>
|
|
</button>
|
|
|
|
<button n="9">
|
|
<name><<</name>
|
|
<desc>unused</desc>
|
|
<repeatable type="bool">false</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
<![CDATA[
|
|
text = "read $FG_ROOT/Input/Joysticks/Saitek/Cyborg-Gold-3d-USB.xml";
|
|
print("Please " ~ text ~ " for the full joystick layout.");
|
|
gui.popupTip(text);
|
|
]]>
|
|
</script>
|
|
</binding>
|
|
</button>
|
|
|
|
<button n="10">
|
|
<name>Hat Up</name>
|
|
<desc>view up, +F3: increase prop pitch, +F4: elevator trim down</desc>
|
|
<repeatable>true</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
view.panViewPitch(1);
|
|
} elsif (m == 1) {
|
|
controls.adjPropeller(1);
|
|
} elsif (m == 2) {
|
|
controls.elevatorTrim(0.75);
|
|
} elsif (m == 3) {
|
|
#
|
|
}
|
|
</script>
|
|
</binding>
|
|
</button>
|
|
|
|
<button n="11">
|
|
<name>Hat Left</name>
|
|
<desc>view left, +F3: mixture leaner, +F4: aileron trim left, +F3+F4: rudder trim left</desc>
|
|
<repeatable>true</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
v = getprop("/sim/current-view/view-number");
|
|
view.panViewDir(v == 0 or v == 4 ? 1 : -1);
|
|
} elsif (m == 1) {
|
|
controls.adjMixture(-1);
|
|
harrier();
|
|
} elsif (m == 2) {
|
|
controls.aileronTrim(-0.75);
|
|
} elsif (m == 3) {
|
|
controls.rudderTrim(-0.75);
|
|
}
|
|
</script>
|
|
</binding>
|
|
</button>
|
|
|
|
<button n="12">
|
|
<name>Hat Right</name>
|
|
<desc>view right, +F3: mixture richer, +F4: aileron trim right, +F3+F4: rudder trim right</desc>
|
|
<repeatable>true</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
v = getprop("/sim/current-view/view-number");
|
|
view.panViewDir(v == 0 or v == 4 ? -1 : 1);
|
|
} elsif (m == 1) {
|
|
controls.adjMixture(1);
|
|
harrier();
|
|
} elsif (m == 2) {
|
|
controls.aileronTrim(0.75);
|
|
} elsif (m == 3) {
|
|
controls.rudderTrim(0.75);
|
|
}
|
|
</script>
|
|
</binding>
|
|
</button>
|
|
|
|
<button n="13">
|
|
<name>Hat Down</name>
|
|
<desc>view down, +F3: decrease prop pitch, +F4: elevator trim up</desc>
|
|
<repeatable>true</repeatable>
|
|
<binding>
|
|
<command>nasal</command>
|
|
<script>
|
|
m = get_mode();
|
|
if (m == 0) {
|
|
view.panViewPitch(-1);
|
|
} elsif (m == 1) {
|
|
controls.adjPropeller(-1);
|
|
} elsif (m == 2) {
|
|
controls.elevatorTrim(-0.75);
|
|
} elsif (m == 3) {
|
|
#
|
|
}
|
|
</script>
|
|
</binding>
|
|
</button>
|
|
</PropertyList>
|
|
|