<?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 previous view (all) button 2 (middle): reset view dir tail wheel lock cockpit view reset all trim button 3 (right): flaps down gear down next view next view (all) 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 weapon 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> var selfN = cmdarg().getParent(); var dataN = selfN.getNode("data"); var modeN = dataN.getNode("mode"); var modifierN = dataN.getNode("modifier"); var f1 = 0; var f2 = 0; var left_brake = 0; var right_brake = 0; var trigger = 0; var modifier = 0; var setmodifier = func(bit, val) { modifierN.setValue(modifier = bits.switch(modifier, bit, val)); } if (props.globals.getNode("/rotors", 0) != nil) { selfN.getNode("axis[0]/binding/power").setIntValue(1); selfN.getNode("axis[1]/binding/power").setIntValue(1); } var viewdir = props.globals.getNode("/sim").getChildren("view"); forindex (var i; viewdir) { var t = viewdir[i].getNode("type"); viewdir[i] = t != nil and t.getValue() == "lookat" ? 1 : -1; } var kbdshift = props.globals.getNode("/devices/status/keyboard/shift", 1); var kbdctrl = props.globals.getNode("/devices/status/keyboard/ctrl", 1); var kbdalt = props.globals.getNode("/devices/status/keyboard/alt", 1); var m = 0; var setmode = func m = modifierN.getValue() + modeN.getValue() * 4; setlistener(modeN, setmode); setlistener(modifierN, setmode, 1); var aircraft = getprop("/sim/aircraft"); var thrust_display = func nil; if (aircraft == "harrier") { thrust_display = func { thv = getprop("/controls/engines/engine[0]/mixture"); gui.popupTip("Thrust vector " ~ int(thv * 120 - 20 + 0.5)); } } </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>3</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> 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> 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 " ~ (i ? "ON" : "OFF")); controls.applyBrakes(0); } elsif (m == 2) { i = !getprop("/controls/flight/speedbrake"); setprop("/controls/flight/speedbrake", i); gui.popupTip("Speed Brake " ~ (i ? "ON" : "OFF")); } elsif (m == 3) { i = !getprop("/controls/engines/engine[0]/reverser"); props.setAll("/controls/engines/engine", "reverser", i); gui.popupTip("Thrust Reverser " ~ (i ? "ON" : "OFF")); } </script> </binding> </mod-up> </button> <button n="1"> <name>Left Button</name> <desc>flaps up, +F3: gear up, +F4: previous active view, +F3+F4: previous view</desc> <repeatable type="bool">false</repeatable> <binding> <command>nasal</command> <script> 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, 0); } elsif (m == 3) { view.stepView(-1, 1); } </script> </binding> <mod-up> <binding> <command>nasal</command> <script> 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> if (m == 0) { view.resetView(); } elsif (m == 1) { i = !getprop("/controls/gear/tailwheel-lock"); setprop("/controls/gear/tailwheel-lock", i); gui.popupTip("Tail Wheel " ~ (i ? "LOCKED" : "UNLOCKED")); } 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 active view, +F3+F4: next view</desc> <repeatable type="bool">false</repeatable> <binding> <command>nasal</command> <script> 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, 0); } elsif (m == 3) { view.stepView(1, 1); } </script> </binding> <mod-up> <binding> <command>nasal</command> <script> 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; 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; 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; 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; 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>setmodifier(0, 1)</script> </binding> <mod-up> <binding> <command>nasal</command> <script>setmodifier(0, 0)</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>setmodifier(1, 1)</script> </binding> <mod-up> <binding> <command>nasal</command> <script>setmodifier(1, 0)</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> 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> if (m == 0) { view.panViewDir(-viewdir[view.index]); } elsif (m == 1) { controls.adjMixture(-1); thrust_display(); } 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> if (m == 0) { view.panViewDir(viewdir[view.index]); } elsif (m == 1) { controls.adjMixture(1); thrust_display(); } 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> 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>