1
0
Fork 0
fgdata/Input/Joysticks/Default/joypad.xml

510 lines
14 KiB
XML

<?xml version="1.0"?>
<!--
generic.xml - FlightGear driver for the DragonRise Inc. Generic USB Joystick
Copyright (C) 2013 Florent Rougon
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************
* Axes and Buttons Layout *
******************************************************************************
In the following ASCII-art representation of the joypad:
- a single digit represents a button (and gives the button number);
- a digit followed by a + or - sign represents an axis direction (and gives
the axis number).
The Top View below shows 4 real axes (0 and 1 on the left stick, 3 and 4 on
the right stick) and 2 pseudo-axes (5 and 6). Pseudo-axes are simple buttons
in the hardware. Contrary to a real axis, each pseudo-axis only allows 3
values: -1, 0, 1.
Don't forget to put the joypad in analog mode! This changes the center point of
axes, for one.
Top View
~~~~~~~~~
6- 0
5- 5+ 8 (SELECT) (START) 9 3 1
6+ ANALOG 2
1- 4-
0- 0+ 3- 3+
1+ 4+
(buttons and axes numbers obtained on Linux)
Bottom View
~~~~~~~~~~~
5 4
7 6
(buttons numbers obtained on Linux)
******************************************************************************
* Buttons and Axes Bindings *
******************************************************************************
Modifiers
~~~~~~~~~
The two pseudo-axes (5 and 6) are used to define three variables (mod1, mod2,
mod3) that act as modifiers for other buttons and axes.
Initially, mod1 == mod2 == mod3 == 0.
Pressing button 6- toggles mod1 between the values 0 and 1.
Pressing button 6+ toggles mod2 between the values 0 and 1 (mod2 is
currently unused).
When neither 5- nor 5+ is pressed: mod3 == 0
As long as 5- is pressed and 5+ is released: mod3 == -1
As long as 5+ is pressed and 5- is released: mod3 == 1
(the result of holding both 5- and 5+ at the same time is undefined)
Bindings that don't depend on modifier states
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Axis 0 Aileron
Axis 1 Elevator
Axis 3 Rudder
Button 4 View Cycle (backward)
Button 5 View Cycle (forward)
Button 6 View Decrease
Button 7 View Increase
When mod3 == 0
~~~~~~~~~~~~~~
[if mod1 == 0]
Axis 4 Throttle
Button 0 View Up
Button 1 View Right
Button 2 View Down
Button 3 View Left
Button 8 Apply Brakes
Button 9 Select Initial View and Recenter
[if mod1 == 1]
Button 3 Trigger (weapon)
Button 1 Trigger1 (other weapon)
When mod3 == -1
~~~~~~~~~~~~~~~
Axis 4 Elevator Trim
Button 0 Flaps Up
Button 2 Flaps Down
Button 3 Brake Left
Button 1 Brake Right
Button 8 Aileron and Rudder Dance (for kids!)
Button 9 Reset Zoom to Default
When mod3 == 1
~~~~~~~~~~~~~~
Axis 4 Mixture Control
Button 0 Select First Engine
Button 1 Select Second Engine
Button 2 Select Third Engine
Button 3 Select Fourth Engine
Button 9 Select All Engines
-->
<PropertyList>
<name>DragonRise Inc. Generic USB Joystick </name>
<nasal>
<script>
var (mod1, mod2, mod3) = (0, 0, 0);
# These variables are used to emulate non-repeatable buttons when
# mod3 != 0.
var (button0_with_mod3, button1_with_mod3, button2_with_mod3,
button3_with_mod3) = (0, 0, 0, 0);
var initial_goal_heading_offset_deg =
getprop("/sim/current-view/goal-heading-offset-deg") or 0.0;
var initial_goal_pitch_offset_deg =
getprop("/sim/current-view/goal-pitch-offset-deg") or 0.0;
</script>
</nasal>
<axis n="0">
<desc>Aileron</desc>
<binding>
<command>property-scale</command>
<property>/controls/flight/aileron</property>
<!-- I need the following offset when the joypad is in analog mode. -->
<offset type="double">-0.01028</offset>
<factor type="double">0.5</factor>
</binding>
</axis>
<axis n="1">
<desc>Elevator</desc>
<binding>
<command>property-scale</command>
<property>/controls/flight/elevator</property>
<!-- I need the following offset when the joypad is in analog mode. -->
<offset type="double">-0.01028</offset>
<factor type="double">-0.5</factor>
</binding>
</axis>
<axis n="3">
<desc>Rudder</desc>
<binding>
<command>property-scale</command>
<property>/controls/flight/rudder</property>
<!-- I need the following offset when the joypad is in analog mode. -->
<offset type="double">-0.01028</offset>
</binding>
</axis>
<axis n="4">
<desc>Throttle [mod3=0] / Mixture Control [mod3=1] / Elevator Trim [mod3=-1]</desc>
<high>
<repeatable type="bool">true</repeatable>
<binding>
<command>nasal</command>
<script>
if (mod3 == 0) {
controls.adjThrottle(-1.0);
} elsif (mod3 == 1) {
controls.adjMixture(-1);
} else {
setprop("/controls/flight/elevator-trim",
-0.001 + getprop("/controls/flight/elevator-trim"));
}
</script>
</binding>
</high>
<low>
<repeatable type="bool">true</repeatable>
<binding>
<command>nasal</command>
<script>
if (mod3 == 0) {
controls.adjThrottle(1.0);
} elsif (mod3 == 1) {
controls.adjMixture(1);
} else {
setprop("/controls/flight/elevator-trim",
0.001 + getprop("/controls/flight/elevator-trim"));
}
</script>
</binding>
</low>
</axis>
<axis n="5">
<name>mod3_switch</name>
<desc>Switch mod3 between the values -1, 0, 1</desc>
<binding>
<command>nasal</command>
<script>
mod3 = cmdarg().getNode("setting").getValue();
# gui.popupTip("DragonRise.mod3 = " ~ mod3, 2);
</script>
</binding>
</axis>
<axis n="6">
<name>mod1_mod2_toggle</name>
<desc>Toggle mod1 and mod2</desc>
<low>
<binding>
<command>nasal</command>
<script>
mod1 = !mod1;
gui.popupTip("DragonRise.mod1 = " ~ mod1, 2);
</script>
</binding>
</low>
<high>
<binding>
<command>nasal</command>
<script>
mod2 = !mod2;
gui.popupTip("DragonRise.mod2 = " ~ mod2, 2);
</script>
</binding>
</high>
</axis>
<button n="0">
<desc>View Up [mod3=0] / Select first engine [mod3=1] / Flaps Up [mod3=-1]</desc>
<repeatable type="bool">true</repeatable>
<binding>
<command>nasal</command>
<script>
if (mod3 == 0) {
setprop("/sim/current-view/goal-pitch-offset-deg",
1.0 + getprop("/sim/current-view/goal-pitch-offset-deg"));
return;
}
# Emulate a non-repeatable button for mod3 != 0
if (button0_with_mod3)
return;
button0_with_mod3 = 1;
if (mod3 == -1) {
controls.flapsDown(-1);
} else {
controls.selectEngine(0);
}
</script>
</binding>
<mod-up>
<binding>
<command>nasal</command>
<script>
button0_with_mod3 = 0;
</script>
</binding>
</mod-up>
</button>
<button n="1">
<desc>View Right / Brake Right [mod3=-1] / Select second engine [mod3=1] / Trigger1 [mod3=0 and mod1]</desc>
<repeatable type="bool">true</repeatable>
<binding>
<command>nasal</command>
<script>
if (mod3 == 0) {
if (mod1) {
# This seems the most common for "trigger"
setprop("/controls/armament/trigger1", 1);
# Many planes use this instead [also true for "trigger1"?]
setprop("/ai/submodels/trigger1", 1);
} else {
setprop("/sim/current-view/goal-heading-offset-deg",
-1.0 + getprop("/sim/current-view/goal-heading-offset-deg"));
}
return;
}
# Emulate a non-repeatable button for mod3 != 0
if (button1_with_mod3)
return;
button1_with_mod3 = 1;
if (mod3 == -1) {
controls.applyBrakes(1, 1);
} else {
controls.selectEngine(1);
}
</script>
</binding>
<mod-up>
<binding>
<command>nasal</command>
<script>
button1_with_mod3 = 0;
controls.applyBrakes(0, 1);
# This seems the most common for "trigger"
setprop("/controls/armament/trigger1", 0);
# Many planes use this instead [also true for "trigger1"?]
setprop("/ai/submodels/trigger1", 0);
</script>
</binding>
</mod-up>
</button>
<button n="2">
<desc>View Down [mod3=0] / Select third engine [mod3=1] / Flaps Down [mod3=-1]</desc>
<repeatable type="bool">true</repeatable>
<binding>
<command>nasal</command>
<script>
if (mod3 == 0) {
setprop("/sim/current-view/goal-pitch-offset-deg",
-1.0 + getprop("/sim/current-view/goal-pitch-offset-deg"));
return;
}
# Emulate a non-repeatable button for mod3 != 0
if (button2_with_mod3)
return;
button2_with_mod3 = 1;
if (mod3 == -1) {
controls.flapsDown(1);
} else {
controls.selectEngine(2);
}
</script>
</binding>
<mod-up>
<binding>
<command>nasal</command>
<script>
button2_with_mod3 = 0;
</script>
</binding>
</mod-up>
</button>
<button n="3">
<desc>View Left / Brake Left [mod3=-1] / Select fourth engine [mod3=1] / Trigger [mod3=0 and mod1]</desc>
<repeatable type="bool">true</repeatable>
<binding>
<command>nasal</command>
<script>
if (mod3 == 0) {
if (mod1) {
# This seems the most common
setprop("/controls/armament/trigger", 1);
# Many planes use this instead
setprop("/ai/submodels/trigger", 1);
} else {
setprop("/sim/current-view/goal-heading-offset-deg",
1.0 + getprop("/sim/current-view/goal-heading-offset-deg"));
}
return;
}
# Emulate a non-repeatable button for mod3 != 0
if (button3_with_mod3)
return;
button3_with_mod3 = 1;
if (mod3 == -1) {
controls.applyBrakes(1, -1);
} else {
controls.selectEngine(3);
}
</script>
</binding>
<mod-up>
<binding>
<command>nasal</command>
<script>
button3_with_mod3 = 0;
controls.applyBrakes(0, -1);
# This seems the most common
setprop("/controls/armament/trigger", 0);
# Many planes use this instead
setprop("/ai/submodels/trigger", 0);
</script>
</binding>
</mod-up>
</button>
<button n="4">
<desc>View Cycle (backward)</desc>
<repeatable type="bool">false</repeatable>
<binding>
<command>nasal</command>
<script>view.stepView(-1)</script>
</binding>
</button>
<button n="5">
<desc>View Cycle (forward)</desc>
<repeatable type="bool">false</repeatable>
<binding>
<command>nasal</command>
<script>view.stepView(1)</script>
</binding>
</button>
<button n="6">
<desc>View Decrease</desc>
<repeatable type="bool">true</repeatable>
<binding>
<command>nasal</command>
<script>view.decrease(0.75)</script>
</binding>
</button>
<button n="7">
<desc>View Increase</desc>
<repeatable type="bool">true</repeatable>
<binding>
<command>nasal</command>
<script>view.increase(0.75)</script>
</binding>
</button>
<button n="8">
<desc>Brakes [mod3=0] / Aileron and Rudder Dance [mod3=-1]</desc>
<binding>
<command>nasal</command>
<script>
if (mod3 == -1) {
interpolate("/controls/flight/aileron",
-0.5, 1, 0.5, 1, -0.5, 1, 0.5, 1, -0.5, 1, 0.5, 1,
-0.5, 1, 0.5, 1);
interpolate("/controls/flight/rudder",
-0.5, 1, 0.5, 1, -0.5, 1, 0.5, 1, -0.5, 1, 0.5, 1,
-0.5, 1, 0.5, 1);
}
elsif (mod3 == 0) {
controls.applyBrakes(1);
}
</script>
</binding>
<mod-up>
<binding>
<command>nasal</command>
<script>controls.applyBrakes(0)</script>
</binding>
</mod-up>
</button>
<button n="9">
<desc>Select Initial View and Recenter [mod3=0] / Reset Zoom to Default [mod3=-1] / Select all engines [mod3=1]</desc>
<binding>
<command>nasal</command>
<script>
if (mod3 == -1) {
setprop("/sim/current-view/field-of-view",
getprop("/sim/view/config/default-field-of-view-deg"));
} elsif (mod3 == 1) {
controls.selectAllEngines();
} else {
setprop("/sim/current-view/view-number", 0);
setprop("/sim/current-view/goal-heading-offset-deg",
initial_goal_heading_offset_deg);
setprop("/sim/current-view/goal-pitch-offset-deg",
initial_goal_pitch_offset_deg);
}
</script>
</binding>
</button>
</PropertyList>
<!-- end of generic.xml -->